From 86405236325204cb5750ce79f674a5ab01114fa7 Mon Sep 17 00:00:00 2001 From: Jason Gerard DeRose Date: Tue, 12 Aug 2008 21:45:54 +0000 Subject: [PATCH] 119: Added ProxyTarget.implemented_by() classmethod; added corresponding unit tests --- ipalib/plugable.py | 12 ++++++++++ ipalib/tests/test_plugable.py | 43 +++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/ipalib/plugable.py b/ipalib/plugable.py index b607f0fac..a91063e7c 100644 --- a/ipalib/plugable.py +++ b/ipalib/plugable.py @@ -135,6 +135,18 @@ class ProxyTarget(ReadOnly): "must be str, frozenset, or have frozenset '__public__' attribute" ) + @classmethod + def implemented_by(cls, arg): + if inspect.isclass(arg): + subclass = arg + else: + subclass = arg.__class__ + assert issubclass(subclass, cls), 'must be subclass of %r' % cls + for name in cls.__public__: + if not hasattr(subclass, name): + return False + return True + class Proxy(ReadOnly): """ diff --git a/ipalib/tests/test_plugable.py b/ipalib/tests/test_plugable.py index b8242dce3..8ce986102 100644 --- a/ipalib/tests/test_plugable.py +++ b/ipalib/tests/test_plugable.py @@ -183,6 +183,49 @@ class test_ProxyTarget(ClassChecker): assert ex.implements(any_object) assert ex.implements(any_object()) + def test_implemented_by(self): + """ + Tests the `implemented_by` classmethod. + """ + class base(self.cls): + __public__ = frozenset(( + 'attr0', + 'attr1', + 'attr2', + )) + + class okay(base): + def attr0(self): + pass + def __get_attr1(self): + assert False # Make sure property isn't accesed on instance + attr1 = property(__get_attr1) + attr2 = 'hello world' + another_attr = 'whatever' + + class fail(base): + def __init__(self): + # Check that class, not instance is inspected: + self.attr2 = 'hello world' + def attr0(self): + pass + def __get_attr1(self): + assert False # Make sure property isn't accesed on instance + attr1 = property(__get_attr1) + another_attr = 'whatever' + + # Test that AssertionError is raised trying to pass something not + # subclass nor instance of base: + raises(AssertionError, base.implemented_by, object) + + # Test on subclass with needed attributes: + assert base.implemented_by(okay) is True + assert base.implemented_by(okay()) is True + + # Test on subclass *without* needed attributes: + assert base.implemented_by(fail) is False + assert base.implemented_by(fail()) is False + class test_Proxy(ClassChecker): """