~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lazy_import.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-03-16 16:58:03 UTC
  • mfrom: (3224.3.1 news-typo)
  • Revision ID: pqm@pqm.ubuntu.com-20080316165803-tisoc9mpob9z544o
(Matt Nordhoff) Trivial NEWS typo fix

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006 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
 
19
19
This includes waiting to import a module until it is actually used.
20
20
 
21
21
Most commonly, the 'lazy_import' function is used to import other modules
22
 
in an on-demand fashion. Typically use looks like::
23
 
 
 
22
in an on-demand fashion. Typically use looks like:
24
23
    from bzrlib.lazy_import import lazy_import
25
24
    lazy_import(globals(), '''
26
25
    from bzrlib import (
31
30
    import bzrlib.branch
32
31
    ''')
33
32
 
34
 
Then 'errors, osutils, branch' and 'bzrlib' will exist as lazy-loaded
35
 
objects which will be replaced with a real object on first use.
 
33
    Then 'errors, osutils, branch' and 'bzrlib' will exist as lazy-loaded
 
34
    objects which will be replaced with a real object on first use.
36
35
 
37
 
In general, it is best to only load modules in this way. This is because
38
 
it isn't safe to pass these variables to other functions before they
39
 
have been replaced. This is especially true for constants, sometimes
40
 
true for classes or functions (when used as a factory, or you want
41
 
to inherit from them).
 
36
    In general, it is best to only load modules in this way. This is because
 
37
    it isn't safe to pass these variables to other functions before they
 
38
    have been replaced. This is especially true for constants, sometimes
 
39
    true for classes or functions (when used as a factory, or you want
 
40
    to inherit from them).
42
41
"""
43
42
 
44
43
 
88
87
                          " to another variable?",
89
88
                extra=e)
90
89
        obj = factory(self, scope, name)
91
 
        if obj is self:
92
 
            raise errors.IllegalUseOfScopeReplacer(name, msg="Object tried"
93
 
                " to replace itself, check it's not using its own scope.")
94
90
        if ScopeReplacer._should_proxy:
95
91
            object.__setattr__(self, '_real_obj', obj)
96
92
        scope[name] = obj
98
94
 
99
95
    def _cleanup(self):
100
96
        """Stop holding on to all the extra stuff"""
101
 
        try:
102
 
            del self._factory
103
 
        except AttributeError:
104
 
            # Oops, we just lost a race with another caller of _cleanup.  Just
105
 
            # ignore it.
106
 
            pass
107
 
 
108
 
        try:
109
 
            del self._scope
110
 
        except AttributeError:
111
 
            # Another race loss.  See above.
112
 
            pass
113
 
 
 
97
        del self._factory
 
98
        del self._scope
114
99
        # We keep _name, so that we can report errors
115
100
        # del self._name
116
101
 
164
149
 
165
150
        :param scope: The scope that objects should be imported into.
166
151
            Typically this is globals()
167
 
        :param name: The variable name. Often this is the same as the
 
152
        :param name: The variable name. Often this is the same as the 
168
153
            module_path. 'bzrlib'
169
154
        :param module_path: A list for the fully specified module path
170
155
            ['bzrlib', 'foo', 'bar']
172
157
            None, indicating the module is being imported.
173
158
        :param children: Children entries to be imported later.
174
159
            This should be a map of children specifications.
175
 
            ::
176
 
            
177
 
                {'foo':(['bzrlib', 'foo'], None,
178
 
                    {'bar':(['bzrlib', 'foo', 'bar'], None {})})
179
 
                }
180
 
 
181
 
        Examples::
182
 
 
 
160
            {'foo':(['bzrlib', 'foo'], None, 
 
161
                {'bar':(['bzrlib', 'foo', 'bar'], None {})})
 
162
            }
 
163
        Examples:
183
164
            import foo => name='foo' module_path='foo',
184
165
                          member=None, children={}
185
166
            import foo.bar => name='foo' module_path='foo', member=None,
189
170
            from foo import bar, baz would get translated into 2 import
190
171
            requests. On for 'name=bar' and one for 'name=baz'
191
172
        """
192
 
        if (member is not None) and children:
193
 
            raise ValueError('Cannot supply both a member and children')
 
173
        if member is not None:
 
174
            assert not children, \
 
175
                'Cannot supply both a member and children'
194
176
 
195
177
        object.__setattr__(self, '_import_replacer_children', children)
196
178
        object.__setattr__(self, '_member', member)
278
260
 
279
261
        :param import_str: The import string to process
280
262
        """
281
 
        if not import_str.startswith('import '):
282
 
            raise ValueError('bad import string %r' % (import_str,))
 
263
        assert import_str.startswith('import ')
283
264
        import_str = import_str[len('import '):]
284
265
 
285
266
        for path in import_str.split(','):
324
305
 
325
306
        :param from_str: The import string to process
326
307
        """
327
 
        if not from_str.startswith('from '):
328
 
            raise ValueError('bad from/import %r' % from_str)
 
308
        assert from_str.startswith('from ')
329
309
        from_str = from_str[len('from '):]
330
310
 
331
311
        from_module, import_list = from_str.split(' import ')
386
366
def lazy_import(scope, text, lazy_import_class=None):
387
367
    """Create lazy imports for all of the imports in text.
388
368
 
389
 
    This is typically used as something like::
390
 
 
391
 
        from bzrlib.lazy_import import lazy_import
392
 
        lazy_import(globals(), '''
393
 
        from bzrlib import (
394
 
            foo,
395
 
            bar,
396
 
            baz,
397
 
            )
398
 
        import bzrlib.branch
399
 
        import bzrlib.transport
400
 
        ''')
 
369
    This is typically used as something like:
 
370
    from bzrlib.lazy_import import lazy_import
 
371
    lazy_import(globals(), '''
 
372
    from bzrlib import (
 
373
        foo,
 
374
        bar,
 
375
        baz,
 
376
        )
 
377
    import bzrlib.branch
 
378
    import bzrlib.transport
 
379
    ''')
401
380
 
402
381
    Then 'foo, bar, baz' and 'bzrlib' will exist as lazy-loaded
403
382
    objects which will be replaced with a real object on first use.