~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/registry.py

  • Committer: John Arbash Meinel
  • Date: 2006-09-27 22:40:45 UTC
  • mto: This revision was merged to the branch mainline in revision 2074.
  • Revision ID: john@arbash-meinel.com-20060927224045-1a4a59afa58632f0
Use helper objects to handle lazy importing

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
"""Classes to provide name-to-object registry-like support."""
18
18
 
19
19
 
 
20
class _ObjectGetter(object):
 
21
    """Hang onto an object, and return it on request.
 
22
 
 
23
    This is used by Registry to make plain objects function similarly
 
24
    to lazily imported objects.
 
25
 
 
26
    Objects can be any sort of python object (class, function, module,
 
27
    instance, etc)
 
28
    """
 
29
 
 
30
    __slots__ = ['_obj']
 
31
 
 
32
    def __init__(self, obj):
 
33
        self._obj = obj
 
34
 
 
35
    def get_obj(self):
 
36
        """Get the object that was saved at creation time"""
 
37
        return self._obj
 
38
 
 
39
 
 
40
class _LazyObjectGetter(_ObjectGetter):
 
41
    """Keep a record of a future object, and on request load it."""
 
42
 
 
43
    __slots__ = ['_module_name', '_member_name', '_imported']
 
44
 
 
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)
 
50
 
 
51
    def get_obj(self):
 
52
        """Get the referenced object.
 
53
 
 
54
        If not imported yet, this will import the requested module.
 
55
        Further requests will just return the already imported object.
 
56
        """
 
57
        if not self._imported:
 
58
            self._do_import()
 
59
        return super(_LazyObjectGetter, self).get_obj()
 
60
 
 
61
    def _do_import(self):
 
62
        obj = __import__(self._module_name, globals(), locals(),
 
63
                         [self._member_name])
 
64
        if member_name:
 
65
            obj = getattr(obj, member_name)
 
66
        self._obj = obj
 
67
        self._imported = True
 
68
 
 
69
 
20
70
class Registry(object):
21
71
    """A class that registers objects to a name.
22
72
 
33
83
        self._help_dict = {}
34
84
        self._info_dict = {}
35
85
 
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.
39
89
 
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)
58
108
 
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)
79
129
 
80
130
    def _add_help_and_info(self, key, help=None, info=None):
95
145
            raised.
96
146
        :return: The previously registered object.
97
147
        """
98
 
        return self._get_one(self._get_key_or_default(key))
 
148
        return self._dict[self._get_key_or_default(key)].get_obj()
99
149
 
100
150
    def _get_key_or_default(self, key=None):
101
151
        """Return either 'key' or the default key if key is None"""
106
156
        else:
107
157
            return self.default_key
108
158
 
109
 
    def _get_one(self, key):
110
 
        """Attempt to return a single entry.
111
 
 
112
 
        This will import the entry if it is lazy, and replace the registry
113
 
        with the imported object.
114
 
 
115
 
        This may raise KeyError if the given key doesn't exist, or ImportError
116
 
        or AttributeError.
117
 
        """
118
 
        is_lazy, info_or_object = self._dict[key]
119
 
        if not is_lazy:
120
 
            # We have a real object to return
121
 
            return info_or_object
122
 
 
123
 
        module_name, member_name = info_or_object
124
 
        obj = __import__(module_name, globals(), locals(), [member_name])
125
 
        if member_name:
126
 
            obj = getattr(obj, member_name)
127
 
        self._dict[key] = (False, obj)
128
 
        return obj
129
 
 
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())
154
183
 
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()
158
187
 
159
188
    def _set_default_key(self, key):
160
189
        if not self._dict.has_key(key):