changeset 798:c690de5abafd stable-0.5.x

Ported [914], [970], and [971] to 0.5.x branch.
author cmlenz
date Thu, 15 Jan 2009 23:50:09 +0000
parents 890dc65c3e75
children 9fe8fdca279e
files genshi/core.py genshi/filters/transform.py genshi/path.py genshi/template/eval.py genshi/template/interpolation.py genshi/template/loader.py genshi/template/markup.py genshi/template/plugin.py genshi/template/tests/eval.py
diffstat 9 files changed, 27 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/genshi/core.py
+++ b/genshi/core.py
@@ -13,6 +13,10 @@
 
 """Core classes for markup processing."""
 
+try:
+    from functools import reduce
+except ImportError:
+    pass # builtin in Python <= 2.5
 from itertools import chain
 import operator
 
@@ -640,6 +644,9 @@
         return QName(self.uri + u'}' + name)
     __getattr__ = __getitem__
 
+    def __hash__(self):
+        return hash(self.uri)
+
     def __repr__(self):
         return '<Namespace "%s">' % self.uri
 
--- a/genshi/filters/transform.py
+++ b/genshi/filters/transform.py
@@ -1037,7 +1037,7 @@
 
     def _inject(self):
         content = self.content
-        if callable(content):
+        if hasattr(content, '__call__'):
             content = content()
         for event in _ensure(content):
             yield None, event
@@ -1170,7 +1170,7 @@
 
         :param stream: The marked event stream to filter
         """
-        callable_value = callable(self.value)
+        callable_value = hasattr(self.value, '__call__')
         for mark, (kind, data, pos) in stream:
             if mark is ENTER:
                 if callable_value:
--- a/genshi/path.py
+++ b/genshi/path.py
@@ -38,6 +38,10 @@
 structures), it only implements a subset of the full XPath 1.0 language.
 """
 
+try:
+    from functools import reduce
+except ImportError:
+    pass # builtin in Python <= 2.5
 from math import ceil, floor
 import operator
 import re
--- a/genshi/template/eval.py
+++ b/genshi/template/eval.py
@@ -23,6 +23,7 @@
     from sets import ImmutableSet as frozenset
     from sets import Set as set
 from textwrap import dedent
+from types import CodeType
 
 from genshi.core import Markup
 from genshi.template.base import TemplateRuntimeError
@@ -453,7 +454,7 @@
 
     # We'd like to just set co_firstlineno, but it's readonly. So we need to
     # clone the code object while adjusting the line number
-    return new.code(0, code.co_nlocals, code.co_stacksize,
+    return CodeType(0, code.co_nlocals, code.co_stacksize,
                     code.co_flags | 0x0040, code.co_code, code.co_consts,
                     code.co_names, code.co_varnames, filename, name, lineno,
                     code.co_lnotab, (), ())
--- a/genshi/template/interpolation.py
+++ b/genshi/template/interpolation.py
@@ -44,7 +44,7 @@
     string.
     
     >>> for kind, data, pos in interpolate("hey ${foo}bar"):
-    ...     print kind, `data`
+    ...     print kind, repr(data)
     TEXT u'hey '
     EXPR Expression('foo')
     TEXT u'bar'
--- a/genshi/template/loader.py
+++ b/genshi/template/loader.py
@@ -124,7 +124,7 @@
         self.default_class = default_class or MarkupTemplate
         self.variable_lookup = variable_lookup
         self.allow_exec = allow_exec
-        if callback is not None and not callable(callback):
+        if callback is not None and not hasattr(callback, '__call__'):
             raise TypeError('The "callback" parameter needs to be callable')
         self.callback = callback
         self._cache = LRUCache(max_cache_size)
--- a/genshi/template/markup.py
+++ b/genshi/template/markup.py
@@ -244,10 +244,9 @@
 
         for event in stream:
 
-            # We (currently) only care about start and end events for matching
+            # We (currently) only care about start events for matching
             # We might care about namespace events in the future, though
-            if not match_templates or (event[0] is not START and
-                                       event[0] is not END):
+            if not match_templates or event[0] is not START:
                 yield event
                 continue
 
--- a/genshi/template/plugin.py
+++ b/genshi/template/plugin.py
@@ -57,7 +57,7 @@
                                      options.get('genshi.max_cache_size'))
 
         loader_callback = options.get('genshi.loader_callback', None)
-        if loader_callback and not callable(loader_callback):
+        if loader_callback and not hasattr(loader_callback, '__call__'):
             raise ConfigurationError('loader callback must be a function')
 
         lookup_errors = options.get('genshi.lookup_errors', 'strict')
--- a/genshi/template/tests/eval.py
+++ b/genshi/template/tests/eval.py
@@ -195,8 +195,9 @@
     def test_compare_ne(self):
         self.assertEqual(False, Expression("1 != 1").evaluate({}))
         self.assertEqual(False, Expression("x != y").evaluate({'x': 1, 'y': 1}))
-        self.assertEqual(False, Expression("1 <> 1").evaluate({}))
-        self.assertEqual(False, Expression("x <> y").evaluate({'x': 1, 'y': 1}))
+        if sys.version < '3':
+            self.assertEqual(False, Expression("1 <> 1").evaluate({}))
+            self.assertEqual(False, Expression("x <> y").evaluate({'x': 1, 'y': 1}))
 
     def test_compare_lt(self):
         self.assertEqual(True, Expression("1 < 2").evaluate({}))
@@ -241,16 +242,9 @@
         self.assertEqual(42, expr.evaluate({'foo': foo, 'bar': {"x": 42}}))
 
     def test_lambda(self):
-        # Define a custom `sorted` function cause the builtin isn't available
-        # on Python 2.3
-        def sorted(items, compfunc):
-            items.sort(compfunc)
-            return items
-        data = {'items': [{'name': 'b', 'value': 0}, {'name': 'a', 'value': 1}],
-                'sorted': sorted}
-        expr = Expression("sorted(items, lambda a, b: cmp(a.name, b.name))")
-        self.assertEqual([{'name': 'a', 'value': 1}, {'name': 'b', 'value': 0}],
-                         expr.evaluate(data))
+        data = {'items': range(5)}
+        expr = Expression("filter(lambda x: x > 2, items)")
+        self.assertEqual([3, 4], expr.evaluate(data))
 
     def test_list_comprehension(self):
         expr = Expression("[n for n in numbers if n < 2]")
@@ -703,7 +697,7 @@
     def test_delitem(self):
         d = {'k': 'foo'}
         Suite("del d['k']").execute({'d': d})
-        self.failIf('k' in d, `d`)
+        self.failIf('k' in d, repr(d))
 
 
 def suite():
Copyright (C) 2012-2017 Edgewall Software