diff options
Diffstat (limited to 'repoze')
| -rw-r--r-- | repoze/bfg/tests/test_zcml.py | 42 | ||||
| -rw-r--r-- | repoze/bfg/zcml.py | 25 |
2 files changed, 65 insertions, 2 deletions
diff --git a/repoze/bfg/tests/test_zcml.py b/repoze/bfg/tests/test_zcml.py index 282c27472..d6eb80c44 100644 --- a/repoze/bfg/tests/test_zcml.py +++ b/repoze/bfg/tests/test_zcml.py @@ -2544,6 +2544,48 @@ class TestExcludeFunction(unittest.TestCase): self.assertEqual(self._callFUT('.foo'), True) self.assertEqual(self._callFUT('foo'), False) +class TestGetMembersFunction(unittest.TestCase): + def _callFUT(self, object, predicate=None): + from repoze.bfg.zcml import getmembers + return getmembers(object, predicate) + + def test_with_attribute_error(self): + class Dummy: + @property + def raises(self): + raise AttributeError('raises') + ob = Dummy() + result = self._callFUT(ob, None) + result.sort() + self.assertEqual(result, + [('__doc__', None), + ('__module__', 'repoze.bfg.tests.test_zcml')] + ) + + def test_without_attribute_error(self): + class Dummy: + def doesntraise(self): + pass + ob = Dummy() + result = self._callFUT(ob, None) + result.sort() + self.assertEqual(result, + [('__doc__', None), + ('__module__', 'repoze.bfg.tests.test_zcml'), + ('doesntraise', ob.doesntraise)] + ) + + def test_predicate(self): + class Dummy: + def doesntraise(self): + pass + ob = Dummy() + def predicate(testing): + return getattr(testing, '__name__', None) == 'doesntraise' + result = self._callFUT(ob, predicate) + result.sort() + self.assertEqual(result,[('doesntraise', ob.doesntraise)]) + class DummyModule: __path__ = "foo" __name__ = "dummy" diff --git a/repoze/bfg/zcml.py b/repoze/bfg/zcml.py index d08a61303..6bf180b3a 100644 --- a/repoze/bfg/zcml.py +++ b/repoze/bfg/zcml.py @@ -707,8 +707,13 @@ class BFGClassGrokker(object): found = BFGViewGrokker().grok(name, class_, **kw) # grok any decorations attached to the class' method (direct - # methods only, not methods of any base class) - methods = inspect.getmembers(class_, inspect.ismethod) + # methods only, not methods of any base class); we can't use + # inspect.getmembers here because it doesn't deal with a + # corner case where objects that inherit from Persistent + # advertises a '__provides__' as per dir(ob) but getattr(ob, + # '__provides__') raises an AttributeError. Unknown why this + # happens, but it doesn't matter: need to deal with it. + methods = getmembers(class_, inspect.ismethod) classmethods = class_.__dict__.keys() for method_name, method in methods: if method_name in classmethods: @@ -739,3 +744,19 @@ class Uncacheable(object): this class only exists for backwards compatibility (<0.8.1)""" file_configure = zcml_configure # backwards compat (>0.8.1) + +def getmembers(object, predicate=None): + """Return all members of an object as (name, value) pairs sorted + by name. Optionally, only return members that satisfy a given + predicate. Differs from inspect.getmembers inasmuch as it ignores + AttributeErrors.""" + results = [] + for key in dir(object): + try: + value = getattr(object, key) + except AttributeError: + continue + if not predicate or predicate(value): + results.append((key, value)) + results.sort() + return results |
