diff --git a/util/adapter.py b/util/adapter.py index 70c196d..d34a54e 100644 --- a/util/adapter.py +++ b/util/adapter.py @@ -56,3 +56,29 @@ class AdapterFactory(object): if adapter is None: return None return adapter(obj) + + +# self-registering adapters + +adapters = AdapterFactory() + + +class AdapterType(type): + """ To be used as metaclass for self-registering adapters. + """ + + def __init__(cls, name, bases, cdict): + super(AdapterType, cls).__init__(name, bases, cdict) + info = list(cdict.get('__adapterinfo__', (adapters, object, ''))) + if len(info) < 2: + info.append(object) + if len(info) < 3: + info.append('') + factory, adapted, name = info + factory.register(cls, adapted, name) + + +class AdapterBase: + + __metaclass__ = AdapterType + diff --git a/util/adapter.txt b/util/adapter.txt index 3afdd1f..4553d36 100644 --- a/util/adapter.txt +++ b/util/adapter.txt @@ -7,6 +7,10 @@ $Id$ To work with adapters we need at least two classes, one for objects that we want to adapt to (the adapter's `context`) and one for the adapters. + +Adapter Classes and Factories +============================= + >>> class Content(object): ... pass @@ -100,3 +104,22 @@ example above. >>> c2 + +Self-registering Adapters +========================= + + >>> from cybertools.util.adapter import adapters, AdapterBase + >>> stateful = AdapterFactory() + + >>> class StateAdapter(AdapterBase): + ... __adapterinfo__ = stateful, Content + ... def __init__(self, context): + ... self.context = context + ... def setState(self, state): + ... self.context._state = state + ... def getState(self): + ... return getattr(self.context, '_state', 'initial') + + >>> stateful._registry + {(, ''): } +