23: Added base.Attribute class that determins the object association via class naming convention instead of through the _obj attribute

This commit is contained in:
Jason Gerard DeRose 2008-07-20 21:42:35 +00:00
parent f3faaf2d29
commit 6f58880dcd
2 changed files with 145 additions and 2 deletions

View File

@ -21,6 +21,7 @@
Base classes for plug-in architecture and generative API.
"""
import re
import inspect
import exceptions
@ -141,6 +142,53 @@ class Named(object):
name = property(__get_name)
class AbstractCommand(object):
def __call__(self):
print 'You called %s()' % self.name
class Attribute(Named):
__locked = False
__obj = None
def __init__(self):
m = re.match('^([a-z]+)__([a-z]+)$', self.__class__.__name__)
assert m
self.__obj_name = m.group(1)
self.__attr_name = m.group(2)
def __get_obj(self):
return self.__obj
obj = property(__get_obj)
def set_obj(self, obj=None):
if self.__locked:
raise exceptions.TwiceSetError(self.__class__.__name__, 'obj')
self.__locked = True
if obj is None:
return
assert isinstance(obj, Object)
assert obj.name == self.__obj_name
self.__obj = obj
def __get_obj_name(self):
return self.__obj_name
obj_name = property(__get_obj_name)
def __get_attr_name(self):
return self.__attr_name
attr_name = property(__get_attr_name)
class Method(AbstractCommand, Attribute):
def _get_name(self):
return '%s_%s' % (self.attr_name, self.obj_name)
class Property(Attribute):
def _get_name(self):
return self.attr_name
class WithObj(Named):
_obj = None
__obj = None
@ -168,8 +216,7 @@ class Command(WithObj):
def __call__(self):
print 'You called %s()' % self.name
class Property(WithObj):
pass
class Object(Named):
__commands = None
@ -187,6 +234,31 @@ class Object(Named):
commands = property(__get_commands, __set_commands)
class AttributeCollector(object):
def __init__(self):
self.__d = {}
def __getitem__(self, key):
assert isinstance(key, str)
if key not in self.__d:
self.__d[key] = {}
return self.__d[key]
def __iter__(self):
for key in self.__d:
yield key
def add(self, i):
assert isinstance(i, Attribute)
self[i.obj_name][i.attr_name] = i
def namespaces(self):
for key in self:
yield (key, NameSpace(self[key]))
class Collector(object):
def __init__(self):
self.__d = {}

View File

@ -191,6 +191,77 @@ def test_Named():
assert i.name == 'named_class'
def test_Attribute():
class user__add(base.Attribute):
pass
i = user__add()
assert i.obj_name == 'user'
assert i.attr_name == 'add'
assert read_only(i, 'obj') is None
class user(base.Object):
pass
u = user()
i.set_obj(u)
assert read_only(i, 'obj') is u
raised = False
try:
i.set_obj(u)
except exceptions.TwiceSetError:
raised = True
assert raised
def test_Method():
class user__mod(base.Method):
pass
i = user__mod()
assert isinstance(i, base.Attribute)
assert isinstance(i, base.AbstractCommand)
assert i.obj_name == 'user'
assert i.attr_name == 'mod'
assert i.name == 'mod_user'
def test_Property():
class user__firstname(base.Property):
pass
i = user__firstname()
assert isinstance(i, base.Attribute)
assert i.obj_name == 'user'
assert i.attr_name == 'firstname'
assert i.name == 'firstname'
def test_AttributeCollector():
class user__add(base.Attribute):
pass
class user__mod(base.Attribute):
pass
class group__add(base.Attribute):
pass
u_a = user__add()
u_m = user__mod()
g_a = group__add()
ac = base.AttributeCollector()
ac.add(u_a)
ac.add(u_m)
ac.add(g_a)
assert set(ac) == set(['user', 'group'])
u = ac['user']
assert set(u) == set(['add', 'mod'])
assert set(u.values()) == set([u_a, u_m])
g = ac['group']
assert g.keys() == ['add']
assert g.values() == [g_a]
def test_WithObj():
class some_object(base.Named):
pass