diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-09-21 16:56:14 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-09-21 16:56:14 -0400 |
| commit | 2aa80d40d2c9a00bb87a145bba1f01c327b6000b (patch) | |
| tree | b27660b881d695c3cba82b93d2020c566c4fa6c0 /lib/sqlalchemy | |
| parent | 36e2b2d8750ca5bcf0345733973f5ed097d2949a (diff) | |
| download | sqlalchemy-2aa80d40d2c9a00bb87a145bba1f01c327b6000b.tar.gz | |
- 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]. Also in 0.6.9.
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/__init__.py | 3 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/__init__.py | 3 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/interfaces.py | 2 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/__init__.py | 1 | ||||
| -rw-r--r-- | lib/sqlalchemy/util/langhelpers.py | 54 |
5 files changed, 50 insertions, 13 deletions
diff --git a/lib/sqlalchemy/__init__.py b/lib/sqlalchemy/__init__.py index c15cc6b69..0b9b7a00e 100644 --- a/lib/sqlalchemy/__init__.py +++ b/lib/sqlalchemy/__init__.py @@ -120,3 +120,6 @@ __all__ = sorted(name for name, obj in locals().items() __version__ = '0.7.3' del inspect, sys + +from sqlalchemy import util as _sa_util +_sa_util.importlater.resolve_all()
\ No newline at end of file diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py index f6b02eaa8..b7f7884f2 100644 --- a/lib/sqlalchemy/orm/__init__.py +++ b/lib/sqlalchemy/orm/__init__.py @@ -1458,3 +1458,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 diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py index 893d6ea2a..334d6d378 100644 --- a/lib/sqlalchemy/orm/interfaces.py +++ b/lib/sqlalchemy/orm/interfaces.py @@ -21,7 +21,7 @@ from itertools import chain from sqlalchemy import exc as sa_exc from sqlalchemy import util from sqlalchemy.sql import operators -deque = util.importlater('collections').deque +deque = __import__('collections').deque mapperutil = util.importlater('sqlalchemy.orm', 'util') diff --git a/lib/sqlalchemy/sql/__init__.py b/lib/sqlalchemy/sql/__init__.py index c591e6802..1b8284781 100644 --- a/lib/sqlalchemy/sql/__init__.py +++ b/lib/sqlalchemy/sql/__init__.py @@ -64,3 +64,4 @@ from sqlalchemy.sql.visitors import ClauseVisitor __tmp = locals().keys() __all__ = sorted([i for i in __tmp if not i.startswith('__')]) + diff --git a/lib/sqlalchemy/util/langhelpers.py b/lib/sqlalchemy/util/langhelpers.py index 4dd9a5270..cf8b2acac 100644 --- a/lib/sqlalchemy/util/langhelpers.py +++ b/lib/sqlalchemy/util/langhelpers.py @@ -527,37 +527,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 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.module, key) except AttributeError: raise AttributeError( "Module %s has no attribute '%s'" % - (self._il_path, key) + (self._full_path, key) ) self.__dict__[key] = attr return attr |
