# HG changeset patch # User cmlenz # Date 1184666536 0 # Node ID e2f9fe115441942af66662f8b31b2ea0b5f5f9fd # Parent 7ea368373ea435528d8b69245ea9bf96fa6246d5 Ported [680] to 0.4.x branch. diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,8 @@ ignored tags (ticket #132). * The HTML sanitizer now strips any CSS comments in style attributes, which could previously be used to hide malicious property values. + * Attribute access in template expressions no longer silently ignores + exceptions other than `AttributeError` raised in the attribute accessor. Version 0.4.2 diff --git a/genshi/template/eval.py b/genshi/template/eval.py --- a/genshi/template/eval.py +++ b/genshi/template/eval.py @@ -257,18 +257,19 @@ if val is UNDEFINED: val = BUILTINS.get(name, val) if val is UNDEFINED: - return cls.undefined(name) + val = cls.undefined(name) return val lookup_name = classmethod(lookup_name) def lookup_attr(cls, data, obj, key): __traceback_hide__ = True - if hasattr(obj, key): - return getattr(obj, key) - try: - return obj[key] - except (KeyError, TypeError): - return cls.undefined(key, owner=obj) + val = getattr(obj, key, UNDEFINED) + if val is UNDEFINED: + try: + val = obj[key] + except (KeyError, TypeError): + val = cls.undefined(key, owner=obj) + return val lookup_attr = classmethod(lookup_attr) def lookup_item(cls, data, obj, key): @@ -281,7 +282,7 @@ if isinstance(key, basestring): val = getattr(obj, key, UNDEFINED) if val is UNDEFINED: - return cls.undefined(key, owner=obj) + val = cls.undefined(key, owner=obj) return val raise lookup_item = classmethod(lookup_item) diff --git a/genshi/template/tests/eval.py b/genshi/template/tests/eval.py --- a/genshi/template/tests/eval.py +++ b/genshi/template/tests/eval.py @@ -338,6 +338,14 @@ self.assertEqual('nil', retval._name) assert retval._owner is something + def test_getattr_exception(self): + class Something(object): + def prop(self): + raise NotImplementedError + prop = property(prop) + self.assertRaises(NotImplementedError, + Expression('s.prop').evaluate, {'s': Something()}) + def test_getitem_undefined_string(self): class Something(object): def __repr__(self): @@ -349,6 +357,13 @@ self.assertEqual('nil', retval._name) assert retval._owner is something + def test_getitem_exception(self): + class Something(object): + def __getitem__(self, key): + raise NotImplementedError + self.assertRaises(NotImplementedError, + Expression('s["foo"]').evaluate, {'s': Something()}) + def test_error_access_undefined(self): expr = Expression("nothing", filename='index.html', lineno=50, lookup='strict')