diff options
author | Robert Collins <robertc@robertcollins.net> | 2016-05-18 18:54:35 +1200 |
---|---|---|
committer | Robert Collins <robertc@robertcollins.net> | 2016-05-18 20:58:37 +1200 |
commit | d3a80f0ecd2c24c9d849a907ffe4680933a76b68 (patch) | |
tree | 7c48aa3de4338dfa51e825ddb25835346cf850a8 /extras/__init__.py | |
parent | 3ab32ecf6a17b574bd28d9abb4155580caf3191c (diff) | |
download | python-test-extras-d3a80f0ecd2c24c9d849a907ffe4680933a76b68.tar.gz |
Handle import cycles.
Diffstat (limited to 'extras/__init__.py')
-rw-r--r-- | extras/__init__.py | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/extras/__init__.py b/extras/__init__.py index 2d34b52..29d2230 100644 --- a/extras/__init__.py +++ b/extras/__init__.py @@ -40,13 +40,17 @@ def try_import(name, alternative=None, error_callback=None): """ module_segments = name.split('.') last_error = None + remainder = [] + # module_name will be what successfully imports. We cannot walk from the + # __import__ result because in import loops (A imports A.B, which imports + # C, which calls try_import("A.B")) A.B will not yet be set. while module_segments: module_name = '.'.join(module_segments) try: - module = __import__(module_name) + __import__(module_name) except ImportError: last_error = sys.exc_info()[1] - module_segments.pop() + remainder.append(module_segments.pop()) continue else: break @@ -54,8 +58,9 @@ def try_import(name, alternative=None, error_callback=None): if last_error is not None and error_callback is not None: error_callback(last_error) return alternative + module = sys.modules[module_name] nonexistent = object() - for segment in name.split('.')[1:]: + for segment in reversed(remainder): module = getattr(module, segment, nonexistent) if module is nonexistent: if last_error is not None and error_callback is not None: |