paste.request.parse_formvars pour analyse des arguments cgi
[restcoda.git] / rest.wsgi
CommitLineData
1795efcd
TN
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4import sys, traceback
5
a6627284
TN
6# configuration (codes d'accès à la base MS-SQL)
7sys.path.append('/home/thomas/public_html/')
8import rest_config
9
0a4c31d4 10# pour savoir quel objet interroger : Routes
1795efcd 11from routes import Mapper
a6627284 12from routes.middleware import RoutesMiddleware
81b8aba3
TN
13# et analyse des paramètres (POST et query_string) pour filtrage
14from paste.request import parse_formvars
1795efcd 15
a6627284 16# pour chercher les données sur MS-SQL
1795efcd 17from pymssql import connect
a6627284
TN
18
19# pour afficher le résultat : jinja
1795efcd
TN
20from jinja import Environment, FileSystemLoader
21from jinja.filters import stringfilter
22
0a4c31d4
TN
23# TODO systeme de cache : beaker
24# from beaker.middleware import CacheMiddleware
1795efcd 25
a6627284 26# formats de sortie autorisés, et content-type correspondant
d588d902
TN
27# formats = { 'xml': 'application/xml', 'html': 'text/html', 'txt': 'text/plain', 'json': 'application/json', 'rss': 'application/rss+xml' }
28formats = { 'xml': 'application/xml', 'html': 'text/html', 'txt': 'text/plain', 'json': 'text/plain', 'rss': 'application/rss+xml' }
1795efcd 29
0a4c31d4 30# les routes RESTful (cf http://routes.groovie.org/manual.html#restful-services)
1795efcd 31mapper = Mapper()
0a4c31d4
TN
32mapper.resource('demlog','demlog')
33mapper.resource('comlog','comlog')
34mapper.resource('demdep','demdep')
35mapper.resource('comdep','comdep')
36mapper.resource('dempub','dempub')
37mapper.resource('compub','compub')
0a4c31d4 38mapper.resource('comare','comare')
db1681c0
TN
39# pour les comarexxx où xxx est un code d'implantation
40mapper.resource('comarei','comare:(impl)',controller='comare')
0a4c31d4 41mapper.resource('comsra','comsre')
db1681c0 42mapper.resource('comsrai','comsre:(impl)',controller='comsre')
f6b772ed
TN
43mapper.resource('dem','dem')
44mapper.resource('com','com')
1795efcd
TN
45
46class objetsql(object):
0a4c31d4 47 """objet de base : dispose d'un accès à MS-SQL (lire les données) et d'un accès à jinja (rendu des données)"""
1795efcd 48 def __init__(self, environ):
a6627284 49 self.bd = connect(host=rest_config.host,user=rest_config.user,password=rest_config.password,database=rest_config.database)
1795efcd
TN
50 self.cursor = self.bd.cursor()
51 self.jinja = Environment(loader=FileSystemLoader('/home/thomas/public_html/'))
1795efcd 52 self.environ = environ
0a4c31d4 53 self.outputformat = environ['wsgiorg.routing_args'][1].get('format','xml')
a6627284 54
1795efcd 55class document(objetsql):
0a4c31d4 56 """objet document CODA (demlog, comlog, demdep... ils ont tous le même format)"""
1795efcd
TN
57 def __init__(self, environ, code_document='%', basename_template='document'):
58 super(document, self).__init__(environ)
59 self.code_document = code_document
60 self.basename_template = basename_template
61
62 def index(self):
63 self.cursor.execute("select top 30 * from auf_v_acces_demcom where code like '%s' order by date_modif desc" % (self.code_document))
64 documents={}
65 documents['code'] = self.code_document
66 documents_liste=[]
67 while 1:
68 document = dict_fetchone(self.cursor)
69 if document == None: break
70 document['code_rest'] = coda2rest(document['code'])
71 documents_liste.append(document)
72 documents['documents'] = documents_liste
73 template = self.jinja.get_template('%s-index.%s' % (self.basename_template, self.outputformat))
74 output = template.render(documents)
75 return self.outputformat, output
76
db1681c0
TN
77 def show_debug(self):
78 return 'txt', '%s' % self.environ
79
0a4c31d4 80 def show(self):
a6627284 81 id = int(self.environ['wsgiorg.routing_args'][1]['id'])
1795efcd
TN
82 self.cursor.execute("select top 1 * from auf_v_acces_demcom where code like '%s' and numero = %d" % (self.code_document, id))
83 document = dict_fetchone(self.cursor)
84 if document == None:
85 raise "document inexistant"
86 document['code_rest'] = coda2rest(document['code'])
87 details = []
88 self.cursor.execute("select * from auf_v_acces_dtls_demcom where code like '%s' and numero = %d" % (self.code_document, id))
89 while 1:
90 detail = dict_fetchone(self.cursor)
91 if detail == None: break
92 details.append(detail)
93 document['details']=details
94 template = self.jinja.get_template('%s.%s' % (self.basename_template, self.outputformat))
95 output = template.render(document)
96 return self.outputformat, output
97
f6b772ed
TN
98class dem(document):
99 def __init__(self, environ):
100 super(dem, self).__init__(environ, code_document = 'DEM-%')
101
102class com(document):
103 def __init__(self, environ):
104 super(com, self).__init__(environ, code_document = 'COM-%')
105
1795efcd
TN
106class demlog(document):
107 def __init__(self, environ):
108 super(demlog, self).__init__(environ, code_document = 'DEM-LOG-AUF')
109
110class comlog(document):
111 def __init__(self, environ):
112 super(comlog, self).__init__(environ, code_document = 'COM-LOG-AUF')
113
0a4c31d4
TN
114class demdep(document):
115 def __init__(self, environ):
116 super(demdep, self).__init__(environ, code_document = 'DEM-DEP-AUF')
117
118class comdep(document):
119 def __init__(self, environ):
120 super(comdep, self).__init__(environ, code_document = 'COM-DEP-AUF')
121
122class dempub(document):
123 def __init__(self, environ):
124 super(dempub, self).__init__(environ, code_document = 'DEM-PUB-AUF')
125
126class compub(document):
127 def __init__(self, environ):
128 super(compub, self).__init__(environ, code_document = 'COM-PUB-AUF')
129
0a4c31d4
TN
130class comsre(document):
131 def __init__(self, environ):
db1681c0
TN
132 # est-ce un appel de comsre ou comsrexxx (avec xxx = implantation)
133 impl = environ['wsgiorg.routing_args'][1].get('impl','%')
134 super(comsre, self).__init__(environ, code_document = 'COM-SRE-%s' % impl)
0a4c31d4
TN
135
136class comare(document):
137 def __init__(self, environ):
db1681c0
TN
138 impl = environ['wsgiorg.routing_args'][1].get('impl','%')
139 super(comare, self).__init__(environ, code_document = 'COM-ARE-%s' % impl)
0a4c31d4 140
a6627284 141def dispatcher(environ, start_response):
81b8aba3
TN
142 """dispatch vers la bonne methode du bon objet, et retour WSGI"""
143 parse_formvars(environ)
a6627284 144 results = environ['wsgiorg.routing_args'][1]
1795efcd
TN
145 try:
146 target_class = globals()[results['controller']]
147 method_name = results['action']
1795efcd
TN
148 method = getattr(target_class,method_name)
149 type, output = method(target_class(environ))
150 start_response("200 OK", [('Content-type', formats[type])])
151 return output.encode('utf-8')
152 except:
153 start_response("404 NOT FOUND", [('Content-type', 'text/plain')])
154 return 'erreur lors du traitement\n%s: %s\n%s' % ( sys.exc_info()[0] , sys.exc_info()[1] , traceback.format_exc())
155
81b8aba3 156# application qui sera lancée par mod_wsgi : on route et on dispatche
a6627284 157application = RoutesMiddleware( dispatcher, mapper)
81b8aba3 158# TODO : ajouter un middleware de cache (beaker)
1795efcd 159
0a4c31d4
TN
160
161#
162# petits utilitaires
163#
1795efcd
TN
164def dict_fetchone(cursor):
165 """Renvoie le resultat d'un fetchone dans un dictionnaire"""
166 result = cursor.fetchone()
167 if result == None: return None
168 result_dict = {}
169 for i in range(len(result)):
170 if isinstance( result[i], str ):
171 result_dict[cursor.description[i][0]] = result[i].decode('iso-8859-1')
172 else:
173 result_dict[cursor.description[i][0]] = result[i]
174 return result_dict
175
a6627284 176import re
db1681c0 177p = re.compile('(dem|com)-(...)-(...)',re.IGNORECASE)
a6627284 178def coda2rest(value):
db1681c0
TN
179 """Traduit un nom CODA vers la base REST correspodante,
180 par exemple DEM-LOG-AUF en demlog ou COM-ARE-VN3 en comarevn3"""
a6627284
TN
181 m = p.search(value)
182 if m == None: return value
db1681c0
TN
183 if m.group(3).lower() == 'auf':
184 return m.group(1).lower() + m.group(2).lower()
185 else:
186 return m.group(1).lower() + m.group(2).lower() + m.group(3).lower()
a6627284 187