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
|
||||
|
||||
|
||||
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):
|
||||
"""
|
||||
Base class for all plugins.
|
||||
|
||||
@@ -32,176 +32,6 @@ from ipalib import plugable, errors, text
|
||||
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):
|
||||
"""
|
||||
Test the `ipalib.plugable.Plugin` class.
|
||||
|
||||
Reference in New Issue
Block a user