diff options
author | Jason Gerard DeRose <jderose@redhat.com> | 2008-08-08 22:45:09 +0000 |
---|---|---|
committer | Jason Gerard DeRose <jderose@redhat.com> | 2008-08-08 22:45:09 +0000 |
commit | 5a1223e94367c4370a94f271ef7e087dbdb02615 (patch) | |
tree | 353cbc374d224c6136c23f59f37fba4c72b30a71 /ipalib | |
parent | 6f144fbaf062d9644af06fdd11020e3d5d349639 (diff) | |
download | freeipa-5a1223e94367c4370a94f271ef7e087dbdb02615.tar.gz freeipa-5a1223e94367c4370a94f271ef7e087dbdb02615.tar.xz freeipa-5a1223e94367c4370a94f271ef7e087dbdb02615.zip |
90: Renamed plugable.Abstract to ProxyTarget, which now subclasses from ReadOnly; updated unit tests
Diffstat (limited to 'ipalib')
-rw-r--r-- | ipalib/plugable.py | 104 | ||||
-rw-r--r-- | ipalib/tests/test_plugable.py | 155 |
2 files changed, 139 insertions, 120 deletions
diff --git a/ipalib/plugable.py b/ipalib/plugable.py index 092e3bdd7..3f53fd4ad 100644 --- a/ipalib/plugable.py +++ b/ipalib/plugable.py @@ -43,7 +43,11 @@ class ReadOnly(object): __locked = False def __lock__(self): - assert self.__locked is False + """ + Puts this instance into a read-only state, after which attempting to + set or delete an attribute will raise AttributeError. + """ + assert self.__locked is False, '__lock__() can only be called once' self.__locked = True def __setattr__(self, name, value): @@ -69,7 +73,7 @@ class ReadOnly(object): return object.__delattr__(self, name) -class Abstract(object): +class ProxyTarget(ReadOnly): __public__ = frozenset() @classmethod @@ -86,52 +90,6 @@ class Abstract(object): ) -class Plugin(object): - """ - Base class for all plugins. - """ - - __api = None - - def __get_api(self): - """ - Returns the plugable.API instance passed to Plugin.finalize(), or - or returns None if finalize() has not yet been called. - """ - return self.__api - api = property(__get_api) - - def finalize(self, api): - """ - After all the plugins are instantiated, the plugable.API calls this - method, passing itself as the only argument. This is where plugins - should check that other plugins they depend upon have actually be - loaded. - """ - assert self.__api is None, 'finalize() can only be called once' - assert api is not None, 'finalize() argument cannot be None' - self.__api = api - - def __get_name(self): - """ - Returns the class name of this instance. - """ - return self.__class__.__name__ - name = property(__get_name) - - def __repr__(self): - """ - Returns a fully qualified <module><name> representation of the class. - """ - return '%s.%s()' % ( - self.__class__.__module__, - self.__class__.__name__ - ) - - - - - class Proxy(ReadOnly): __slots__ = ( '__base', @@ -155,7 +113,6 @@ class Proxy(ReadOnly): check_identifier(self.name) self.__lock__() - def __iter__(self): for name in sorted(self.__public__): yield name @@ -185,6 +142,55 @@ class Proxy(ReadOnly): ) +class Plugin(object): + """ + Base class for all plugins. + """ + + __api = None + + def __get_api(self): + """ + Returns the plugable.API instance passed to Plugin.finalize(), or + or returns None if finalize() has not yet been called. + """ + return self.__api + api = property(__get_api) + + def finalize(self, api): + """ + After all the plugins are instantiated, the plugable.API calls this + method, passing itself as the only argument. This is where plugins + should check that other plugins they depend upon have actually be + loaded. + """ + assert self.__api is None, 'finalize() can only be called once' + assert api is not None, 'finalize() argument cannot be None' + self.__api = api + + def __get_name(self): + """ + Returns the class name of this instance. + """ + return self.__class__.__name__ + name = property(__get_name) + + def __repr__(self): + """ + Returns a fully qualified <module><name> representation of the class. + """ + return '%s.%s()' % ( + self.__class__.__module__, + self.__class__.__name__ + ) + + + + + + + + class NameSpace(ReadOnly): """ A read-only namespace of (key, value) pairs that can be accessed diff --git a/ipalib/tests/test_plugable.py b/ipalib/tests/test_plugable.py index 1f42aa85c..c3245e775 100644 --- a/ipalib/tests/test_plugable.py +++ b/ipalib/tests/test_plugable.py @@ -26,6 +26,33 @@ from tstutil import ClassChecker from ipalib import plugable, errors +def test_valid_identifier(): + """ + Test the plugable.valid_identifier function. + """ + f = plugable.check_identifier + okay = [ + 'user_add', + 'stuff2junk', + 'sixty9', + ] + nope = [ + '_user_add', + '__user_add', + 'user_add_', + 'user_add__', + '_user_add_', + '__user_add__', + '60nine', + ] + for name in okay: + f(name) + for name in nope: + raises(errors.NameSpaceError, f, name) + for name in okay: + raises(errors.NameSpaceError, f, name.upper()) + + class test_ReadOnly(ClassChecker): """ Test the plugable.ReadOnly class @@ -34,6 +61,7 @@ class test_ReadOnly(ClassChecker): def test_class(self): assert self.cls.__bases__ == (object,) + assert callable(self.cls.__lock__) def test_when_unlocked(self): """ @@ -73,79 +101,64 @@ class test_ReadOnly(ClassChecker): assert read_only(obj, 'an_attribute') == 'Hello world!' +class test_ProxyTarget(ClassChecker): + """ + Test the plugable.ProxyTarget class. + """ + _cls = plugable.ProxyTarget -def test_valid_identifier(): - f = plugable.check_identifier - okay = [ - 'user_add', - 'stuff2junk', - 'sixty9', - ] - nope = [ - '_user_add', - '__user_add', - 'user_add_', - 'user_add__', - '_user_add_', - '__user_add__', - '60nine', - ] - for name in okay: - f(name) - for name in nope: - raises(errors.NameSpaceError, f, name) - for name in okay: - raises(errors.NameSpaceError, f, name.upper()) - - -def test_Abstract(): - cls = plugable.Abstract - - class example(cls): - __public__ = frozenset(( - 'some_method', - 'some_property', - )) - - # Test using str: - assert example.implements('some_method') - assert not example.implements('another_method') - - # Test using frozenset: - assert example.implements(frozenset(['some_method'])) - assert not example.implements( - frozenset(['some_method', 'another_method']) - ) - - # Test using another object/class with __public__ frozenset: - assert example.implements(example) - assert example().implements(example) - assert example.implements(example()) - assert example().implements(example()) - - class subset(cls): - __public__ = frozenset(( - 'some_property', - )) - assert example.implements(subset) - assert not subset.implements(example) - - class superset(cls): - __public__ = frozenset(( - 'some_method', - 'some_property', - 'another_property', - )) - assert not example.implements(superset) - assert superset.implements(example) + def test_class(self): + assert self.cls.__bases__ == (plugable.ReadOnly,) + assert self.cls.implements(frozenset()) - class any_object(object): - __public__ = frozenset(( - 'some_method', - 'some_property', - )) - assert example.implements(any_object) - assert example.implements(any_object()) + def test_implements(self): + """ + Test the implements() classmethod + """ + class example(self.cls): + __public__ = frozenset(( + 'some_method', + 'some_property', + )) + class superset(self.cls): + __public__ = frozenset(( + 'some_method', + 'some_property', + 'another_property', + )) + class subset(self.cls): + __public__ = frozenset(( + 'some_property', + )) + class any_object(object): + __public__ = frozenset(( + 'some_method', + 'some_property', + )) + + for ex in (example, example()): + # Test using str: + assert ex.implements('some_method') + assert not ex.implements('another_method') + + # Test using frozenset: + assert ex.implements(frozenset(['some_method'])) + assert not ex.implements( + frozenset(['some_method', 'another_method']) + ) + + # Test using another object/class with __public__ frozenset: + assert ex.implements(example) + assert ex.implements(example()) + + assert ex.implements(subset) + assert not subset.implements(ex) + + assert not ex.implements(superset) + assert superset.implements(ex) + + assert ex.implements(any_object) + assert ex.implements(any_object()) def test_Plugin(): |