Back to index

plone3  3.1.7
Script.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
00004 #
00005 # This software is subject to the provisions of the Zope Public License,
00006 # Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
00007 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00008 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00009 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00010 # FOR A PARTICULAR PURPOSE
00011 #
00012 # THIS FILE CONTAINS MODIFIED CODE FROM ZOPE 2.6.2
00013 ##############################################################################
00014 
00015 import logging
00016 import re
00017 
00018 import Globals
00019 from Shared.DC.Scripts.Bindings import NameAssignments as BaseNameAssignments
00020 from Products.PythonScripts.PythonScript import PythonScript as BasePythonScript
00021 from Products.CMFCore.FSPythonScript import FSPythonScript as BaseFSPythonScript, bad_func_code
00022 from ZODB.POSException import ConflictError
00023 
00024 logger = logging.getLogger('CMFFormController')
00025 
00026 defaultBindings = {'name_context': 'context',
00027                    'name_container': 'container',
00028                    'name_m_self': 'script',
00029                    'name_ns': '',
00030                    'name_subpath': 'traverse_subpath',
00031                    'name_state': 'state'}
00032 
00033 _nice_bind_names = {'context': 'name_context',
00034                     'container': 'name_container',
00035                     'script': 'name_m_self',
00036                     'namespace': 'name_ns',
00037                     'subpath': 'name_subpath',
00038                     'state': 'name_state'}
00039 
00040 _first_indent = re.compile('(?m)^ *(?! |$)')
00041 _nonempty_line = re.compile('(?m)^(.*\S.*)$')
00042 
00043 
00044 class NameAssignments(BaseNameAssignments):
00045     _exprs = list(BaseNameAssignments._exprs)
00046     _exprs.append(('name_state', 'self._getState()'))
00047     _exprs = tuple(_exprs)
00048 
00049 
00050 class PythonScript(BasePythonScript):
00051 
00052     def __init__(self, id, filepath=None):
00053         self.id = id
00054         self._filepath = filepath
00055         self.ZBindings_edit(defaultBindings)
00056         self._makeFunction()
00057 
00058     def _setupBindings(self, names={}):
00059         self._bind_names = names = NameAssignments(names)
00060         return names
00061 
00062     def _metadata_map(self):
00063         m = {
00064             'title': self.title,
00065             'parameters': self._params,
00066            }
00067         bindmap = self.getBindingAssignments().getAssignedNames()
00068         for k, v in _nice_bind_names.items():
00069             m['bind '+k] = bindmap.get(v, '')
00070         return m
00071 
00072     def write(self, text):
00073         """ Change the Script by parsing a read()-style source text. """
00074         self._validateProxy()
00075         mdata = self._metadata_map()
00076         bindmap = self.getBindingAssignments().getAssignedNames()
00077         bup = 0
00078 
00079         st = 0
00080         try:
00081             while 1:
00082                 # Find the next non-empty line
00083                 m = _nonempty_line.search(text, st)
00084                 if not m:
00085                     # There were no non-empty body lines
00086                     body = ''
00087                     break
00088                 line = m.group(0).strip()
00089                 if line[:2] != '##':
00090                     # We have found the first line of the body
00091                     body = text[m.start(0):]
00092                     break
00093 
00094                 st = m.end(0)
00095                 # Parse this header line
00096                 if len(line) == 2 or line[2] == ' ' or '=' not in line:
00097                     # Null header line
00098                     continue
00099                 k, v = line[2:].split('=', 1)
00100                 k = k.strip().lower()
00101                 v = v.strip()
00102                 if not mdata.has_key(k):
00103                     raise SyntaxError('Unrecognized header line "%s" in file %s' % (line, self._filepath))
00104                 if v == mdata[k]:
00105                     # Unchanged value
00106                     continue
00107 
00108                 # Set metadata value
00109                 if k == 'title':
00110                     self.title = v
00111                 elif k == 'parameters':
00112                     self._params = v
00113                 elif k[:5] == 'bind ':
00114                     bindmap[_nice_bind_names[k[5:]]] = v
00115                     bup = 1
00116 
00117             body = body.rstrip()
00118             if body:
00119                 body = body + '\n'
00120             if body != self._body:
00121                 self._body = body
00122             if bup:
00123                 self.ZBindings_edit(bindmap)
00124             else:
00125                 self._makeFunction()
00126         except (ConflictError, KeyboardInterrupt):
00127             raise
00128         except:
00129             logger.exception('%s write failed' % self.meta_type)
00130             raise
00131 
00132 Globals.InitializeClass(PythonScript)
00133 
00134 
00135 class FSPythonScript(BaseFSPythonScript, PythonScript):
00136     def _createZODBClone(self):
00137         """Create a ZODB (editable) equivalent of this object."""
00138         obj = PythonScript(self.getId(), filepath=self._filepath)
00139         obj.write(self.read())
00140         return obj
00141 
00142     def __call__(self, *args, **kw):
00143         '''Calls the script.'''
00144         self._updateFromFS()
00145         return BaseFSPythonScript.__call__(self, *args, **kw)
00146 
00147     def _write(self, text, compile):
00148         '''
00149         Parses the source, storing the body, params, title, bindings,
00150         and source in self.  If compile is set, compiles the
00151         function.
00152         '''
00153         ps = PythonScript(self.id, filepath=self._filepath)
00154         ps.write(text)
00155         if compile:
00156             ps._makeFunction(1)
00157             self._v_f = f = ps._v_f
00158             if f is not None:
00159                 self.func_code = f.func_code
00160                 self.func_defaults = f.func_defaults
00161             else:
00162                 # There were errors in the compile.
00163                 # No signature.
00164                 self.func_code = bad_func_code()
00165                 self.func_defaults = None
00166         self._body = ps._body
00167         self._params = ps._params
00168         self.title = ps.title
00169         self._setupBindings(ps.getBindingAssignments().getAssignedNames())
00170         self._source = ps.read()  # Find out what the script sees.
00171 
00172     def _metadata_map(self):
00173         m = {
00174             'title': self.title,
00175             'parameters': self._params,
00176            }
00177         bindmap = self.getBindingAssignments().getAssignedNames()
00178         for k, v in _nice_bind_names.items():
00179             m['bind '+k] = bindmap.get(v, '')
00180         return m
00181 
00182     _setupBindings = PythonScript._setupBindings
00183     _metadata_map = PythonScript._metadata_map
00184     write = PythonScript.write
00185 
00186 Globals.InitializeClass(FSPythonScript)