enthought/apptools — pull request #7 by rkern (2013-03-13 22:35:50+00:00)
Title: ENH: A fancypants registry to map types to objects.

We frequently want to map types/classes to certain kinds of objects. For example, associating views/presenters/controllers/`ModelViews` to model classes. This PR adds a generic implementation of just such a registry, bringing together features from all of the various reimplementations I have done in multiple projects.

```
from apptools.type_registry.api import TypeRegistry
from apptools.type_registry.tests.dummies import A, B, C
# Inheritance: A->B->C

reg = TypeRegistry()
# Push an object for the class A using the class object.
reg.push(A, 'A')
# Look up by the class.
assert reg.lookup_by_type(A) == 'A'
# Or from an instance.
assert reg.lookup(A()) == 'A'
# Inheritance hierarchies are climbed:
assert reg.lookup_by_type(B) == 'A'
# But stop at the first one.
reg.push(B, 'B')
assert reg.lookup_by_type(C) == 'B'

# Types can be specified by '__module__:__name__' so objects can be registered
# before even importing the types in question.
reg = TypeRegistry()
reg.push('dummies:A', 'A')
assert reg.lookup_by_type(C) == 'A'

# ABCs are checked, though every registered ABC must be checked if a concrete type
# cannot be found since the ABCs do not appear in the looked-up type's MRO.
from apptools.type_registry.tests.dummies import Abstract, Concrete
reg.push_abc(Abstract, 'Abstract')
assert Abstract not in Concrete.mro()
assert reg.lookup_by_type(Concrete) == 'Abstract'

# Each registry entry is a stack that can be pushed and popped.
reg = TypeRegistry()
reg.push(A, 'A1')
reg.push(A, 'A2')
assert reg.lookup_by_type(A) == 'A2'
assert reg.pop(A) == 'A2'
assert reg.lookup_by_type(A) == 'A1'

# For when you want to specify the registered objects as '__module__:__name__' strings
# as well as the types, use LazyRegistry. They will be imported on-demand. This lets
# you contribute these mappings in Envisage Plugin ExtensionPoints without needing to
# have loaded either the types or the registered objects.
from apptools.type_registry.api import LazyRegistry
reg = LazyRegistry()
reg.push('dummies:A', 'apptools.type_registry.api:LazyRegistry')
assert reg.lookup_by_type(A) is LazyRegistry
```