67: Deleted NameSpace, Proxy; renamed NameSpace2, Proxy2 to NameSpace, Proxy

This commit is contained in:
Jason Gerard DeRose 2008-08-06 23:22:29 +00:00
parent e63453a858
commit 03bad04e7b
2 changed files with 27 additions and 253 deletions

View File

@ -123,52 +123,6 @@ class ReadOnly(object):
class Proxy(ReadOnly): class Proxy(ReadOnly):
"""
Used to only export certain attributes into the generative API.
Subclasses must list names of attributes to be proxied in the __slots__
class attribute.
"""
__slots__ = (
'__obj',
'name',
)
def __init__(self, obj, proxy_name=None):
"""
Proxy attributes on `obj`.
"""
if proxy_name is None:
proxy_name = obj.__class__.__name__
check_identifier(proxy_name)
object.__setattr__(self, '_Proxy__obj', obj)
object.__setattr__(self, 'name', proxy_name)
for name in self.__slots__:
attr = getattr(obj, name)
if callable(attr):
object.__setattr__(self, name, attr)
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.__obj)
def __str__(self):
return to_cli(self.name)
def _clone(self, new_name):
return self.__class__(self.__obj, proxy_name=new_name)
def __getattr__(self, name):
if name in self.__slots__:
return getattr(self.__obj, name)
raise AttributeError('attribute %r not in %s.__slots__' % (
name,
self.__class__.__name__
)
)
class Proxy2(ReadOnly):
__slots__ = ( __slots__ = (
'base', 'base',
'name', 'name',
@ -180,7 +134,7 @@ class Proxy2(ReadOnly):
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, 'base', base) object.__setattr__(self, 'base', base)
object.__setattr__(self, '_Proxy2__target', target) object.__setattr__(self, '_Proxy__target', target)
# Check base.public # Check base.public
assert type(self.base.public) is frozenset assert type(self.base.public) is frozenset
@ -206,8 +160,11 @@ class Proxy2(ReadOnly):
def __call__(self, *args, **kw): def __call__(self, *args, **kw):
return self['__call__'](*args, **kw) return self['__call__'](*args, **kw)
def _clone(self, name_attr):
return self.__class__(self.base, self.__target, name_attr)
class NameSpace2(ReadOnly):
class NameSpace(ReadOnly):
""" """
A read-only namespace of (key, value) pairs that can be accessed A read-only namespace of (key, value) pairs that can be accessed
both as instance attributes and as dictionary items. both as instance attributes and as dictionary items.
@ -215,12 +172,12 @@ class NameSpace2(ReadOnly):
def __init__(self, proxies): def __init__(self, proxies):
""" """
NameSpace2 NameSpace
""" """
object.__setattr__(self, '_NameSpace2__proxies', tuple(proxies)) object.__setattr__(self, '_NameSpace__proxies', tuple(proxies))
object.__setattr__(self, '_NameSpace2__d', dict()) object.__setattr__(self, '_NameSpace__d', dict())
for proxy in self.__proxies: for proxy in self.__proxies:
assert isinstance(proxy, Proxy2) 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)
@ -258,68 +215,6 @@ class NameSpace2(ReadOnly):
return '%s(<%d proxies>)' % (self.__class__.__name__, len(self)) return '%s(<%d proxies>)' % (self.__class__.__name__, len(self))
class NameSpace(ReadOnly):
"""
A read-only namespace of (key, value) pairs that can be accessed
both as instance attributes and as dictionary items.
"""
def __init__(self, items):
"""
`items` should be an iterable providing the members of this
NameSpace.
"""
object.__setattr__(self, '_NameSpace__items', tuple(items))
# dict mapping Python name to item:
object.__setattr__(self, '_NameSpace__pname', {})
# dict mapping human-readibly name to item:
object.__setattr__(self, '_NameSpace__hname', {})
for item in self.__items:
object.__setattr__(self, item.name, item)
for (key, d) in [
(item.name, self.__pname),
(str(item), self.__hname),
]:
assert key not in d
d[key] = item
def __iter__(self):
"""
Iterates through the items in this NameSpace in the same order they
were passed in the contructor.
"""
for item in self.__items:
yield item
def __len__(self):
"""
Returns number of items in this NameSpace.
"""
return len(self.__items)
def __contains__(self, key):
"""
Returns True if an item with pname or hname `key` is in this
NameSpace.
"""
return (key in self.__pname) or (key in self.__hname)
def __getitem__(self, key):
"""
Returns item with pname or hname `key`; otherwise raises KeyError.
"""
if key in self.__pname:
return self.__pname[key]
if key in self.__hname:
return self.__hname[key]
raise KeyError('NameSpace has no item for key %r' % key)
def __repr__(self):
return '%s(<%d proxies>)' % (self.__class__.__name__, len(self))
class Registrar(object): class Registrar(object):
def __init__(self, *allowed): def __init__(self, *allowed):

View File

@ -105,71 +105,7 @@ def test_ReadOnly():
def test_Proxy(): def test_Proxy():
assert issubclass(plugable.Proxy, plugable.ReadOnly) cls = plugable.Proxy
class CommandProxy(plugable.Proxy):
__slots__ = (
'validate',
'__call__',
)
class do_something(object):
def __repr__(self):
return '<my repr>'
def __call__(self, arg):
return arg + 1
def validate(self, arg):
return arg + 2
def not_public(self, arg):
return arg + 3
# Test basic Proxy functionality
i = do_something()
p = CommandProxy(i)
assert '__dict__' not in dir(p)
assert p.name == 'do_something'
assert str(p) == 'do-something'
assert repr(p) == 'CommandProxy(<my repr>)'
assert p(1) == 2
assert p.validate(1) == 3
# Test that proxy_name can be overriden:
i = do_something()
p = CommandProxy(i, proxy_name='user_add')
assert '__dict__' not in dir(p)
assert p.name == 'user_add'
assert str(p) == 'user-add'
assert repr(p) == 'CommandProxy(<my repr>)'
assert p(1) == 2
assert p.validate(1) == 3
# Test that attributes not listed in __slots__ are not present:
name = 'not_public'
i = do_something()
p = CommandProxy(i)
assert getattr(i, name)(1) == 4
raises(AttributeError, getattr, p, name)
# Test that attributes are read-only:
name = 'validate'
i = do_something()
p = CommandProxy(i)
assert getattr(p, name)(1) == 3
assert read_only(p, name)(1) == 3
# Test cloning:
i = do_something()
p = CommandProxy(i)
c = p._clone('do_a_thing')
assert isinstance(c, CommandProxy)
assert c.name == 'do_a_thing'
def test_Proxy2():
cls = plugable.Proxy2
assert issubclass(cls, plugable.ReadOnly) assert issubclass(cls, plugable.ReadOnly)
# Setup: # Setup:
@ -209,7 +145,7 @@ def test_Proxy2():
i = plugin() i = plugin()
p = cls(base, i) p = cls(base, i)
assert read_only(p, 'base') is base assert read_only(p, 'base') is base
assert read_only(p, 'name') is 'user_add' assert read_only(p, 'name') == 'user_add'
assert list(p) == sorted(base.public) assert list(p) == sorted(base.public)
# Test normal methods: # Test normal methods:
@ -230,11 +166,22 @@ def test_Proxy2():
# Test name_attr='name' kw arg # Test name_attr='name' kw arg
i = plugin() i = plugin()
p = cls(base, i, 'attr_name')
assert read_only(p, 'name') == 'add'
# Test _clone():
i = plugin()
p = cls(base, i) p = cls(base, i)
assert read_only(p, 'name') == 'user_add'
c = p._clone('attr_name')
assert isinstance(c, cls)
assert read_only(c, 'name') == 'add'
assert c is not p
assert c('whoever') == p('whoever')
def test_NameSpace2(): def test_NameSpace():
cls = plugable.NameSpace2 cls = plugable.NameSpace
assert issubclass(cls, plugable.ReadOnly) assert issubclass(cls, plugable.ReadOnly)
class base(object): class base(object):
@ -254,7 +201,7 @@ def test_NameSpace2():
def get_proxies(n): def get_proxies(n):
for i in xrange(n): for i in xrange(n):
yield plugable.Proxy2(base, plugin(get_name(i))) yield plugable.Proxy(base, plugin(get_name(i)))
cnt = 20 cnt = 20
ns = cls(get_proxies(cnt)) ns = cls(get_proxies(cnt))
@ -265,7 +212,7 @@ def test_NameSpace2():
# Test __iter__ # Test __iter__
i = None i = None
for (i, proxy) in enumerate(ns): for (i, proxy) in enumerate(ns):
assert type(proxy) is plugable.Proxy2 assert type(proxy) is plugable.Proxy
assert proxy.name == get_name(i) assert proxy.name == get_name(i)
assert i == cnt - 1 assert i == cnt - 1
@ -276,7 +223,7 @@ def test_NameSpace2():
assert name in ns assert name in ns
proxy = ns[name] proxy = ns[name]
assert proxy.name == name assert proxy.name == name
assert type(proxy) is plugable.Proxy2 assert type(proxy) is plugable.Proxy
assert proxy in proxies assert proxy in proxies
assert read_only(ns, name) is proxy assert read_only(ns, name) is proxy
@ -291,8 +238,6 @@ def test_NameSpace2():
no_set(ns, name) no_set(ns, name)
def test_Registrar(): def test_Registrar():
class Base1(object): class Base1(object):
pass pass
@ -404,72 +349,6 @@ def test_Registrar():
assert r[base.__name__] == d assert r[base.__name__] == d
def test_NameSpace():
assert issubclass(plugable.NameSpace, plugable.ReadOnly)
class DummyProxy(object):
def __init__(self, name):
self.__name = name
def __get_name(self):
return self.__name
name = property(__get_name)
def __str__(self):
return plugable.to_cli(self.__name)
def get_name(i):
return 'noun_verb%d' % i
def get_cli(i):
return 'noun-verb%d' % i
def get_proxies(n):
for i in xrange(n):
yield DummyProxy(get_name(i))
cnt = 20
ns = plugable.NameSpace(get_proxies(cnt))
# Test __len__
assert len(ns) == cnt
# Test __iter__
i = None
for (i, item) in enumerate(ns):
assert type(item) is DummyProxy
assert item.name == get_name(i)
assert str(item) == get_cli(i)
assert i == cnt - 1
# Test __contains__, __getitem__, getattr():
for i in xrange(cnt):
name = get_name(i)
cli = get_cli(i)
assert name in ns
assert cli in ns
item = ns[name]
assert isinstance(item, DummyProxy)
assert item.name == name
assert str(item) == cli
assert ns[name] is item
assert ns[cli] is item
assert read_only(ns, name) is item
# Test dir():
assert set(get_name(i) for i in xrange(cnt)).issubset(set(dir(ns)))
# Test that KeyError, AttributeError is raised:
name = get_name(cnt)
cli = get_cli(cnt)
assert name not in ns
assert cli not in ns
raises(KeyError, getitem, ns, name)
raises(KeyError, getitem, ns, cli)
raises(AttributeError, getattr, ns, name)
no_set(ns, name)
def test_API(): def test_API():
assert issubclass(plugable.API, plugable.ReadOnly) assert issubclass(plugable.API, plugable.ReadOnly)