doc et commentaires
authorThomas NOEL <thomas@new-dev.(none)>
Fri, 4 Jul 2008 14:43:15 +0000 (10:43 -0400)
committerThomas NOEL <thomas.noel@auf.org>
Fri, 4 Jul 2008 14:43:15 +0000 (10:43 -0400)
document.py
objetsql.py
rest.py [new file with mode: 0644]
rest.wsgi [deleted file]
utils.py

index 1c0a189..a9eeba0 100644 (file)
@@ -1,6 +1,13 @@
 #!/usr/bin/python
 # -*- coding: utf-8 -*-
 
+#
+# Classes pour les documents DEM-* et COM-*
+#
+# Ces documents ont tous les même format. On créé donc un objet "document"
+# générique, qui sera hérité. Chaque classe fille précisera le code du document.
+#
+
 from objetsql import *
 from utils import *
 
@@ -11,6 +18,7 @@ class document(objetsql):
         super(document, self).__init__(environ)
         self.code_document = code_document
         self.prefix_template = prefix_template
+       # TODO : voir si on peut faire le filtrage dans "objetsql"
        # filtrage : on extrait la liste des filtres "acceptes" pour en faire des where
         sqlwhere = []
        for filter in self.accept_like_filters:
@@ -90,6 +98,10 @@ class document(objetsql):
         output = template.render( document )
        return self.outputformat, output
 
+#
+# les classes filles précisent le code_document
+#
+
 class dem(document):
     def __init__(self, environ):
         super(dem, self).__init__(environ, code_document = 'DEM-%')
index 6facd04..c726ef9 100644 (file)
@@ -1,34 +1,52 @@
 #!/usr/bin/python
 # -*- coding: utf-8 -*-
 
-from jinja import Environment, FileSystemLoader
-ejinja = Environment(loader=FileSystemLoader('/home/thomas/public_html/templates/'))
+#
+# Un "objetsql" dispose de tout ce qui est nécessaire pour extraire
+# les données (accès au MS-SQL) et pour en faire le rendu final
+# (accès au système de template)
+#
+# Il analyse également l'environnement WSGI afin d'en extraire
+# les données de filtrage (extrait des arguments de l'URL, après le ?)
+#
 
+# l'accès à MS-SQL
 from pymssql import connect
 
+# le système de template
+from jinja import Environment, FileSystemLoader
+ejinja = Environment(loader=FileSystemLoader('/home/thomas/public_html/templates/'))
+
+# le système d'analyse des variables HTTP
 from paste.request import parse_formvars
 
+# accès à la configuration (données pour la connexion MS-SQL)
 import sys
 sys.path.append('/home/thomas/public_html/')
 import rest_config
 
+
 class objetsql(object):
-    """objet de base : dispose d'un accès à MS-SQL (lire les données) et d'un accès à jinja (rendu des données)"""
+    """Objet de base : dispose d'un accès à MS-SQL (lire les données) et d'un accès à jinja (rendu des données)"""
     def __init__(self, environ):
+        """Conserve l'environnement WSGI et analyse les variables HTTP"""
        self.environ = environ
         parse_formvars(environ)                                            # extraction des variables de query_string et POST
        self.filters = environ['paste.parsed_formvars'][0].dict_of_lists() # puis traduction en dictionnaire {var1:[val1,val2], ...}
     def template(self,template):
+        """Retourne un environnement de rendu"""
         self.outputformat = self.environ['wsgiorg.routing_args'][1].get('format','xml')
        return ejinja.get_template('%s.%s' % (template,self.outputformat))
     def cursor(self):
+        """Retourne un curseur vers la base de données"""
         if not hasattr(self,'db_connect'):
             self.db_connect = connect(host=rest_config.host,user=rest_config.user,password=rest_config.password,database=rest_config.database)
        if not hasattr(self,'db_cursor'):
            self.db_cursor = self.db_connect.cursor()
        return self.db_cursor
     def __del__(self):
-        # coupe la connexion à MSSQL à la mort de l'objet (normalement ça se fait tout seul mais j'en suis pas sûr sûr)
+       """Destructeur : coupe la connexion à MSSQL à la mort de l'objet"""
+        # (normalement ça se fait tout seul mais j'en suis pas sûr sûr)
         if hasattr(self,'db_connect'):
            db_connect.close()
 
diff --git a/rest.py b/rest.py
new file mode 100644 (file)
index 0000000..0c3caf6
--- /dev/null
+++ b/rest.py
@@ -0,0 +1,73 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import sys, traceback
+
+# configuration (codes d'accès à la base MS-SQL)
+sys.path.append('/home/thomas/public_html/')
+import rest_config
+
+# pour savoir quel objet interroger : Routes
+from routes import Mapper
+from routes.middleware import RoutesMiddleware
+
+# Gestion des erreurs
+from jinja.exceptions import TemplateNotFound
+
+# TODO : ajouter un middleware de cache (beaker, basé sur REQUEST_URI quand la methode est GET)
+# from beaker.middleware import CacheMiddleware
+
+# formats de sortie autorisés, et content-type correspondant
+# formats = { 'xml': 'application/xml', 'html': 'text/html', 'txt': 'text/plain', 'json': 'application/json', 'rss': 'application/rss+xml' }
+formats = { 'xml': 'application/xml', 'html': 'text/html', 'txt': 'text/plain', 'json': 'text/plain', 'rss': 'application/rss+xml' } # pour debug : json en text/plain
+
+
+# les routes RESTful (cf http://routes.groovie.org/manual.html#restful-services)
+mapper = Mapper()
+mapper.resource('demlog','demlog')
+mapper.resource('comlog','comlog')
+mapper.resource('demdep','demdep')
+mapper.resource('comdep','comdep')
+mapper.resource('dempub','dempub')
+mapper.resource('compub','compub')
+mapper.resource('comare','comare')
+mapper.resource('comarei','comare:(impl)',controller='comare') # pour les comarexxx où xxx est un code d'implantation
+mapper.resource('comsre','comsre')
+mapper.resource('comsrei','comsre:(impl)',controller='comsre')
+mapper.resource('comxre','comxre') # comxre = comare + comsre
+mapper.resource('comxrei','comxre:(impl)',controller='comxre')
+mapper.resource('dem','dem')
+mapper.resource('com','com')
+
+# objets disponibles
+from document import demlog, comlog, demdep, comdep, dempub, compub, comare, comsre, comxre, dem, com
+
+def dispatcher(environ, start_response):
+    """dispatch vers la bonne methode du bon objet, et retour WSGI"""
+    results = environ['wsgiorg.routing_args'][1] # résultat du middleware Routes
+    try:
+        # On cherche l'objet puis la méthode
+        target_class = globals()[results['controller']]
+        method = getattr(target_class,results['action'])
+    except:
+        # Si erreur pendant la recherche, on renvoie un 404
+        start_response("404 Not Found", [('Content-type', 'text/html')])
+       return '<html><body><h2>404 objet ou action invalide</h2><pre>%s: %s\n%s</pre></body></html>' % ( sys.exc_info()[0] , sys.exc_info()[1] , traceback.format_exc())
+    try:
+        # On lance la méthode et on renvoie le résultat
+        type, output = method(target_class(environ))
+       start_response("200 OK", [('Content-type', formats[type])])
+        return output.encode('utf-8') 
+    # gestion des problèmes possibles pendant l'exécution
+    except TemplateNotFound, template:
+        start_response("415 Unsupported Media Type", [('Content-type', 'text/html')])
+       return '<html><body><h2>415 format non supporté (%s inexistant)</h2></body></html>' % template
+    except:
+        start_response("500 INTERNAL ERROR", [('Content-type', 'text/html')])
+        return '<html><body><h2>500 erreur lors du traitement</h2><pre>%s: %s\n%s</pre></body></html>' % ( sys.exc_info()[0] , sys.exc_info()[1] , traceback.format_exc())
+
+
+# application() sera lancée par mod_wsgi : on route et on dispatche
+application = RoutesMiddleware( dispatcher, mapper )
+
+
diff --git a/rest.wsgi b/rest.wsgi
deleted file mode 100644 (file)
index 0c3caf6..0000000
--- a/rest.wsgi
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-import sys, traceback
-
-# configuration (codes d'accès à la base MS-SQL)
-sys.path.append('/home/thomas/public_html/')
-import rest_config
-
-# pour savoir quel objet interroger : Routes
-from routes import Mapper
-from routes.middleware import RoutesMiddleware
-
-# Gestion des erreurs
-from jinja.exceptions import TemplateNotFound
-
-# TODO : ajouter un middleware de cache (beaker, basé sur REQUEST_URI quand la methode est GET)
-# from beaker.middleware import CacheMiddleware
-
-# formats de sortie autorisés, et content-type correspondant
-# formats = { 'xml': 'application/xml', 'html': 'text/html', 'txt': 'text/plain', 'json': 'application/json', 'rss': 'application/rss+xml' }
-formats = { 'xml': 'application/xml', 'html': 'text/html', 'txt': 'text/plain', 'json': 'text/plain', 'rss': 'application/rss+xml' } # pour debug : json en text/plain
-
-
-# les routes RESTful (cf http://routes.groovie.org/manual.html#restful-services)
-mapper = Mapper()
-mapper.resource('demlog','demlog')
-mapper.resource('comlog','comlog')
-mapper.resource('demdep','demdep')
-mapper.resource('comdep','comdep')
-mapper.resource('dempub','dempub')
-mapper.resource('compub','compub')
-mapper.resource('comare','comare')
-mapper.resource('comarei','comare:(impl)',controller='comare') # pour les comarexxx où xxx est un code d'implantation
-mapper.resource('comsre','comsre')
-mapper.resource('comsrei','comsre:(impl)',controller='comsre')
-mapper.resource('comxre','comxre') # comxre = comare + comsre
-mapper.resource('comxrei','comxre:(impl)',controller='comxre')
-mapper.resource('dem','dem')
-mapper.resource('com','com')
-
-# objets disponibles
-from document import demlog, comlog, demdep, comdep, dempub, compub, comare, comsre, comxre, dem, com
-
-def dispatcher(environ, start_response):
-    """dispatch vers la bonne methode du bon objet, et retour WSGI"""
-    results = environ['wsgiorg.routing_args'][1] # résultat du middleware Routes
-    try:
-        # On cherche l'objet puis la méthode
-        target_class = globals()[results['controller']]
-        method = getattr(target_class,results['action'])
-    except:
-        # Si erreur pendant la recherche, on renvoie un 404
-        start_response("404 Not Found", [('Content-type', 'text/html')])
-       return '<html><body><h2>404 objet ou action invalide</h2><pre>%s: %s\n%s</pre></body></html>' % ( sys.exc_info()[0] , sys.exc_info()[1] , traceback.format_exc())
-    try:
-        # On lance la méthode et on renvoie le résultat
-        type, output = method(target_class(environ))
-       start_response("200 OK", [('Content-type', formats[type])])
-        return output.encode('utf-8') 
-    # gestion des problèmes possibles pendant l'exécution
-    except TemplateNotFound, template:
-        start_response("415 Unsupported Media Type", [('Content-type', 'text/html')])
-       return '<html><body><h2>415 format non supporté (%s inexistant)</h2></body></html>' % template
-    except:
-        start_response("500 INTERNAL ERROR", [('Content-type', 'text/html')])
-        return '<html><body><h2>500 erreur lors du traitement</h2><pre>%s: %s\n%s</pre></body></html>' % ( sys.exc_info()[0] , sys.exc_info()[1] , traceback.format_exc())
-
-
-# application() sera lancée par mod_wsgi : on route et on dispatche
-application = RoutesMiddleware( dispatcher, mapper )
-
-
index af27fcf..dedff97 100644 (file)
--- a/utils.py
+++ b/utils.py
@@ -2,10 +2,11 @@
 # -*- coding: utf-8 -*-
 
 #
-# petits utilitaires
+# petits utilitaires divers
 #
+
 def dict_fetchone(cursor):
-    """Renvoie le resultat d'un fetchone dans un dictionnaire"""
+    """Renvoie le resultat d'un fetchone (db-api 2.0) dans un dictionnaire"""
     result = cursor.fetchone()
     if result == None: return None
     result_dict = {}
@@ -16,10 +17,11 @@ def dict_fetchone(cursor):
             result_dict[cursor.description[i][0]] = result[i]
     return result_dict
 
+
 import re 
 p = re.compile('(dem|com)-(...)-(...)',re.IGNORECASE)
 def coda2rest(value):
-    """Traduit un nom CODA vers la base REST correspodante, 
+    """Traduit un nom CODA vers la base REST correspondante, 
     par exemple DEM-LOG-AUF en demlog ou COM-ARE-VN3 en comarevn3"""
     m = p.search(value)
     if m == None: return value