[Checkins] SVN: z3c.pt/trunk/ Added symbol_mapping attribute to code stream such that function dependencies can be registered at compile-time.
Malthe Borch
mborch at gmail.com
Sun Aug 31 17:14:32 EDT 2008
Log message for revision 90632:
Added symbol_mapping attribute to code stream such that function dependencies can be registered at compile-time.
Changed:
U z3c.pt/trunk/CHANGES.txt
U z3c.pt/trunk/benchmark/benchmark/tests.py
U z3c.pt/trunk/src/z3c/pt/clauses.py
U z3c.pt/trunk/src/z3c/pt/expressions.py
U z3c.pt/trunk/src/z3c/pt/generation.py
U z3c.pt/trunk/src/z3c/pt/pagetemplate.py
U z3c.pt/trunk/src/z3c/pt/translation.py
U z3c.pt/trunk/src/z3c/pt/types.py
U z3c.pt/trunk/src/z3c/pt/utils.py
U z3c.pt/trunk/src/z3c/pt/zpt.py
-=-
Modified: z3c.pt/trunk/CHANGES.txt
===================================================================
--- z3c.pt/trunk/CHANGES.txt 2008-08-31 16:15:26 UTC (rev 90631)
+++ z3c.pt/trunk/CHANGES.txt 2008-08-31 21:14:30 UTC (rev 90632)
@@ -4,6 +4,9 @@
Version 1.0dev
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+- Added ``symbol_mapping`` attribute to code streams such that
+ function dependencies can be registered at compile-time. [malthe]
+
- Allow BaseTemplate-derived classes (PageTemplate, PageTemplateFile,
et. al) to accept a ``doctype`` argument, which will override the
doctype supplied by the source of the template if specified. [chrism]
Modified: z3c.pt/trunk/benchmark/benchmark/tests.py
===================================================================
--- z3c.pt/trunk/benchmark/benchmark/tests.py 2008-08-31 16:15:26 UTC (rev 90631)
+++ z3c.pt/trunk/benchmark/benchmark/tests.py 2008-08-31 21:14:30 UTC (rev 90632)
@@ -302,8 +302,10 @@
# In order to have a fair comparision, we need real zope.i18n handling
zopefile.pt_getEngineContext = _pt_getEngineContext
+
+ assert config.SYMBOLS.i18n_context=='_i18n_context'
- t_z3c = timing(z3cfile, table=table, context=self.env)
+ t_z3c = timing(z3cfile, table=table, _i18n_context=self.env)
t_zope = timing(zopefile, table=table, env=self.env)
print "z3c.pt: %.2f" % t_z3c
Modified: z3c.pt/trunk/src/z3c/pt/clauses.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/clauses.py 2008-08-31 16:15:26 UTC (rev 90631)
+++ z3c.pt/trunk/src/z3c/pt/clauses.py 2008-08-31 21:14:30 UTC (rev 90632)
@@ -87,7 +87,7 @@
def __init__(self, parts, variable=None):
if not isinstance(parts, types.parts):
parts = types.parts((parts,))
-
+
self.parts = parts
self.variable = variable
@@ -114,6 +114,9 @@
def _assign(self, variable, value, stream):
stream.annotate(value)
symbols = stream.symbols.as_dict()
+
+ if value.symbol_mapping:
+ stream.symbol_mapping.update(value.symbol_mapping)
if isinstance(value, types.template):
value = types.value(value % symbols)
@@ -743,11 +746,7 @@
value = assign = None
def __init__(self, value):
- if isinstance(value, types.parts):
- self.assign = Assign(value)
- else:
- self.value = value
-
+ self.assign = Assign(value)
self.structure = not isinstance(value, types.escape)
def begin(self, stream):
@@ -791,11 +790,12 @@
# validate XML if enabled
if config.VALIDATION:
try:
- etree.import_elementtree()
+ _et = etree.import_elementtree()
except ImportError:
raise ImportError(
"ElementTree (required when XML validation is enabled).")
+ stream.symbol_mapping[stream.symbols.elementtree] = _et
write("%(elementtree)s.fromstring('<div>%%s</div>' %% %(tmp)s)")
def end(self, stream):
Modified: z3c.pt/trunk/src/z3c/pt/expressions.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/expressions.py 2008-08-31 16:15:26 UTC (rev 90631)
+++ z3c.pt/trunk/src/z3c/pt/expressions.py 2008-08-31 21:14:30 UTC (rev 90632)
@@ -9,6 +9,7 @@
import interfaces
import types
+import config
_marker = object()
@@ -604,42 +605,7 @@
r'^((nocall|not):\s*)*([A-Za-z_][A-Za-z0-9_]*)'+
r'(/[A-Za-z_ at -][A-Za-z0-9_ at -\\.]*)*$')
- @classmethod
- def traverse(cls, base, request, call, *path_items):
- """See ``zope.app.pagetemplate.engine``."""
- _callable = callable(base)
-
- for i in range(len(path_items)):
- name = path_items[i]
-
- next = getattr(base, name, _marker)
- if next is not _marker:
- _callable = callable(next)
-
- if _callable:
- base = next()
- else:
- base = next
- continue
- else:
- # special-case dicts for performance reasons
- if getattr(base, '__class__', None) == dict:
- base = base[name]
- else:
- base = zope.traversing.adapters.traversePathElement(
- base, name, path_items[i+1:], request=request)
-
- _callable = callable(base)
-
- if not isinstance(base, (basestring, tuple, list)):
- base = zope.security.proxy.ProxyFactory(base)
-
- if call and _callable:
- base = base()
-
- return base
-
def validate(self, string):
if not self.path_regex.match(string):
raise SyntaxError("Not a valid path-expression.")
@@ -691,11 +657,49 @@
components = ()
value = types.value(
- '_path(%s, request, %s, %s)' % (base, not nocall, ', '.join(components)))
+ '%s(%s, request, %s, %s)' % \
+ (config.SYMBOLS.path, base, not nocall, ', '.join(components)))
if negate:
value = types.value('not(%s)' % value)
+ value.symbol_mapping[config.SYMBOLS.path] = path_traverse
+
return value
+def path_traverse(base, request, call, *path_items):
+ """See ``zope.app.pagetemplate.engine``."""
+
+ _callable = callable(base)
+
+ for i in range(len(path_items)):
+ name = path_items[i]
+
+ next = getattr(base, name, _marker)
+ if next is not _marker:
+ _callable = callable(next)
+
+ if _callable:
+ base = next()
+ else:
+ base = next
+ continue
+ else:
+ # special-case dicts for performance reasons
+ if getattr(base, '__class__', None) == dict:
+ base = base[name]
+ else:
+ base = zope.traversing.adapters.traversePathElement(
+ base, name, path_items[i+1:], request=request)
+
+ _callable = callable(base)
+
+ if not isinstance(base, (basestring, tuple, list)):
+ base = zope.security.proxy.ProxyFactory(base)
+
+ if call and _callable:
+ base = base()
+
+ return base
+
path_translation = PathTranslation()
Modified: z3c.pt/trunk/src/z3c/pt/generation.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/generation.py 2008-08-31 16:15:26 UTC (rev 90631)
+++ z3c.pt/trunk/src/z3c/pt/generation.py 2008-08-31 21:14:30 UTC (rev 90632)
@@ -10,10 +10,6 @@
def render(%(init)s, %(args)s%(extra)s%(language)s=None):
\t%(out)s, %(write)s = %(init)s.initialize_stream()
\t%(attributes)s, %(repeat)s = %(init)s.initialize_tal()
-\t%(marker)s = %(init)s.initialize_helpers()
-\t%(path)s = %(init)s.initialize_traversal()
-\t%(translate)s = %(init)s.fast_translate
-\t%(elementtree)s = %(init)s.initialize_elementtree()
\t%(scope)s = {}
%(body)s
@@ -23,13 +19,12 @@
macro_wrapper = """\
def render(%(init)s, %(kwargs)s%(extra)s):
\t%(attributes)s, %(repeat)s = %(init)s.initialize_tal()
-\t%(marker)s = %(init)s.initialize_helpers()
-\t%(path)s = %(init)s.initialize_traversal()
-\t%(translate)s = %(init)s.fast_translate
-\t%(elementtree)s = %(init)s.initialize_elementtree()
%(body)s
"""
+class marker(object):
+ pass
+
def fast_translate(msgid, domain=None, mapping=None, context=None,
target_language=None, default=None):
"""This translation function does not attempt to negotiate a
@@ -55,22 +50,10 @@
def initialize_tal():
return ({}, utils.repeatdict())
-def initialize_helpers():
- return (object(), )
-
def initialize_stream():
out = BufferIO()
return (out, out.write)
-def initialize_traversal():
- return expressions.path_translation.traverse
-
-def initialize_elementtree():
- try:
- return etree.import_elementtree()
- except ImportError:
- return None
-
class BufferIO(list):
write = list.append
@@ -88,6 +71,7 @@
def __init__(self, symbols=None, indentation=0, indentation_string="\t"):
BufferIO.__init__(self)
self.symbols = symbols or object
+ self.symbol_mapping = {}
self.indentation = indentation
self.indentation_string = indentation_string
self.queue = ''
Modified: z3c.pt/trunk/src/z3c/pt/pagetemplate.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/pagetemplate.py 2008-08-31 16:15:26 UTC (rev 90631)
+++ z3c.pt/trunk/src/z3c/pt/pagetemplate.py 2008-08-31 21:14:30 UTC (rev 90632)
@@ -74,7 +74,7 @@
"""If ``filename`` is a relative path, the module path of the
class where the instance is used to get an absolute path."""
- def __init__(self, filename, **kwargs):
+ def __init__(self, filename, content_type=None, **kwargs):
if not os.path.isabs(filename):
for depth in (1, 2):
frame = sys._getframe(depth)
Modified: z3c.pt/trunk/src/z3c/pt/translation.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/translation.py 2008-08-31 16:15:26 UTC (rev 90631)
+++ z3c.pt/trunk/src/z3c/pt/translation.py 2008-08-31 21:14:30 UTC (rev 90632)
@@ -280,6 +280,7 @@
# write translation to output if successful, otherwise
# fallback to default rendition;
result = types.value(self.symbols.result)
+ result.symbol_mapping[self.symbols.marker] = generation.marker
condition = types.template('%(result)s is not %(marker)s')
_.append(clauses.Condition(condition,
[clauses.UnicodeWrite(result)]))
@@ -330,11 +331,17 @@
return msgid
def translate_expression(self, value, mapping=None, default=None):
- format = "_translate(%s, domain=%%(domain)s, mapping=%s, " \
+ format = "%%(translate)s(%s, domain=%%(domain)s, mapping=%s, " \
"target_language=%%(language)s, default=%s)"
- return types.template(
+ template = types.template(
format % (value, mapping, default))
+ # add translate-method to symbol mapping
+ translate = generation.fast_translate
+ template.symbol_mapping[config.SYMBOLS.translate] = translate
+
+ return template
+
class Element(etree.ElementBase):
"""Template element class.
@@ -486,6 +493,7 @@
# start generation
self.root.start(stream)
+ body = stream.getvalue()
# prepare args
ignore = 'target_language',
@@ -504,21 +512,25 @@
extra += '%s=None, ' % selector
# wrap generated Python-code in function definition
- body = stream.getvalue()
mapping = dict(
args=args, kwargs=kwargs, extra=extra, body=body)
mapping.update(stream.symbols.__dict__)
source = wrapper % mapping
+ # set symbol mappings as globals
+ _globals = stream.symbol_mapping
+
# compile code
- suite = codegen.Suite(source)
+ suite = codegen.Suite(source, globals=_globals)
+ suite._globals.update(_globals)
+
+ # execute code
_locals = {}
- _globals = {}
exec suite.code in suite._globals, _locals
+ render = _locals['render']
+
+ return ByteCodeTemplate(render, self.root, self.parser, stream)
- return ByteCodeTemplate(
- _locals['render'], self.root, self.parser, stream)
-
class ByteCodeTemplate(object):
"""Template compiled to byte-code."""
Modified: z3c.pt/trunk/src/z3c/pt/types.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/types.py 2008-08-31 16:15:26 UTC (rev 90631)
+++ z3c.pt/trunk/src/z3c/pt/types.py 2008-08-31 21:14:30 UTC (rev 90632)
@@ -1,11 +1,17 @@
+from utils import emptydict
+
class expression:
- pass
+ symbol_mapping = emptydict()
class parts(tuple, expression):
def __repr__(self):
return 'parts'+tuple.__repr__(self)
-class value(str, expression):
+class value(str, expression):
+ def __init__(self, *args):
+ super(value, self).__init__(*args)
+ self.symbol_mapping = {}
+
def __repr__(self):
return 'value(%s)' % str.__repr__(self)
Modified: z3c.pt/trunk/src/z3c/pt/utils.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/utils.py 2008-08-31 16:15:26 UTC (rev 90631)
+++ z3c.pt/trunk/src/z3c/pt/utils.py 2008-08-31 21:14:30 UTC (rev 90632)
@@ -49,6 +49,10 @@
def __hash__(self):
return self.hash
+class emptydict(dict):
+ def __setitem__(self, key, value):
+ raise TypeError("Read-only dictionary does not support assignment.")
+
class repeatitem(object):
def __init__(self, iterator, length):
self.length = length
Modified: z3c.pt/trunk/src/z3c/pt/zpt.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/zpt.py 2008-08-31 16:15:26 UTC (rev 90631)
+++ z3c.pt/trunk/src/z3c/pt/zpt.py 2008-08-31 21:14:30 UTC (rev 90632)
@@ -195,6 +195,10 @@
default_expression = 'python'
+ def __init__(self, default_expression=None):
+ if default_expression is not None:
+ self.default_expression = default_expression
+
@classmethod
def parse(cls, body):
root, doctype = super(ZopePageTemplateParser, cls).parse(body)
More information about the Checkins
mailing list