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/util/langhelpers.py | |
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/util/langhelpers.py')
-rw-r--r-- | lib/sqlalchemy/util/langhelpers.py | 54 |
1 files changed, 42 insertions, 12 deletions
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 |