diff options
author | Benjamin Peterson <benjamin@python.org> | 2014-03-13 22:06:32 -0500 |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2014-03-13 22:06:32 -0500 |
commit | 0025775659a9ec6c52ef460c6fff0d6f37a052ff (patch) | |
tree | 470c13accf3ab7182db747b9a4130196ffc4681a | |
parent | 9ed4680ff64c1bb9d8bb04c28cf07d5e80dc6855 (diff) | |
download | six-0025775659a9ec6c52ef460c6fff0d6f37a052ff.tar.gz |
just pretend attributes of unimportable lazy modules don't exist
Suggested by Diana Clarke.
-rw-r--r-- | CHANGES | 2 | ||||
-rw-r--r-- | documentation/index.rst | 10 | ||||
-rw-r--r-- | six.py | 23 |
3 files changed, 21 insertions, 14 deletions
@@ -6,6 +6,8 @@ This file lists the changes in each six version. Development version ------------------- +- Raise an AttributeError for every attribute of unimportable modules. + - Issue #56: Make the fake modules six.moves puts into sys.modules appear not to have a __path__ unless they are loaded. diff --git a/documentation/index.rst b/documentation/index.rst index 99e82e1..3d7828b 100644 --- a/documentation/index.rst +++ b/documentation/index.rst @@ -450,11 +450,11 @@ functionality; its structure mimics the structure of the Python 3 interpreter. For example, ``sys.modules["six.moves.winreg"].LoadKey`` would fail on any non-Windows platform. Unfortunately, some applications try to load attributes on every module in :data:`py3:sys.modules`. six mitigates - this problem for some applications by pretending ``__file__`` and - ``__name__`` don't exist on lazy modules that aren't loaded. That doesn't - work in every case, though. If you are encountering this problem and don't - use any from imports directly from ``six.moves`` modules, you can workaround - the issue by removing the six proxy modules:: + this problem for some applications by pretending attributes on unimportable + modules don't exist. This hack doesn't work in every case, though. If you are + encountering problems with the lazy modules and don't use any from imports + directly from ``six.moves`` modules, you can workaround the issue by removing + the six proxy modules:: d = [name for name in sys.modules if name.startswith("six.moves.")] for name in d: @@ -105,17 +105,22 @@ class MovedModule(_LazyDescr): return _import_module(self.mod) def __getattr__(self, attr): - # Hack around the Django autoreloader. The reloader tries to get - # __file__ or __name__ of every module in sys.modules. This doesn't work - # well if this MovedModule is for an module that is unavailable on this - # machine (like winreg on Unix systems). Thus, we pretend __file__ and - # __name__ don't exist if the module hasn't been loaded yet. We give - # __path__ the same treatment for Google AppEngine. See issues #51, #53 - # and #56. + # It turns out many Python frameworks like to traverse sys.modules and + # try to load various attributes. This causes problems if this is a + # platform-specific module on the wrong platform, like _winreg on + # Unixes. Therefore, we silently pretend unimportable modules do not + # have any attributes. See issues #51, #53, #56, and #63 for the full + # tales of woe. + # + # First, if possible, avoid loading the module just to look at __file__, + # __name__, or __path__. if (attr in ("__file__", "__name__", "__path__") and self.mod not in sys.modules): - raise AttributeError - _module = self._resolve() + raise AttributeError(attr) + try: + _module = self._resolve() + except ImportError: + raise AttributeError(attr) value = getattr(_module, attr) setattr(self, attr, value) return value |