]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
patch from 0.7: Adjusted the "importlater" mechanism, which is
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 21 Sep 2011 21:00:44 +0000 (17:00 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 21 Sep 2011 21:00:44 +0000 (17:00 -0400)
used internally to resolve import cycles,
such that the usage of __import__ is completed
when the import of sqlalchemy or sqlalchemy.orm
is done, thereby avoiding any usage of __import__
after the application starts new threads,
fixes [ticket:2279].

CHANGES
lib/sqlalchemy/__init__.py
lib/sqlalchemy/orm/__init__.py
lib/sqlalchemy/sql/__init__.py
lib/sqlalchemy/util.py

diff --git a/CHANGES b/CHANGES
index a7bb9a59fdce129ca474669127c1ab2dac2607e1..98a34e9d268d9b2cc8731e18e341166fdee17f2a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -5,6 +5,15 @@ CHANGES
 =======
 0.6.9
 =====
+- general
+   - Adjusted the "importlater" mechanism, which is
+     used internally to resolve import cycles,
+     such that the usage of __import__ is completed
+     when the import of sqlalchemy or sqlalchemy.orm
+     is done, thereby avoiding any usage of __import__
+     after the application starts new threads,
+     fixes [ticket:2279].
+
 - orm
   - Fixed bug whereby the source clause
     used by query.join() would be inconsistent
index 8d4e2a57d397bb49140b4c80758bcb9e93ed382b..6af9bce750fd58873ef7718842be990e0e41f48a 100644 (file)
@@ -118,3 +118,6 @@ __all__ = sorted(name for name, obj in locals().items()
 __version__ = '0.6.9'
 
 del inspect, sys
+
+from sqlalchemy import util as _sa_util
+_sa_util.importlater.resolve_all()
\ No newline at end of file
index 1e9959939bafed07e4bd5dd2dd81a24fd4e7bb4a..3fdbd8795d204f28338ff4aeb844d02948923921 100644 (file)
@@ -1315,3 +1315,6 @@ def undefer_group(name):
 
     """
     return strategies.UndeferGroupOption(name)
+
+from sqlalchemy import util as _sa_util
+_sa_util.importlater.resolve_all()
\ No newline at end of file
index 80aa769284af675c03b09795e6d3b06ef78f50e8..822c1390997f2672272a85144ec078ef867ea993 100644 (file)
@@ -63,3 +63,4 @@ from sqlalchemy.sql.visitors import ClauseVisitor
 
 __tmp = locals().keys()
 __all__ = sorted([i for i in __tmp if not i.startswith('__')])
+
index 68cd185dd59d0f246dda9145f3930040ad4ec111..634c7d51911700b17545ce02a7c96bfbbcfa36b2 100644 (file)
@@ -1584,37 +1584,67 @@ class importlater(object):
         from mypackage.somemodule import somesubmod
 
     except evaluted upon attribute access to "somesubmod".
+    
+    importlater() currently requires that resolve_all() be
+    called, typically at the bottom of a package's __init__.py.
+    This is so that __import__ still called only at 
+    module import time, and not potentially within
+    a non-main thread later on.
 
     """
+
+    _unresolved = set()
+
     def __init__(self, path, addtl=None):
         self._il_path = path
         self._il_addtl = addtl
+        importlater._unresolved.add(self)
+
+    @classmethod
+    def resolve_all(cls):
+        for m in list(importlater._unresolved):
+            m._resolve()
+
+    @property
+    def _full_path(self):
+        if self._il_addtl:
+            return self._il_path + "." + self._il_addtl
+        else:
+            return self._il_path
 
     @memoized_property
-    def _il_module(self):
+    def module(self):
+        if self in importlater._unresolved:
+            raise ImportError(
+                    "importlater.resolve_all() hasn't been called")
+
+        m = self._initial_import
         if self._il_addtl:
-            m = __import__(self._il_path, globals(), locals(), 
-                                [self._il_addtl])
-            try:
-                return getattr(m, self._il_addtl)
-            except AttributeError:
-                raise ImportError(
-                        "Module %s has no attribute '%s'" % 
-                        (self._il_path, self._il_addtl)
-                    )
+            m = getattr(m, self._il_addtl)
         else:
-            m = __import__(self._il_path)
             for token in self._il_path.split(".")[1:]:
                 m = getattr(m, token)
-            return m
+        return m
+
+    def _resolve(self):
+        importlater._unresolved.discard(self)
+        if self._il_addtl:
+            self._initial_import = __import__(
+                                self._il_path, globals(), locals(), 
+                                [self._il_addtl])
+        else:
+            self._initial_import = __import__(self._il_path)
 
     def __getattr__(self, key):
+        if key == 'module':
+            raise ImportError("Could not resolve module %s" 
+                                % self._full_path)
         try:
-            attr = getattr(self._il_module, key)
+            attr = getattr(self.module, key)
         except AttributeError:
             raise AttributeError(
-                        "Module %s has no attribute '%s'" % 
-                        (self._il_path, key)
+                        "Module %s has no attribute '%s'" %
+                        (self._full_path, key)
                     )
         self.__dict__[key] = attr
         return attr