[Python-3000-checkins] r59902 - in python/branches/py3k-importhook: Lib/test/test_imp.py Python/import.c

christian.heimes python-3000-checkins at python.org
Fri Jan 11 01:41:34 CET 2008


Author: christian.heimes
Date: Fri Jan 11 01:41:34 2008
New Revision: 59902

Modified:
   python/branches/py3k-importhook/Lib/test/test_imp.py
   python/branches/py3k-importhook/Python/import.c
Log:
Changed an implementation detail that causes the hooks to be called in a more predictable order. If a hook for module is registered during the processing of  the versy same module than the hook is called after the already registered hooks.
Hooks for loaded modules are still executed ASAP.

Modified: python/branches/py3k-importhook/Lib/test/test_imp.py
==============================================================================
--- python/branches/py3k-importhook/Lib/test/test_imp.py	(original)
+++ python/branches/py3k-importhook/Lib/test/test_imp.py	Fri Jan 11 01:41:34 2008
@@ -101,6 +101,26 @@
     ("pih_test a b __init__", "package = 2"),
 ]
 
+mod_callback = """
+import imp
+
+def callback(mod):
+    imp.test_callbacks.append(("pih_test%s", mod.__name__))
+
+imp.register_post_import_hook(callback, "pih_test")
+imp.register_post_import_hook(callback, "pih_test.a")
+imp.register_post_import_hook(callback, "pih_test.a.b")
+"""
+
+hier_withregister = [
+    ("pih_test", None),
+    ("pih_test __init__", mod_callback % ''),
+    ("pih_test a", None),
+    ("pih_test a __init__", mod_callback % '.a'),
+    ("pih_test a b", None),
+    ("pih_test a b __init__", mod_callback % '.a.b'),
+]
+
 class CallBack:
     def __init__(self):
         self.mods = {}
@@ -116,11 +136,13 @@
         self.sys_pih = sys.post_import_hooks.copy()
         self.module_names = set(sys.modules)
         self.sys_path = list(sys.path)
+        imp.test_callbacks = []
         self.tmpdir = None
 
     def tearDown(self):
         sys.post_import_hooks = self.sys_pih
         sys.path = self.sys_path
+        del imp.test_callbacks
         for name in list(sys.modules):
             if name not in self.module_names:
                 del sys.modules[name]
@@ -218,6 +240,40 @@
         self.assertEqual(callback.names,
                          ["pih_test", "pih_test.a", "pih_test.a.b"])
 
+    def test_hook_hirarchie(self):
+        self.tmpdir = mkhier(hier_withregister)
+
+        def callback(mod):
+            imp.test_callbacks.append(('', mod.__name__))
+
+        imp.register_post_import_hook(callback, "pih_test")
+        imp.register_post_import_hook(callback, "pih_test.a")
+        imp.register_post_import_hook(callback, "pih_test.a.b")
+
+        expected = []
+        self.assertEqual(imp.test_callbacks, expected)
+
+        import pih_test
+        expected.append(("", "pih_test"))
+        expected.append(("pih_test", "pih_test"))
+        self.assertEqual(imp.test_callbacks, expected)
+
+        import pih_test.a
+        expected.append(("pih_test.a", "pih_test"))
+        expected.append(("", "pih_test.a"))
+        expected.append(("pih_test", "pih_test.a"))
+        expected.append(("pih_test.a", "pih_test.a"))
+        self.assertEqual(imp.test_callbacks, expected)
+
+        import pih_test.a.b
+        expected.append(("pih_test.a.b", "pih_test"))
+        expected.append(("pih_test.a.b", "pih_test.a"))
+        expected.append(("", "pih_test.a.b"))
+        expected.append(("pih_test", "pih_test.a.b"))
+        expected.append(("pih_test.a", "pih_test.a.b"))
+        expected.append(("pih_test.a.b", "pih_test.a.b"))
+        self.assertEqual(imp.test_callbacks, expected)
+
     def test_notifyloaded_byname(self):
         callback = CallBack()
 

Modified: python/branches/py3k-importhook/Python/import.c
==============================================================================
--- python/branches/py3k-importhook/Python/import.c	(original)
+++ python/branches/py3k-importhook/Python/import.c	Fri Jan 11 01:41:34 2008
@@ -718,12 +718,9 @@
 		/* Either no hooks are defined or they are already fired */
 		if (hooks == NULL)
 			PyErr_Clear();
-		goto end;
+		goto success;
 	}
 	Py_INCREF(hooks);
-	if (PyDict_SetItem(registry, mod_name, Py_None) < 0) {
-		goto end;
-	}
 	if (!PyList_Check(hooks)) {
 		PyErr_Format(PyExc_TypeError,
 			     "expected None or list of hooks, got '%.200s'",
@@ -739,13 +736,20 @@
 		o = PyObject_CallFunctionObjArgs(hook, module, NULL);
 		Py_DECREF(hook);
 		if (o == NULL) {
-			goto error;
+			goto removehooks;
 		}
 		Py_DECREF(o);
 	}
+	if (PyErr_Occurred()) {
+		return NULL;
+	}
 
-    end:
+    success:
 	status = 0;
+    removehooks:
+	if (PyDict_SetItem(registry, mod_name, Py_None) < 0) {
+		status = -1;
+	}
     error:
 	Py_XDECREF(mod_name);
 	Py_XDECREF(it);
@@ -838,6 +842,7 @@
 	locked = 1;
 
 	hooks = PyDict_GetItem(registry, mod_name);
+	Py_XINCREF(hooks);
 	/* module may be already loaded, get the module object from sys */
 	if (hooks == NULL || hooks == Py_None) {
 		PyObject *module = NULL;
@@ -856,7 +861,7 @@
 			if (o == NULL) {
 				goto error;
 			}
-			goto end;
+			goto success;
 		}
 		else {
 			/* no hook has been registered so far */
@@ -882,7 +887,7 @@
 		goto error;
 	}
 
-    end:
+    success:
 	status = 0;
     error:
 	Py_XDECREF(callable);


More information about the Python-3000-checkins mailing list