Commit 6b03c39e authored by Arnaud Fontaine's avatar Arnaud Fontaine

ZODB Components: Execute code in two steps: compile(), then 'exec' instead of only 'exec'.

This is much faster, eg defining a max function is about 39 times faster and
even more on more complicated code:

$ python -mtimeit -s 'code = "def max(a, b): return a > b and a or b"' 'exec code'
10000 loops, best of 3: 25.2 usec per loop
$ python -mtimeit -s 'code = compile("def max(a, b): return a > b and a or b", "<string>", "exec")' 'exec code'
1000000 loops, best of 3: 0.632 usec per loop

Another reason is for traceback/pdb readability as __file__ is displayed in
the backtrace, but with 'exec' __file__ equals to '<string>', compile() allows
to specify a readable name easily without having to override __file__.

Also, set __file__ to the Component relative URL instead of the ID for
readability sake.
parent 0698cfe5
......@@ -140,8 +140,9 @@ class ComponentDynamicPackage(ModuleType):
module = __import__(fullname, fromlist=[fullname.rsplit('.', 1)[0]],
level=0)
return getattr(getSite().portal_components,
module.__file__[1:-1]).getTextContent(validated_only=True)
component = getSite().unrestrictedTraverse(module.__file__[1:-1])
return component.getTextContent(validated_only=True)
def find_module(self, fullname, path=None):
"""
......@@ -320,6 +321,7 @@ class ComponentDynamicPackage(ModuleType):
module_fullname_alias = self._namespace + '.' + name
component = getattr(site.portal_components, component_id)
relative_url = component.getRelativeUrl()
module_fullname = '%s.%s_version.%s' % (self._namespace, version, name)
module = ModuleType(module_fullname, component.getDescription())
......@@ -345,12 +347,13 @@ class ComponentDynamicPackage(ModuleType):
sys.modules[module_fullname_alias] = module
# This must be set for imports at least (see PEP 302)
module.__file__ = '<' + component.getId() + '>'
module.__file__ = '<' + relative_url + '>'
try:
# XXX: Any loading from ZODB while exec'ing the source code will result
# in a deadlock
exec source_code_str in module.__dict__
source_code_obj = compile(source_code_str, module.__file__, 'exec')
exec source_code_obj in module.__dict__
except Exception, error:
del sys.modules[module_fullname]
if module_fullname_alias:
......
......@@ -143,7 +143,8 @@ def patch_linecache():
module_globals = get_globals(sys._getframe(1))
# Get source code of ZODB Components (following PEP 302)
if filename == '<string>' and '__loader__' in module_globals:
if (filename.startswith('<portal_components/') and
'__loader__' in module_globals):
data = None
name = module_globals.get('__name__')
loader = module_globals['__loader__']
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment