1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 import sys, os, re, imp, urllib
63 from string import split, join
64 from types import *
65 from cStringIO import StringIO
66 from traceback import print_tb
67
68
69 from Acquisition import Implicit, Acquired
70 from Persistence import Persistent
71 from AccessControl.Role import RoleManager
72 from AccessControl import ClassSecurityInfo
73 from OFS.SimpleItem import Item
74 from OFS.PropertyManager import PropertyManager
75 from Globals import MessageDialog, DevelopmentMode
76 from Products.PageTemplates.PageTemplateFile import PageTemplateFile
77 from App.Management import Navigation
78 from OFS.Cache import Cacheable
79 from OFS.Folder import Folder
80
81
82 from orm2.adapters.pgsql.datasource import zpsycopg_db_conn
83 import orm2.debug
84 from orm2.ui.procedure import procedure as orm2_ui_procedure
85
86 if DevelopmentMode:
87 orm2.debug.debug.verbose = True
88 orm2.debug.sqllog.verbose = True
89
91 -class NoSuch(ORMModeException): pass
93
94
95 unwanted_request_keys = {
96 'AUTHENTICATION_PATH' : 0, 'BASE1' : 0, 'BASE2' : 0, 'BASE3' : 0,
97 'BASE4' : 0, 'GATEWAY_INTERFACE' : 0,
98 'HTTP_PRAGMA' : 0, 'PARENTS' : 0,
99 'PATH_INFO' : 0, 'PATH_TRANSLATED' : 0, 'PUBLISHED' : 0,
100 'RESPONSE' : 0, 'SCRIPT_NAME' : 0,
101 'SERVER_NAME' : 0, 'SERVER_PORT' : 0, 'SERVER_PROTOCOL' : 0,
102 'SERVER_SOFTWARE' : 0, 'SERVER_URL' : 0, 'SESSION' : 0,
103 'TraversalRequestNameStack' : 0, 'URL' : 0, 'URL1' : 0, 'URL2' : 0,
104 'URL3':0 }
105
106 charset_re=re.compile(r'text/[0-9a-z]+\s*;\s*charset=([-_0-9a-z]+' +
107 r')(?:(?:\s*;)|\Z)', re.IGNORECASE)
108
109 doc_string_param_re=re.compile(r'@param\s*(.*?)\s*:')
110
111 -def manage_addORMProcedure(self, id,
112 model_name, procedures_name, class_name,
113 db_connection_name, session_on=False,
114 REQUEST=None):
137
138
143
145 if not hasattr(self, "_v_module") or DevelopmentMode:
146 imp.acquire_lock()
147 try:
148 parts = split(self.module_name, ".")
149
150 path = None
151 name = []
152 for package in parts[:-1]:
153 name.append(package)
154 file, filename, description = imp.find_module(package,
155 path)
156 module = imp.load_module(join(name, "."),
157 file, filename,
158 description)
159 path = module.__path__
160
161 file, filename, description = imp.find_module(parts[-1],
162 path)
163
164 self._v_module = imp.load_module(self.module_name, file,
165 filename, description)
166
167 sys.modules[self.module_name] = self._v_module
168 self.last_error = []
169
170 except Exception, e:
171 self._v_module = None
172 exception, desc, traceback = sys.exc_info()
173 f = StringIO()
174 print_tb(traceback, file=f)
175 traceback = f.getvalue()
176
177 print >> sys.stderr, "-" * 60
178 print traceback
179 print exception
180 print desc
181 print >> sys.stderr, "-" * 60
182
183
184
185
186
187
188
189
190
191 self.last_error = [ exception, desc, traceback, ]
192
193
194
195
196 imp.release_lock()
197
198 if hasattr(self._v_module, "__reload__"):
199 self._v_module.__reload__()
200
201 if hasattr(self._v_module, "__relationships__"):
202 self._v_module.__relationships__(self._v_module)
203
204 return self._v_module
205
206
207
208
210 self.module_name = name
211 self.last_error = None
212
213 if hasattr(self, "_v_module"):
214 del self._v_module
215
216
217 manage_addORMProcedureForm = PageTemplateFile(
218 "www/ORMProcedure.pt", globals())
219
220 -class ORMProcedure(Item, Implicit, Cacheable, Persistent, PropertyManager):
221 """
222 This object type allows you to call ORM 'mode' functions from within
223 your Zope application.
224 """
225
226 meta_type = "ORM Procedure"
227 manage_form = PageTemplateFile("www/ORMProcedure.pt", globals())
228
229 manage_options = (
230 ( {"label": "Edit", "action": "manage_form"},) +
231 Item.manage_options +
232 Cacheable.manage_options +
233 RoleManager.manage_options +
234 PropertyManager.manage_options )
235
236 ZopeTime=Acquired
237 HelpSys=Acquired
238
239 security = ClassSecurityInfo()
240
241 - def __init__(self, id, model_name, procedures_name, class_name,
242 db_connection_name, session_on,
243 REQUEST=None):
247
248 security.declareProtected("Change External Methods", 'manage_edit')
249 - def manage_edit(self, model_name, procedures_name, class_name,
250 db_connection_name, session_on,
251 REQUEST=None):
270
271
272 security.declareProtected("View", 'index_html')
274 """
275 Call the mode function and do cache management.
276 """
277 result = self.ZCacheable_get(default=None)
278
279 if result is None:
280 data = self.om_exec(*args, **kw)
281 mime_type = self.REQUEST.RESPONSE.headers.get(
282 "content-type", "text/plain")
283 self.ZCacheable_set(data=(data, mime_type))
284 else:
285 data, mime_type = result
286 self.REQUEST.RESPONSE.setHeader("Content-Type", mime_type)
287
288 return data
289
290 __call__ = index_html
291
292
294 formdata = kw
295
296
297
298
299
300
301
302
303
304
305
306 encoding = sys.getdefaultencoding()
307
308
309 if self.REQUEST.RESPONSE.headers.has_key('content-type'):
310 match = charset_re.match(
311 self.REQUEST.RESPONSE.headers['content-type'])
312 if match:
313 encoding = match.group(1)
314
315
316
317
318 for key in self.REQUEST.keys():
319 if not unwanted_request_keys.has_key(key):
320 value = self.REQUEST[key]
321
322
323 if type(value) == StringType:
324 try:
325 value = unicode(value, encoding)
326 except UnicodeDecodeError:
327 pass
328
329 formdata[key] = value
330
331 ds = self._ds()
332
333
334 formdata["ds"] = ds
335 formdata["base_url"] = self.absolute_url()
336 formdata["request"] = self.REQUEST
337 formdata["response"] = self.REQUEST.RESPONSE
338 formdata["REQUEST"] = self.REQUEST
339 formdata["RESPONSE"] = self.REQUEST.RESPONSE
340 formdata["context"] = self
341 formdata["formdata"] = formdata.copy()
342 formdata["form"] = formdata["formdata"]
343
344 if self.session_on():
345 formdata["session"] = self.REQUEST.SESSION
346
347
348
349
350
351 model = self._model.module()
352 formdata["model"] = model
353
354 procedure_class = self._procedure_class(formdata)
355
356 if procedure_class is None:
357 raise Exception("Illegal method name!")
358
359 procedure_instance = procedure_class(self, formdata)
360
361 if hasattr(procedure_class, "__call_param_names__"):
362 param_names = procedure_class.__call_param_names__
363 elif procedure_instance.__call__.__doc__ is not None:
364 doc = procedure_instance.__call__.__doc__
365 param_names = doc_string_param_re.findall(doc)
366 procedure_class.__call_param_names__ = param_names
367 else:
368 param_names = []
369
370 kw = {}
371 if param_names != []:
372 for param_name in param_names:
373 if formdata.has_key(param_name):
374 kw[param_name] = formdata[param_name]
375
376 try:
377 ret = procedure_instance(**kw)
378 except:
379 if ds is not None: ds.rollback()
380 raise
381
382
383
384 if ds is not None: ds.rollback()
385
386 return ret
387
389 module = self._procedures.module()
390 if module is None:
391 raise Exception("module is None")
392
393 procedure_class = getattr(module, self._class_name, None)
394 if procedure_class is None:
395 msg = "Procedure_class is None (%s)." % repr(self._class_name)
396 raise Exception(msg)
397
398 return procedure_class
399
400
402 """
403 Return True if this adapter provied the mode functions with a
404 session object
405 """
406 return self._session_on
407
409 """
410 Accessor. Return the name of the Python module where the
411 mode function resides.
412 """
413 return self._model.module_name
414
416 """
417 Return the exception text of the last error loading the model module,
418 otherwise an empty string.
419 """
420 return self._model.last_error
421
423 """
424 Accessor. Return the name of the Python module with the
425 procedures in it.
426 """
427 return self._procedures.module_name
428
430 """
431 Return the exception text of the last error loading the procedures
432 module, otherwise an empty string.
433 """
434 return self._procedures.last_error
435
437 """
438 Return the class name
439 """
440 return self._class_name
441
443 """
444 Return the name of the databse connection used for this
445 mode.
446 """
447 return self._db_connection_name
448
450 """
451 Return an ORM datasource object or None if self._db_connection_name
452 is not set.
453 """
454 if self._db_connection_name:
455
456
457
458
459
460 ds = zpsycopg_db_conn(self, self.db_connection_name())
461 return ds
462 else:
463 return None
464
465
467 """
468 Return the modification time of the module's source(!) file.
469 The time is returned as the number of seconds since the epoch.
470 """
471 module_file = module.__file__
472
473
474 parts = split(module_file, ".")
475 fname = join(parts[:-1], ".")
476 try:
477 py_file = fname + ".py"
478 py_mtime = os.stat(py_file).st_mtime
479 except OSError:
480 py_mtime = 0
481
482 try:
483 pyc_file = fname + ".pyc"
484 pyc_mtime = os.stat(pyc_file).st_mtime
485 except OSError:
486 pyc_mtime = 0
487
488 return max(py_mtime, pyc_mtime)
489
491 "Just call self"
492 return self(*args, **kw)
493
495 """
496 Return an absolute_url to this object + procedure_name + params in kw
497 """
498 if not hasattr(self._procedures.module(), procedure_name):
499 raise Exception("Illegal procedure name: %s" % procedure_name)
500
501 for name, value in kw.items():
502 if type(value) == UnicodeType:
503 kw[name] = value.encode()
504
505 params = urllib.urlencode(kw)
506
507 if params:
508 params = "?" + params
509 else:
510 params = ""
511
512 url = "%s/%s%s" % ( self.absolute_url(), procedure_name, params, )
513
514 return url
515