~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lazy_import.py

  • Committer: Aaron Bentley
  • Date: 2006-09-29 18:58:43 UTC
  • mto: This revision was merged to the branch mainline in revision 2127.
  • Revision ID: abentley@panoramicfeedback.com-20060929185843-6841128d849c46a2
Get page generation working

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 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 obj is self:
91
 
            raise errors.IllegalUseOfScopeReplacer(name, msg="Object tried"
92
 
                " to replace itself, check it's not using its own scope.")
93
 
        if ScopeReplacer._should_proxy:
94
 
            object.__setattr__(self, '_real_obj', obj)
95
91
        scope[name] = obj
96
92
        return obj
97
93
 
103
99
        # del self._name
104
100
 
105
101
    def __getattribute__(self, attr):
106
 
        obj = object.__getattribute__(self, '_real_obj')
107
 
        if obj is None:
108
 
            _replace = object.__getattribute__(self, '_replace')
109
 
            obj = _replace()
110
 
            _cleanup = object.__getattribute__(self, '_cleanup')
111
 
            _cleanup()
 
102
        _replace = object.__getattribute__(self, '_replace')
 
103
        obj = _replace()
 
104
        _cleanup = object.__getattribute__(self, '_cleanup')
 
105
        _cleanup()
112
106
        return getattr(obj, attr)
113
107
 
114
 
    def __setattr__(self, attr, value):
115
 
        obj = object.__getattribute__(self, '_real_obj')
116
 
        if obj is None:
117
 
            _replace = object.__getattribute__(self, '_replace')
118
 
            obj = _replace()
119
 
            _cleanup = object.__getattribute__(self, '_cleanup')
120
 
            _cleanup()
121
 
        return setattr(obj, attr, value)
122
 
 
123
108
    def __call__(self, *args, **kwargs):
124
109
        _replace = object.__getattribute__(self, '_replace')
125
110
        obj = _replace()
152
137
 
153
138
        :param scope: The scope that objects should be imported into.
154
139
            Typically this is globals()
155
 
        :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 
156
141
            module_path. 'bzrlib'
157
142
        :param module_path: A list for the fully specified module path
158
143
            ['bzrlib', 'foo', 'bar']
160
145
            None, indicating the module is being imported.
161
146
        :param children: Children entries to be imported later.
162
147
            This should be a map of children specifications.
163
 
            {'foo':(['bzrlib', 'foo'], None,
 
148
            {'foo':(['bzrlib', 'foo'], None, 
164
149
                {'bar':(['bzrlib', 'foo', 'bar'], None {})})
165
150
            }
166
151
        Examples:
173
158
            from foo import bar, baz would get translated into 2 import
174
159
            requests. On for 'name=bar' and one for 'name=baz'
175
160
        """
176
 
        if (member is not None) and children:
177
 
            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'
178
164
 
179
 
        object.__setattr__(self, '_import_replacer_children', children)
180
 
        object.__setattr__(self, '_member', member)
181
 
        object.__setattr__(self, '_module_path', module_path)
 
165
        self._import_replacer_children = children
 
166
        self._member = member
 
167
        self._module_path = module_path
182
168
 
183
169
        # Indirecting through __class__ so that children can
184
170
        # override _import (especially our instrumented version)
262
248
 
263
249
        :param import_str: The import string to process
264
250
        """
265
 
        if not import_str.startswith('import '):
266
 
            raise ValueError('bad import string %r' % (import_str,))
 
251
        assert import_str.startswith('import ')
267
252
        import_str = import_str[len('import '):]
268
253
 
269
254
        for path in import_str.split(','):
308
293
 
309
294
        :param from_str: The import string to process
310
295
        """
311
 
        if not from_str.startswith('from '):
312
 
            raise ValueError('bad from/import %r' % from_str)
 
296
        assert from_str.startswith('from ')
313
297
        from_str = from_str[len('from '):]
314
298
 
315
299
        from_module, import_list = from_str.split(' import ')
393
377
    # This is just a helper around ImportProcessor.lazy_import
394
378
    proc = ImportProcessor(lazy_import_class=lazy_import_class)
395
379
    return proc.lazy_import(scope, text)
396
 
 
397
 
 
398
 
# The only module that this module depends on is 'bzrlib.errors'. But it
399
 
# can actually be imported lazily, since we only need it if there is a
400
 
# problem.
401
 
 
402
 
lazy_import(globals(), """
403
 
from bzrlib import errors
404
 
""")