from weakref import ref |
from weakref import ref |
import sys |
import sys |
|
|
__all__ = ['Role', 'ClassRole', 'roledict_for'] |
__all__ = ['Role', 'ClassRole', 'Registry', 'roledict_for'] |
|
|
_roledicts = {} |
_roledicts = {} |
|
|
|
|
class ClassRole(Role): |
class ClassRole(Role): |
"""Attachment/annotation for classes and types""" |
"""Attachment/annotation for classes and types""" |
|
__slots__ = () |
|
|
class __metaclass__(Role.__class__): |
class __metaclass__(Role.__class__): |
def __call__(cls, ob, *data): |
def __call__(cls, ob, *data): |
frame = sys._getframe(level) |
frame = sys._getframe(level) |
if kw: |
if kw: |
raise TypeError("Unexpected keyword arguments", kw) |
raise TypeError("Unexpected keyword arguments", kw) |
|
return cls.for_frame(frame, *args) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
decorate(classmethod) |
|
def for_frame(cls, frame, *args): |
a = frame.f_locals |
a = frame.f_locals |
role_key = cls.role_key(*args) |
role_key = cls.role_key(*args) |
try: |
try: |
decorate_class(ob.__decorate, frame=frame) |
decorate_class(ob.__decorate, frame=frame) |
return ob |
return ob |
|
|
|
|
decorate(classmethod) |
decorate(classmethod) |
def exists_for(cls, ob, *key): |
def exists_for(cls, ob, *key): |
"""Does an aspect of this type for the given key exist?""" |
"""Does an aspect of this type for the given key exist?""" |
|
|
|
|
|
|
|
class Registry(ClassRole, dict): |
|
"""ClassRole that's a dictionary with mro-based inheritance""" |
|
|
|
__slots__ = () |
|
|
|
def __new__(cls, subject): |
|
if cls is Registry: |
|
raise TypeError("You must subclass Registry to use it") |
|
return super(Registry, cls).__new__(cls) |
|
|
|
def __init__(self, subject): |
|
dict.__init__(self) |
|
super(Registry, self).__init__(subject) |
|
|
|
def created_for(self, cls): |
|
"""Inherit the contents of base classes""" |
|
try: |
|
mro = cls.__mro__[::-1] |
|
except AttributeError: |
|
mro = type(cls.__name__, (cls,object), {}).__mro__[1:][::-1] |
|
|
|
data = {} |
|
self.defined_in_class = dict(self) |
|
|
|
mytype = type(self) |
|
for base in mro[:-1]: |
|
data.update(mytype(base)) |
|
data.update(self) |
|
|
|
self.update(data) |
|
|
|
def set(self, key, value): |
|
if key in self and self[key]!=value: |
|
raise ValueError("%s[%r] already contains %r; can't set to %r" |
|
% (self.__class__.__name__, key, self[key], value) |
|
) |
|
self[key] = value |
|
|
|
|
|
|