summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurelien Campeas <aurelien.campeas@logilab.fr>2012-07-30 11:22:03 +0200
committerAurelien Campeas <aurelien.campeas@logilab.fr>2012-07-30 11:22:03 +0200
commit62126b894bc1d1c6a88db5bf4cae86ea20b48d6e (patch)
tree91711fee01fc8f182c89b5001996d7a9010d76ee
parent507c60ba25e29654ec1a6245d684fb0d96dd12b5 (diff)
downloadlogilab-common-62126b894bc1d1c6a88db5bf4cae86ea20b48d6e.tar.gz
[modutils] fix load_module_from_path (closes #100935)
A very old bug in modutils, that leads to doubly loading some modules. By chance on Linux (or the platform we typically use) it seems one the two module gets forgoten as soon as loaded. Unfortunately on Windows, with CubicWeb, it was found that the first module instance was the one on which the mro was built and the second one hosted the super(...) call with a different class id for the litteral within super(ThisClass, self).... The exact reason for the dual behaviour is still unknown but it could well be one of those 'platform dependant' bits that riddle Python.
-rw-r--r--modutils.py3
-rw-r--r--test/data/lmfp/__init__.py2
-rw-r--r--test/data/lmfp/foo.py6
-rw-r--r--test/unittest_modutils.py10
4 files changed, 21 insertions, 0 deletions
diff --git a/modutils.py b/modutils.py
index 2aa4ce3..ebad473 100644
--- a/modutils.py
+++ b/modutils.py
@@ -158,6 +158,9 @@ def load_module_from_modpath(parts, path=None, use_sys=1):
if len(modpath) != len(parts):
# even with use_sys=False, should try to get outer packages from sys.modules
module = sys.modules.get(curname)
+ elif use_sys:
+ # because it may have been indirectly loaded through a parent
+ module = sys.modules.get(curname)
if module is None:
mp_file, mp_filename, mp_desc = find_module(part, path)
module = load_module(curname, mp_file, mp_filename, mp_desc)
diff --git a/test/data/lmfp/__init__.py b/test/data/lmfp/__init__.py
new file mode 100644
index 0000000..74b26b8
--- /dev/null
+++ b/test/data/lmfp/__init__.py
@@ -0,0 +1,2 @@
+# force a "direct" python import
+from . import foo
diff --git a/test/data/lmfp/foo.py b/test/data/lmfp/foo.py
new file mode 100644
index 0000000..8f7de1e
--- /dev/null
+++ b/test/data/lmfp/foo.py
@@ -0,0 +1,6 @@
+import sys
+if not getattr(sys, 'bar', None):
+ sys.just_once = []
+# there used to be two numbers here because
+# of a load_module_from_path bug
+sys.just_once.append(42)
diff --git a/test/unittest_modutils.py b/test/unittest_modutils.py
index 4b12bc1..6a2b62e 100644
--- a/test/unittest_modutils.py
+++ b/test/unittest_modutils.py
@@ -128,6 +128,16 @@ class modpath_from_file_tc(ModutilsTestCase):
self.assertRaises(Exception, modutils.modpath_from_file, '/turlututu')
+class load_module_from_path_tc(ModutilsTestCase):
+
+ def test_do_not_load_twice(self):
+ sys.path.insert(0, self.datadir)
+ foo = modutils.load_module_from_modpath(['lmfp', 'foo'])
+ lmfp = modutils.load_module_from_modpath(['lmfp'])
+ self.assertEqual(len(sys.just_once), 1)
+ sys.path.pop(0)
+ del sys.just_once
+
class file_from_modpath_tc(ModutilsTestCase):
"""given a mod path (i.e. splited module / package name), return the
corresponding file, giving priority to source file over precompiled file