17
17
"""Classes to provide name-to-object registry-like support."""
20
class _ObjectGetter(object):
21
"""Hang onto an object, and return it on request.
23
This is used by Registry to make plain objects function similarly
24
to lazily imported objects.
26
Objects can be any sort of python object (class, function, module,
32
def __init__(self, obj):
36
"""Get the object that was saved at creation time"""
40
class _LazyObjectGetter(_ObjectGetter):
41
"""Keep a record of a future object, and on request load it."""
43
__slots__ = ['_module_name', '_member_name', '_imported']
45
def __init__(self, module_name, member_name):
46
self._module_name = module_name
47
self._member_name = member_name
48
self._imported = False
49
super(_LazyObjectGetter, self).__init__(None)
52
"""Get the referenced object.
54
If not imported yet, this will import the requested module.
55
Further requests will just return the already imported object.
57
if not self._imported:
59
return super(_LazyObjectGetter, self).get_obj()
62
obj = __import__(self._module_name, globals(), locals(),
65
obj = getattr(obj, member_name)
20
70
class Registry(object):
21
71
"""A class that registers objects to a name.
33
83
self._help_dict = {}
34
84
self._info_dict = {}
36
def register(self, key, object, help=None, info=None,
86
def register(self, key, obj, help=None, info=None,
37
87
override_existing=False):
38
88
"""Register a new object to a name.
40
90
:param key: This is the key to use to request the object later.
41
:param object: The object to register.
91
:param obj: The object to register.
42
92
:param help: Help text for this entry. This may be a string or
43
93
a callable. If it is a callable, it should take two
44
94
parameters, this registry and the key that the help was
53
103
if not override_existing:
54
104
if key in self._dict:
55
105
raise KeyError('Key %r already registered' % key)
56
self._dict[key] = (False, object)
106
self._dict[key] = _ObjectGetter(obj)
57
107
self._add_help_and_info(key, help=help, info=info)
59
109
def register_lazy(self, key, module_name, member_name,
74
124
if not override_existing:
75
125
if key in self._dict:
76
126
raise KeyError('Key %r already registered' % key)
77
self._dict[key] = (True, (module_name, member_name))
127
self._dict[key] = _LazyObjectGetter(module_name, member_name)
78
128
self._add_help_and_info(key, help=help, info=info)
80
130
def _add_help_and_info(self, key, help=None, info=None):
96
146
:return: The previously registered object.
98
return self._get_one(self._get_key_or_default(key))
148
return self._dict[self._get_key_or_default(key)].get_obj()
100
150
def _get_key_or_default(self, key=None):
101
151
"""Return either 'key' or the default key if key is None"""
107
157
return self.default_key
109
def _get_one(self, key):
110
"""Attempt to return a single entry.
112
This will import the entry if it is lazy, and replace the registry
113
with the imported object.
115
This may raise KeyError if the given key doesn't exist, or ImportError
118
is_lazy, info_or_object = self._dict[key]
120
# We have a real object to return
121
return info_or_object
123
module_name, member_name = info_or_object
124
obj = __import__(module_name, globals(), locals(), [member_name])
126
obj = getattr(obj, member_name)
127
self._dict[key] = (False, obj)
130
159
def get_help(self, key=None):
131
160
"""Get the help text associated with the given key"""
132
161
the_help = self._help_dict[self._get_key_or_default(key)]
153
182
return sorted(self._dict.keys())
155
184
def iteritems(self):
156
for key in self._dict.iterkeys():
157
yield key, self._get_one(key)
185
for key, getter in self._dict.iteritems():
186
yield key, getter.get_obj()
159
188
def _set_default_key(self, key):
160
189
if not self._dict.has_key(key):