~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lazy_import.py

  • Committer: John Arbash Meinel
  • Date: 2006-09-20 14:51:03 UTC
  • mfrom: (0.8.23 version_info)
  • mto: This revision was merged to the branch mainline in revision 2028.
  • Revision ID: john@arbash-meinel.com-20060920145103-02725c6d6c886040
[merge] version-info plugin, and cleanup for layout in bzr

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 Canonical Ltd
 
1
# Copyright (C) 2006 by Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
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
16
16
 
17
17
"""Functionality to create lazy evaluation objects.
18
18
 
40
40
    to inherit from them).
41
41
"""
42
42
 
 
43
import re
 
44
import sys
 
45
 
 
46
from bzrlib import (
 
47
    errors,
 
48
    )
 
49
 
43
50
 
44
51
class ScopeReplacer(object):
45
52
    """A lazy object that will replace itself in the appropriate scope.
48
55
    needed.
49
56
    """
50
57
 
51
 
    __slots__ = ('_scope', '_factory', '_name', '_real_obj')
52
 
 
53
 
    # Setting this to True will allow you to do x = y, and still access members
54
 
    # from both variables. This should not normally be enabled, but is useful
55
 
    # when building documentation.
56
 
    _should_proxy = False
 
58
    __slots__ = ('_scope', '_factory', '_name')
57
59
 
58
60
    def __init__(self, scope, factory, name):
59
61
        """Create a temporary object in the specified scope.
64
66
            It will be passed (self, scope, name)
65
67
        :param name: The variable name in the given scope.
66
68
        """
67
 
        object.__setattr__(self, '_scope', scope)
68
 
        object.__setattr__(self, '_factory', factory)
69
 
        object.__setattr__(self, '_name', name)
70
 
        object.__setattr__(self, '_real_obj', None)
 
69
        self._scope = scope
 
70
        self._factory = factory
 
71
        self._name = name
71
72
        scope[name] = self
72
73
 
73
74
    def _replace(self):
87
88
                          " to another variable?",
88
89
                extra=e)
89
90
        obj = factory(self, scope, name)
90
 
        if ScopeReplacer._should_proxy:
91
 
            object.__setattr__(self, '_real_obj', obj)
92
91
        scope[name] = obj
93
92
        return obj
94
93
 
100
99
        # del self._name
101
100
 
102
101
    def __getattribute__(self, attr):
103
 
        obj = object.__getattribute__(self, '_real_obj')
104
 
        if obj is None:
105
 
            _replace = object.__getattribute__(self, '_replace')
106
 
            obj = _replace()
107
 
            _cleanup = object.__getattribute__(self, '_cleanup')
108
 
            _cleanup()
 
102
        _replace = object.__getattribute__(self, '_replace')
 
103
        obj = _replace()
 
104
        _cleanup = object.__getattribute__(self, '_cleanup')
 
105
        _cleanup()
109
106
        return getattr(obj, attr)
110
107
 
111
 
    def __setattr__(self, attr, value):
112
 
        obj = object.__getattribute__(self, '_real_obj')
113
 
        if obj is None:
114
 
            _replace = object.__getattribute__(self, '_replace')
115
 
            obj = _replace()
116
 
            _cleanup = object.__getattribute__(self, '_cleanup')
117
 
            _cleanup()
118
 
        return setattr(obj, attr, value)
119
 
 
120
108
    def __call__(self, *args, **kwargs):
121
109
        _replace = object.__getattribute__(self, '_replace')
122
110
        obj = _replace()
149
137
 
150
138
        :param scope: The scope that objects should be imported into.
151
139
            Typically this is globals()
152
 
        :param name: The variable name. Often this is the same as the
 
140
        :param name: The variable name. Often this is the same as the 
153
141
            module_path. 'bzrlib'
154
142
        :param module_path: A list for the fully specified module path
155
143
            ['bzrlib', 'foo', 'bar']
157
145
            None, indicating the module is being imported.
158
146
        :param children: Children entries to be imported later.
159
147
            This should be a map of children specifications.
160
 
            {'foo':(['bzrlib', 'foo'], None,
 
148
            {'foo':(['bzrlib', 'foo'], None, 
161
149
                {'bar':(['bzrlib', 'foo', 'bar'], None {})})
162
150
            }
163
151
        Examples:
170
158
            from foo import bar, baz would get translated into 2 import
171
159
            requests. On for 'name=bar' and one for 'name=baz'
172
160
        """
173
 
        if (member is not None) and children:
174
 
            raise ValueError('Cannot supply both a member and children')
 
161
        if member is not None:
 
162
            assert not children, \
 
163
                'Cannot supply both a member and children'
175
164
 
176
 
        object.__setattr__(self, '_import_replacer_children', children)
177
 
        object.__setattr__(self, '_member', member)
178
 
        object.__setattr__(self, '_module_path', module_path)
 
165
        self._import_replacer_children = children
 
166
        self._member = member
 
167
        self._module_path = module_path
179
168
 
180
169
        # Indirecting through __class__ so that children can
181
170
        # override _import (especially our instrumented version)
259
248
 
260
249
        :param import_str: The import string to process
261
250
        """
262
 
        if not import_str.startswith('import '):
263
 
            raise ValueError('bad import string %r' % (import_str,))
 
251
        assert import_str.startswith('import ')
264
252
        import_str = import_str[len('import '):]
265
253
 
266
254
        for path in import_str.split(','):
305
293
 
306
294
        :param from_str: The import string to process
307
295
        """
308
 
        if not from_str.startswith('from '):
309
 
            raise ValueError('bad from/import %r' % from_str)
 
296
        assert from_str.startswith('from ')
310
297
        from_str = from_str[len('from '):]
311
298
 
312
299
        from_module, import_list = from_str.split(' import ')
390
377
    # This is just a helper around ImportProcessor.lazy_import
391
378
    proc = ImportProcessor(lazy_import_class=lazy_import_class)
392
379
    return proc.lazy_import(scope, text)
393
 
 
394
 
 
395
 
# The only module that this module depends on is 'bzrlib.errors'. But it
396
 
# can actually be imported lazily, since we only need it if there is a
397
 
# problem.
398
 
 
399
 
lazy_import(globals(), """
400
 
from bzrlib import errors
401
 
""")