mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-24 08:00:02 -06:00
85: Added ReadOnly._lock() method to make class easier to use; updated subclasses and unit tests
This commit is contained in:
parent
6dc60a18c7
commit
58a3b1d091
@ -118,25 +118,33 @@ class ReadOnly(object):
|
|||||||
"""
|
"""
|
||||||
Base class for classes with read-only attributes.
|
Base class for classes with read-only attributes.
|
||||||
"""
|
"""
|
||||||
__slots__ = tuple()
|
__locked = False
|
||||||
|
|
||||||
|
def _lock(self):
|
||||||
|
assert self.__locked is False
|
||||||
|
self.__locked = True
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
"""
|
"""
|
||||||
This raises an AttributeError anytime an attempt is made to set an
|
Raises an AttributeError if ReadOnly._lock() has already been called;
|
||||||
attribute.
|
otherwise calls object.__setattr__()
|
||||||
"""
|
"""
|
||||||
raise AttributeError('read-only: cannot set %s.%s' %
|
if self.__locked:
|
||||||
(self.__class__.__name__, name)
|
raise AttributeError('read-only: cannot set %s.%s' %
|
||||||
)
|
(self.__class__.__name__, name)
|
||||||
|
)
|
||||||
|
return object.__setattr__(self, name, value)
|
||||||
|
|
||||||
def __delattr__(self, name):
|
def __delattr__(self, name):
|
||||||
"""
|
"""
|
||||||
This raises an AttributeError anytime an attempt is made to delete an
|
Raises an AttributeError if ReadOnly._lock() has already been called;
|
||||||
attribute.
|
otherwise calls object.__delattr__()
|
||||||
"""
|
"""
|
||||||
raise AttributeError('read-only: cannot del %s.%s' %
|
if self.__locked:
|
||||||
(self.__class__.__name__, name)
|
raise AttributeError('read-only: cannot del %s.%s' %
|
||||||
)
|
(self.__class__.__name__, name)
|
||||||
|
)
|
||||||
|
return object.__delattr__(self, name)
|
||||||
|
|
||||||
|
|
||||||
class Proxy(ReadOnly):
|
class Proxy(ReadOnly):
|
||||||
@ -153,17 +161,15 @@ class Proxy(ReadOnly):
|
|||||||
raise TypeError('arg1 must be a class, got %r' % base)
|
raise TypeError('arg1 must be a class, got %r' % base)
|
||||||
if not isinstance(target, base):
|
if not isinstance(target, base):
|
||||||
raise ValueError('arg2 must be instance of arg1, got %r' % target)
|
raise ValueError('arg2 must be instance of arg1, got %r' % target)
|
||||||
object.__setattr__(self, '_Proxy__base', base)
|
self.__base = base
|
||||||
object.__setattr__(self, '_Proxy__target', target)
|
self.__target = target
|
||||||
object.__setattr__(self, '_Proxy__name_attr', name_attr)
|
self.__name_attr = name_attr
|
||||||
object.__setattr__(self, '__public__', base.__public__)
|
self.name = getattr(target, name_attr)
|
||||||
object.__setattr__(self, 'name', getattr(target, name_attr))
|
self.__public__ = base.__public__
|
||||||
|
|
||||||
# Check __public__
|
|
||||||
assert type(self.__public__) is frozenset
|
assert type(self.__public__) is frozenset
|
||||||
|
|
||||||
# Check name
|
|
||||||
check_identifier(self.name)
|
check_identifier(self.name)
|
||||||
|
self._lock()
|
||||||
|
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
for name in sorted(self.__public__):
|
for name in sorted(self.__public__):
|
||||||
@ -204,14 +210,15 @@ class NameSpace(ReadOnly):
|
|||||||
"""
|
"""
|
||||||
NameSpace
|
NameSpace
|
||||||
"""
|
"""
|
||||||
object.__setattr__(self, '_NameSpace__proxies', tuple(proxies))
|
self.__proxies = tuple(proxies)
|
||||||
object.__setattr__(self, '_NameSpace__d', dict())
|
self.__d = dict()
|
||||||
for proxy in self.__proxies:
|
for proxy in self.__proxies:
|
||||||
assert isinstance(proxy, Proxy)
|
assert isinstance(proxy, Proxy)
|
||||||
assert proxy.name not in self.__d
|
assert proxy.name not in self.__d
|
||||||
self.__d[proxy.name] = proxy
|
self.__d[proxy.name] = proxy
|
||||||
assert not hasattr(self, proxy.name)
|
assert not hasattr(self, proxy.name)
|
||||||
object.__setattr__(self, proxy.name, proxy)
|
setattr(self, proxy.name, proxy)
|
||||||
|
self._lock()
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
"""
|
"""
|
||||||
@ -338,8 +345,8 @@ class Registrar(object):
|
|||||||
class API(ReadOnly):
|
class API(ReadOnly):
|
||||||
def __init__(self, *allowed):
|
def __init__(self, *allowed):
|
||||||
keys = tuple(b.__name__ for b in allowed)
|
keys = tuple(b.__name__ for b in allowed)
|
||||||
object.__setattr__(self, '_API__keys', keys)
|
self.register = Registrar(*allowed)
|
||||||
object.__setattr__(self, 'register', Registrar(*allowed))
|
self._lock()
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
"""
|
"""
|
||||||
|
@ -139,6 +139,7 @@ def test_Plugin():
|
|||||||
|
|
||||||
def test_ReadOnly():
|
def test_ReadOnly():
|
||||||
obj = plugable.ReadOnly()
|
obj = plugable.ReadOnly()
|
||||||
|
obj._lock()
|
||||||
names = ['not_an_attribute', 'an_attribute']
|
names = ['not_an_attribute', 'an_attribute']
|
||||||
for name in names:
|
for name in names:
|
||||||
no_set(obj, name)
|
no_set(obj, name)
|
||||||
@ -146,7 +147,8 @@ def test_ReadOnly():
|
|||||||
|
|
||||||
class some_ro_class(plugable.ReadOnly):
|
class some_ro_class(plugable.ReadOnly):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
object.__setattr__(self, 'an_attribute', 'Hello world!')
|
self.an_attribute = 'Hello world!'
|
||||||
|
self._lock()
|
||||||
obj = some_ro_class()
|
obj = some_ro_class()
|
||||||
for name in names:
|
for name in names:
|
||||||
no_set(obj, name)
|
no_set(obj, name)
|
||||||
|
Loading…
Reference in New Issue
Block a user