summaryrefslogtreecommitdiffstats
path: root/ipalib
diff options
context:
space:
mode:
authorJason Gerard DeRose <jderose@redhat.com>2008-08-15 05:07:17 +0000
committerJason Gerard DeRose <jderose@redhat.com>2008-08-15 05:07:17 +0000
commita24f2121d553644513dc90d423b9ac968de34bc2 (patch)
tree368972377dd3c5c38f41e41e7f50a8cb1348ffd9 /ipalib
parent5ed58fdb4213908b406fe625d0727ecc15dbd1cf (diff)
downloadfreeipa-a24f2121d553644513dc90d423b9ac968de34bc2.tar.gz
freeipa-a24f2121d553644513dc90d423b9ac968de34bc2.tar.xz
freeipa-a24f2121d553644513dc90d423b9ac968de34bc2.zip
178: Registrar now subclasses from DictProxy; made Registrar.__iter__ behave same as the other container emulation in plugable.py, and made the dictorary interface return the base and the attribute interface return the MagicDict; updated API class and unit tests
Diffstat (limited to 'ipalib')
-rw-r--r--ipalib/plugable.py85
-rw-r--r--ipalib/tests/test_plugable.py49
2 files changed, 47 insertions, 87 deletions
diff --git a/ipalib/plugable.py b/ipalib/plugable.py
index b8d2b3906..57ab8bc74 100644
--- a/ipalib/plugable.py
+++ b/ipalib/plugable.py
@@ -546,7 +546,7 @@ class NameSpace(DictProxy):
return '%s(<%d members>)' % (self.__class__.__name__, len(self))
-class Registrar(ReadOnly):
+class Registrar(DictProxy):
"""
Collects plugin classes as they are registered.
@@ -561,30 +561,19 @@ class Registrar(ReadOnly):
:param allowed: Base classes from which plugins accepted by this
Registrar must subclass.
"""
-
- class Val(ReadOnly):
- """
- Internal class used so that only one mapping is needed.
- """
- def __init__(self, base):
- assert inspect.isclass(base)
- self.base = base
- self.name = base.__name__
- self.sub_d = dict()
- self.dictproxy = MagicDict(self.sub_d)
- lock(self)
-
- self.__allowed = allowed
- self.__d = {}
+ self.__allowed = dict((base, {}) for base in allowed)
self.__registered = set()
- for base in self.__allowed:
- val = Val(base)
- assert not (
- val.name in self.__d or hasattr(self, val.name)
- )
- self.__d[val.name] = val
- setattr(self, val.name, val.dictproxy)
- lock(self)
+ super(Registrar, self).__init__(
+ dict(self.__base_iter())
+ )
+
+ def __base_iter(self):
+ for (base, sub_d) in self.__allowed.iteritems():
+ assert inspect.isclass(base)
+ name = base.__name__
+ assert not hasattr(self, name)
+ setattr(self, name, MagicDict(sub_d))
+ yield (name, base)
def __findbases(self, klass):
"""
@@ -597,12 +586,12 @@ class Registrar(ReadOnly):
"""
assert inspect.isclass(klass)
found = False
- for base in self.__allowed:
+ for (base, sub_d) in self.__allowed.iteritems():
if issubclass(klass, base):
found = True
- yield base
+ yield (base, sub_d)
if not found:
- raise errors.SubclassError(klass, self.__allowed)
+ raise errors.SubclassError(klass, self.__allowed.keys())
def __call__(self, klass, override=False):
"""
@@ -619,17 +608,15 @@ class Registrar(ReadOnly):
raise errors.DuplicateError(klass)
# Find the base class or raise SubclassError:
- for base in self.__findbases(klass):
- sub_d = self.__d[base.__name__].sub_d
-
+ for (base, sub_d) in self.__findbases(klass):
# Check override:
if klass.__name__ in sub_d:
- # Must use override=True to override:
if not override:
+ # Must use override=True to override:
raise errors.OverrideError(base, klass)
else:
- # There was nothing already registered to override:
if override:
+ # There was nothing already registered to override:
raise errors.MissingOverrideError(base, klass)
# The plugin is okay, add to sub_d:
@@ -638,29 +625,6 @@ class Registrar(ReadOnly):
# The plugin is okay, add to __registered:
self.__registered.add(klass)
- def __getitem__(self, key):
- """
- Returns the MagicDict for plugins subclassed from the base named ``key``.
- """
- if key not in self.__d:
- raise KeyError('no base class named %r' % key)
- return self.__d[key].dictproxy
-
- def __contains__(self, key):
- """
- Returns True if a base class named ``key`` is in this Registrar.
- """
- return key in self.__d
-
- def __iter__(self):
- """
- Iterates through a (base, registered_plugins) tuple for each allowed
- base.
- """
- for base in self.__allowed:
- sub_d = self.__d[base.__name__].sub_d
- yield (base, tuple(sub_d[k] for k in sorted(sub_d)))
-
class API(DictProxy):
"""
@@ -687,16 +651,19 @@ class API(DictProxy):
plugin = instances[klass]
yield PluginProxy(base, plugin)
- for (base, classes) in self.register:
- namespace = NameSpace(plugin_iter(base, classes))
- name = base.__name__
+ for name in self.register:
+ base = self.register[name]
+ magic = getattr(self.register, name)
+ namespace = NameSpace(
+ plugin_iter(base, (magic[k] for k in magic))
+ )
assert not (
name in self.__d or hasattr(self, name)
)
self.__d[name] = namespace
object.__setattr__(self, name, namespace)
- for plugin in instances.values():
+ for plugin in instances.itervalues():
plugin.finalize(self)
lock(plugin)
assert plugin.api is self
diff --git a/ipalib/tests/test_plugable.py b/ipalib/tests/test_plugable.py
index aeb3ddf6e..aece3fb81 100644
--- a/ipalib/tests/test_plugable.py
+++ b/ipalib/tests/test_plugable.py
@@ -643,12 +643,17 @@ def test_Registrar():
# Test creation of Registrar:
r = plugable.Registrar(Base1, Base2)
+ # Test __iter__:
+ assert list(r) == ['Base1', 'Base2']
+
# Test __hasitem__, __getitem__:
for base in [Base1, Base2]:
- assert base.__name__ in r
- dp = r[base.__name__]
- assert type(dp) is plugable.MagicDict
- assert len(dp) == 0
+ name = base.__name__
+ assert name in r
+ assert r[name] is base
+ magic = getattr(r, name)
+ assert type(magic) is plugable.MagicDict
+ assert len(magic) == 0
# Check that TypeError is raised trying to register something that isn't
# a class:
@@ -660,12 +665,9 @@ def test_Registrar():
# Check that registration works
r(plugin1)
- dp = r['Base1']
- assert type(dp) is plugable.MagicDict
- assert len(dp) == 1
- assert r.Base1 is dp
- assert dp['plugin1'] is plugin1
- assert dp.plugin1 is plugin1
+ assert len(r.Base1) == 1
+ assert r.Base1['plugin1'] is plugin1
+ assert r.Base1.plugin1 is plugin1
# Check that DuplicateError is raised trying to register exact class
# again:
@@ -696,7 +698,7 @@ def test_Registrar():
assert len(r.Base2) == 1
assert r.Base2.plugin2 is plugin2
- # Setup to test __iter__:
+ # Setup to test more registration:
class plugin1a(Base1):
pass
r(plugin1a)
@@ -713,25 +715,16 @@ def test_Registrar():
pass
r(plugin2b)
- m = {
- 'Base1': set([plugin1, plugin1a, plugin1b]),
- 'Base2': set([plugin2, plugin2a, plugin2b]),
- }
-
- # Now test __iter__:
- for (base, plugins) in r:
- assert base in [Base1, Base2]
- assert set(plugins) == m[base.__name__]
- assert len(list(r)) == 2
-
# Again test __hasitem__, __getitem__:
for base in [Base1, Base2]:
- assert base.__name__ in r
- dp = r[base.__name__]
- assert len(dp) == 3
- for key in dp:
- klass = dp[key]
- assert getattr(dp, key) is klass
+ name = base.__name__
+ assert name in r
+ assert r[name] is base
+ magic = getattr(r, name)
+ assert len(magic) == 3
+ for key in magic:
+ klass = magic[key]
+ assert getattr(magic, key) is klass
assert issubclass(klass, base)