mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-23 15:40:01 -06:00
90: Renamed plugable.Abstract to ProxyTarget, which now subclasses from ReadOnly; updated unit tests
This commit is contained in:
parent
6f144fbaf0
commit
5a1223e943
@ -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):
|
||||
|
@ -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_Abstract():
|
||||
cls = plugable.Abstract
|
||||
|
||||
class example(cls):
|
||||
def test_implements(self):
|
||||
"""
|
||||
Test the implements() classmethod
|
||||
"""
|
||||
class example(self.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):
|
||||
class superset(self.cls):
|
||||
__public__ = frozenset((
|
||||
'some_method',
|
||||
'some_property',
|
||||
'another_property',
|
||||
))
|
||||
assert not example.implements(superset)
|
||||
assert superset.implements(example)
|
||||
|
||||
class subset(self.cls):
|
||||
__public__ = frozenset((
|
||||
'some_property',
|
||||
))
|
||||
class any_object(object):
|
||||
__public__ = frozenset((
|
||||
'some_method',
|
||||
'some_property',
|
||||
))
|
||||
assert example.implements(any_object)
|
||||
assert example.implements(any_object())
|
||||
|
||||
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():
|
||||
|
Loading…
Reference in New Issue
Block a user