# HG changeset patch # User cmlenz # Date 1184666452 0 # Node ID c17342ef9efbf3386098e113452e130cf73b0e53 # Parent 461d9d0e85a45e1edea0e3b535983ddd8dce93d1 Attribute access in template expressions no longer silently ignores exceptions other than `AttributeError` raised in the attribute accessor. diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -34,6 +34,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 @@ -259,18 +259,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): @@ -283,7 +284,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')