#!/usr/bin/python
# -*- coding: UTF-8 -*-


"""
    Programme permettant de tester les acces a une base de donnees avec
    SQLAlchemy.
"""


###############################################################################
# Informations de versions
###############################################################################
__project__   = 'Applications Bases de donnees'
__author__    = 'Simon CHOLLET (s.chollet@llr.in2p3.fr)'
__modifiers__ = ''
__date__      = '19/09/2011'
__version__   = '1.0'


###############################################################################
# Importations
###############################################################################
# Module systeme : pour la gestion des arguments
import sys

# Module SQLAlchemy
import sqlalchemy as SQLA
import sqlalchemy.orm as ORM


###############################################################################
# Definitions specifiques
###############################################################################
# Serveur + Base de donnees de type MySQL
#    Connecteur = mysqldb
#    Serveur    = localhost
#    Port       = 3306
#    User       = test
#    Paswword   = tempor
#    Base       = annuaire
MYSQL_DATA_PATH = "mysql://test:tempor@localhost:3306/annuaire"

# Chemin du fichier contenant les donnees de type SQLite
SQLITE_DATA_PATH = "sqlite:////tmp/annuaire.db"

# Mode d'utilisation de la base de donnees :
# 'mysql' ou 'sqlite'
DB_MODE = 'mysql'


###############################################################################
# Declaration des classes / fonctions
###############################################################################
class Person(object):
    def __init__(self, title, name, sname, birth, exper):
        """
            Constructeur pour la classe personne
        """
        # Mise a jour des attributs
        self.title = title
        self.name  = name
        self.sname = sname
        self.birth = birth
        self.exper = exper

    def __repr__(self):
        """ Methode permettant d'afficher les informations d'une personne """
        return "<Personne('%s', '%s', '%s', '%s', '%s')>" % (self.title,
            self.name, self.sname, self.birth, self.exper)


#
#
# Fonction appelee lors de la demande
# d'execution de la classe/module
if __name__ == "__main__":

    # Message de bienvenue
    print ">>> PySQLAlchemy <<<"

    # Selon le mode d'utilisation
    if DB_MODE == 'mysql':
        engine = SQLA.create_engine(MYSQL_DATA_PATH, echo=False)
    elif DB_MODE == 'sqlite':
        engine = SQLA.create_engine(SQLITE_DATA_PATH, echo=False)
    else:
        print " * MODE ('%s') NON SUPPORTE !!!" % (DB_MODE)
        sys.exit()
    print " * MODE = '%s'" % (DB_MODE)

    # Creation du catalogue et de la table associee
    metadata = SQLA.MetaData()
    persons_table = SQLA.Table('persons', metadata,
        SQLA.Column('ID', SQLA.Integer, primary_key=True),
        SQLA.Column('title', SQLA.String(255)),
        SQLA.Column('name', SQLA.String(255)),
        SQLA.Column('sname', SQLA.String(255)),
        SQLA.Column('birth', SQLA.String(255)),
        SQLA.Column('exper', SQLA.Integer))

    # Suppression de la table si necessaire :
    # 'drop_all' verifie avant que la table existe
    metadata.drop_all(engine)
    
    # Creation de la table si necessaire :
    # 'create_all' verifie avant que la table n'existe pas
    metadata.create_all(engine)

    # Association de la classe Persons et de la table
    ORM.mapper(Person, persons_table)

    # Creation d'une session de communication avec la base de donnees
    Session = ORM.sessionmaker(bind=engine)
    session = Session()

    # Ajout des personnes dans la base de donnees
    session.add_all([    
        Person('Mr', 'DUPONT', 'Pierre', '1960-06-30', '30'),
        Person('Melle', 'LA PIERRE', 'Marie', '1963-07-21', '20'),
        Person('Mme', 'MOUTE', 'Catherine', '1970-04-23', '15'),
        Person('Mr', 'DURAND', 'Jean-Pierre', '1980-01-12', '5')])

    # On "commit" les modifications :
    # On transfere les demandes SQL precedement
    # effectuees dans la base elle-meme
    session.commit()

    # Affichage de toutes les personnes de la base
    personsList = []
    for person in session.query(Person).order_by(Person.ID):
        # L'attribut ID n'est pas un attribut propre a la classe Person
        # cet attribut est donne par la base de donnees
        personsList.append(person)

    # Affichage de messages d'informations
    # Affiche :
    #   >>> PySQLAlchemy <<<
    #    * MODE = 'mysql'
    #    * Creation de la table : persons
    #    * Ajout de 4 personnes dans l'annuaire
    #    * Liste des personnes inserees :
    #       > ID, Titre, Nom, Prenom, Naissance, Experience
    #       > 1, Mr, DUPONT, Pierre, 1960-06-30, 30
    #       > 2, Melle, LA PIERRE, Marie, 1963-07-21, 20
    #       > 3, Mme, MOUTE, Catherine, 1970-04-23, 15
    #       > 4, Mr, DURAND, Jean-Pierre, 1980-01-12, 5
    print " * Creation de la table : persons"
    print " * Ajout de %d personnes dans l'annuaire" % (len(personsList))
    print " * Liste des personnes inserees :"
    print "    > ID, Titre, Nom, Prenom, Naissance, Experience"
    for person in personsList:
        print "    > %s, %s, %s, %s, %s, %s" % (person.ID, person.title,
            person.name, person.sname, person.birth, person.exper)

    # Recherche d'une personne dans l'annuaire
    personsList = session.query(Person).filter("ID>=2").order_by("ID").all()
    # Affiche :
    #    * Recherche de personnes dans l'annuaire, avec ID >= 2 :
    #       > ID, Titre, Nom, Prenom, Naissance, Experience
    #       > 2, Melle, LA PIERRE, Marie, 1963-07-21, 20
    #       > 3, Mme, MOUTE, Catherine, 1970-04-23, 15
    #       > 4, Mr, DURAND, Jean-Pierre, 1980-01-12, 5
    print
    print " * Recherche de personnes dans l'annuaire, avec ID >= 2 :"
    print "    > ID, Titre, Nom, Prenom, Naissance, Experience"
    for person in personsList:
        print "    > %s, %s, %s, %s, %s, %s" % (person.ID, person.title,
            person.name, person.sname, person.birth, person.exper)

    # Modification d'une personne dans l'annuaire
    personsList = session.query(Person).filter("ID=2").all()
    # Affiche :
    #    * Modification de la personne ID=2 dans l'annuaire :
    #       > ID, Titre, Nom, Prenom, Naissance, Experience
    #       > 2, Melle, LAPIERRE, Marie, 1963-07-21, 20
    print
    print " * Modification de la personne ID=2 dans l'annuaire :"
    print "    > ID, Titre, Nom, Prenom, Naissance, Experience"
    for person in personsList:
        person.name = "LAPIERRE"
        print "    > %s, %s, %s, %s, %s, %s" % (person.ID, person.title,
            person.name, person.sname, person.birth, person.exper)

    # Suppression d'une personne dans l'annuaire
    personsList = session.query(Person).filter("ID=3").all()
    for person in personsList:
        session.delete(person)
    # Affiche :
    #    * Suppression de la personne ID=3 dans l'annuaire :
    #       > ID, Titre, Nom, Prenom, Naissance, Experience
    #       > 1, Mr, DUPONT, Pierre, 1960-06-30, 30
    #       > 2, Melle, LAPIERRE, Marie, 1963-07-21, 20
    #       > 4, Mr, DURAND, Jean-Pierre, 1980-01-12, 5
    print
    print " * Suppression de la personne ID=3 dans l'annuaire :"
    print "    > ID, Titre, Nom, Prenom, Naissance, Experience"
    for person in session.query(Person).order_by(Person.ID):
        print "    > %s, %s, %s, %s, %s, %s" % (person.ID, person.title,
            person.name, person.sname, person.birth, person.exper)

    # On "commit" les modifications :
    # On transfere les demandes SQL precedement effectuees dans la base elle-meme
    session.commit()