RESTfulisation
[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
0a4c31d4 13# et analyse de query_string (TODO: etudier parse au lieu de cgi)
1795efcd
TN
14from cgi import parse_qs
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')
38# TODO à étudier pour permettre les comarexxx
39mapper.resource('comare','comare')
40mapper.resource('comsra','comsre')
1795efcd
TN
41
42class objetsql(object):
0a4c31d4 43 """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 44 def __init__(self, environ):
a6627284 45 self.bd = connect(host=rest_config.host,user=rest_config.user,password=rest_config.password,database=rest_config.database)
1795efcd
TN
46 self.cursor = self.bd.cursor()
47 self.jinja = Environment(loader=FileSystemLoader('/home/thomas/public_html/'))
1795efcd 48 self.environ = environ
0a4c31d4 49 self.outputformat = environ['wsgiorg.routing_args'][1].get('format','xml')
a6627284 50
1795efcd 51class document(objetsql):
0a4c31d4 52 """objet document CODA (demlog, comlog, demdep... ils ont tous le même format)"""
1795efcd
TN
53 def __init__(self, environ, code_document='%', basename_template='document'):
54 super(document, self).__init__(environ)
55 self.code_document = code_document
56 self.basename_template = basename_template
57
58 def index(self):
59 self.cursor.execute("select top 30 * from auf_v_acces_demcom where code like '%s' order by date_modif desc" % (self.code_document))
60 documents={}
61 documents['code'] = self.code_document
62 documents_liste=[]
63 while 1:
64 document = dict_fetchone(self.cursor)
65 if document == None: break
66 document['code_rest'] = coda2rest(document['code'])
67 documents_liste.append(document)
68 documents['documents'] = documents_liste
69 template = self.jinja.get_template('%s-index.%s' % (self.basename_template, self.outputformat))
70 output = template.render(documents)
71 return self.outputformat, output
72
0a4c31d4 73 def show(self):
a6627284 74 id = int(self.environ['wsgiorg.routing_args'][1]['id'])
1795efcd
TN
75 self.cursor.execute("select top 1 * from auf_v_acces_demcom where code like '%s' and numero = %d" % (self.code_document, id))
76 document = dict_fetchone(self.cursor)
77 if document == None:
78 raise "document inexistant"
79 document['code_rest'] = coda2rest(document['code'])
80 details = []
81 self.cursor.execute("select * from auf_v_acces_dtls_demcom where code like '%s' and numero = %d" % (self.code_document, id))
82 while 1:
83 detail = dict_fetchone(self.cursor)
84 if detail == None: break
85 details.append(detail)
86 document['details']=details
87 template = self.jinja.get_template('%s.%s' % (self.basename_template, self.outputformat))
88 output = template.render(document)
89 return self.outputformat, output
90
91class demlog(document):
92 def __init__(self, environ):
93 super(demlog, self).__init__(environ, code_document = 'DEM-LOG-AUF')
94
95class comlog(document):
96 def __init__(self, environ):
97 super(comlog, self).__init__(environ, code_document = 'COM-LOG-AUF')
98
0a4c31d4
TN
99class demdep(document):
100 def __init__(self, environ):
101 super(demdep, self).__init__(environ, code_document = 'DEM-DEP-AUF')
102
103class comdep(document):
104 def __init__(self, environ):
105 super(comdep, self).__init__(environ, code_document = 'COM-DEP-AUF')
106
107class dempub(document):
108 def __init__(self, environ):
109 super(dempub, self).__init__(environ, code_document = 'DEM-PUB-AUF')
110
111class compub(document):
112 def __init__(self, environ):
113 super(compub, self).__init__(environ, code_document = 'COM-PUB-AUF')
114
115# TODO : voir la possibilité d'appel de comsre/sn1.rss
116class comsre(document):
117 def __init__(self, environ):
118 super(comsre, self).__init__(environ, code_document = 'COM-SRE-%')
119
120class comare(document):
121 def __init__(self, environ):
122 super(comare, self).__init__(environ, code_document = 'COM-ARE-%')
123
124
a6627284 125def dispatcher(environ, start_response):
1795efcd 126 """sera lancée par mod_wsgi"""
a6627284
TN
127 if environ.has_key('QUERY_STRING'):
128 environ['org.auf.filters'] = parse_qs(environ['QUERY_STRING'])
129 else:
130 environ['org.auf.filters'] = {}
131 results = environ['wsgiorg.routing_args'][1]
1795efcd
TN
132 try:
133 target_class = globals()[results['controller']]
134 method_name = results['action']
1795efcd
TN
135 method = getattr(target_class,method_name)
136 type, output = method(target_class(environ))
137 start_response("200 OK", [('Content-type', formats[type])])
138 return output.encode('utf-8')
139 except:
140 start_response("404 NOT FOUND", [('Content-type', 'text/plain')])
141 return 'erreur lors du traitement\n%s: %s\n%s' % ( sys.exc_info()[0] , sys.exc_info()[1] , traceback.format_exc())
142
a6627284 143application = RoutesMiddleware( dispatcher, mapper)
1795efcd 144
0a4c31d4
TN
145
146#
147# petits utilitaires
148#
1795efcd
TN
149def dict_fetchone(cursor):
150 """Renvoie le resultat d'un fetchone dans un dictionnaire"""
151 result = cursor.fetchone()
152 if result == None: return None
153 result_dict = {}
154 for i in range(len(result)):
155 if isinstance( result[i], str ):
156 result_dict[cursor.description[i][0]] = result[i].decode('iso-8859-1')
157 else:
158 result_dict[cursor.description[i][0]] = result[i]
159 return result_dict
160
a6627284
TN
161import re
162p = re.compile('(dem|com)-(...)-auf',re.IGNORECASE)
163def coda2rest(value):
164 """Traduit un nom CODA en l'objet correspodant, par exemple DEM-LOG-AUF en demlog"""
165 m = p.search(value)
166 if m == None: return value
167 return m.group(1).lower() + m.group(2).lower()
168