90: Renamed plugable.Abstract to ProxyTarget, which now subclasses from ReadOnly; updated unit tests

This commit is contained in:
Jason Gerard DeRose 2008-08-08 22:45:09 +00:00
parent 6f144fbaf0
commit 5a1223e943
2 changed files with 136 additions and 117 deletions

View File

@ -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,6 +90,58 @@ class Abstract(object):
)
class Proxy(ReadOnly):
__slots__ = (
'__base',
'__target',
'__name_attr',
'name',
'__public__',
)
def __init__(self, base, target, name_attr='name'):
if not inspect.isclass(base):
raise TypeError('arg1 must be a class, got %r' % base)
if not isinstance(target, base):
raise ValueError('arg2 must be instance of arg1, got %r' % target)
self.__base = base
self.__target = target
self.__name_attr = name_attr
self.name = getattr(target, name_attr)
self.__public__ = base.__public__
assert type(self.__public__) is frozenset
check_identifier(self.name)
self.__lock__()
def __iter__(self):
for name in sorted(self.__public__):
yield name
def __getitem__(self, key):
if key in self.__public__:
return getattr(self.__target, key)
raise KeyError('no proxy attribute %r' % key)
def __getattr__(self, name):
if name in self.__public__:
return getattr(self.__target, name)
raise AttributeError('no proxy attribute %r' % name)
def __call__(self, *args, **kw):
return self['__call__'](*args, **kw)
def _clone(self, name_attr):
return self.__class__(self.__base, self.__target, name_attr)
def __repr__(self):
return '%s(%s, %r, %r)' % (
self.__class__.__name__,
self.__base.__name__,
self.__target,
self.__name_attr,
)
class Plugin(object):
"""
Base class for all plugins.
@ -132,57 +188,7 @@ class Plugin(object):
class Proxy(ReadOnly):
__slots__ = (
'__base',
'__target',
'__name_attr',
'name',
'__public__',
)
def __init__(self, base, target, name_attr='name'):
if not inspect.isclass(base):
raise TypeError('arg1 must be a class, got %r' % base)
if not isinstance(target, base):
raise ValueError('arg2 must be instance of arg1, got %r' % target)
self.__base = base
self.__target = target
self.__name_attr = name_attr
self.name = getattr(target, name_attr)
self.__public__ = base.__public__
assert type(self.__public__) is frozenset
check_identifier(self.name)
self.__lock__()
def __iter__(self):
for name in sorted(self.__public__):
yield name
def __getitem__(self, key):
if key in self.__public__:
return getattr(self.__target, key)
raise KeyError('no proxy attribute %r' % key)
def __getattr__(self, name):
if name in self.__public__:
return getattr(self.__target, name)
raise AttributeError('no proxy attribute %r' % name)
def __call__(self, *args, **kw):
return self['__call__'](*args, **kw)
def _clone(self, name_attr):
return self.__class__(self.__base, self.__target, name_attr)
def __repr__(self):
return '%s(%s, %r, %r)' % (
self.__class__.__name__,
self.__base.__name__,
self.__target,
self.__name_attr,
)
class NameSpace(ReadOnly):

View File

@ -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_class(self):
assert self.cls.__bases__ == (plugable.ReadOnly,)
assert self.cls.implements(frozenset())
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',
))
def test_Abstract():
cls = plugable.Abstract
for ex in (example, example()):
# Test using str:
assert ex.implements('some_method')
assert not ex.implements('another_method')
class example(cls):
__public__ = frozenset((
'some_method',
'some_property',
))
# Test using frozenset:
assert ex.implements(frozenset(['some_method']))
assert not ex.implements(
frozenset(['some_method', 'another_method'])
)
# Test using str:
assert example.implements('some_method')
assert not example.implements('another_method')
# Test using another object/class with __public__ frozenset:
assert ex.implements(example)
assert ex.implements(example())
# Test using frozenset:
assert example.implements(frozenset(['some_method']))
assert not example.implements(
frozenset(['some_method', 'another_method'])
)
assert ex.implements(subset)
assert not subset.implements(ex)
# Test using another object/class with __public__ frozenset:
assert example.implements(example)
assert example().implements(example)
assert example.implements(example())
assert example().implements(example())
assert not ex.implements(superset)
assert superset.implements(ex)
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)
class any_object(object):
__public__ = frozenset((
'some_method',
'some_property',
))
assert example.implements(any_object)
assert example.implements(any_object())
assert ex.implements(any_object)
assert ex.implements(any_object())
def test_Plugin():