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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 import sys, os, re, imp, urllib
81 from string import split, join
82 from types import *
83 from cStringIO import StringIO
84 from traceback import print_tb
85
86
87 from Acquisition import Implicit, Acquired
88 from Persistence import Persistent
89 from AccessControl.Role import RoleManager
90 from AccessControl import ClassSecurityInfo, getSecurityManager
91 from AccessControl.unauthorized import Unauthorized
92 from OFS.SimpleItem import Item
93 from Globals import MessageDialog, DevelopmentMode
94 from Products.PageTemplates.PageTemplateFile import PageTemplateFile
95 from App.Management import Navigation
96 from OFS.Cache import Cacheable
97 from OFS.Folder import Folder
98
99
100 from orm2.adapters.pgsql.datasource import zpsycopg_db_conn
101 import orm2.debug
102 from orm2.ui.procedure import procedure as orm2_ui_procedure
103
104 if DevelopmentMode:
105 orm2.debug.debug.verbose = True
106 orm2.debug.sqllog.verbose = True
107
111
112
113 unwanted_request_keys = {
114 'AUTHENTICATION_PATH' : 0, 'BASE1' : 0, 'BASE2' : 0, 'BASE3' : 0,
115 'BASE4' : 0, 'GATEWAY_INTERFACE' : 0,
116 'HTTP_PRAGMA' : 0, 'PARENTS' : 0,
117 'PATH_INFO' : 0, 'PATH_TRANSLATED' : 0, 'PUBLISHED' : 0,
118 'RESPONSE' : 0, 'SCRIPT_NAME' : 0,
119 'SERVER_NAME' : 0, 'SERVER_PORT' : 0, 'SERVER_PROTOCOL' : 0,
120 'SERVER_SOFTWARE' : 0, 'SERVER_URL' : 0, 'SESSION' : 0,
121 'TraversalRequestNameStack' : 0, 'URL' : 0, 'URL1' : 0, 'URL2' : 0,
122 'URL3':0 }
123
124 charset_re=re.compile(r'text/[0-9a-z]+\s*;\s*charset=([-_0-9a-z]+' +
125 r')(?:(?:\s*;)|\Z)', re.IGNORECASE)
126
127 doc_string_param_re=re.compile(r'@param\s*(.*?)\s*:')
128
154
155
160
162 if not hasattr(self, "_v_module") or DevelopmentMode:
163 imp.acquire_lock()
164 try:
165 parts = split(self.module_name, ".")
166
167 path = None
168 name = []
169 for package in parts[:-1]:
170 name.append(package)
171 file, filename, description = imp.find_module(package,
172 path)
173 module = imp.load_module(join(name, "."),
174 file, filename,
175 description)
176 path = module.__path__
177
178 file, filename, description = imp.find_module(parts[-1],
179 path)
180
181 self._v_module = imp.load_module(self.module_name, file,
182 filename, description)
183
184 sys.modules[self.module_name] = self._v_module
185 self.last_error = []
186
187 except Exception, e:
188 self._v_module = None
189 exception, desc, traceback = sys.exc_info()
190 f = StringIO()
191 print_tb(traceback, file=f)
192 traceback = f.getvalue()
193
194 print >> sys.stderr, "-" * 60
195 print traceback
196 print exception
197 print desc
198 print >> sys.stderr, "-" * 60
199
200
201
202
203
204
205
206
207
208 self.last_error = [ exception, desc, traceback, ]
209
210
211
212
213 imp.release_lock()
214
215 if hasattr(self._v_module, "__reload__"):
216 self._v_module.__reload__()
217
218 if hasattr(self._v_module, "__relationships__"):
219 self._v_module.__relationships__(self._v_module)
220
221 return self._v_module
222
223
224
225
227 self.module_name = name
228 self.last_error = None
229
230 if hasattr(self, "_v_module"):
231 del self._v_module
232
233
234 manage_addORMProcedureModuleForm = PageTemplateFile(
235 "www/ORMProcedureModule.pt", globals())
236
238 """
239 This object type allows you to call ORM 'mode' functions from within
240 your Zope application.
241 """
242
243 meta_type = "ORM Procedure Module"
244 manage_form = PageTemplateFile("www/ORMProcedureModule.pt", globals())
245
246 manage_options = (
247 ( Folder.manage_options[0],
248 {"label": "Edit", "action": "manage_form"},) +
249 Folder.manage_options[1:] +
250 Cacheable.manage_options)
251
252
253 __ac_permissions__ = (
254 ('View management screens', ('manage_form',)),
255 ('Change External Methods', ('manage_edit',)),
256 ('Call ORM mode function', ('__call__',)),)
257
258 ZopeTime=Acquired
259 HelpSys=Acquired
260
261 security = ClassSecurityInfo()
262
263 - def __init__(self, id, model_name, procedures_name,
264 db_connection_name, session_on,
265 REQUEST=None):
269
270 - def manage_edit(self, model_name, procedures_name,
271 db_connection_name, session_on,
272 REQUEST=None):
289
290
292 """
293 Call the mode function and do cache management.
294 """
295 security=getSecurityManager()
296 user = security.getUser()
297 if not user.has_permission("View", self):
298 raise Unauthorized()
299
300 result = self.ZCacheable_get(default=None)
301
302 if result is None:
303 data = self.om_exec(*args, **kw)
304 mime_type = self.REQUEST.RESPONSE.headers.get(
305 "content-type", "text/plain")
306 self.ZCacheable_set(data=(data, mime_type))
307 else:
308 data, mime_type = result
309 self.REQUEST.RESPONSE.setHeader("Content-Type", mime_type)
310
311 return data
312
313
315 formdata = kw
316
317
318
319
320
321
322
323
324
325
326
327 encoding = sys.getdefaultencoding()
328
329
330 if self.REQUEST.RESPONSE.headers.has_key('content-type'):
331 match = charset_re.match(
332 self.REQUEST.RESPONSE.headers['content-type'])
333 if match:
334 encoding = match.group(1)
335
336
337
338
339 for key in self.REQUEST.keys():
340 if unwanted_request_keys.has_key(key):
341 continue
342 else:
343 value = self.REQUEST[key]
344
345
346 if type(value) == StringType:
347 try:
348 value = unicode(value, encoding)
349 except UnicodeDecodeError:
350 pass
351
352 formdata[key] = value
353
354
355 ds = self._ds()
356
357
358 formdata["ds"] = ds
359 formdata["base_url"] = self.absolute_url()
360 formdata["request"] = self.REQUEST
361 formdata["response"] = self.REQUEST.RESPONSE
362 formdata["REQUEST"] = self.REQUEST
363 formdata["RESPONSE"] = self.REQUEST.RESPONSE
364 formdata["context"] = self
365
366 if self.session_on():
367 formdata["session"] = self.REQUEST.SESSION
368
369
370
371
372
373 model = self._model.module()
374 formdata["model"] = model
375
376 procedure_class = self._procedure_class(formdata)
377
378 if procedure_class is None:
379 raise Exception("Illegal method name!")
380
381 procedure_instance = procedure_class(self, formdata)
382
383 if hasattr(procedure_class, "__call_param_names__"):
384 param_names = procedure_class.__call_param_names__
385 elif procedure_instance.__call__.__doc__ is not None:
386 doc = procedure_instance.__call__.__doc__
387 param_names = doc_string_param_re.findall(doc)
388 procedure_class.__call_param_names__ = param_names
389 else:
390 param_names = []
391
392 kw = {}
393 if param_names != []:
394 for param_name in param_names:
395 if formdata.has_key(param_name):
396 kw[param_name] = formdata[param_name]
397
398 try:
399 ret = procedure_instance(**kw)
400 except:
401 if ds is not None: ds.rollback()
402 raise
403
404
405
406 if ds is not None: ds.rollback()
407
408 return ret
409
411 return formdata.get("orm_procedure_class", None)
412
414 """
415 Return True if this adapter provied the mode functions with a
416 session object
417 """
418 return self._session_on
419
421 """
422 Accessor. Return the name of the Python module where the
423 mode function resides.
424 """
425 return self._model.module_name
426
428 """
429 Return the exception text of the last error loading the model module,
430 otherwise an empty string.
431 """
432 return self._model.last_error
433
435 """
436 Accessor. Return the name of the Python module with the
437 procedures in it.
438 """
439 return self._procedures.module_name
440
442 """
443 Return the exception text of the last error loading the procedures
444 module, otherwise an empty string.
445 """
446 return self._procedures.last_error
447
449 """
450 Return the name of the databse connection used for this
451 mode.
452 """
453 return self._db_connection_name
454
456 """
457 Return an ORM datasource object or None if self._db_connection_name
458 is not set.
459 """
460 if self._db_connection_name:
461
462
463
464
465
466 ds = zpsycopg_db_conn(self, self.db_connection_name())
467 return ds
468 else:
469 return None
470
471
473 """
474 Return the modification time of the module's source(!) file.
475 The time is returned as the number of seconds since the epoch.
476 """
477 module_file = module.__file__
478
479
480 parts = split(module_file, ".")
481 fname = join(parts[:-1], ".")
482 try:
483 py_file = fname + ".py"
484 py_mtime = os.stat(py_file).st_mtime
485 except OSError:
486 py_mtime = 0
487
488 try:
489 pyc_file = fname + ".pyc"
490 pyc_mtime = os.stat(pyc_file).st_mtime
491 except OSError:
492 pyc_mtime = 0
493
494 return max(py_mtime, pyc_mtime)
495
496
498 if len(REQUEST.path) > 0:
499 path = REQUEST.path
500 else:
501 path = ["index_html"]
502
503 if path[0].startswith("manage_"):
504 return
505 else:
506 procedure_name = path[0]
507 if len(path) > 1:
508 path_info = path[1:]
509 else:
510 path_info = []
511
512 module = self._procedures.module()
513 if module is None: return
514
515 procedure_class = getattr(module, procedure_name, None)
516
517 if type(procedure_class) == ClassType and \
518 issubclass(procedure_class, orm2_ui_procedure):
519 REQUEST.set("orm_procedure_class", procedure_class)
520 REQUEST.set("path_info", path_info)
521
522
523 REQUEST['TraversalRequestNameStack'] = []
524
526 "Just call self"
527 if not self.REQUEST.has_key("orm_procedure_class"):
528 return self.aq_parent.index_html()
529 else:
530 return self(*args, **kw)
531
533 """
534 Return an absolute_url to this object + procedure_name + params in kw
535 """
536 if not hasattr(self._procedures.module(), procedure_name):
537 raise Exception("Illegal procedure name: %s" % procedure_name)
538
539 for name, value in kw.items():
540 if type(value) == UnicodeType:
541 kw[name] = value.encode()
542
543 params = urllib.urlencode(kw)
544
545 if params:
546 params = "?" + params
547 else:
548 params = ""
549
550 url = "%s/%s%s" % ( self.absolute_url(), procedure_name, params, )
551
552 return url
553