[Checkins] SVN: z3c.pt/trunk/ Refactoring.
Malthe Borch
mborch at gmail.com
Sun Jan 8 16:30:43 UTC 2012
Log message for revision 123986:
Refactoring.
Changed:
U z3c.pt/trunk/CHANGES.txt
U z3c.pt/trunk/setup.py
U z3c.pt/trunk/src/z3c/pt/expressions.py
U z3c.pt/trunk/src/z3c/pt/pagetemplate.py
-=-
Modified: z3c.pt/trunk/CHANGES.txt
===================================================================
--- z3c.pt/trunk/CHANGES.txt 2012-01-08 16:30:18 UTC (rev 123985)
+++ z3c.pt/trunk/CHANGES.txt 2012-01-08 16:30:43 UTC (rev 123986)
@@ -3,9 +3,22 @@
In next release ...
-- The ``ZopeTraverser`` class now gets ``econtext`` instead of the
- name ``request``.
+Features:
+- The ``request`` symbol is no longer required to evaluate a path
+ expression; it now defaults to ``None`` if not present in the
+ namespace.
+
+Bugfixes:
+
+- The content provider expression now correctly applies TAL namespace
+ data.
+
+Changes:
+
+- The ``ZopeTraverser`` class has been removed and replaced with a
+ simple function.
+
2.1.5 (2011-11-24)
~~~~~~~~~~~~~~~~~~
Modified: z3c.pt/trunk/setup.py
===================================================================
--- z3c.pt/trunk/setup.py 2012-01-08 16:30:18 UTC (rev 123985)
+++ z3c.pt/trunk/setup.py 2012-01-08 16:30:43 UTC (rev 123986)
@@ -10,7 +10,7 @@
'zope.i18n >= 3.5',
'zope.traversing',
'zope.contentprovider',
- 'Chameleon >= 2.4.0',
+ 'Chameleon >= 2.7.2',
]
setup(name='z3c.pt',
Modified: z3c.pt/trunk/src/z3c/pt/expressions.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/expressions.py 2012-01-08 16:30:18 UTC (rev 123985)
+++ z3c.pt/trunk/src/z3c/pt/expressions.py 2012-01-08 16:30:43 UTC (rev 123986)
@@ -6,7 +6,9 @@
from zope.traversing.adapters import traversePathElement
from zope.contentprovider.interfaces import IContentProvider
from zope.contentprovider.interfaces import ContentProviderLookupError
+from zope.contentprovider.tales import addTALNamespaceData
from zope.traversing.interfaces import ITraversable
+from zope.location.interfaces import ILocation
try:
from zope.contentprovider.interfaces import BeforeUpdateEvent
@@ -15,14 +17,13 @@
from types import MethodType
-from chameleon.tales import PathExpr as BasePathExpr
+from chameleon.tales import TalesExpr
from chameleon.tales import ExistsExpr as BaseExistsExpr
from chameleon.tales import PythonExpr as BasePythonExpr
from chameleon.tales import StringExpr
from chameleon.codegen import template
from chameleon.astutil import load
from chameleon.astutil import Symbol
-from chameleon.astutil import Static
from chameleon.astutil import Builtin
from chameleon.astutil import NameLookupRewriteVisitor
from chameleon.exc import ExpressionError
@@ -30,73 +31,100 @@
_marker = object()
-def identity(x):
- return x
+def render_content_provider(econtext, name):
+ name = name.strip()
+ context = econtext.get('context')
+ request = econtext.get('request')
+ view = econtext.get('view')
-class ContentProviderTraverser(object):
- def __call__(self, context, request, view, name):
- cp = zope.component.queryMultiAdapter(
- (context, request, view), IContentProvider, name=name)
+ cp = zope.component.queryMultiAdapter(
+ (context, request, view), IContentProvider, name=name)
- # provide a useful error message, if the provider was not found.
- if cp is None:
- raise ContentProviderLookupError(name)
+ # provide a useful error message, if the provider was not found.
+ if cp is None:
+ raise ContentProviderLookupError(name)
- if BeforeUpdateEvent is not None:
- zope.event.notify(BeforeUpdateEvent(cp, request))
- cp.update()
- return cp.render()
+ # add the __name__ attribute if it implements ILocation
+ if ILocation.providedBy(cp):
+ cp.__name__ = name
+ # Insert the data gotten from the context
+ addTALNamespaceData(cp, econtext)
-class ZopeTraverser(object):
- def __init__(self, proxify=identity):
- self.proxify = proxify
+ # Stage 1: Do the state update.
+ if BeforeUpdateEvent is not None:
+ zope.event.notify(BeforeUpdateEvent(cp, request))
+ cp.update()
- def __call__(self, base, econtext, call, *path_items):
- """See ``zope.app.pagetemplate.engine``."""
+ # Stage 2: Render the HTML content.
+ return cp.render()
- if bool(path_items):
- request = econtext.get('request')
- path_items = list(path_items)
- path_items.reverse()
- while len(path_items):
- name = path_items.pop()
- ns_used = ':' in name
- if ns_used:
- namespace, name = name.split(':', 1)
- base = namespaces.function_namespaces[namespace](base)
- if ITraversable.providedBy(base):
- base = self.proxify(traversePathElement(
- base, name, path_items, request=request))
- continue
+def path_traverse(base, econtext, call, path_items):
+ if path_items:
+ request = econtext.get('request')
+ path_items = list(path_items)
+ path_items.reverse()
- # special-case dicts for performance reasons
- if isinstance(base, dict):
- next = base.get(name, _marker)
- else:
- next = getattr(base, name, _marker)
-
- if next is not _marker:
- base = next
- if ns_used and isinstance(base, MethodType):
- base = base()
- continue
- else:
+ while len(path_items):
+ name = path_items.pop()
+ ns_used = ':' in name
+ if ns_used:
+ namespace, name = name.split(':', 1)
+ base = namespaces.function_namespaces[namespace](base)
+ if ITraversable.providedBy(base):
base = traversePathElement(
base, name, path_items, request=request)
- if not isinstance(base, (basestring, tuple, list)):
- base = self.proxify(base)
+ # base = proxify(base)
- if call and getattr(base, '__call__', _marker) is not _marker:
- return base()
+ continue
- return base
+ # special-case dicts for performance reasons
+ if isinstance(base, dict):
+ next = base.get(name, _marker)
+ else:
+ next = getattr(base, name, _marker)
+ if next is not _marker:
+ base = next
+ if ns_used and isinstance(base, MethodType):
+ base = base()
+ continue
+ else:
+ base = traversePathElement(
+ base, name, path_items, request=request)
-class PathExpr(BasePathExpr):
+ # if not isinstance(base, (basestring, tuple, list)):
+ # base = proxify(base)
+
+ if call and getattr(base, '__call__', _marker) is not _marker:
+ return base()
+
+ return base
+
+
+class ContextExpressionMixin(object):
+ """Mixin-class for expression compilers."""
+
+ transform = None
+
+ def __call__(self, target, engine):
+ # Make call to superclass to assign value to target
+ assignment = super(ContextExpressionMixin, self).\
+ __call__(target, engine)
+
+ transform = template(
+ "target = transform(econtext, target)",
+ target=target,
+ transform=self.transform,
+ )
+
+ return assignment + transform
+
+
+class PathExpr(TalesExpr):
path_regex = re.compile(
r'^(?:(nocall|not):\s*)*((?:[A-Za-z_][A-Za-z0-9_:]*)' +
r'(?:/[?A-Za-z_@\-+][?A-Za-z0-9_@\-\.+/:]*)*)$')
@@ -104,9 +132,7 @@
interpolation_regex = re.compile(
r'\?[A-Za-z][A-Za-z0-9_]+')
- traverser = Static(
- template("cls()", cls=Symbol(ZopeTraverser), mode="eval")
- )
+ traverser = Symbol(path_traverse)
def translate(self, string, target):
"""
@@ -166,16 +192,14 @@
components = ()
call = template(
- "traverse(base, econtext, call)",
+ "traverse(base, econtext, call, path_items)",
traverse=self.traverser,
base=load(base),
call=load(str(not nocall)),
+ path_items=ast.Tuple(elts=components),
mode="eval",
)
- if components:
- call.args.extend(components)
-
return template("target = value", target=target, value=call)
@@ -194,22 +218,10 @@
super(ExistsExpr, self).__init__("nocall:" + expression)
-class ProviderExpr(StringExpr):
- traverser = Static(
- template("cls()", cls=Symbol(ContentProviderTraverser), mode="eval")
- )
+class ProviderExpr(ContextExpressionMixin, StringExpr):
+ transform = Symbol(render_content_provider)
- def __call__(self, target, engine):
- assignment = super(ProviderExpr, self).__call__(target, engine)
- return assignment + \
- template(
- "target = traverse(context, request, view, target.strip())",
- target=target,
- traverse=self.traverser,
- )
-
-
class PythonExpr(BasePythonExpr):
builtins = dict(
(name, template(
Modified: z3c.pt/trunk/src/z3c/pt/pagetemplate.py
===================================================================
--- z3c.pt/trunk/src/z3c/pt/pagetemplate.py 2012-01-08 16:30:18 UTC (rev 123985)
+++ z3c.pt/trunk/src/z3c/pt/pagetemplate.py 2012-01-08 16:30:43 UTC (rev 123986)
@@ -83,6 +83,8 @@
strict = False
+ trim_attribute_space = True
+
@property
def boolean_attributes(self):
if self.content_type == 'text/xml':
More information about the checkins
mailing list