summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2014-03-13 22:06:32 -0500
committerBenjamin Peterson <benjamin@python.org>2014-03-13 22:06:32 -0500
commit0025775659a9ec6c52ef460c6fff0d6f37a052ff (patch)
tree470c13accf3ab7182db747b9a4130196ffc4681a
parent9ed4680ff64c1bb9d8bb04c28cf07d5e80dc6855 (diff)
downloadsix-0025775659a9ec6c52ef460c6fff0d6f37a052ff.tar.gz
just pretend attributes of unimportable lazy modules don't exist
Suggested by Diana Clarke.
-rw-r--r--CHANGES2
-rw-r--r--documentation/index.rst10
-rw-r--r--six.py23
3 files changed, 21 insertions, 14 deletions
diff --git a/CHANGES b/CHANGES
index f9d3530..3dae7cb 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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:
diff --git a/six.py b/six.py
index 58cb95b..c86dc98 100644
--- a/six.py
+++ b/six.py
@@ -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