13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
"""Classes to provide name-to-object registry-like support."""
19
from __future__ import absolute_import
21
from .pyutils import get_named_object
23
from .sixish import viewitems
26
20
class _ObjectGetter(object):
27
21
"""Maintain a reference to an object, and return the object on request.
73
58
return the imported object.
75
60
if not self._imported:
76
self._obj = get_named_object(self._module_name, self._member_name)
78
62
return super(_LazyObjectGetter, self).get_obj()
81
return "<%s.%s object at %x, module=%r attribute=%r imported=%r>" % (
82
self.__class__.__module__, self.__class__.__name__, id(self),
83
self._module_name, self._member_name, self._imported)
65
obj = __import__(self._module_name, globals(), locals(),
68
obj = getattr(obj, self._member_name)
86
73
class Registry(object):
104
91
self._default_key = None
105
92
# Map from key => (is_lazy, info)
108
94
self._help_dict = {}
109
95
self._info_dict = {}
112
"""Return a set of the format names which are aliases."""
113
return dict(viewitems(self._aliases))
117
for alias, target in viewitems(self._aliases):
118
ret.setdefault(target, []).append(alias)
121
97
def register(self, key, obj, help=None, info=None,
122
98
override_existing=False):
123
99
"""Register a new object to a name.
126
102
:param obj: The object to register.
127
103
:param help: Help text for this entry. This may be a string or
128
104
a callable. If it is a callable, it should take two
129
parameters (registry, key): this registry and the key that
105
parameters (registry, key): this registry and the key that
130
106
the help was registered under.
131
107
:param info: More information for this entry. Registry.get_info()
132
108
can be used to get this information. Registry treats this as an
146
122
override_existing=False):
147
123
"""Register a new object to be loaded on request.
149
:param key: This is the key to use to request the object later.
150
125
:param module_name: The python path to the module. Such as 'os.path'.
151
:param member_name: The member of the module to return. If empty or
126
:param member_name: The member of the module to return. If empty or
152
127
None, get() will return the module itself.
153
128
:param help: Help text for this entry. This may be a string or
155
:param info: More information for this entry. Registry.get_info()
156
can be used to get this information. Registry treats this as an
157
opaque storage location (it is defined by the caller).
130
:param info: More information for this entry. Registry
158
131
:param override_existing: If True, replace the existing object
159
132
with the new one. If False, if there is already something
160
133
registered with the same key, raise a KeyError
165
138
self._dict[key] = _LazyObjectGetter(module_name, member_name)
166
139
self._add_help_and_info(key, help=help, info=info)
168
def register_alias(self, key, target, info=None):
169
"""Register an alias.
171
:param key: Alias name
172
:param target: Target key name
174
if key in self._dict and key not in self._aliases:
175
raise KeyError('Key %r already registered and not an alias' % key)
176
self._dict[key] = self._dict[target]
177
self._aliases[key] = target
179
info = self._info_dict[target]
180
self._add_help_and_info(key, help=self._help_dict[target], info=info)
182
141
def _add_help_and_info(self, key, help=None, info=None):
183
142
"""Add the help and information about this key"""
184
143
self._help_dict[key] = help
188
147
"""Return the object register()'ed to the given key.
190
149
May raise ImportError if the object was registered lazily and
191
there are any problems, or AttributeError if the module does not
150
there are any problems, or AttributeError if the module does not
192
151
have the supplied member.
194
153
:param key: The key to obtain the object for. If no object has been
204
163
return self._dict[self._get_key_or_default(key)].get_obj()
206
def _get_module(self, key):
207
"""Return the module the object will be or was loaded from.
209
:param key: The key to obtain the module for.
210
:return: The name of the module
212
return self._dict[key].get_module()
214
def get_prefix(self, fullname):
215
"""Return an object whose key is a prefix of the supplied value.
217
:fullname: The name to find a prefix for
218
:return: a tuple of (object, remainder), where the remainder is the
219
portion of the name that did not match the key.
221
for key in self.keys():
222
if fullname.startswith(key):
223
return self.get(key), fullname[len(key):]
225
165
def _get_key_or_default(self, key=None):
226
166
"""Return either 'key' or the default key if key is None"""
227
167
if key is not None:
256
196
"""Get a list of registered entries"""
257
return sorted(self._dict)
197
return sorted(self._dict.keys())
259
199
def iteritems(self):
260
for key in self._dict:
261
yield key, self._dict[key].get_obj()
264
# We should not use the iteritems() implementation below (see bug
266
return [(key, self._dict[key].get_obj()) for key in self.keys()]
200
for key, getter in self._dict.iteritems():
201
yield key, getter.get_obj()
268
203
def _set_default_key(self, key):
269
if key not in self._dict:
204
if not self._dict.has_key(key):
270
205
raise KeyError('No object registered under key %s.' % key)
272
207
self._default_key = key
277
212
default_key = property(_get_default_key, _set_default_key,
278
213
doc="Current value of the default key."
279
214
" Can be set to any existing key.")
282
class FormatRegistry(Registry):
283
"""Registry specialised for handling formats."""
285
def __init__(self, other_registry=None):
286
Registry.__init__(self)
287
self._other_registry = other_registry
289
def register(self, key, obj, help=None, info=None,
290
override_existing=False):
291
Registry.register(self, key, obj, help=help, info=info,
292
override_existing=override_existing)
293
if self._other_registry is not None:
294
self._other_registry.register(key, obj, help=help,
295
info=info, override_existing=override_existing)
297
def register_lazy(self, key, module_name, member_name,
298
help=None, info=None,
299
override_existing=False):
300
# Overridden to allow capturing registrations to two seperate
301
# registries in a single call.
302
Registry.register_lazy(self, key, module_name, member_name,
303
help=help, info=info, override_existing=override_existing)
304
if self._other_registry is not None:
305
self._other_registry.register_lazy(key, module_name, member_name,
306
help=help, info=info, override_existing=override_existing)
308
def remove(self, key):
309
Registry.remove(self, key)
310
if self._other_registry is not None:
311
self._other_registry.remove(key)
313
def get(self, format_string):
314
r = Registry.get(self, format_string)