[Checkins] SVN: z3c.pt/trunk/ System variables are now defined in a configuration class.
Malthe Borch
mborch at gmail.com
Thu Aug 21 09:34:44 EDT 2008
Log message for revision 90064:
System variables are now defined in a configuration class.
Changed:
U z3c.pt/trunk/CHANGES.txt
U z3c.pt/trunk/src/z3c/pt/clauses.py
U z3c.pt/trunk/src/z3c/pt/config.py
U z3c.pt/trunk/src/z3c/pt/generation.py
U z3c.pt/trunk/src/z3c/pt/testing.py
U z3c.pt/trunk/src/z3c/pt/translation.py
U z3c.pt/trunk/src/z3c/pt/types.py
-=-
Modified: z3c.pt/trunk/CHANGES.txt
===================================================================
--- z3c.pt/trunk/CHANGES.txt 2008-08-21 13:28:30 UTC (rev 90063)
+++ z3c.pt/trunk/CHANGES.txt 2008-08-21 13:34:43 UTC (rev 90064)
@@ -4,6 +4,8 @@
Version 1.0dev
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+- System variables are now defined in a configuration class. [malthe]
+
- Improve performance of codegen by not repeatedly calling
an expensive "flatten" function. [chrism]
Modified: z3c.pt/trunk/src/z3c/pt/clauses.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/clauses.py 2008-08-21 13:28:30 UTC (rev 90063)
+++ z3c.pt/trunk/src/z3c/pt/clauses.py 2008-08-21 13:34:43 UTC (rev 90064)
@@ -7,11 +7,11 @@
class Assign(object):
"""
- >>> from z3c.pt.generation import CodeIO; stream = CodeIO()
- >>> from z3c.pt.testing import pyexp
+ >>> from z3c.pt import testing
We'll define some values for use in the tests.
-
+
+ >>> _out, _write, stream = testing.setup_stream()
>>> one = types.value("1")
>>> bad_float = types.value("float('abc')")
>>> abc = types.value("'abc'")
@@ -113,7 +113,10 @@
def _assign(self, variable, value, stream):
stream.annotate(value)
+ symbols = stream.symbols.as_dict()
+ if isinstance(value, types.template):
+ value = types.value(value % symbols)
if isinstance(value, types.value):
stream.write("%s = %s" % (variable, value))
elif isinstance(value, types.join):
@@ -121,6 +124,8 @@
_v_count = 0
for part in value:
+ if isinstance(part, types.template):
+ part = types.value(part % symbols)
if isinstance(part, (types.parts, types.join)):
_v = stream.save()
assign = Assign(part, _v)
@@ -149,100 +154,100 @@
class Define(object):
"""
- >>> from z3c.pt.generation import CodeIO; stream = CodeIO()
- >>> from z3c.pt.testing import pyexp
-
+ >>> from z3c.pt import testing
+
Variable scope:
- >>> define = Define("a", pyexp("b"))
- >>> b = object()
- >>> define.begin(stream)
- >>> exec stream.getvalue()
- >>> a is b
- True
- >>> del a
- >>> define.end(stream)
- >>> exec stream.getvalue()
- >>> a
- Traceback (most recent call last):
- ...
- NameError: name 'a' is not defined
- >>> b is not None
- True
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> define = Define("a", testing.pyexp("b"))
+ >>> b = object()
+ >>> define.begin(stream)
+ >>> exec stream.getvalue()
+ >>> a is b
+ True
+ >>> del a
+ >>> define.end(stream)
+ >>> exec stream.getvalue()
+ >>> a
+ Traceback (most recent call last):
+ ...
+ NameError: name 'a' is not defined
+ >>> b is not None
+ True
Multiple defines:
- >>> stream = CodeIO()
- >>> define1 = Define("a", pyexp("b"))
- >>> define2 = Define("c", pyexp("d"))
- >>> d = object()
- >>> define1.begin(stream)
- >>> define2.begin(stream)
- >>> exec stream.getvalue()
- >>> a is b and c is d
- True
- >>> define2.end(stream)
- >>> define1.end(stream)
- >>> del a; del c
- >>> stream.scope[-1].remove('a'); stream.scope[-1].remove('c')
- >>> exec stream.getvalue()
- >>> a
- Traceback (most recent call last):
- ...
- NameError: name 'a' is not defined
- >>> c
- Traceback (most recent call last):
- ...
- NameError: name 'c' is not defined
- >>> b is not None and d is not None
- True
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> define1 = Define("a", testing.pyexp("b"))
+ >>> define2 = Define("c", testing.pyexp("d"))
+ >>> d = object()
+ >>> define1.begin(stream)
+ >>> define2.begin(stream)
+ >>> exec stream.getvalue()
+ >>> a is b and c is d
+ True
+ >>> define2.end(stream)
+ >>> define1.end(stream)
+ >>> del a; del c
+ >>> stream.scope[-1].remove('a'); stream.scope[-1].remove('c')
+ >>> exec stream.getvalue()
+ >>> a
+ Traceback (most recent call last):
+ ...
+ NameError: name 'a' is not defined
+ >>> c
+ Traceback (most recent call last):
+ ...
+ NameError: name 'c' is not defined
+ >>> b is not None and d is not None
+ True
Tuple assignments:
- >>> stream = CodeIO()
- >>> define = Define(types.declaration(('e', 'f')), pyexp("[1, 2]"))
- >>> define.begin(stream)
- >>> exec stream.getvalue()
- >>> e == 1 and f == 2
- True
- >>> define.end(stream)
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> define = Define(types.declaration(('e', 'f')), testing.pyexp("[1, 2]"))
+ >>> define.begin(stream)
+ >>> exec stream.getvalue()
+ >>> e == 1 and f == 2
+ True
+ >>> define.end(stream)
Verify scope is preserved on tuple assignment:
- >>> stream = CodeIO()
- >>> e = None; f = None
- >>> stream.scope[-1].add('e'); stream.scope[-1].add('f')
- >>> stream.scope.append(set())
- >>> define.begin(stream)
- >>> define.end(stream)
- >>> exec stream.getvalue()
- >>> e is None and f is None
- True
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> e = None; f = None
+ >>> stream.scope[-1].add('e'); stream.scope[-1].add('f')
+ >>> stream.scope.append(set())
+ >>> define.begin(stream)
+ >>> define.end(stream)
+ >>> exec stream.getvalue()
+ >>> e is None and f is None
+ True
Using semicolons in expressions within a define:
- >>> stream = CodeIO()
- >>> define = Define("a", pyexp("';'"))
- >>> define.begin(stream)
- >>> exec stream.getvalue()
- >>> a
- ';'
- >>> define.end(stream)
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> define = Define("a", testing.pyexp("';'"))
+ >>> define.begin(stream)
+ >>> exec stream.getvalue()
+ >>> a
+ ';'
+ >>> define.end(stream)
Scope:
- >>> stream = CodeIO()
- >>> a = 1
- >>> stream.scope[-1].add('a')
- >>> stream.scope.append(set())
- >>> define = Define("a", pyexp("2"))
- >>> define.begin(stream)
- >>> define.end(stream)
- >>> exec stream.getvalue()
- >>> a
- 1
-
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> a = 1
+ >>> stream.scope[-1].add('a')
+ >>> stream.scope.append(set())
+ >>> define = Define("a", testing.pyexp("2"))
+ >>> define.begin(stream)
+ >>> define.end(stream)
+ >>> exec stream.getvalue()
+ >>> a
+ 1
"""
+
def __init__(self, declaration, expression, dictionary=None):
if not isinstance(declaration, types.declaration):
declaration = types.declaration((declaration,))
@@ -308,53 +313,51 @@
class Condition(object):
"""
- >>> from z3c.pt.generation import CodeIO
- >>> from z3c.pt.testing import pyexp
- >>> from StringIO import StringIO
-
+ >>> from z3c.pt import testing
+
Unlimited scope:
-
- >>> stream = CodeIO()
- >>> true = Condition(pyexp("True"))
- >>> false = Condition(pyexp("False"))
- >>> true.begin(stream)
- >>> stream.write("print 'Hello'")
- >>> true.end(stream)
- >>> false.begin(stream)
- >>> stream.write("print 'Universe!'")
- >>> false.end(stream)
- >>> stream.write("print 'World!'")
- >>> exec stream.getvalue()
- Hello
- World!
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> true = Condition(testing.pyexp("True"))
+ >>> false = Condition(testing.pyexp("False"))
+ >>> true.begin(stream)
+ >>> stream.write("print 'Hello'")
+ >>> true.end(stream)
+ >>> false.begin(stream)
+ >>> stream.write("print 'Universe!'")
+ >>> false.end(stream)
+ >>> stream.write("print 'World!'")
+ >>> exec stream.getvalue()
+ Hello
+ World!
+
Finalized limited scope:
- >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
- >>> true = Condition(pyexp("True"), [Write(pyexp("'Hello'"))])
- >>> false = Condition(pyexp("False"), [Write(pyexp("'Hallo'"))])
- >>> true.begin(stream)
- >>> true.end(stream)
- >>> false.begin(stream)
- >>> false.end(stream)
- >>> exec stream.getvalue()
- >>> _out.getvalue()
- 'Hello'
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> true = Condition(testing.pyexp("True"), [Write(testing.pyexp("'Hello'"))])
+ >>> false = Condition(testing.pyexp("False"), [Write(testing.pyexp("'Hallo'"))])
+ >>> true.begin(stream)
+ >>> true.end(stream)
+ >>> false.begin(stream)
+ >>> false.end(stream)
+ >>> exec stream.getvalue()
+ >>> _out.getvalue()
+ 'Hello'
Open limited scope:
- >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
- >>> true = Condition(pyexp("True"), [Tag('div')], finalize=False)
- >>> false = Condition(pyexp("False"), [Tag('span')], finalize=False)
- >>> true.begin(stream)
- >>> stream.out("Hello World!")
- >>> true.end(stream)
- >>> false.begin(stream)
- >>> false.end(stream)
- >>> exec stream.getvalue()
- >>> _out.getvalue()
- '<div>Hello World!</div>'
-
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> true = Condition(testing.pyexp("True"), [Tag('div')], finalize=False)
+ >>> false = Condition(testing.pyexp("False"), [Tag('span')], finalize=False)
+ >>> true.begin(stream)
+ >>> stream.out("Hello World!")
+ >>> true.end(stream)
+ >>> false.begin(stream)
+ >>> false.end(stream)
+ >>> exec stream.getvalue()
+ >>> _out.getvalue()
+ '<div>Hello World!</div>'
+
"""
def __init__(self, value, clauses=None, finalize=True):
@@ -432,42 +435,40 @@
class Tag(object):
"""
- >>> from z3c.pt.generation import CodeIO
- >>> from z3c.pt.testing import pyexp
- >>> from StringIO import StringIO
+ >>> from z3c.pt import testing
- Dynamic attribute:
-
- >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
- >>> tag = Tag('div', dict(alt=pyexp(repr('Hello World!'))))
- >>> tag.begin(stream)
- >>> stream.out('Hello Universe!')
- >>> tag.end(stream)
- >>> exec stream.getvalue()
- >>> _out.getvalue()
- '<div alt="Hello World!">Hello Universe!</div>'
+ Dynamic attribute:
- Self-closing tag:
-
- >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
- >>> tag = Tag('br', {}, True)
- >>> tag.begin(stream)
- >>> tag.end(stream)
- >>> exec stream.getvalue()
- >>> _out.getvalue()
- '<br />'
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> tag = Tag('div', dict(alt=testing.pyexp(repr('Hello World!'))))
+ >>> tag.begin(stream)
+ >>> stream.out('Hello Universe!')
+ >>> tag.end(stream)
+ >>> exec stream.getvalue()
+ >>> _out.getvalue()
+ '<div alt="Hello World!">Hello Universe!</div>'
- Unicode:
-
- >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
- >>> tag = Tag('div', dict(alt=pyexp(repr('La Pe\xc3\xb1a'))))
- >>> tag.begin(stream)
- >>> stream.out('Hello Universe!')
- >>> tag.end(stream)
- >>> exec stream.getvalue()
- >>> _out.getvalue() == '<div alt="La Pe\xc3\xb1a">Hello Universe!</div>'
- True
-
+ Self-closing tag:
+
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> tag = Tag('br', {}, True)
+ >>> tag.begin(stream)
+ >>> tag.end(stream)
+ >>> exec stream.getvalue()
+ >>> _out.getvalue()
+ '<br />'
+
+ Unicode:
+
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> tag = Tag('div', dict(alt=testing.pyexp(repr('La Pe\xc3\xb1a'))))
+ >>> tag.begin(stream)
+ >>> stream.out('Hello Universe!')
+ >>> tag.end(stream)
+ >>> exec stream.getvalue()
+ >>> _out.getvalue() == '<div alt="La Pe\xc3\xb1a">Hello Universe!</div>'
+ True
+
"""
def __init__(self, tag, attributes=None,
@@ -501,16 +502,17 @@
self.attributes.items())
if self.expression:
- self.expression.begin(stream, '_exp')
+ self.expression.begin(stream, stream.symbols.tmp)
names = ", ".join([repr(a) for a, e in static]+[repr(a) for a, v in dynamic])
if self.expression:
for attribute, expression in static:
- stream.write("if '%s' not in _exp:" % attribute)
+ stream.write("if '%s' not in %s:" % (attribute, stream.symbols.tmp))
stream.indent()
stream.write(
- "_write(' %s=\"%s\"')" % (attribute, escape(expression, '"')))
+ "%s(' %s=\"%s\"')" % (
+ stream.symbols.write, attribute, escape(expression, '"')))
stream.outdent()
else:
for attribute, expression in static:
@@ -523,7 +525,8 @@
temp2 = stream.save()
if self.expression:
- stream.write("for %s, %s in _exp.items():" % (temp, temp2))
+ stream.write("for %s, %s in %s.items():" % \
+ (temp, temp2, stream.symbols.tmp))
stream.indent()
if unicode_required_flag:
stream.write(
@@ -535,7 +538,8 @@
stream.write("%s = %s.encode('utf-8')" % (t, t))
stream.outdent()
stream.escape(temp2)
- stream.write("_write(' %%s=\"%%s\"' %% (%s, %s))" % (temp, temp2))
+ stream.write("%s(' %%s=\"%%s\"' %% (%s, %s))" % \
+ (stream.symbols.write, temp, temp2))
stream.outdent()
stream.write("elif %s is not None:" % temp2)
else:
@@ -543,7 +547,8 @@
stream.indent()
stream.write("%s = str(%s)" % (temp2, temp2))
stream.escape(temp2)
- stream.write("_write(' %%s=\"%%s\"' %% (%s, %s))" % (temp, temp2))
+ stream.write("%s(' %%s=\"%%s\"' %% (%s, %s))" % \
+ (stream.symbols.write, temp, temp2))
stream.outdent()
stream.outdent()
@@ -554,21 +559,21 @@
if unicode_required_flag:
stream.write("if isinstance(%s, unicode):" % temp)
stream.indent()
- stream.write("_write(' %s=\"')" % attribute)
- stream.write("_esc = %s.encode('utf-8')" % temp)
- stream.escape("_esc")
- stream.write("_write(_esc)")
- stream.write("_write('\"')")
+ stream.write("%s(' %s=\"')" % (stream.symbols.write, attribute))
+ stream.write("%s = %s.encode('utf-8')" % (stream.symbols.tmp, temp))
+ stream.escape(stream.symbols.tmp)
+ stream.write("%s(%s)" % (stream.symbols.write, stream.symbols.tmp))
+ stream.write("%s('\"')" % stream.symbols.write)
stream.outdent()
stream.write("elif %s is not None:" % temp)
else:
stream.write("if %s is not None:" % temp)
stream.indent()
- stream.write("_write(' %s=\"')" % attribute)
- stream.write("_esc = str(%s)" % temp)
- stream.escape("_esc")
- stream.write("_write(_esc)")
- stream.write("_write('\"')")
+ stream.write("%s(' %s=\"')" % (stream.symbols.write, attribute))
+ stream.write("%s = str(%s)" % (stream.symbols.tmp, temp))
+ stream.escape(stream.symbols.tmp)
+ stream.write("%s(%s)" % (stream.symbols.write, stream.symbols.tmp))
+ stream.write("%s('\"')" % stream.symbols.write)
stream.outdent()
assign.end(stream)
@@ -589,64 +594,62 @@
class Repeat(object):
"""
- >>> from z3c.pt.generation import CodeIO
- >>> from z3c.pt.testing import pyexp
+ >>> from z3c.pt import testing
We need to set up the repeat object.
- >>> from z3c.pt import utils
- >>> repeat = utils.repeatdict()
+ >>> from z3c.pt import utils
+ >>> repeat = utils.repeatdict()
Simple repeat loop and repeat data structure:
- >>> from StringIO import StringIO
- >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
- >>> _repeat = Repeat("i", pyexp("range(5)"))
- >>> _repeat.begin(stream)
- >>> stream.write("r = repeat['i']")
- >>> stream.write(
- ... "print (i, r.index, r.start, r.end, r.number(), r.odd(), r.even())")
- >>> _repeat.end(stream)
- >>> exec stream.getvalue()
- (0, 0, True, False, 1, False, True)
- (1, 1, False, False, 2, True, False)
- (2, 2, False, False, 3, False, True)
- (3, 3, False, False, 4, True, False)
- (4, 4, False, True, 5, False, True)
- >>> _repeat.end(stream)
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> _repeat = Repeat("i", testing.pyexp("range(5)"))
+ >>> _repeat.begin(stream)
+ >>> stream.write("r = repeat['i']")
+ >>> stream.write(
+ ... "print (i, r.index, r.start, r.end, r.number(), r.odd(), r.even())")
+ >>> _repeat.end(stream)
+ >>> exec stream.getvalue()
+ (0, 0, True, False, 1, False, True)
+ (1, 1, False, False, 2, True, False)
+ (2, 2, False, False, 3, False, True)
+ (3, 3, False, False, 4, True, False)
+ (4, 4, False, True, 5, False, True)
+ >>> _repeat.end(stream)
A repeat over an empty set.
- >>> stream = CodeIO()
- >>> _repeat = Repeat("j", pyexp("range(0)"))
- >>> _repeat.begin(stream)
- >>> _repeat.end(stream)
- >>> exec stream.getvalue()
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> _repeat = Repeat("j", testing.pyexp("range(0)"))
+ >>> _repeat.begin(stream)
+ >>> _repeat.end(stream)
+ >>> exec stream.getvalue()
A repeat over a non-iterable raises an exception.
- >>> stream = CodeIO()
- >>> _repeat = Repeat("j", pyexp("None"))
- >>> _repeat.begin(stream)
- >>> _repeat.end(stream)
- >>> exec stream.getvalue()
- Traceback (most recent call last):
- ...
- TypeError: Can only repeat over an iterable object (None).
-
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> _repeat = Repeat("j", testing.pyexp("None"))
+ >>> _repeat.begin(stream)
+ >>> _repeat.end(stream)
+ >>> exec stream.getvalue()
+ Traceback (most recent call last):
+ ...
+ TypeError: Can only repeat over an iterable object (None).
+
Simple for loop:
+
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> _for = Repeat("i", testing.pyexp("range(3)"), repeatdict=False)
+ >>> _for.begin(stream)
+ >>> stream.write("print i")
+ >>> _for.end(stream)
+ >>> exec stream.getvalue()
+ 0
+ 1
+ 2
+ >>> _for.end(stream)
- >>> stream = CodeIO()
- >>> _for = Repeat("i", pyexp("range(3)"), repeatdict=False)
- >>> _for.begin(stream)
- >>> stream.write("print i")
- >>> _for.end(stream)
- >>> exec stream.getvalue()
- 0
- 1
- 2
- >>> _for.end(stream)
-
"""
def __init__(self, v, e, scope=(), repeatdict=True):
@@ -701,14 +704,12 @@
class Write(object):
"""
- >>> from z3c.pt.generation import CodeIO
- >>> from z3c.pt.testing import pyexp
- >>> from StringIO import StringIO
+ >>> from z3c.pt import testing
Basic write:
-
- >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
- >>> write = Write(pyexp("'New York'"))
+
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> write = Write(testing.pyexp("'New York'"))
>>> write.begin(stream)
>>> write.end(stream)
>>> exec stream.getvalue()
@@ -717,8 +718,8 @@
Try-except parts:
- >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
- >>> write = Write(pyexp("undefined | 'New Delhi'"))
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> write = Write(testing.pyexp("undefined | 'New Delhi'"))
>>> write.begin(stream)
>>> write.end(stream)
>>> exec stream.getvalue()
@@ -727,7 +728,7 @@
Unicode:
- >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
+ >>> _out, _write, stream = testing.setup_stream()
>>> write = Write(types.value("unicode('La Pe\xc3\xb1a', 'utf-8')"))
>>> write.begin(stream)
>>> write.end(stream)
@@ -752,44 +753,34 @@
def begin(self, stream):
temp = stream.save()
+ def write(template):
+ stream.write(template % stream.symbols.as_dict())
+
if self.value:
expr = self.value
else:
self.assign.begin(stream, temp)
expr = temp
- stream.write("_urf = %s" % expr)
-
- stream.write("if _urf is not None:")
+ stream.write("%s = %s" % (stream.symbols.tmp, expr))
+ write("if %(tmp)s is not None:")
stream.indent()
if unicode_required_flag:
- stream.write("if isinstance(_urf, unicode):")
+ write("if isinstance(%(tmp)s, unicode):")
stream.indent()
- stream.write("_urf = _urf.encode('utf-8')")
+ write("%(tmp)s = %(tmp)s.encode('utf-8')")
stream.outdent()
- stream.write("else:")
+ write("else:")
stream.indent()
- stream.write("_urf = str(_urf)")
+ write("%(tmp)s = str(%(tmp)s)")
stream.outdent()
else:
- stream.write("_urf = str(_urf)")
+ write("%(tmp)s = str(%(tmp)s)")
if self.structure:
- stream.write("_write(_urf)")
+ write("%(write)s(%(tmp)s)")
else:
- # Inlined escape function
- stream.write("if '&' in _urf:")
- stream.indent()
- stream.write("_urf = _urf.replace('&', '&')")
- stream.outdent()
- stream.write("if '<' in _urf:")
- stream.indent()
- stream.write("_urf = _urf.replace('<', '<')")
- stream.outdent()
- stream.write("if '>' in _urf:")
- stream.indent()
- stream.write("_urf = _urf.replace('>', '>')")
- stream.outdent()
- stream.write("_write(_urf)")
+ stream.escape(stream.symbols.tmp)
+ write("%(write)s(%(tmp)s)")
stream.outdent()
# validate XML if enabled
@@ -802,7 +793,7 @@
stream.write("import z3c.pt.etree")
stream.write("_ET = z3c.pt.etree.import_elementtree()")
- stream.write("_ET.fromstring('<div>%s</div>' % _urf)")
+ write("_ET.fromstring('<div>%%s</div>' %% %(tmp)s)")
def end(self, stream):
if self.assign:
@@ -811,12 +802,11 @@
class UnicodeWrite(Write):
"""
- >>> from z3c.pt.generation import CodeIO
- >>> from StringIO import StringIO
+ >>> from z3c.pt import testing
Basic write:
- >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
+ >>> _out, _write, stream = testing.setup_stream()
>>> write = Write(types.value("'New York'"))
>>> write.begin(stream)
>>> write.end(stream)
@@ -826,7 +816,7 @@
Unicode:
- >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
+ >>> _out, _write, stream = testing.setup_stream()
>>> write = Write(types.value("unicode('La Pe\xc3\xb1a', 'utf-8')"))
>>> write.begin(stream)
>>> write.end(stream)
@@ -839,7 +829,7 @@
Invalid:
- >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
+ >>> _out, _write, stream = testing.setup_stream()
>>> write = Write(types.value("None"))
>>> write.begin(stream)
>>> write.end(stream)
@@ -857,21 +847,19 @@
self.assign.begin(stream, temp)
expr = temp
- stream.write("_write(%s)" % expr)
+ stream.write("%s(%s)" % (stream.symbols.write, expr))
class Out(object):
"""
- >>> from z3c.pt.generation import CodeIO
- >>> from z3c.pt.testing import pyexp
- >>> from StringIO import StringIO
+ >>> from z3c.pt import testing
- >>> _out = StringIO(); _write = _out.write; stream = CodeIO()
- >>> out = Out('Hello World!')
- >>> out.begin(stream)
- >>> out.end(stream)
- >>> exec stream.getvalue()
- >>> _out.getvalue()
- 'Hello World!'
+ >>> _out, _write, stream = testing.setup_stream()
+ >>> out = Out('Hello World!')
+ >>> out.begin(stream)
+ >>> out.end(stream)
+ >>> exec stream.getvalue()
+ >>> _out.getvalue()
+ 'Hello World!'
"""
def __init__(self, string, defer=False):
Modified: z3c.pt/trunk/src/z3c/pt/config.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/config.py 2008-08-21 13:28:30 UTC (rev 90063)
+++ z3c.pt/trunk/src/z3c/pt/config.py 2008-08-21 13:34:43 UTC (rev 90064)
@@ -21,3 +21,29 @@
I18N_NS = "http://xml.zope.org/namespaces/i18n"
PY_NS = "http://genshi.edgewall.org"
NS_MAP = dict(py=PY_NS, tal=TAL_NS, metal=METAL_NS)
+
+class SYMBOLS(object):
+ slot = '_slot'
+ metal = '_metal'
+ macro = '_macro'
+ scope = '_scope'
+ out = '_out'
+ tmp = '_tmp'
+ write = '_write'
+ mapping = '_mapping'
+ result = '_result'
+ marker = '_marker'
+ domain = '_domain'
+ context = '_context'
+ attributes = '_attributes'
+ negotiate = '_negotiate'
+ translate = '_translate'
+ path = '_path'
+ repeat = 'repeat'
+ language = 'target_language'
+ generation = 'generation'
+
+ @classmethod
+ def as_dict(cls):
+ return dict((name, getattr(cls, name)) for name in dir(cls))
+
Modified: z3c.pt/trunk/src/z3c/pt/generation.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/generation.py 2008-08-21 13:28:30 UTC (rev 90063)
+++ z3c.pt/trunk/src/z3c/pt/generation.py 2008-08-21 13:34:43 UTC (rev 90064)
@@ -10,23 +10,24 @@
from z3c.pt.config import DISABLE_I18N
template_wrapper = """\
-def render(%(args)s%(extra)starget_language=None):
-\tglobal generation
+def render(%(args)s%(extra)s%(language)s=None):
+\tglobal %(generation)s
-\t_out, _write = generation.initialize_stream()
-\t_attributes, repeat = generation.initialize_tal()
-\t_domain, _negotiate, _translate = generation.initialize_i18n()
-\t_marker = generation.initialize_helpers()
-\t_path = generation.initialize_traversal()
-\t_scope = {}
-\t_target_language = _negotiate(_context, target_language)
+\t%(out)s, %(write)s = generation.initialize_stream()
+\t%(attributes)s, %(repeat)s = generation.initialize_tal()
+\t%(domain)s, %(negotiate)s, %(translate)s = generation.initialize_i18n()
+\t%(marker)s = %(generation)s.initialize_helpers()
+\t%(path)s = %(generation)s.initialize_traversal()
+\t%(scope)s = {}
+
+\t%(language)s = %(negotiate)s(%(context)s, %(language)s)
%(code)s
-\treturn _out.getvalue()
+\treturn %(out)s.getvalue()
"""
macro_wrapper = """\
def render(%(kwargs)s%(extra)s):
-\tglobal generation
+\tglobal %(generation)s
%(code)s
"""
@@ -67,44 +68,6 @@
def initialize_traversal():
return expressions.PathTranslation.traverse
-class Generator(object):
- def __init__(self, params, wrapper):
- self.params = list(params)
- self.wrapper = wrapper
- self.stream = CodeIO(indentation=1, indentation_string="\t")
-
- # initialize variable scope
- self.stream.scope.append(set(('_out', '_write', '_scope') + tuple(params)))
-
- def __call__(self):
- params = self.params
- extra = ''
-
- # prepare args
- args = ', '.join(params)
- if args:
- args += ', '
-
- # prepare kwargs
- kwargs = ', '.join("%s=None" % param for param in params)
- if kwargs:
- kwargs += ', '
-
- # prepare selectors
- for selector in self.stream.selectors:
- extra += '%s=None, ' % selector
-
- # we need to ensure we have _context for the i18n handling in
- # the arguments. the default template implementations pass
- # this in explicitly.
- if '_context' not in params:
- extra += '_context=None, '
-
- code = self.stream.getvalue()
- return self.wrapper % dict(
- args=args, kwargs=kwargs, extra=extra, code=code), \
- {'generation': z3c.pt.generation}
-
class BufferIO(list):
write = list.append
@@ -127,8 +90,9 @@
t_prefix = '_tmp'
v_prefix = '_var'
- def __init__(self, indentation=0, indentation_string="\t"):
+ def __init__(self, symbols=None, indentation=0, indentation_string="\t"):
BufferIO.__init__(self)
+ self.symbols = symbols or object
self.indentation = indentation
self.indentation_string = indentation_string
self.queue = ''
@@ -169,8 +133,9 @@
if self.queue:
queue = self.queue
self.queue = ''
- self.write("_write('%s')" %
- queue.replace('\n', '\\n').replace("'", "\\'"))
+ self.write(
+ "%s('%s')" %
+ (self.symbols.write, queue.replace('\n', '\\n').replace("'", "\\'")))
def write(self, string):
if isinstance(string, unicode):
Modified: z3c.pt/trunk/src/z3c/pt/testing.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/testing.py 2008-08-21 13:28:30 UTC (rev 90063)
+++ z3c.pt/trunk/src/z3c/pt/testing.py 2008-08-21 13:34:43 UTC (rev 90064)
@@ -1,4 +1,5 @@
import translation
+import generation
import expressions
import macro
import etree
@@ -8,9 +9,21 @@
import zpt
import genshi
+from StringIO import StringIO
+
def pyexp(string):
return expressions.PythonTranslation.expression(string)
+def setup_stream():
+ class symbols(translation.Element.symbols):
+ out = '_out'
+ write = '_write'
+
+ out = StringIO()
+ write = out.write
+ stream = generation.CodeIO(symbols)
+ return out, write, stream
+
def cook(generator, **kwargs):
source, _globals = generator()
_locals = {}
Modified: z3c.pt/trunk/src/z3c/pt/translation.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/translation.py 2008-08-21 13:28:30 UTC (rev 90063)
+++ z3c.pt/trunk/src/z3c/pt/translation.py 2008-08-21 13:34:43 UTC (rev 90064)
@@ -15,16 +15,13 @@
class Element(etree.ElementBase):
"""Base compiler element class.
- This class represents a node in the template tree. To start
- compilation at this node, use the ``start`` method, providing a
- code stream object.
+ This class represents an element in the template document tree. To
+ start compilation at this node, use the ``start`` method,
+ providing a code stream object.
"""
- metal_slot_prefix = '_fill'
- metal_variable = '_metal'
- macro_variable = '_macro'
- scope_variable = '_scope'
-
+ symbols = config.SYMBOLS
+
def start(self, stream):
self._stream = stream
self.visit()
@@ -82,14 +79,14 @@
# i18n domain
if self.node.translation_domain is not None:
_.append(clauses.Define(
- "_domain", types.value(repr(self.node.translation_domain))))
+ self.symbols.domain, types.value(repr(self.node.translation_domain))))
# variable definitions
if self.node.define is not None:
for declaration, expression in self.node.define:
if declaration.global_scope:
_.append(clauses.Define(
- declaration, expression, self.scope_variable))
+ declaration, expression, self.symbols.scope))
else:
_.append(clauses.Define(declaration, expression))
@@ -103,13 +100,13 @@
# define macro
subclauses = []
subclauses.append(clauses.Method(
- self.macro_variable, macro.args))
+ self.symbols.macro, macro.args))
subclauses.append(clauses.Visit(element))
_.append(clauses.Group(subclauses))
# assign to variable
_.append(clauses.Define(
- macro.name, types.parts((types.value(self.macro_variable),))))
+ macro.name, types.parts((types.value(self.symbols.macro),))))
# tag tail (deferred)
tail = self.tail
@@ -136,7 +133,7 @@
# macro slot definition
if self.node.define_slot:
# check if slot has been filled
- variable = self.metal_slot_prefix + self.node.define_slot
+ variable = self.symbols.slot + self.node.define_slot
if variable in itertools.chain(*self.stream.scope):
content = types.value(variable)
@@ -223,19 +220,19 @@
kwargs = []
for element in self.xpath(
'.//*[@metal:fill-slot]', namespaces={'metal': config.METAL_NS}):
- variable = self.metal_slot_prefix+element.node.fill_slot
+ variable = self.symbols.slot+element.node.fill_slot
kwargs.append((variable, variable))
subclauses = []
subclauses.append(clauses.Define(
- types.declaration(('_out', '_write')),
- types.value('generation.initialize_stream()')))
+ types.declaration((self.symbols.out, self.symbols.write)),
+ types.template('%(generation)s.initialize_stream()')))
subclauses.append(clauses.Visit(element))
subclauses.append(clauses.Assign(
- types.value('_out.getvalue()'), variable))
+ types.template('%(out)s.getvalue()'), variable))
_.append(clauses.Group(subclauses))
- _.append(clauses.Assign(self.node.use_macro, self.metal_variable))
+ _.append(clauses.Assign(self.node.use_macro, self.symbols.metal))
# compute macro function arguments and create argument string
arguments = ", ".join(
@@ -244,7 +241,7 @@
tuple("%s=%s" % kwarg for kwarg in kwargs))
_.append(clauses.Write(
- types.value("%s(%s)" % (self.metal_variable, arguments))))
+ types.value("%s(%s)" % (self.symbols.metal, arguments))))
# translate body
elif self.node.translate is not None:
@@ -257,7 +254,7 @@
elements = [e for e in self if e.i18n_name]
if elements:
- mapping = '_mapping'
+ mapping = self.symbols.mapping
_.append(clauses.Assign(types.value('{}'), mapping))
else:
mapping = 'None'
@@ -267,23 +264,23 @@
subclauses = []
subclauses.append(clauses.Define(
- types.declaration(('_out', '_write')),
- types.value('generation.initialize_stream()')))
+ types.declaration((self.symbols.out, self.symbols.write)),
+ types.template('%(generation)s.initialize_stream()')))
subclauses.append(clauses.Visit(element))
subclauses.append(clauses.Assign(
- types.value('_out.getvalue()'),
+ types.template('%(out)s.getvalue()'),
"%s['%s']" % (mapping, name)))
_.append(clauses.Group(subclauses))
_.append(clauses.Assign(
_translate(types.value(repr(msgid)), mapping=mapping,
- default='_marker'), '_result'))
+ default=self.symbols.marker), self.symbols.result))
# write translation to output if successful, otherwise
# fallback to default rendition;
- result = types.value('_result')
- condition = types.value('_result is not _marker')
+ result = types.value(self.symbols.result)
+ condition = types.template('%(result)s is not %(marker)s')
_.append(clauses.Condition(condition,
[clauses.UnicodeWrite(result)]))
@@ -444,9 +441,16 @@
wrapper = generation.macro_wrapper
else:
wrapper = generation.template_wrapper
- generator = generation.Generator(params, wrapper)
- stream = generator.stream
+ # initialize code stream object
+ stream = generation.CodeIO(
+ root.symbols, indentation=1, indentation_string="\t")
+
+ # initialize variable scope
+ stream.scope.append(set(
+ (stream.symbols.out, stream.symbols.write, stream.symbols.scope) + \
+ tuple(params)))
+
# output doctype if any
if doctype and isinstance(doctype, (str, unicode)):
dt = (doctype +'\n').encode('utf-8')
@@ -456,9 +460,47 @@
stream.end([doctype])
stream.scope.pop()
+ # start generation
root.start(stream)
- return generator
+ extra = ''
+
+ # prepare args
+ args = ', '.join(params)
+ if args:
+ args += ', '
+
+ # prepare kwargs
+ kwargs = ', '.join("%s=None" % param for param in params)
+ if kwargs:
+ kwargs += ', '
+
+ # prepare selectors
+ for selector in stream.selectors:
+ extra += '%s=None, ' % selector
+
+ # we need to ensure we have _context for the i18n handling in
+ # the arguments. the default template implementations pass
+ # this in explicitly.
+ if stream.symbols.context not in params:
+ extra += '%s=None, ' % stream.symbols.context
+
+ code = stream.getvalue()
+
+ class generator(object):
+ @property
+ def stream(self):
+ return stream
+
+ def __call__(self):
+ parameters = dict(
+ args=args, kwargs=kwargs, extra=extra, code=code)
+ parameters.update(stream.symbols.__dict__)
+
+ return wrapper % parameters, {stream.symbols.generation: generation}
+
+ return generator()
+
def translate_text(body, parser, *args, **kwargs):
root, doctype = parser.parse("<html xmlns='%s'></html>" % config.XHTML_NS)
root.text = body
@@ -466,9 +508,10 @@
return translate_etree(root, doctype=doctype, *args, **kwargs)
def _translate(value, mapping=None, default=None):
- format = ("_translate(%s, domain=_domain, mapping=%s, context=_context, "
- "target_language=_target_language, default=%s)")
- return types.value(format % (value, mapping, default))
+ format = "_translate(%s, domain=%%(domain)s, mapping=%s, context=%%(context)s, " \
+ "target_language=%%(language)s, default=%s)"
+ return types.template(
+ format % (value, mapping, default))
def _not(value):
return types.value("not (%s)" % value)
Modified: z3c.pt/trunk/src/z3c/pt/types.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/types.py 2008-08-21 13:28:30 UTC (rev 90063)
+++ z3c.pt/trunk/src/z3c/pt/types.py 2008-08-21 13:34:43 UTC (rev 90064)
@@ -9,6 +9,10 @@
def __repr__(self):
return 'value(%s)' % str.__repr__(self)
+class template(value):
+ def __repr__(self):
+ return 'template(%s)' % str.__repr__(self)
+
class join(tuple, expression):
def __repr__(self):
return 'join'+tuple.__repr__(self)
More information about the Checkins
mailing list