[Python-checkins] r57319 - in sandbox/trunk/import_in_py: Py3K_TODO _importlib.py regrtest.sh tests/test_fs_loader.py
brett.cannon
python-checkins at python.org
Thu Aug 23 16:37:20 CEST 2007
Author: brett.cannon
Date: Thu Aug 23 16:37:20 2007
New Revision: 57319
Modified:
sandbox/trunk/import_in_py/Py3K_TODO
sandbox/trunk/import_in_py/_importlib.py
sandbox/trunk/import_in_py/regrtest.sh
sandbox/trunk/import_in_py/tests/test_fs_loader.py
Log:
Add proper support for reloading of modules by not deleting the module if the
reload failed. This led to exception handling during module initialization
being pushed into module_init.
test_import now passes.
Modified: sandbox/trunk/import_in_py/Py3K_TODO
==============================================================================
--- sandbox/trunk/import_in_py/Py3K_TODO (original)
+++ sandbox/trunk/import_in_py/Py3K_TODO Thu Aug 23 16:37:20 2007
@@ -5,8 +5,6 @@
* Be backwards-compatible.
+ Must pass 2.6 stdlib test suite using importlib.
- Use regrtest.sh editing so all tests are run.
- - test_import
- * test_failing_reload
- test_xmlrpc
* Passes in isolation.
* Rewrite zipimport.
Modified: sandbox/trunk/import_in_py/_importlib.py
==============================================================================
--- sandbox/trunk/import_in_py/_importlib.py (original)
+++ sandbox/trunk/import_in_py/_importlib.py Thu Aug 23 16:37:20 2007
@@ -271,17 +271,44 @@
def init_module(loader, code_object, name, path, is_pkg):
- """Return an initialized module."""
+ """Return an initialized module.
+
+ If initialization fails and the module did not already exist, then remove
+ it from sys.modules to prevent a partially initialized module from being
+ left around. If this action is for a reload (i.e., the module already
+ existed), leave the original module state in place.
+
+ """
module = sys.modules.get(name)
- if module is None:
+ is_reload = True if module is not None else False
+ if not is_reload:
module = imp.new_module(name)
sys.modules[name] = module
+ else:
+ original_values = {}
+ modified_attrs = ['__loader__', '__name__', '__file__']
+ for attr in modified_attrs:
+ try:
+ original_values[attr] = getattr(module, attr)
+ except AttributeError:
+ pass
module.__loader__ = loader
module.__name__ = name
module.__file__ = path
if is_pkg:
module.__path__ = [module.__file__.rsplit(path_sep, 1)[0]]
- exec code_object in module.__dict__
+ try:
+ exec code_object in module.__dict__
+ except:
+ if not is_reload:
+ del sys.modules[name]
+ else:
+ for attr in modified_attrs:
+ if attr in original_values:
+ setattr(module, attr, original_values[attr])
+ else:
+ delattr(module, attr)
+ raise
return module
@@ -392,13 +419,7 @@
self._bytecode_path())
except ValueError:
raise ImportError("loader cannot handle %s" % fullname)
- try:
- return self._module_init(code_object, fullname, path, self._is_pkg)
- except:
- # Don't leave a partially initialized module in sys.modules.
- if fullname in sys.modules:
- del sys.modules[fullname]
- raise
+ return self._module_init(code_object, fullname, path, self._is_pkg)
@check_name
def mod_time(self, name):
Modified: sandbox/trunk/import_in_py/regrtest.sh
==============================================================================
--- sandbox/trunk/import_in_py/regrtest.sh (original)
+++ sandbox/trunk/import_in_py/regrtest.sh Thu Aug 23 16:37:20 2007
@@ -2,5 +2,5 @@
# 'verbose=1' argument outputs test runs.
# 'tests' argument specifies tests to run.
echo 'test_pkg failure known and is OK'
-$1 -c "import importlib; importlib._set__import__(); from test.regrtest import main; main(['test_import'])"
+$1 -c "import importlib; importlib._set__import__(); from test.regrtest import main; main()"
echo 'test_pkg failure known and is OK'
Modified: sandbox/trunk/import_in_py/tests/test_fs_loader.py
==============================================================================
--- sandbox/trunk/import_in_py/tests/test_fs_loader.py (original)
+++ sandbox/trunk/import_in_py/tests/test_fs_loader.py Thu Aug 23 16:37:20 2007
@@ -1,5 +1,6 @@
import importlib
+from tests import mock_importlib
from tests.ext_help import find_ext_location
from tests.py_help import TestPyPycPackages
@@ -140,6 +141,24 @@
test_support.unlink(self.pyc_path)
self.assertRaises(ImportError, loader.load_module, self.module_name)
+ def test_reload_failure(self):
+ # If a module is reloaded and something happens during loading, the
+ # module should be left in place and not cleared out.
+ test_support.unlink(self.pyc_path)
+ with open(self.py_path, 'w') as source_file:
+ source_file.write('x = 42/0')
+ mock_module = mock_importlib.MockModule(self.module_name)
+ mock_module.__file__ = 'blah'
+ if hasattr(mock_module, '__loader__'):
+ delattr(mock_module, '__loader__')
+ sys.modules[self.module_name] = mock_module
+ loader = importlib._PyFileLoader(self.module_name, self.py_path, False)
+ self.assertRaises(ZeroDivisionError, loader.load_module,
+ self.module_name)
+ self.assert_(self.module_name in sys.modules)
+ self.assertEquals(mock_module.__file__, 'blah')
+ self.assert_(not hasattr(mock_module, '__loader__'))
+
def log_call(instance, method_name):
"""Log a method call."""
More information about the Python-checkins
mailing list