[Scodoc-devel] [SVN] Scolar : [1202] - Upgrade vers psycopg2: nouveau module d' interface avec postgresql.

eviennet at lipn.univ-paris13.fr eviennet at lipn.univ-paris13.fr
Mar 12 Mar 23:28:03 CET 2013


Une pièce jointe HTML a été nettoyée...
URL: <https://www-rt.iutv.univ-paris13.fr/pipermail/scodoc-devel/attachments/20130312/5dc556bc/attachment-0001.html>
-------------- section suivante --------------
Modified: trunk/ImportScolars.py
===================================================================
--- trunk/ImportScolars.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/ImportScolars.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -159,8 +159,8 @@
     et les inscrit dans le semestre indiqu\xE9 (et \xE0 TOUS ses modules)
     """
     log('scolars_import_excel_file: formsemestre_id=%s'%formsemestre_id)
-    cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cnx = context.GetDBConnexion(autocommit=False)
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     annee_courante = time.localtime()[0]
     always_require_ine = context.get_preference('always_require_ine') 
     exceldata = datafile.read()
@@ -299,7 +299,7 @@
         log('scolars_import_excel_file: aborting transaction !')
         # Nota: db transaction is sometimes partly commited...
         # here we try to remove all created students
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         for etudid in created_etudids:
             log('scolars_import_excel_file: deleting etudid=%s'%etudid)
             cursor.execute('delete from notes_moduleimpl_inscription where etudid=%(etudid)s', { 'etudid':etudid })
@@ -384,7 +384,7 @@
     """
     log('scolars_import_admission: formsemestre_id=%s'%formsemestre_id)
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     annee_courante = time.localtime()[0]
     exceldata = datafile.read()
     if not exceldata:

Modified: trunk/VERSION.py
===================================================================
--- trunk/VERSION.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/VERSION.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -1,12 +1,16 @@
 # -*- mode: python -*-
 # -*- coding: iso8859-15 -*-
 
-SCOVERSION = "6.4"
+SCOVERSION = "6.5"
 
 SCONAME = "ScoDoc"
 
 SCONEWS = """
-
+<h4>Ann\xE9e 2013</h4>
+<ul>
+<li>Modernisation de certains de composants logiciels</li>
+<li>Saisie des absences par mati\xE8res</li>
+</ul>
 <h4>Ann\xE9e 2012</h4>
 <ul>
 <li>Table lyc\xE9es d'origine avec carte google</li>

Modified: trunk/ZAbsences.py
===================================================================
--- trunk/ZAbsences.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/ZAbsences.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -336,7 +336,7 @@
         estjust = _toboolean(estjust)
         matin = _toboolean(matin)
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute('insert into absences (etudid,jour,estabs,estjust,matin,description, moduleimpl_id) values (%(etudid)s, %(jour)s, TRUE, %(estjust)s, %(matin)s, %(description)s, %(moduleimpl_id)s )', vars())
         logdb(REQUEST, cnx, 'AddAbsence', etudid=etudid,
               msg='JOUR=%(jour)s,MATIN=%(matin)s,ESTJUST=%(estjust)s,description=%(description)s,moduleimpl_id=%(moduleimpl_id)s'%vars())
@@ -351,7 +351,7 @@
             raise ScoValueError('date justificatif trop loin dans le futur !')
         matin = _toboolean(matin)
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute('insert into absences (etudid,jour,estabs,estjust,matin, description) values (%(etudid)s,%(jour)s, FALSE, TRUE, %(matin)s, %(description)s )', vars() )
         logdb(REQUEST, cnx, 'AddJustif', etudid=etudid,
               msg='JOUR=%(jour)s,MATIN=%(matin)s'%vars())
@@ -365,7 +365,7 @@
         # unpublished
         matin = _toboolean(matin)
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         req = 'delete from absences where jour=%(jour)s and matin=%(matin)s and etudid=%(etudid)s and estabs'
         if moduleimpl_id:
             req += ' and moduleimpl_id=%(moduleimpl_id)s'
@@ -380,7 +380,7 @@
         # unpublished
         matin = _toboolean(matin)
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute('delete from absences where jour=%(jour)s and matin=%(matin)s and etudid=%(etudid)s and ESTJUST AND NOT ESTABS', vars() )
         cursor.execute('update absences set estjust=false where jour=%(jour)s and matin=%(matin)s and etudid=%(etudid)s', vars() )
         logdb(REQUEST, cnx, 'AnnuleJustif', etudid=etudid,
@@ -396,7 +396,7 @@
     #     """
     #     # unpublished
     #     cnx = self.GetDBConnexion()
-    #     cursor = cnx.cursor()
+    #     cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     #     # supr les absences non justifiees
     #     cursor.execute("delete from absences where etudid=%(etudid)s and (not estjust) and moduleimpl_id=(moduleimpl_id)s and jour BETWEEN %(datedebut)s AND %(datefin)s",
     #                    vars() )
@@ -430,7 +430,7 @@
                 self._AnnuleAbsence(etudid, jour, matin, moduleimpl_id, REQUEST)
             return
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         # supr les absences non justifiees
         for date in dates:
             cursor.execute(
@@ -467,7 +467,7 @@
         else:
             modul = ''
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute("""SELECT COUNT(*) AS NbAbs FROM (
     SELECT DISTINCT A.JOUR, A.MATIN
     FROM ABSENCES A
@@ -491,7 +491,7 @@
         else:
             modul = ''
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute("""SELECT COUNT(*) AS NbAbsJust FROM (
   SELECT DISTINCT A.JOUR, A.MATIN
   FROM ABSENCES A, ABSENCES B
@@ -509,7 +509,7 @@
     def _ListeAbsDate(self, etudid, beg_date, end_date):
         # Liste des absences et justifs entre deux dates
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute("""SELECT jour, matin, estabs, estjust, description FROM ABSENCES A 
      WHERE A.ETUDID = %(etudid)s
      AND A.jour >= %(beg_date)s 
@@ -550,7 +550,7 @@
     def ListeAbsJust(self, etudid, datedebut):
         "Liste des absences justifiees (par ordre chronologique)"
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute("""SELECT DISTINCT A.ETUDID, A.JOUR, A.MATIN FROM ABSENCES A, ABSENCES B
  WHERE A.ETUDID = %(etudid)s
  AND A.ETUDID = B.ETUDID 
@@ -567,7 +567,7 @@
     def ListeAbsNonJust(self, etudid, datedebut):
         "Liste des absences NON justifiees (par ordre chronologique)"
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute("""SELECT ETUDID, JOUR, MATIN FROM ABSENCES A 
     WHERE A.ETUDID = %(etudid)s
     AND A.estabs 
@@ -589,7 +589,7 @@
         Si only_no_abs: seulement les justificatifs correspondant aux jours sans absences relev\xE9es.
         """
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         req = """SELECT DISTINCT ETUDID, JOUR, MATIN FROM ABSENCES A
  WHERE A.ETUDID = %(etudid)s
  AND A.ESTJUST
@@ -613,9 +613,9 @@
         "Description associee a l'absence"
         if not cursor:
             cnx = self.GetDBConnexion()
-            cursor = cnx.cursor()
+            cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         a = a.copy()
-        a['jour'] = a['jour'].date
+        # a['jour'] = a['jour'].date()
         if a['matin']: # devrait etre booleen... :-(
             a['matin'] = True
         else:
@@ -634,9 +634,7 @@
                     M = Mlist[0]
                     module += '%s ' % M['module']['code']
 
-	    # retir\xE9 par D.SOUDIERE (exp\xE9rimental)	
-        #if desc and module:
-	if desc:
+        if desc:
             return '(%s) %s' % (desc, module)
             return desc
         if module:
@@ -650,7 +648,7 @@
         is_just: idem
         """
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         req = """SELECT DISTINCT etudid, jour, matin FROM ABSENCES A 
     WHERE A.jour = %(date)s
     """
@@ -673,7 +671,7 @@
     def ListeAbsNonJustJour(self, date, am=True, pm=True):
         "Liste des absences non justifiees ce jour"
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         reqa = ''
         if not am:
             reqa += " AND NOT matin "
@@ -1154,7 +1152,7 @@
         # examens ces jours l\xE0 ?
         if with_evals:
             cnx = self.GetDBConnexion()
-            cursor = cnx.cursor()
+            cursor = cnx.cursor(cursor_factory=ScoDocCursor)
             for a in absnonjust + absjust:
                 cursor.execute("""select eval.*
                 from notes_evaluation eval, notes_moduleimpl_inscription mi, notes_moduleimpl m
@@ -1213,7 +1211,7 @@
                 if with_evals:
                     a['exams'] = descr_exams(a)
                 a['datedmy'] = a['jour'].strftime('%d/%m/%Y')
-                a['matin_o'] = a['matin']
+                a['matin_o'] = int(a['matin'])
                 a['matin'] = matin(a['matin'])
 		index=a['description'].find(')')
 		if index != -1:

Modified: trunk/ZEntreprises.py
===================================================================
--- trunk/ZEntreprises.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/ZEntreprises.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -68,10 +68,10 @@
     def delete(self, cnx, oid):
         "delete correspondants and contacts, then self"
         # first, delete all correspondants and contacts
-        cursor = cnx.cursor()
-        cursor.execute('delete from entreprise_contact where entreprise_id=%(entreprise_id)d',
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
+        cursor.execute('delete from entreprise_contact where entreprise_id=%(entreprise_id)s',
                        { 'entreprise_id' : oid } )    
-        cursor.execute('delete from entreprise_correspondant where entreprise_id=%(entreprise_id)d',
+        cursor.execute('delete from entreprise_correspondant where entreprise_id=%(entreprise_id)s',
                        { 'entreprise_id' : oid } )
         cnx.commit()
         EditableTable.delete(self, cnx, oid)
@@ -100,7 +100,7 @@
     def list_by_etud(self, cnx, args={},
                      sort_on_contact=False, disable_formatting=False):
         "cherche rentreprise ayant eu contact avec etudiant"
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute('select E.*, I.nom as etud_nom, I.prenom as etud_prenom, C.date from entreprises E, entreprise_contact C, identite I where C.entreprise_id = E.entreprise_id and C.etudid = I.etudid and I.nom ~* %(etud_nom)s ORDER BY E.nom',
                        args )
         titles, res = [ x[0] for x in cursor.description ], cursor.dictfetchall()
@@ -413,7 +413,7 @@
         if not etudiant:
             return 1, None
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute('select etudid, nom, prenom from identite where upper(nom) ~ upper(%(etudiant)s) or etudid=%(etudiant)s',
                        { 'etudiant' : etudiant } )
         r = cursor.fetchall()
@@ -438,7 +438,7 @@
         raise NotImplementedError
         # XXXXX fonction non achevee , non testee...
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         vals = dictfilter(args, self.dbfields)
         # DBSelect    
         what=['*']

Modified: trunk/ZNotes.py
===================================================================
--- trunk/ZNotes.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/ZNotes.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -602,7 +602,7 @@
     def do_matiere_formation_id(self, matiere_id):
         "get formation_id from matiere"
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute('select UE.formation_id from notes_matieres M, notes_ue UE where M.matiere_id = %(matiere_id)s and M.ue_id = UE.ue_id',
                        { 'matiere_id' : matiere_id } )
         res = cursor.fetchall()
@@ -1033,7 +1033,7 @@
         "delete moduleimpl (desinscrit tous les etudiants)"
         cnx = self.GetDBConnexion()
         # --- desinscription des etudiants
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         req = "DELETE FROM notes_moduleimpl_inscription WHERE moduleimpl_id=%(moduleimpl_id)s"
         cursor.execute( req, { 'moduleimpl_id' : oid } )
         # --- suppression des enseignants
@@ -1433,7 +1433,7 @@
                     sem_ens[ensd['ens_id']]['mods'].append(mod)
         # compte les absences ajout\xE9es par chacun dans tout le semestre
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         for ens in sem_ens:
             cursor.execute("select * from scolog L, notes_formsemestre_inscription I where method='AddAbsence' and authenticated_user=%(authenticated_user)s and L.etudid = I.etudid and  I.formsemestre_id=%(formsemestre_id)s and date > %(date_debut)s and date < %(date_fin)s", { 'authenticated_user' : ens, 'formsemestre_id' : formsemestre_id, 'date_debut' : DateDMYtoISO(sem['date_debut']), 'date_fin' : DateDMYtoISO(sem['date_fin']) })
             
@@ -1648,7 +1648,7 @@
         insem = insem[0]
         # -- desinscription de tous les modules
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute( "select moduleimpl_inscription_id from notes_moduleimpl_inscription Im, notes_moduleimpl M  where Im.etudid=%(etudid)s and Im.moduleimpl_id = M.moduleimpl_id and M.formsemestre_id = %(formsemestre_id)s",
                         { 'etudid' : etudid, 'formsemestre_id' : formsemestre_id } )
         res = cursor.fetchall()
@@ -1703,7 +1703,7 @@
         "retourne liste des etudids inscrits a ce module"
         req = "select distinct Im.etudid from notes_moduleimpl_inscription Im, notes_formsemestre_inscription Isem, notes_moduleimpl M where Isem.etudid=Im.etudid and Im.moduleimpl_id=M.moduleimpl_id and M.moduleimpl_id = %(moduleimpl_id)s"
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()    
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)    
         cursor.execute( req, { 'moduleimpl_id' : moduleimpl_id } )
         res = cursor.fetchall()
         return [ x[0] for x in res ]
@@ -1713,7 +1713,7 @@
                                             moduleimpl_id,formsemestre_id):
         "inscrit tous les etudiants inscrit au semestre a ce module"
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         req = """INSERT INTO notes_moduleimpl_inscription
                              (moduleimpl_id, etudid)
                     SELECT %(moduleimpl_id)s, I.etudid
@@ -1740,7 +1740,7 @@
         # Desinscriptions
         if reset:
             cnx = self.GetDBConnexion()
-            cursor = cnx.cursor()
+            cursor = cnx.cursor(cursor_factory=ScoDocCursor)
             cursor.execute( "delete from notes_moduleimpl_inscription where moduleimpl_id = %(moduleimpl_id)s", { 'moduleimpl_id' : moduleimpl_id })
         # Inscriptions au module:
         inmod_set = Set( [ x['etudid'] for x in self.do_moduleimpl_inscription_list( args={ 'moduleimpl_id' : moduleimpl_id } ) ])
@@ -2270,7 +2270,7 @@
             if r != None:
                 return r
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute("select * from " + table + " where evaluation_id=%(evaluation_id)s",
                        { 'evaluation_id' : evaluation_id } )
         res = cursor.dictfetchall()

Modified: trunk/ZScoUsers.py
===================================================================
--- trunk/ZScoUsers.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/ZScoUsers.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -136,9 +136,10 @@
         # not published
         try:
             # a database adaptor called UsersDB must exist
-            cnx = self.UsersDB().db 
+            self.UsersDB().encoding = 'LATIN1'
+            cnx = self.UsersDB().getconn(init=False)
         except:
-            # backward compat: try to use same DB
+            # backward compat: try to use same DB (usually will not work !!!)
             log('warning: ZScoUsers using Sco DB connexion')
             cnx = self.GetDBConnexion() 
         cnx.commit() # sync !
@@ -354,7 +355,7 @@
         assert len(user) == 1, 'database inconsistency: len(r)=%d'%len(r)
         # should not occur, already tested in _can_handle_passwd
         cnx = self.GetUsersDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute('update sco_users set date_modif_passwd=now(), passwd_temp=0 where user_name=%(user_name)s',
                        { 'user_name' : user_name } )
         cnx.commit()
@@ -737,7 +738,7 @@
 
         # Des noms/pr\xE9noms semblables existent ?            
         cnx = self.GetUsersDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute('select * from sco_users where lower(nom) ~ %(nom)s and lower(prenom) ~ %(prenom)s;', { 'nom' : nom.lower().strip(), 'prenom' : prenom.lower().strip() } )
         res = cursor.dictfetchall()
         if edit:
@@ -1028,7 +1029,7 @@
         self.do_change_password(user_name, password)
         # Flag it as temporary:
         cnx = self.GetUsersDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         ui = { 'user_name' : user_name }
         cursor.execute("update sco_users set passwd_temp=1 where user_name='%(user_name)s'" % ui)
 

Modified: trunk/ZScolar.py
===================================================================
--- trunk/ZScolar.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/ZScolar.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -29,14 +29,15 @@
 """
 
 import sys
+import traceback
 import time, string, glob, re
 import urllib, urllib2, cgi, xml
 try: from cStringIO import StringIO
 except: from StringIO import StringIO
 from zipfile import ZipFile
+import thread
+import psycopg2
 
-import psycopg
-
 # Zope modules:
 from OFS.SimpleItem import Item # Basic zope object
 from OFS.PropertyManager import PropertyManager # provide the 'Properties' tab with the
@@ -63,6 +64,7 @@
 log( 'ZScolar home=%s' % file_path )
 
 from sco_utils import *
+import notesdb
 from notesdb import *
 from scolog import logdb
 
@@ -91,10 +93,7 @@
 from sco_formsemestre_status import makeMenu
 from VERSION import SCOVERSION, SCONEWS
 
-try:
-    import Products.ZPsycopgDA.DA as ZopeDA
-except:
-    import ZPsycopgDA.DA as ZopeDA # interp.py
+# import essai_cas
 
 # ---------------
 
@@ -111,7 +110,7 @@
     meta_type = 'ZScolar'
     security=ClassSecurityInfo()
     file_path = Globals.package_home(globals())
-    
+
     # This is the list of the methods associated to 'tabs' in the ZMI
     # Be aware that The first in the list is the one shown by default, so if
     # the 'View' tab is the first, you will never see your tabs by cliquing
@@ -128,14 +127,14 @@
         )
         + Item.manage_options            # add the 'Undo' & 'Owner' tab 
         + RoleManager.manage_options     # add the 'Security' tab
-        )
-
+        )    
+    
     # no permissions, only called from python
     def __init__(self, id, title, db_cnx_string=None):
-	"initialise a new instance of ZScolar"
+        "initialise a new instance of ZScolar"
         log('*** creating ZScolar instance')
         self.id = id
-	self.title = title
+        self.title = title
         self._db_cnx_string = db_cnx_string        
         self._cnx = None
         # --- add editable DTML documents:
@@ -144,19 +143,19 @@
         #                    'sidebar_dept')
         
         # --- add DB connector
-        id = 'DB'
-        da = ZopeDA.Connection(
-            id, 'DB connector', db_cnx_string, False,
-            check=1, tilevel=2, encoding='iso8859-15')
-        self._setObject(id, da)
+        #id = 'DB'
+        #da = ZopeDA.Connection(
+        #    id, 'DB connector', db_cnx_string, False,
+        #    check=1, tilevel=2, encoding='iso8859-15')
+        #self._setObject(id, da)
         # --- add Scousers instance
         id = 'Users'
         obj = ZScoUsers.ZScoUsers( id, 'Gestion utilisateurs zope')
-	self._setObject(id, obj)        
+        self._setObject(id, obj)        
         # --- add Notes instance
         id = 'Notes'
         obj = ZNotes.ZNotes( id, 'Gestion Notes')
-	self._setObject(id, obj)
+        self._setObject(id, obj)
         # --- add Absences instance
         id = 'Absences'
         obj = ZAbsences.ZAbsences(id, 'Gestion absences')
@@ -165,7 +164,7 @@
         id = 'Entreprises'
         obj = ZEntreprises.ZEntreprises(id, 'Suivi entreprises')
         self._setObject(id, obj)
-
+        
         #
         self.manage_addProperty('roles_initialized', '0', 'string')
     
@@ -266,7 +265,7 @@
         raise ValueError('essai exception')
         #raise ScoValueError('essai exception !', dest_url='totoro', REQUEST=REQUEST)
 
-        #cursor = cnx.cursor()
+        #cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         #cursor.execute("select * from notes_formations")
         #b += str(cursor.fetchall())
         #b = self.Notes.gloups()
@@ -327,32 +326,23 @@
     #    GESTION DE LA BD
     #
     # --------------------------------------------------------------------
-    security.declareProtected('Change DTML Documents', 'GetDBConnexion')    
+    security.declareProtected('Change DTML Documents', 'GetDBConnexionString')    
     def GetDBConnexionString(self):
         # should not be published (but used from contained classes via acquisition)
         return self._db_cnx_string
 
     security.declareProtected('Change DTML Documents', 'GetDBConnexion')
-    def GetDBConnexion(self,new=False):
-        # should not be published (but used from contained classes via acquisition)
-        if not self._db_cnx_string:
-            raise ScolarError('invalid db connexion string')
-        cnx = self.DB().db # a database adaptor called DB must exists        
-        cnx.commit() # sync !
-        return cnx
-#         if new:
-#             log('GetDBConnexion: requested new connexion')
-#             return DB.connect( self._db_cnx_string )        
-#         if self._cnx:
-#             self._cnx.commit() # terminate transaction
-#             return _cnx
-#         log('GetDBConnexion: opening new db connexion')
-#         self._cnx = DB.connect( self._db_cnx_string )
-#         return self._cnx
+    GetDBConnexion = notesdb.GetDBConnexion
+    #    def GetDBConnexion(self, autocommit=True):
+    #    # should not be published (but used from contained classes via acquisition)
+    #    
+    #    if not getattr(self, '_zscolar_initialized', False):
+    #        self.initialize()
+    #    cnx = self._pg_pool.getconn(key=(thread.get_ident(),autocommit))
+    #    cnx.autocommit = autocommit
+    #    # self.DB().encoding = 'LATIN1' # necessaire car anciennes installs en iso8859-15
+    #    return cnx
 
-#    def g(self):
-#        "debug"
-#        return '<html><body>voila:' + str(self.DB) + '<br>' + str(self.DB()) + '<br>' + str(dir(self.DB().db)) + '</body></html>'
 
     security.declareProtected(ScoView, "TrivialFormulator")
     def TrivialFormulator(self, form_url, values, formdescription=(), initvalues={},
@@ -437,7 +427,10 @@
         "Check date and convert to ISO string"
         return DateDMYtoISO(dmy)
 
-
+    # XXX essai XXX
+    # security.declareProtected(ScoView, 'essai_cas')
+    # essai_cas = essai_cas.essai_cas
+    
     # --------------------------------------------------------------------
     #
     #    PREFERENCES
@@ -553,7 +546,7 @@
     def listScoLog(self,etudid):
         "liste des operations effectuees sur cet etudiant"
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute("select * from scolog where etudid=%(etudid)s ORDER BY DATE DESC",
                        {'etudid':etudid})
         return cursor.dictfetchall()
@@ -1338,7 +1331,7 @@
         """chaine decrivant la situation actuelle de l'etudiant
         """
         cnx = self.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute("select I.formsemestre_id, I.etat from notes_formsemestre_inscription I,  notes_formsemestre S where etudid=%(etudid)s and S.formsemestre_id = I.formsemestre_id and date_debut < now() and date_fin > now() order by S.date_debut desc;",                       
                        {'etudid' : etudid} )
         r = cursor.dictfetchone()
@@ -1771,7 +1764,7 @@
         cnx = self.GetDBConnexion()
         self.Notes.do_formsemestre_inscription_edit(args=ins, formsemestre_id=formsemestre_id)
         logdb(REQUEST,cnx,method='cancelDem', etudid=etudid)
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute( "delete from scolar_events where etudid=%(etudid)s and formsemestre_id=%(formsemestre_id)s and event_type='DEMISSION'",
                         { 'etudid':etudid, 'formsemestre_id':formsemestre_id})
         cnx.commit()
@@ -2031,7 +2024,7 @@
                    'absences', 
                    'billet_absence',
                    'identite' ]
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         for table in tables:
             cursor.execute( "delete from %s where etudid=%%(etudid)s" % table,
                             etud )            
@@ -2455,8 +2448,8 @@
             db_cnx_string = 'user=%s dbname=%s port=%s' % (db_user, db_name, SCO_DEFAULT_SQL_PORT)
         # v\xE9rifie que la bd existe et possede le meme nom de dept.
         try:
-            cnx = psycopg.connect(db_cnx_string)        
-            cursor = cnx.cursor()
+            cnx = psycopg2.connect(db_cnx_string)        
+            cursor = cnx.cursor(cursor_factory=ScoDocCursor)
             cursor.execute( "select * from sco_prefs where name='DeptName'" )
         except:
             return _simple_error_page(context,

Added: trunk/config/install_psycopg2.sh
===================================================================
--- trunk/config/install_psycopg2.sh	                        (rev 0)
+++ trunk/config/install_psycopg2.sh	2013-03-12 22:28:03 UTC (rev 1202)
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# Install pyscopg2 postgresql driver
+
+# This script installs from shipped archive
+
+PYTHON=python2.4
+
+SRC_ARCHIVE="/opt/scodoc/instance/Products/ScoDoc/config/softs/psycopg2-2.4.6.tar.gz"
+
+# Test if psycopg2 installed
+ver=$($PYTHON <<EOF
+try:
+    import psycopg2
+    print psycopg2.__version__.split()[0]
+except:
+    print '0'
+EOF
+)
+
+if [ "$ver" != "2.4.6" ]
+then
+ echo "Installing pyscopg2"
+ apt-get install gcc
+ cd /tmp
+ tar xfz $SRC_ARCHIVE 
+ cd  psycopg2-2.4.6
+ $PYTHON setup.py install
+fi
+


Property changes on: trunk/config/install_psycopg2.sh
___________________________________________________________________
Added: svn:executable
   + *

Modified: trunk/config/postupgrade-db.py
===================================================================
--- trunk/config/postupgrade-db.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/config/postupgrade-db.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -357,7 +357,7 @@
         r = cursor.fetchall()
         if not r:
             log("adding semestre_id %s" % i)
-            cursor.execute("INSERT INTO notes_semestres (semestre_id) VALUES (%(i)d)", { 'i' : i } )
+            cursor.execute("INSERT INTO notes_semestres (semestre_id) VALUES (%(i)s)", { 'i' : i } )
     # ECTS associes aux UE:
     check_field(cnx, 'notes_ue', 'ects',
                 ['alter table notes_ue add column ects float DEFAULT NULL',

Added: trunk/config/softs/psycopg2-2.4.6.tar.gz
===================================================================
(Binary files differ)


Property changes on: trunk/config/softs/psycopg2-2.4.6.tar.gz
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Modified: trunk/config/upgrade.sh
===================================================================
--- trunk/config/upgrade.sh	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/config/upgrade.sh	2013-03-12 22:28:03 UTC (rev 1202)
@@ -67,6 +67,9 @@
 ./install_simplejson.sh
 export PYTHON_EGG_CACHE=/tmp/.egg_cache
 
+# check and install psycopg2
+./install_psycopg2.sh 
+
 # post-upgrade scripts
 echo "Executing post-upgrade script..."
 "$SCODOC_DIR"/config/postupgrade.py

Modified: trunk/notes_log.py
===================================================================
--- trunk/notes_log.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/notes_log.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -2,7 +2,6 @@
 # -*- coding: iso8859-15 -*-
 
 import pdb,os,sys,time,re,inspect
-from sco_utils import SCO_ENCODING
 from email.MIMEMultipart import MIMEMultipart
 from email.MIMEText import MIMEText
 from email.Header import Header
@@ -84,13 +83,14 @@
 
 # Alarms by email:
 def sendAlarm( context, subj, txt ):
+    import sco_utils
     msg = MIMEMultipart()
-    subj = Header( subj,  SCO_ENCODING )
+    subj = Header( subj,  sco_utils.SCO_ENCODING )
     msg['Subject'] = subj
     msg['From'] = context.get_preference('email_from_addr')
     msg['To'] = ALARM_DESTINATION
     msg.epilogue = ''
-    txt = MIMEText( txt, 'plain', SCO_ENCODING )
+    txt = MIMEText( txt, 'plain', sco_utils.SCO_ENCODING )
     msg.attach(txt)
     context.sendEmail(msg)
 

Modified: trunk/notes_table.py
===================================================================
--- trunk/notes_table.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/notes_table.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -721,7 +721,7 @@
         Si la decision n'a pas \xE9t\xE9 prise, la cl\xE9 etudid n'est pas pr\xE9sente.
         """
         cnx = self.context.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute("select etudid, code, assidu, compense_formsemestre_id, event_date from scolar_formsemestre_validation where formsemestre_id=%(formsemestre_id)s and ue_id is NULL;",
                        {'formsemestre_id' : self.formsemestre_id} )
         decisions_jury = {}
@@ -774,12 +774,14 @@
                     ue_cap['moy_ue'] = moy_ue_cap
                     if type(moy_ue_cap) == FloatType and moy_ue_cap >= self.parcours.NOTES_BARRE_VALID_UE:
                         if not cnx:
-                            cnx = self.context.GetDBConnexion()
+                            cnx = self.context.GetDBConnexion(autocommit=False)
                         sco_parcours_dut.do_formsemestre_validate_ue(cnx, nt_cap, ue_cap['formsemestre_id'], etudid,  ue_cap['ue_id'], ue_cap['code'])
                     else:
                         log('*** valid inconsistency: moy_ue_cap=%s (etudid=%s, ue_id=%s formsemestre_id=%s)' % (moy_ue_cap, etudid, ue_cap['ue_id'], ue_cap['formsemestre_id']))
                 ue_cap['moy'] = ue_cap['moy_ue'] # backward compat (needs refactoring)
                 self.ue_capitalisees[etudid].append(ue_cap)
+        if cnx:
+            cnx.commit()
     
     def comp_ue_coefs(self, cnx):
         """Les coefficients sont attribu\xE9s aux modules, pas aux UE.
@@ -814,7 +816,7 @@
         (ne compte que les notes en attente dans des \xE9valuation avec coef. non nul).
         """
         cnx = self.context.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute("select n.* from notes_notes n, notes_evaluation e, notes_moduleimpl m, notes_moduleimpl_inscription i where n.etudid = %(etudid)s and n.value = %(code_attente)s and n.evaluation_id=e.evaluation_id and e.moduleimpl_id=m.moduleimpl_id and m.formsemestre_id=%(formsemestre_id)s and e.coefficient != 0 and m.moduleimpl_id=i.moduleimpl_id and i.etudid=%(etudid)s",
                        {'formsemestre_id' : self.formsemestre_id, 'etudid' : etudid, 'code_attente' : NOTES_ATTENTE} )
         return len(cursor.fetchall()) > 0

Modified: trunk/notesdb.py
===================================================================
--- trunk/notesdb.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/notesdb.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -2,7 +2,9 @@
 # -*- coding: iso8859-15 -*-
 
 import pdb, os, sys, string
-import psycopg
+import traceback
+import psycopg2
+import thread
 from notes_log import log
 from sco_exceptions import *
 from types import *
@@ -24,12 +26,41 @@
     # XX voir aussi sco_utils.unescape_html
     return s.replace('&', '&')
 
-DB = psycopg
+# Ramene une connexion a la base de donnees scolarite
+# pour l'instance donnee par context
+# La connexion est unique (r\xE9utilis\xE9e) pour chaque thread
+# et est par d\xE9faut en autocommit
+_pools = {}
+def GetDBConnexion(context, autocommit=True):
+    pool = _pools.get( context._db_cnx_string, None)
+    if not pool:
+        pool = psycopg2.pool.ThreadedConnectionPool(2, 8, dsn=context._db_cnx_string )
+        _pools[context._db_cnx_string] = pool
+        log('GetDBConnexion: created pool for "%s"' % context._db_cnx_string)
+    cnx = pool.getconn(key=(thread.get_ident(),autocommit))
+    #log('GetDBConnexion: autocommit=%s cnx=%s' % (autocommit,cnx))
+    if cnx.autocommit != autocommit:
+        cnx.autocommit = autocommit
+    return cnx
 
+
+class ScoDocCursor(psycopg2.extensions.cursor):
+    """A database cursor emulating some methods of psycopg v1 cursors"""
+    def dictfetchall(cursor):
+        col_names = [ d[0] for d in cursor.description ]
+        return [ dict(zip(col_names, row)) for row in cursor.fetchall() ]
+    def dictfetchone(cursor):
+        col_names = [ d[0] for d in cursor.description ]
+        row = cursor.fetchone()
+        if row:
+            return dict(zip(col_names, row))
+        else:
+            return {}
+
 def SimpleQuery(context, query, args, cursor=None):
     if not cursor:
         cnx = context.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     #log( 'SimpleQuery(%s)' % (query % args) )
     cursor.execute( query, args )
     return cursor
@@ -40,7 +71,7 @@
 
 def DBInsertDict( cnx, table, vals, commit=0,convert_empty_to_nulls=1):
     "insert into table values in dict 'vals'"
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     if convert_empty_to_nulls:
         for col in vals.keys():
             if vals[col] == '':
@@ -59,7 +90,7 @@
         else:
             cursor.execute('insert into %s default values'
                            % table )
-        oid = cursor.lastoid()
+        oid = cursor.lastrowid
     except:
         log('DBInsertDict: EXCEPTION !')
         log('DBInsertDict: table=%s, vals=%s' % (str(table),str(vals)))
@@ -78,7 +109,7 @@
     Returns cnx, columns_names, list of tuples
     aux_tables = ( tablename, id_name )
     """
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     if sortkey:
         orderby = ' order by ' + sortkey
     else:
@@ -129,6 +160,7 @@
         cursor.execute( req, vals )
     except:
         log('Exception in DBSelectArgs:\n\treq="%s"\n\tvals="%s"\n' % (req,vals))
+        log(traceback.format_exc())
         raise ScoException()
     return cursor.dictfetchall()
 
@@ -136,7 +168,7 @@
                   convert_empty_to_nulls=1 ):
     if not vals or where is None:
         return
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     if convert_empty_to_nulls:
         for col in vals.keys():
             if vals[col] == '':
@@ -155,7 +187,7 @@
         cnx.commit()
 
 def DBDelete(cnx, table, colid, val, commit=False ):
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     try:
         cursor.execute('delete from ' + table + ' where %s=%%(%s)s'%(colid,colid),
                        { colid: val })
@@ -214,7 +246,7 @@
         # insert
         oid = DBInsertDict(cnx, self.table_name, vals, commit=True )        
         # get back new object id
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         cursor.execute("select %(id_name)s from %(table_name)s where oid=%(oid)s"
                        %
                        { 'id_name' : self.id_name,
@@ -302,7 +334,7 @@
             #self.sql_default_values = vals
             #
             # M\xE9thode sp\xE9cifique \xE0 postgresql (>= 7.4)
-            cursor = cnx.cursor()
+            cursor = cnx.cursor(cursor_factory=ScoDocCursor)
             cursor.execute("SELECT column_name, data_type, column_default FROM information_schema.columns WHERE table_name = '%s'" % self.table_name)
             d = {}
             for info in cursor.dictfetchall():
@@ -494,7 +526,7 @@
 
     Will raise exception if violation of integerity constraint !
     """
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     cursor.execute("select * from %s where %s=%%(old_value)s" 
                    % (table, column),
                    { 'old_value' :  old_value } )

Modified: trunk/sco_abs_notification.py
===================================================================
--- trunk/sco_abs_notification.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/sco_abs_notification.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -86,7 +86,7 @@
     """Actually send the notification by email, and register it in database"""
     cnx = context.GetDBConnexion()
     log('abs_notify: sending notification to %s' % destinations)
-    cursor=cnx.cursor()
+    cursor=cnx.cursor(cursor_factory=ScoDocCursor)
     for email in destinations:
         del msg['To']
         msg['To'] = email
@@ -156,7 +156,7 @@
     """nbabs lors de la derni\xE8re notification envoy\xE9e pour cet \xE9tudiant dans ce semestre
     ou sans semestre (ce dernier cas est n\xE9cessaire pour la transition au nouveau code)"""
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     cursor.execute("""select * from absences_notifications where etudid = %(etudid)s and (formsemestre_id = %(formsemestre_id)s or formsemestre_id is NULL) order by notification_date desc""",
                    vars() )
     res = cursor.dictfetchone()
@@ -168,7 +168,7 @@
 def user_nbdays_since_last_notif(context, email_addr, etudid):
     """nb days since last notification to this email, or None if no previous notification"""
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     cursor.execute("""select * from absences_notifications where email = %(email_addr)s and etudid=%(etudid)s order by notification_date desc""", {'email_addr' : email_addr, 'etudid' : etudid} )
     res = cursor.dictfetchone()
     if res:

Modified: trunk/sco_evaluations.py
===================================================================
--- trunk/sco_evaluations.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/sco_evaluations.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -31,6 +31,7 @@
 
 from notes_log import log
 from sco_utils import *
+from notesdb import *
 import sco_news
 import sco_groups
 import ZAbsences
@@ -227,7 +228,7 @@
     """
     req = "select evaluation_id from notes_evaluation E, notes_moduleimpl MI where MI.formsemestre_id = %(formsemestre_id)s and MI.moduleimpl_id = E.moduleimpl_id"
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()    
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)    
     cursor.execute( req, { 'formsemestre_id' : formsemestre_id } )
     res = cursor.fetchall()
     evaluation_ids = [ x[0] for x in res ]
@@ -241,7 +242,7 @@
     """Liste des evals pour ce semestre"""
     req = "select E.* from notes_evaluation E, notes_moduleimpl MI where MI.formsemestre_id = %(formsemestre_id)s and MI.moduleimpl_id = E.moduleimpl_id"
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()    
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)    
     cursor.execute( req, { 'formsemestre_id' : formsemestre_id } )
     return cursor.dictfetchall()
 
@@ -263,7 +264,9 @@
         else:
             nb_evals_en_cours += 1
         dates.append(e['last_modif'])
-    dates.sort()
+
+    dates = sort_dates(dates)
+    
     if len(dates):
         last_modif = dates[-1] # date de derniere modif d'une note dans un module
     else:

Modified: trunk/sco_formations.py
===================================================================
--- trunk/sco_formations.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/sco_formations.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -31,7 +31,7 @@
 from sco_utils import *
 import xml.dom.minidom
 
-from notesdb import quote_dict
+from notesdb import *
 from notes_log import log
 
 def formation_export(context, formation_id, export_ids=False, format=None, REQUEST=None):
@@ -113,7 +113,7 @@
     log('F_quoted=%s' % F_quoted )
     # find new version number
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     log('select max(version) from notes_formations where acronyme=%(acronyme)s and titre=%(titre)s' % F_quoted)
     cursor.execute('select max(version) from notes_formations where acronyme=%(acronyme)s and titre=%(titre)s', F_quoted)
     res = cursor.fetchall()

Modified: trunk/sco_formsemestre_edit.py
===================================================================
--- trunk/sco_formsemestre_edit.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/sco_formsemestre_edit.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -144,7 +144,7 @@
 
     # Liste des ID de semestres
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     cursor.execute( "select semestre_id from notes_semestres" )
     semestre_id_list = [ str(x[0]) for x in cursor.fetchall() ]
     semestre_id_labels = []
@@ -846,7 +846,7 @@
         
         context.do_moduleimpl_delete(mod['moduleimpl_id'], formsemestre_id=formsemestre_id)
     # --- Desinscription des etudiants
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     req = "DELETE FROM notes_formsemestre_inscription WHERE formsemestre_id=%(formsemestre_id)s"
     cursor.execute( req, { 'formsemestre_id' : formsemestre_id } )
     # --- Suppression des evenements

Modified: trunk/sco_formsemestre_validation.py
===================================================================
--- trunk/sco_formsemestre_validation.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/sco_formsemestre_validation.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -685,7 +685,7 @@
     nt = context._getNotesCache().get_NotesTable(context, formsemestre_id) #> get_etudids, get_etud_decision_sem, get_ues, get_etud_decision_ues, get_etud_ue_status
     etudids = nt.get_etudids()
     modifs = [] # liste d'\xE9tudiants modifi\xE9s
-    cnx = context.GetDBConnexion()
+    cnx = context.GetDBConnexion(autocommit=False)
     for etudid in etudids:
         etud = context.getEtudInfo(etudid=etudid, filled=True)[0]
         Se = sco_parcours_dut.SituationEtudParcours(context, etud, formsemestre_id)
@@ -720,6 +720,7 @@
                 modifs.append(msg)
                 log(msg)
                 sco_parcours_dut.do_formsemestre_validate_ue(cnx, nt, formsemestre_id, etudid, ue_id, code_ue)
+    cnx.commit()
     #
     H = [context.sco_header(REQUEST, page_title='R\xE9paration des codes UE'),
          sco_formsemestre_status.formsemestre_status_head(context, REQUEST=REQUEST,
@@ -739,8 +740,8 @@
     """Suppression des decisions de jury pour un etudiant.
     """
     log('formsemestre_validation_suppress_etud( %s, %s)' % (formsemestre_id, etudid))
-    cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cnx = context.GetDBConnexion(autocommit=False)
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     args = { 'formsemestre_id' : formsemestre_id, 'etudid' : etudid }
     try:
         # -- Validation du semestre et des UEs
@@ -836,15 +837,16 @@
                                          REQUEST=None):
     """Enregistre validation d'UE"""
     sem = context.get_formsemestre(formsemestre_id)
-    cnx = context.GetDBConnexion()
+    cnx = context.GetDBConnexion(autocommit=False)
     nt = context._getNotesCache().get_NotesTable(context, formsemestre_id ) #> get_etud_ue_status
 
     sco_parcours_dut.do_formsemestre_validate_ue(
         cnx, nt, None, etudid, ue_id, 'ADM', moy_ue=moy_ue, date=date, semestre_id=semestre_id)
 
     logdb(REQUEST, cnx, method='formsemestre_validate_previous_ue',
-          etudid=etudid, msg='Validation UE %s' % ue_id)
+          etudid=etudid, msg='Validation UE %s' % ue_id, commit=False)
     _invalidate_etud_formation_caches(context, etudid, sem['formation_id'])
+    cnx.commit()
 
 def _invalidate_etud_formation_caches(context, etudid, formation_id):
     "Invalide tous les semestres de cette formation o\xF9 l'etudiant est inscrit..."
@@ -888,7 +890,7 @@
     """Suppress a validation (ue_id, etudid) and redirect to formsemestre"""
     log('etud_ue_suppress_validation( %s, %s, %s)' % (etudid, formsemestre_id, ue_id))
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     cursor.execute("DELETE FROM scolar_formsemestre_validation WHERE etudid=%(etudid)s and ue_id=%(ue_id)s", 
                    { 'etudid' : etudid, 'ue_id' : ue_id } )
     

Modified: trunk/sco_groups.py
===================================================================
--- trunk/sco_groups.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/sco_groups.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -165,7 +165,7 @@
     """legacy code: used by group_list and trombino
     """
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     group = get_group(context, group_id)
     sem = context.Notes.get_formsemestre(group['formsemestre_id'])
     other_partitions = [ p for p in get_partitions_list(context, sem['formsemestre_id'] ) if p['partition_id'] != group['partition_id'] and p['partition_name'] ]
@@ -363,7 +363,7 @@
     Warning: don't check if group_id exists (the caller should check).
     """
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     args = { 'etudid' : etudid, 'group_id' : group_id }
     # d\xE9j\xE0 inscrit ?
     r = SimpleDictFetch(context, "SELECT * FROM group_membership gm WHERE etudid=%(etudid)s and group_id=%(group_id)s", args, cursor=cursor)
@@ -442,7 +442,7 @@
                 change_etud_group_in_partition(context, etudid, group_id, partition, REQUEST=REQUEST)
         # Retire les anciens membres:
         cnx = context.GetDBConnexion()
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         for etudid in old_members_set:            
             log('removing %s from group %s' % (etudid,group_id))
             SimpleQuery(context, "DELETE FROM group_membership WHERE etudid=%(etudid)s and group_id=%(group_id)s", { 'etudid' : etudid, 'group_id' : group_id }, cursor=cursor)
@@ -929,7 +929,7 @@
         req += " and Isem.etat='I'"
     req += r
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     cursor.execute( req, { 'evaluation_id' : evaluation_id } )
     #log('listeetuds_groups: getallstudents=%s  groups=%s' % (getallstudents,groups))
     #log('req=%s' % (req % { 'evaluation_id' : "'"+evaluation_id+"'" }))
@@ -948,7 +948,7 @@
     else:
         c =  ' AND p.partition_name is not NULL'
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()    
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)    
     cursor.execute( "SELECT DISTINCT gd.group_id FROM group_descr gd, group_membership gm, partition p, notes_moduleimpl m, notes_evaluation e WHERE gm.group_id = gd.group_id and gd.partition_id = p.partition_id and p.formsemestre_id = m.formsemestre_id and m.moduleimpl_id = e.moduleimpl_id and e.evaluation_id = %(evaluation_id)s" + c, { 'evaluation_id' : evaluation_id } )
     res = cursor.fetchall()
     group_ids = [ x[0] for x in res ]
@@ -956,7 +956,7 @@
 
 def listgroups(context, group_ids):
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     groups = []
     for group_id in group_ids:
         cursor.execute( "SELECT gd.*, p.* FROM group_descr gd, partition p WHERE p.partition_id = gd.partition_id AND gd.group_id = %(group_id)s",

Modified: trunk/sco_inscr_passage.py
===================================================================
--- trunk/sco_inscr_passage.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/sco_inscr_passage.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -118,7 +118,7 @@
     SAUF sem \xE0 la date de d\xE9but de sem.
     """    
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     sem['date_debut_iso'] = DateDMYtoISO(sem['date_debut'])
     cursor.execute("""select I.etudid
                       from notes_formsemestre_inscription I, notes_formsemestre S

Modified: trunk/sco_moduleimpl_inscriptions.py
===================================================================
--- trunk/sco_moduleimpl_inscriptions.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/sco_moduleimpl_inscriptions.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -373,7 +373,7 @@
     """Desincrit l'etudiant de tous les modules de cette UE dans ce semestre.
     """
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     cursor.execute( """DELETE FROM notes_moduleimpl_inscription 
     WHERE moduleimpl_inscription_id IN (
       SELECT i.moduleimpl_inscription_id FROM
@@ -403,7 +403,7 @@
         raise ScoValueError("%s n'est pas inscrit au semestre !" % etudid)
     
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     cursor.execute( """SELECT mi.moduleimpl_id 
       FROM notes_moduleimpl mi, notes_modules mod, notes_formsemestre sem
       WHERE sem.formsemestre_id = %(formsemestre_id)s

Modified: trunk/sco_news.py
===================================================================
--- trunk/sco_news.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/sco_news.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -96,7 +96,7 @@
     """
     # XXX mauvais algo: oblige a extraire toutes les news pour faire le resume
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     cursor.execute( 'select * from scolar_news order by date asc' )
     selected_news = {} # (type,object) : news dict
     for r in resultset(cursor):

Modified: trunk/sco_parcours_dut.py
===================================================================
--- trunk/sco_parcours_dut.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/sco_parcours_dut.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -394,7 +394,7 @@
         """Enregistre la decision (instance de DecisionSem)
         Enregistre codes semestre et UE, et autorisations inscription.
         """
-        cnx = self.znotes.GetDBConnexion()
+        cnx = self.znotes.GetDBConnexion(autocommit=False)
         # -- check
         if decision.code_etat == 'ADC':
             fsid = decision.formsemestre_id_utilise_pour_compenser
@@ -419,6 +419,7 @@
                 decision.code_etat, decision.assiduite,
                 decision.formsemestre_id_utilise_pour_compenser)
         logdb(REQUEST, cnx, method='validate_sem', etudid=self.etudid,
+              commit=False,
               msg='formsemestre_id=%s code=%s'%(self.formsemestre_id, decision.code_etat))
         # -- decisions UEs
         formsemestre_validate_ues(self.znotes, self.formsemestre_id, self.etudid,
@@ -435,6 +436,7 @@
                 self.etudid, decision.new_code_prev, assidu=1,
                 formsemestre_id_utilise_pour_compenser=fsid)
             logdb(REQUEST, cnx, method='validate_sem', etudid=self.etudid,
+                  commit=False,
                   msg='formsemestre_id=%s code=%s'%(self.prev['formsemestre_id'],
                                                     decision.new_code_prev))
             # modifs des codes d'UE (pourraient passer de ADM a CMP, meme sans modif des notes)
@@ -446,7 +448,7 @@
             self.znotes._inval_cache(formsemestre_id=self.prev['formsemestre_id']) #> modif decisions jury (sem, UE)
 
         # -- supprime autorisations venant de ce formsemestre        
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         try:
             cursor.execute("""delete from scolar_autorisation_inscription
             where etudid = %(etudid)s and origin_formsemestre_id=%(origin_formsemestre_id)s
@@ -541,7 +543,7 @@
     "Ajoute ou change validation semestre"
     args = { 'formsemestre_id' : formsemestre_id, 'etudid' : etudid }
     # delete existing
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     try:
         cursor.execute("""delete from scolar_formsemestre_validation
         where etudid = %(etudid)s and formsemestre_id=%(formsemestre_id)s and ue_id is null""", args )    
@@ -570,7 +572,7 @@
     args = { 'formsemestre_id' : formsemestre_id, 'etudid' : etudid, 'code' : code,
              'assidu': int(assidu)}
     log('formsemestre_update_validation_sem: %s' % args )
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     to_invalidate = []
 
     # enleve compensations si necessaire
@@ -609,7 +611,7 @@
     Les UE des semestres NON ASSIDUS ne sont jamais valid\xE9es (code AJ).
     """
     valid_semestre = CODES_SEM_VALIDES.get(code_etat_sem, False)
-    cnx = znotes.GetDBConnexion()
+    cnx = znotes.GetDBConnexion(autocommit=False)
     nt = znotes._getNotesCache().get_NotesTable(znotes, formsemestre_id ) #> get_ues, get_etud_ue_status
     ue_ids = [ x['ue_id'] for x in nt.get_ues(etudid=etudid, filter_sport=True) ]
     for ue_id in ue_ids:
@@ -630,7 +632,8 @@
         
         if REQUEST:
             logdb(REQUEST, cnx, method='validate_ue', etudid=etudid,
-                  msg='ue_id=%s code=%s'%(ue_id, code_ue))
+                  msg='ue_id=%s code=%s'%(ue_id, code_ue), commit=False)
+    cnx.commit()
 
 def do_formsemestre_validate_ue(cnx, nt, formsemestre_id, etudid, ue_id, code, moy_ue=None, date=None, semestre_id=None):
     "Ajoute ou change validation UE"
@@ -642,7 +645,7 @@
         args['event_date'] = date
         
     # delete existing
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     try:
         cond =  "etudid = %(etudid)s and ue_id=%(ue_id)s"
         if formsemestre_id:
@@ -665,7 +668,7 @@
 
 def etud_est_inscrit_ue(cnx, etudid, formsemestre_id, ue_id):
     """Vrai si l'\xE9tudiant est inscrit a au moins un module de cette UE dans ce semestre"""
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     cursor.execute("""select mi.* from notes_moduleimpl mi, notes_modules mo, notes_ue ue, notes_moduleimpl_inscription i
     where i.etudid = %(etudid)s and i.moduleimpl_id=mi.moduleimpl_id
     and mi.formsemestre_id = %(formsemestre_id)s
@@ -709,7 +712,7 @@
                   } ]
     """
     cnx = znotes.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     cursor.execute("""select SFV.*, ue.ue_code from notes_ue ue, notes_formations nf, notes_formations nf2,
     scolar_formsemestre_validation SFV, notes_formsemestre sem
 
@@ -743,7 +746,7 @@
     cnx = znotes.GetDBConnexion()
     sem = znotes.do_formsemestre_list({'formsemestre_id' : formsemestre_id})[0]
     F = znotes.formation_list( args={ 'formation_id' : sem['formation_id'] } )[0]
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     cursor.execute("""select sem.formsemestre_id
     from notes_formsemestre sem, notes_formations F
     where sem.formation_id = F.formation_id

Modified: trunk/sco_saisie_notes.py
===================================================================
--- trunk/sco_saisie_notes.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/sco_saisie_notes.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -719,7 +719,7 @@
     Return number of changed notes
     """
     uid = str(uid)
-    now = apply(DB.Timestamp, time.localtime()[:6]) #datetime.datetime.now().isoformat()
+    now = apply(psycopg2.Timestamp, time.localtime()[:6]) #datetime.datetime.now().isoformat()
     # Verifie inscription et valeur note
     inscrits = {}.fromkeys(sco_groups.do_evaluation_listeetuds_groups(
             context, evaluation_id, getallstudents=True, include_dems=True))
@@ -729,15 +729,15 @@
     # Recherche notes existantes
     NotesDB = context._notes_getall(evaluation_id)
     # Met a jour la base
-    cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cnx = context.GetDBConnexion(autocommit=False)
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     nb_changed = 0
     nb_suppress = 0
     E = context.do_evaluation_list( {'evaluation_id' : evaluation_id})[0]
     M = context.do_moduleimpl_list(args={ 'moduleimpl_id' : E['moduleimpl_id']})[0]
     existing_decisions = [] # etudids pour lesquels il y a une decision de jury et que la note change
     try:
-        for (etudid,value) in notes:
+        for (etudid,value) in notes:            
             changed = False
             if not NotesDB.has_key(etudid):
                 # nouvelle note
@@ -747,7 +747,7 @@
                               'value': value, 'comment' : comment, 'uid' : uid, 
                               'date' : now}
                         quote_dict(aa)
-                        cursor.execute('insert into notes_notes (etudid,evaluation_id,value,comment,date,uid) values (%(etudid)s,%(evaluation_id)s,%(value)f,%(comment)s,%(date)s,%(uid)s)', aa )
+                        cursor.execute('insert into notes_notes (etudid,evaluation_id,value,comment,date,uid) values (%(etudid)s,%(evaluation_id)s,%(value)s,%(comment)s,%(date)s,%(uid)s)', aa )
                     changed = True
             else:
                 # il y a deja une note

Modified: trunk/sco_synchro_etuds.py
===================================================================
--- trunk/sco_synchro_etuds.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/sco_synchro_etuds.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -30,7 +30,7 @@
 
 
 from sco_utils import *
-from notes_log import log
+
 import sco_portal_apogee
 import sco_inscr_passage
 import scolars
@@ -387,7 +387,7 @@
     # si tres grosse base, il serait mieux de faire une requete
     # d'interrogation par etudiant.
     cnx = context.GetDBConnexion()
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     cursor.execute( 'select ' + EKEY_SCO + ', etudid from identite' )
     key2etudid = dict( [ (x[0], x[1]) for x in cursor.fetchall() ] )
     all_set = set(key2etudid.keys())
@@ -496,7 +496,7 @@
         log('do_import_etuds_from_portal: aborting transaction !')
         # Nota: db transaction is sometimes partly commited...
         # here we try to remove all created students
-        cursor = cnx.cursor()
+        cursor = cnx.cursor(cursor_factory=ScoDocCursor)
         for etudid in created_etudids:
             log('do_import_etuds_from_portal: deleting etudid=%s'%etudid)
             cursor.execute('delete from notes_moduleimpl_inscription where etudid=%(etudid)s', { 'etudid':etudid })

Modified: trunk/sco_undo_notes.py
===================================================================
--- trunk/sco_undo_notes.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/sco_undo_notes.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -45,7 +45,7 @@
  - annuler une modif d'une note
 """
 
-from mx.DateTime import TimeDelta, DateTime
+import datetime
 
 from sco_utils import *
 from notesdb import *
@@ -56,7 +56,7 @@
 
 # deux notes (de m\xEAme uid) sont consid\xE9r\xE9es comme de la m\xEAme op\xE9ration si
 # elles sont s\xE9par\xE9es de moins de 2*tolerance:
-OPERATION_DATE_TOLERANCE = TimeDelta(seconds=0.1)
+OPERATION_DATE_TOLERANCE = datetime.timedelta(seconds=0.1)
 
 
 class NotesOperation(dict):

Modified: trunk/sco_utils.py
===================================================================
--- trunk/sco_utils.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/sco_utils.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -48,8 +48,8 @@
 from sco_exceptions import *
 from sco_permissions import *
 from TrivialFormulator import TrivialFormulator, TF, tf_error_message
+from notes_log import log
 
-
 # ----- CALCUL ET PRESENTATION DES NOTES
 NOTES_PRECISION=1e-4 # evite eventuelles erreurs d'arrondis
 NOTES_MIN = 0.       # valeur minimale admise pour une note
@@ -579,3 +579,14 @@
         attrs['border'] = 0
     s = ' '.join([ '%s="%s"' % (k, attrs[k]) for k in attrs ])
     return '<img %s src="/ScoDoc/static/icons/%s.%s" />' % (s, name, file_format)
+
+
+def sort_dates(L, reverse=False):
+    """Return sorted list of dates, allowing None items (they are put at the beginning)"""
+    mindate = datetime.datetime(datetime.MINYEAR, 1, 1)
+    try:
+        return sorted(L, key=lambda x: x or mindate, reverse=reverse)
+    except:
+        # Helps debugging 
+        log('sort_dates( %s )' % L )
+        raise

Modified: trunk/scolars.py
===================================================================
--- trunk/scolars.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/scolars.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -190,7 +190,7 @@
     if FORBIDDEN_CHARS_EXP.search(nom) or FORBIDDEN_CHARS_EXP.search(prenom):
         return False, 0
     # Now count homonyms:
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     req = 'select etudid from identite where lower(nom) ~ %(nom)s and lower(prenom) ~ %(prenom)s'
     if etudid:
         req += '  and etudid <> %(etudid)s'

Modified: trunk/scolog.py
===================================================================
--- trunk/scolog.py	2013-03-12 21:13:30 UTC (rev 1201)
+++ trunk/scolog.py	2013-03-12 22:28:03 UTC (rev 1202)
@@ -28,7 +28,7 @@
 
 import pdb,os,sys,psycopg
 from sco_exceptions import *
-from notesdb import quote_dict
+from notesdb import *
 from notes_log import retreive_request
 DB = psycopg
 
@@ -47,7 +47,7 @@
                  'remote_host' : None }
     args.update( { 'method' : method, 'etudid' : etudid, 'msg' : msg })
     quote_dict(args)
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     cursor.execute('insert into scolog (authenticated_user,remote_addr,remote_host,method,etudid,msg) values (%(authenticated_user)s,%(remote_addr)s,%(remote_host)s,%(method)s,%(etudid)s,%(msg)s)', args )
     if commit:
         cnx.commit()
@@ -55,6 +55,6 @@
 def loglist(cnx, method=None, authenticated_user=None):
     """List of events logged for these method and user
     """
-    cursor = cnx.cursor()
+    cursor = cnx.cursor(cursor_factory=ScoDocCursor)
     cursor.execute('select * from scolog where method=%(method)s and authenticated_user=%(authenticated_user)s', { 'method' : method, 'authenticated_user' : authenticated_user})
     return cursor.dictfetchall()


Plus d'informations sur la liste de diffusion Scodoc-devel