mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
plugable: Remove SetProxy, DictProxy and MagicDict
https://fedorahosted.org/freeipa/ticket/3090 Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
This commit is contained in:
@@ -105,116 +105,6 @@ class Registry(object):
|
|||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
class SetProxy(ReadOnly):
|
|
||||||
"""
|
|
||||||
A read-only container with set/sequence behaviour.
|
|
||||||
|
|
||||||
This container acts as a proxy to an actual set-like object (a set,
|
|
||||||
frozenset, or dict) that is passed to the constructor. To the extent
|
|
||||||
possible in Python, this underlying set-like object cannot be modified
|
|
||||||
through the SetProxy... which just means you wont do it accidentally.
|
|
||||||
"""
|
|
||||||
def __init__(self, s):
|
|
||||||
"""
|
|
||||||
:param s: The target set-like object (a set, frozenset, or dict)
|
|
||||||
"""
|
|
||||||
allowed = (set, frozenset, dict)
|
|
||||||
if type(s) not in allowed:
|
|
||||||
raise TypeError('%r not in %r' % (type(s), allowed))
|
|
||||||
self.__s = s
|
|
||||||
if not is_production_mode(self):
|
|
||||||
lock(self)
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
"""
|
|
||||||
Return the number of items in this container.
|
|
||||||
"""
|
|
||||||
return len(self.__s)
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
"""
|
|
||||||
Iterate (in ascending order) through keys.
|
|
||||||
"""
|
|
||||||
for key in sorted(self.__s):
|
|
||||||
yield key
|
|
||||||
|
|
||||||
def __contains__(self, key):
|
|
||||||
"""
|
|
||||||
Return True if this container contains ``key``.
|
|
||||||
|
|
||||||
:param key: The key to test for membership.
|
|
||||||
"""
|
|
||||||
return key in self.__s
|
|
||||||
|
|
||||||
|
|
||||||
class DictProxy(SetProxy):
|
|
||||||
"""
|
|
||||||
A read-only container with mapping behaviour.
|
|
||||||
|
|
||||||
This container acts as a proxy to an actual mapping object (a dict) that
|
|
||||||
is passed to the constructor. To the extent possible in Python, this
|
|
||||||
underlying mapping object cannot be modified through the DictProxy...
|
|
||||||
which just means you wont do it accidentally.
|
|
||||||
|
|
||||||
Also see `SetProxy`.
|
|
||||||
"""
|
|
||||||
def __init__(self, d):
|
|
||||||
"""
|
|
||||||
:param d: The target mapping object (a dict)
|
|
||||||
"""
|
|
||||||
if type(d) is not dict:
|
|
||||||
raise TypeError('%r is not %r' % (type(d), dict))
|
|
||||||
self.__d = d
|
|
||||||
super(DictProxy, self).__init__(d)
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
"""
|
|
||||||
Return the value corresponding to ``key``.
|
|
||||||
|
|
||||||
:param key: The key of the value you wish to retrieve.
|
|
||||||
"""
|
|
||||||
return self.__d[key]
|
|
||||||
|
|
||||||
def __call__(self):
|
|
||||||
"""
|
|
||||||
Iterate (in ascending order by key) through values.
|
|
||||||
"""
|
|
||||||
for key in self:
|
|
||||||
yield self.__d[key]
|
|
||||||
|
|
||||||
|
|
||||||
class MagicDict(DictProxy):
|
|
||||||
"""
|
|
||||||
A mapping container whose values can be accessed as attributes.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
>>> magic = MagicDict({'the_key': 'the value'})
|
|
||||||
>>> magic['the_key']
|
|
||||||
'the value'
|
|
||||||
>>> magic.the_key
|
|
||||||
'the value'
|
|
||||||
|
|
||||||
This container acts as a proxy to an actual mapping object (a dict) that
|
|
||||||
is passed to the constructor. To the extent possible in Python, this
|
|
||||||
underlying mapping object cannot be modified through the MagicDict...
|
|
||||||
which just means you wont do it accidentally.
|
|
||||||
|
|
||||||
Also see `DictProxy` and `SetProxy`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __getattr__(self, name):
|
|
||||||
"""
|
|
||||||
Return the value corresponding to ``name``.
|
|
||||||
|
|
||||||
:param name: The name of the attribute you wish to retrieve.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return self[name]
|
|
||||||
except KeyError:
|
|
||||||
raise AttributeError('no magic attribute %r' % name)
|
|
||||||
|
|
||||||
|
|
||||||
class Plugin(ReadOnly):
|
class Plugin(ReadOnly):
|
||||||
"""
|
"""
|
||||||
Base class for all plugins.
|
Base class for all plugins.
|
||||||
|
|||||||
@@ -32,176 +32,6 @@ from ipalib import plugable, errors, text
|
|||||||
from ipaplatform.paths import paths
|
from ipaplatform.paths import paths
|
||||||
|
|
||||||
|
|
||||||
class test_SetProxy(ClassChecker):
|
|
||||||
"""
|
|
||||||
Test the `ipalib.plugable.SetProxy` class.
|
|
||||||
"""
|
|
||||||
_cls = plugable.SetProxy
|
|
||||||
|
|
||||||
def test_class(self):
|
|
||||||
"""
|
|
||||||
Test the `ipalib.plugable.SetProxy` class.
|
|
||||||
"""
|
|
||||||
assert self.cls.__bases__ == (plugable.ReadOnly,)
|
|
||||||
|
|
||||||
def test_init(self):
|
|
||||||
"""
|
|
||||||
Test the `ipalib.plugable.SetProxy.__init__` method.
|
|
||||||
"""
|
|
||||||
okay = (set, frozenset, dict)
|
|
||||||
fail = (list, tuple)
|
|
||||||
for t in okay:
|
|
||||||
self.cls(t())
|
|
||||||
raises(TypeError, self.cls, t)
|
|
||||||
for t in fail:
|
|
||||||
raises(TypeError, self.cls, t())
|
|
||||||
raises(TypeError, self.cls, t)
|
|
||||||
|
|
||||||
def test_SetProxy(self):
|
|
||||||
"""
|
|
||||||
Test container emulation of `ipalib.plugable.SetProxy` class.
|
|
||||||
"""
|
|
||||||
def get_key(i):
|
|
||||||
return 'key_%d' % i
|
|
||||||
|
|
||||||
cnt = 10
|
|
||||||
target = set()
|
|
||||||
proxy = self.cls(target)
|
|
||||||
for i in xrange(cnt):
|
|
||||||
key = get_key(i)
|
|
||||||
|
|
||||||
# Check initial state
|
|
||||||
assert len(proxy) == len(target)
|
|
||||||
assert list(proxy) == sorted(target)
|
|
||||||
assert key not in proxy
|
|
||||||
assert key not in target
|
|
||||||
|
|
||||||
# Add and test again
|
|
||||||
target.add(key)
|
|
||||||
assert len(proxy) == len(target)
|
|
||||||
assert list(proxy) == sorted(target)
|
|
||||||
assert key in proxy
|
|
||||||
assert key in target
|
|
||||||
|
|
||||||
|
|
||||||
class test_DictProxy(ClassChecker):
|
|
||||||
"""
|
|
||||||
Test the `ipalib.plugable.DictProxy` class.
|
|
||||||
"""
|
|
||||||
_cls = plugable.DictProxy
|
|
||||||
|
|
||||||
def test_class(self):
|
|
||||||
"""
|
|
||||||
Test the `ipalib.plugable.DictProxy` class.
|
|
||||||
"""
|
|
||||||
assert self.cls.__bases__ == (plugable.SetProxy,)
|
|
||||||
|
|
||||||
def test_init(self):
|
|
||||||
"""
|
|
||||||
Test the `ipalib.plugable.DictProxy.__init__` method.
|
|
||||||
"""
|
|
||||||
self.cls(dict())
|
|
||||||
raises(TypeError, self.cls, dict)
|
|
||||||
fail = (set, frozenset, list, tuple)
|
|
||||||
for t in fail:
|
|
||||||
raises(TypeError, self.cls, t())
|
|
||||||
raises(TypeError, self.cls, t)
|
|
||||||
|
|
||||||
def test_DictProxy(self):
|
|
||||||
"""
|
|
||||||
Test container emulation of `ipalib.plugable.DictProxy` class.
|
|
||||||
"""
|
|
||||||
def get_kv(i):
|
|
||||||
return (
|
|
||||||
'key_%d' % i,
|
|
||||||
'val_%d' % i,
|
|
||||||
)
|
|
||||||
cnt = 10
|
|
||||||
target = dict()
|
|
||||||
proxy = self.cls(target)
|
|
||||||
for i in xrange(cnt):
|
|
||||||
(key, val) = get_kv(i)
|
|
||||||
|
|
||||||
# Check initial state
|
|
||||||
assert len(proxy) == len(target)
|
|
||||||
assert list(proxy) == sorted(target)
|
|
||||||
assert list(proxy()) == [target[k] for k in sorted(target)]
|
|
||||||
assert key not in proxy
|
|
||||||
raises(KeyError, getitem, proxy, key)
|
|
||||||
|
|
||||||
# Add and test again
|
|
||||||
target[key] = val
|
|
||||||
assert len(proxy) == len(target)
|
|
||||||
assert list(proxy) == sorted(target)
|
|
||||||
assert list(proxy()) == [target[k] for k in sorted(target)]
|
|
||||||
|
|
||||||
# Verify TypeError is raised trying to set/del via proxy
|
|
||||||
raises(TypeError, setitem, proxy, key, val)
|
|
||||||
raises(TypeError, delitem, proxy, key)
|
|
||||||
|
|
||||||
|
|
||||||
class test_MagicDict(ClassChecker):
|
|
||||||
"""
|
|
||||||
Test the `ipalib.plugable.MagicDict` class.
|
|
||||||
"""
|
|
||||||
_cls = plugable.MagicDict
|
|
||||||
|
|
||||||
def test_class(self):
|
|
||||||
"""
|
|
||||||
Test the `ipalib.plugable.MagicDict` class.
|
|
||||||
"""
|
|
||||||
assert self.cls.__bases__ == (plugable.DictProxy,)
|
|
||||||
for non_dict in ('hello', 69, object):
|
|
||||||
raises(TypeError, self.cls, non_dict)
|
|
||||||
|
|
||||||
def test_MagicDict(self):
|
|
||||||
"""
|
|
||||||
Test container emulation of `ipalib.plugable.MagicDict` class.
|
|
||||||
"""
|
|
||||||
cnt = 10
|
|
||||||
keys = []
|
|
||||||
d = dict()
|
|
||||||
dictproxy = self.cls(d)
|
|
||||||
for i in xrange(cnt):
|
|
||||||
key = 'key_%d' % i
|
|
||||||
val = 'val_%d' % i
|
|
||||||
keys.append(key)
|
|
||||||
|
|
||||||
# Test thet key does not yet exist
|
|
||||||
assert len(dictproxy) == i
|
|
||||||
assert key not in dictproxy
|
|
||||||
assert not hasattr(dictproxy, key)
|
|
||||||
raises(KeyError, getitem, dictproxy, key)
|
|
||||||
raises(AttributeError, getattr, dictproxy, key)
|
|
||||||
|
|
||||||
# Test that items/attributes cannot be set on dictproxy:
|
|
||||||
raises(TypeError, setitem, dictproxy, key, val)
|
|
||||||
raises(AttributeError, setattr, dictproxy, key, val)
|
|
||||||
|
|
||||||
# Test that additions in d are reflected in dictproxy:
|
|
||||||
d[key] = val
|
|
||||||
assert len(dictproxy) == i + 1
|
|
||||||
assert key in dictproxy
|
|
||||||
assert hasattr(dictproxy, key)
|
|
||||||
assert dictproxy[key] is val
|
|
||||||
assert read_only(dictproxy, key) is val
|
|
||||||
|
|
||||||
# Test __iter__
|
|
||||||
assert list(dictproxy) == keys
|
|
||||||
|
|
||||||
for key in keys:
|
|
||||||
# Test that items cannot be deleted through dictproxy:
|
|
||||||
raises(TypeError, delitem, dictproxy, key)
|
|
||||||
raises(AttributeError, delattr, dictproxy, key)
|
|
||||||
|
|
||||||
# Test that deletions in d are reflected in dictproxy
|
|
||||||
del d[key]
|
|
||||||
assert len(dictproxy) == len(d)
|
|
||||||
assert key not in dictproxy
|
|
||||||
raises(KeyError, getitem, dictproxy, key)
|
|
||||||
raises(AttributeError, getattr, dictproxy, key)
|
|
||||||
|
|
||||||
|
|
||||||
class test_Plugin(ClassChecker):
|
class test_Plugin(ClassChecker):
|
||||||
"""
|
"""
|
||||||
Test the `ipalib.plugable.Plugin` class.
|
Test the `ipalib.plugable.Plugin` class.
|
||||||
|
|||||||
Reference in New Issue
Block a user