tests json
[restcoda.git] / rest.wsgi
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3
4 import sys, traceback
5
6 # configuration (codes d'accès à la base MS-SQL)
7 sys.path.append('/home/thomas/public_html/')
8 import rest_config
9
10 # pour savoir quel objet interroger : Routes et analyse de query_string
11 from routes import Mapper
12 from routes.middleware import RoutesMiddleware
13 from cgi import parse_qs
14
15 # pour chercher les données sur MS-SQL
16 from pymssql import connect
17
18 # pour afficher le résultat : jinja
19 from jinja import Environment, FileSystemLoader
20 from jinja.filters import stringfilter
21
22 # systeme de cache : beaker
23 from beaker.middleware import CacheMiddleware
24
25 # formats de sortie autorisés, et content-type correspondant
26 # formats = { 'xml': 'application/xml', 'html': 'text/html', 'txt': 'text/plain', 'json': 'application/json', 'rss': 'application/rss+xml' }
27 formats = { 'xml': 'application/xml', 'html': 'text/html', 'txt': 'text/plain', 'json': 'text/plain', 'rss': 'application/rss+xml' }
28
29 # les routes
30 mapper = Mapper()
31 mapper.connect(':controller/')
32 mapper.connect(':controller/:id', action='get')
33 mapper.connect(':controller/:action/:id')
34 mapper.create_regs(['document','demlog','comlog'])
35
36 # objet de base : dispose d'un accès à MS-SQL (lire les données) et d'un accès à jinja (rendu des données)
37 class objetsql(object):
38     def __init__(self, environ):
39         self.bd = connect(host=rest_config.host,user=rest_config.user,password=rest_config.password,database=rest_config.database)
40         self.cursor = self.bd.cursor()
41         self.jinja = Environment(loader=FileSystemLoader('/home/thomas/public_html/'))
42         self.environ = environ
43         if (self.environ['org.auf.filters'].has_key('format')):
44             self.outputformat=self.environ['org.auf.filters']['format'][0]
45         else:
46             self.outputformat='xml'
47
48 class document(objetsql):
49     def __init__(self, environ, code_document='%', basename_template='document'):
50         super(document, self).__init__(environ)
51         self.code_document = code_document
52         self.basename_template = basename_template
53
54     def index(self):
55         self.cursor.execute("select top 30 * from auf_v_acces_demcom where code like '%s' order by date_modif desc" % (self.code_document))
56         documents={}
57         documents['code'] = self.code_document
58         documents_liste=[]
59         while 1:
60             document = dict_fetchone(self.cursor)
61             if document == None: break
62             document['code_rest'] = coda2rest(document['code'])
63             documents_liste.append(document)
64         documents['documents'] = documents_liste
65         template = self.jinja.get_template('%s-index.%s' % (self.basename_template, self.outputformat))
66         output = template.render(documents)
67         return self.outputformat, output
68
69     def get(self):
70         id = int(self.environ['wsgiorg.routing_args'][1]['id'])
71         self.cursor.execute("select top 1 * from auf_v_acces_demcom where code like '%s' and numero = %d" % (self.code_document, id))
72         document = dict_fetchone(self.cursor)
73         if document == None:
74             raise "document inexistant"
75         document['code_rest'] = coda2rest(document['code'])
76         details = []
77         self.cursor.execute("select * from auf_v_acces_dtls_demcom where code like '%s' and numero = %d" % (self.code_document, id))
78         while 1:
79             detail = dict_fetchone(self.cursor)
80             if detail == None: break
81             details.append(detail)
82         document['details']=details
83         template = self.jinja.get_template('%s.%s' % (self.basename_template, self.outputformat))
84         output = template.render(document)
85         return self.outputformat, output
86
87 class demlog(document):
88     def __init__(self, environ):
89         super(demlog, self).__init__(environ, code_document = 'DEM-LOG-AUF')
90
91 class comlog(document):
92     def __init__(self, environ):
93         super(comlog, self).__init__(environ, code_document = 'COM-LOG-AUF')
94
95 def dispatcher(environ, start_response):
96     """sera lancée par mod_wsgi"""
97     if environ.has_key('QUERY_STRING'):
98         environ['org.auf.filters'] = parse_qs(environ['QUERY_STRING'])
99     else:
100         environ['org.auf.filters'] = {}
101     results = environ['wsgiorg.routing_args'][1]
102     try:
103         target_class = globals()[results['controller']]
104         method_name = results['action']
105         if environ['REQUEST_METHOD'] != 'GET':
106             method_name = environ['REQUEST_METHOD'] + '_' + method_name
107         method = getattr(target_class,method_name)
108         type, output = method(target_class(environ))
109         start_response("200 OK", [('Content-type', formats[type])])
110         return output.encode('utf-8')
111     except:
112         start_response("404 NOT FOUND", [('Content-type', 'text/plain')])
113         return 'erreur lors du traitement\n%s: %s\n%s' % ( sys.exc_info()[0] , sys.exc_info()[1] , traceback.format_exc())
114
115 application = RoutesMiddleware( dispatcher, mapper)
116
117 # utilitaires
118 def dict_fetchone(cursor):
119     """Renvoie le resultat d'un fetchone dans un dictionnaire"""
120     result = cursor.fetchone()
121     if result == None: return None
122     result_dict = {}
123     for i in range(len(result)):
124         if isinstance( result[i], str ):
125             result_dict[cursor.description[i][0]] = result[i].decode('iso-8859-1')
126         else:
127             result_dict[cursor.description[i][0]] = result[i]
128     return result_dict
129
130 import re 
131 p = re.compile('(dem|com)-(...)-auf',re.IGNORECASE)
132 def coda2rest(value):
133     """Traduit un nom CODA en l'objet correspodant, par exemple DEM-LOG-AUF en demlog"""
134     m = p.search(value)
135     if m == None: return value
136     return m.group(1).lower() + m.group(2).lower()
137