Rev 2400: An attempt to allow disabiling lazy imports, and tracking down all the in http://bzr.arbash-meinel.com/branches/bzr/0.16-dev/doc-cleanup

John Arbash Meinel john at arbash-meinel.com
Wed Apr 4 22:26:26 BST 2007


At http://bzr.arbash-meinel.com/branches/bzr/0.16-dev/doc-cleanup

------------------------------------------------------------
revno: 2400
revision-id: john at arbash-meinel.com-20070404212608-bejliupz7iil1uhq
parent: pqm at pqm.ubuntu.com-20070404140524-48cdc6512763399e
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: doc-cleanup
timestamp: Wed 2007-04-04 16:26:08 -0500
message:
  An attempt to allow disabiling lazy imports, and tracking down all the
  circular imports that depended on them.
  However, after 'fixing' circular imports, it seems that lazy importing fails.
  (bzrlib.branch seems to be an invalid lazy object).
  Just didn't want to lose the work, but this doesn't seem to be the way to go.
modified:
  bzrlib/bzrdir.py               bzrdir.py-20060131065624-156dfea39c4387cb
  bzrlib/conflicts.py            conflicts.py-20051001061850-78ef952ba63d2b42
  bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
  bzrlib/inventory.py            inventory.py-20050309040759-6648b84ca2005b37
  bzrlib/lazy_import.py          lazy_import.py-20060910203832-f77c54gf3n232za0-1
  bzrlib/tests/test_lazy_import.py test_lazy_import.py-20060910203832-f77c54gf3n232za0-2
  bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
  bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
-------------- next part --------------
=== modified file 'bzrlib/bzrdir.py'
--- a/bzrlib/bzrdir.py	2007-04-01 06:19:16 +0000
+++ b/bzrlib/bzrdir.py	2007-04-04 21:26:08 +0000
@@ -38,7 +38,6 @@
 from stat import S_ISDIR
 import unittest
 
-import bzrlib
 from bzrlib import (
     errors,
     lockable_files,
@@ -50,8 +49,6 @@
     urlutils,
     xml4,
     xml5,
-    workingtree,
-    workingtree_4,
     )
 from bzrlib.osutils import (
     safe_unicode,
@@ -2141,6 +2138,8 @@
         else:
             # TODO: conversions of Branch and Tree should be done by
             # InterXFormat lookups
+            # Avoid circular imports
+            from bzrlib import workingtree, workingtree_4
             if (isinstance(tree, workingtree.WorkingTree3) and
                 not isinstance(tree, workingtree_4.WorkingTree4) and
                 isinstance(self.target_format.workingtree_format,

=== modified file 'bzrlib/conflicts.py'
--- a/bzrlib/conflicts.py	2007-03-06 15:36:36 +0000
+++ b/bzrlib/conflicts.py	2007-04-04 21:26:08 +0000
@@ -26,7 +26,6 @@
 import errno
 
 from bzrlib import (
-    builtins,
     commands,
     errors,
     osutils,
@@ -96,6 +95,8 @@
             tree = WorkingTree.open_containing('.')[0]
             resolve(tree)
         else:
+            # Avoid circular imports
+            from bzrlib import builtins
             tree, file_list = builtins.tree_files(file_list)
             if file_list is None:
                 un_resolved, resolved = tree.auto_resolve()

=== modified file 'bzrlib/errors.py'
--- a/bzrlib/errors.py	2007-04-01 06:19:16 +0000
+++ b/bzrlib/errors.py	2007-04-04 21:26:08 +0000
@@ -19,7 +19,6 @@
 
 
 from bzrlib import (
-    osutils,
     symbol_versioning,
     )
 from bzrlib.patches import (
@@ -1547,6 +1546,8 @@
     _fmt = "Could not move %(from_path)s%(operator)s %(to_path)s%(extra)s"
 
     def __init__(self, from_path='', to_path='', extra=None):
+        # Avoid circular imports
+        from bzrlib import osutils
         BzrError.__init__(self)
         if extra:
             self.extra = ': ' + str(extra)

=== modified file 'bzrlib/inventory.py'
--- a/bzrlib/inventory.py	2007-04-04 02:31:25 +0000
+++ b/bzrlib/inventory.py	2007-04-04 21:26:08 +0000
@@ -42,7 +42,6 @@
     generate_ids,
     osutils,
     symbol_versioning,
-    workingtree,
     )
 """)
 

=== modified file 'bzrlib/lazy_import.py'
--- a/bzrlib/lazy_import.py	2006-10-16 01:25:46 +0000
+++ b/bzrlib/lazy_import.py	2007-04-04 21:26:08 +0000
@@ -40,6 +40,8 @@
     to inherit from them).
 """
 
+import os
+
 
 class ScopeReplacer(object):
     """A lazy object that will replace itself in the appropriate scope.
@@ -48,7 +50,7 @@
     needed.
     """
 
-    __slots__ = ('_scope', '_factory', '_name')
+    __slots__ = ('_scope', '_factory', '_name', '_scope_name')
 
     def __init__(self, scope, factory, name):
         """Create a temporary object in the specified scope.
@@ -60,6 +62,13 @@
         :param name: The variable name in the given scope.
         """
         self._scope = scope
+        scope_name = getattr(scope, '__name__', None)
+        if scope_name is None:
+            try:
+                scope_name = scope['__name__']
+            except:
+                scope_name = '<unknown>'
+        self._scope_name = scope_name
         self._factory = factory
         self._name = name
         scope[name] = self
@@ -76,9 +85,11 @@
             # replaced would cause them to keep getting replaced
             # (only they are replacing the wrong variable). So we
             # make it forbidden, and try to give a good error.
+            from bzrlib import errors
+            scope_name = object.__getattribute__(self, '_scope_name')
             raise errors.IllegalUseOfScopeReplacer(
                 name, msg="Object already cleaned up, did you assign it"
-                          " to another variable?",
+                          " to another variable? %s" % (scope_name,),
                 extra=e)
         obj = factory(self, scope, name)
         scope[name] = obj
@@ -231,6 +242,7 @@
             elif line.startswith('from '):
                 self._convert_from_str(line)
             else:
+                from bzrlib import errors
                 raise errors.InvalidImportLine(line,
                     "doesn't start with 'import ' or 'from '")
 
@@ -256,6 +268,7 @@
                 name = as_hunks[1].strip()
                 module_path = as_hunks[0].strip().split('.')
                 if name in self.imports:
+                    from bzrlib import errors
                     raise errors.ImportNameCollision(name)
                 # No children available in 'import foo as bar'
                 self.imports[name] = (module_path, None, {})
@@ -307,6 +320,7 @@
             else:
                 name = module = path
             if name in self.imports:
+                from bzrlib import errors
                 raise errors.ImportNameCollision(name)
             self.imports[name] = (from_module_path, module, {})
 
@@ -340,10 +354,45 @@
                 else:
                     out.append(line.replace('(', '').replace(')', ''))
         if cur is not None:
+            from bzrlib import errors
             raise errors.InvalidImportLine(cur, 'Unmatched parenthesis')
         return out
 
 
+class DirectImporter(object):
+    """A replacement for ImportReplacer which imports immediately.
+
+    This is useful when doing things like analyzing code for documentation,
+    etc.
+    """
+
+    def __init__(self, scope, name, module_path, member=None, children={}):
+        scope[name] = self._do_import(scope, module_path, member, children)
+
+    def _do_import(self, scope, module_path, member, children):
+        module_python_path = '.'.join(module_path)
+        try:
+            if member is not None:
+                module = __import__(module_python_path, scope, scope, [member])
+                return getattr(module, member)
+            else:
+                module = __import__(module_python_path, scope, scope, [])
+                for path in module_path[1:]:
+                    module = getattr(module, path)
+        except ImportError, e:
+            print 'Failed to import: %s' % (e,)
+            raise
+
+        # Prepare the children to be imported
+        for child_name, (child_path, child_member, grandchildren) in \
+                children.iteritems():
+            # instantiated. (This helps with instrumented tests)
+            self.__class__(module.__dict__, name=child_name,
+                module_path=child_path, member=child_member,
+                children=grandchildren)
+        return module
+
+
 def lazy_import(scope, text, lazy_import_class=None):
     """Create lazy imports for all of the imports in text.
 
@@ -368,6 +417,8 @@
     have been used.
     """
     # This is just a helper around ImportProcessor.lazy_import
+    if disable_lazy and lazy_import_class is None:
+        lazy_import_class = DirectImporter
     proc = ImportProcessor(lazy_import_class=lazy_import_class)
     return proc.lazy_import(scope, text)
 
@@ -376,6 +427,9 @@
 # can actually be imported lazily, since we only need it if there is a
 # problem.
 
-lazy_import(globals(), """
-from bzrlib import errors
-""")
+disable_lazy = bool(os.environ.get('BZR_NO_LAZY_IMPORTS', False))
+
+
+# lazy_import(globals(), """
+# from bzrlib import errors
+# """)

=== modified file 'bzrlib/tests/test_lazy_import.py'
--- a/bzrlib/tests/test_lazy_import.py	2006-10-11 23:08:27 +0000
+++ b/bzrlib/tests/test_lazy_import.py	2007-04-04 21:26:08 +0000
@@ -1041,3 +1041,35 @@
                           ('_import', 'root8'),
                           ('import', self.root_name, []),
                          ], self.actions)
+
+    def test_direct_import(self):
+        """We can replace the lazy class with one that imports directly."""
+        try:
+            root9
+        except NameError:
+            pass # root9 should not be defined yet
+        else:
+            self.fail('root9 was not supposed to exist yet')
+        lazy_import.lazy_import(globals(),
+                                'import %s as root9' % (self.root_name,),
+                                lazy_import_class=lazy_import.DirectImporter)
+
+        # At this point root9 should be the real module, how to test for that?
+        self.assertEqual(1, root9.var1)
+        self.assertEqual(1, root9.func1(1))
+
+    def test_direct_import_deep(self):
+        try:
+            submoda8
+        except NameError:
+            pass # submoda8 should not be defined yet
+        else:
+            self.fail('submoda8 was not supposed to exist yet')
+        text = """\
+import %(root_name)s.%(sub_name)s.%(submoda_name)s as submoda8
+""" % self.__dict__
+        proc = lazy_import.ImportProcessor(lazy_import.DirectImporter)
+        proc.lazy_import(scope=globals(), text=text)
+
+        # At this point we should have a direct import of submoda8
+        self.assertEqual(4, submoda8.var4)

=== modified file 'bzrlib/workingtree.py'
--- a/bzrlib/workingtree.py	2007-04-01 06:19:16 +0000
+++ b/bzrlib/workingtree.py	2007-04-04 21:26:08 +0000
@@ -79,7 +79,6 @@
 import bzrlib.branch
 from bzrlib.transport import get_transport
 import bzrlib.ui
-from bzrlib.workingtree_4 import WorkingTreeFormat4
 """)
 
 from bzrlib import symbol_versioning
@@ -2701,6 +2700,7 @@
         return self.get_format_string()
 
 
+from bzrlib.workingtree_4 import WorkingTreeFormat4
 __default_format = WorkingTreeFormat4()
 WorkingTreeFormat.register_format(__default_format)
 WorkingTreeFormat.register_format(WorkingTreeFormat3())

=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py	2007-03-31 03:19:39 +0000
+++ b/bzrlib/workingtree_4.py	2007-04-04 21:26:08 +0000
@@ -29,69 +29,39 @@
 from bzrlib.lazy_import import lazy_import
 lazy_import(globals(), """
 from bisect import bisect_left
-import collections
-from copy import deepcopy
 import errno
-import itertools
-import operator
 import stat
-from time import time
-import warnings
 
 import bzrlib
 from bzrlib import (
     bzrdir,
     cache_utf8,
-    conflicts as _mod_conflicts,
-    delta,
     dirstate,
     errors,
     generate_ids,
-    globbing,
-    hashcache,
-    ignores,
-    merge,
     osutils,
     revisiontree,
-    textui,
     transform,
-    urlutils,
-    xml5,
-    xml6,
     )
 import bzrlib.branch
-from bzrlib.transport import get_transport
-import bzrlib.ui
 """)
 
-from bzrlib import symbol_versioning
 from bzrlib.decorators import needs_read_lock, needs_write_lock
-from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID, entry_factory
-from bzrlib.lockable_files import LockableFiles, TransportLock
-from bzrlib.lockdir import LockDir
-import bzrlib.mutabletree
+from bzrlib.inventory import Inventory, ROOT_ID, entry_factory
+from bzrlib.lockable_files import LockableFiles
 from bzrlib.mutabletree import needs_tree_write_lock
 from bzrlib.osutils import (
     file_kind,
     isdir,
-    normpath,
     pathjoin,
-    rand_chars,
     realpath,
     safe_unicode,
     splitpath,
     )
-from bzrlib.trace import mutter, note
+from bzrlib.trace import mutter
 from bzrlib.transport.local import LocalTransport
 from bzrlib.tree import InterTree
-from bzrlib.progress import DummyProgress, ProgressPhase
-from bzrlib.revision import NULL_REVISION, CURRENT_REVISION
-from bzrlib.rio import RioReader, rio_file, Stanza
-from bzrlib.symbol_versioning import (deprecated_passed,
-        deprecated_method,
-        deprecated_function,
-        DEPRECATED_PARAMETER,
-        )
+from bzrlib.revision import NULL_REVISION
 from bzrlib.tree import Tree
 from bzrlib.workingtree import WorkingTree, WorkingTree3, WorkingTreeFormat3
 
@@ -128,7 +98,6 @@
         """
         self._format = _format
         self.bzrdir = _bzrdir
-        from bzrlib.trace import note, mutter
         assert isinstance(basedir, basestring), \
             "base directory %r is not a string" % basedir
         basedir = safe_unicode(basedir)



More information about the bazaar-commits mailing list