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

christian.heimes python-3000-checkins at python.org
Thu Jan 10 23:10:03 CET 2008


Author: christian.heimes
Date: Thu Jan 10 23:10:03 2008
New Revision: 59897

Modified:
   python/branches/py3k-importhook/Lib/test/test_imp.py
   python/branches/py3k-importhook/Python/import.c
Log:
Added notify_byname as I proposed on the mailing list
Added macro UNLOCK_IMPORT

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	Thu Jan 10 23:10:03 2008
@@ -115,10 +115,12 @@
     def setUp(self):
         self.sys_pih = sys.post_import_hooks.copy()
         self.module_names = set(sys.modules)
+        self.sys_path = list(sys.path)
         self.tmpdir = None
 
     def tearDown(self):
         sys.post_import_hooks = self.sys_pih
+        sys.path = self.sys_path
         for name in list(sys.modules):
             if name not in self.module_names:
                 del sys.modules[name]
@@ -216,6 +218,25 @@
         self.assertEqual(callback.names,
                          ["pih_test", "pih_test.a", "pih_test.a.b"])
 
+    def test_notifyloaded_byname(self):
+        callback = CallBack()
+
+        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")
+        self.assertEqual(callback.names, [])
+
+        for name in ("pih_test", "pih_test.a", "pih_test.a.b"):
+            mod = imp.new_module(name)
+            sys.modules[name] = mod
+        self.assertEqual(callback.names, [])
+
+        mod2 = imp.notify_module_loaded("pih_test.a.b")
+        self.failUnless(mod is mod2, (mod, mod2))
+        self.assertEqual(mod.__name__,  "pih_test.a.b")
+
+        self.assertEqual(callback.names,
+                         ["pih_test", "pih_test.a", "pih_test.a.b"])
 
 def test_main():
     test_support.run_unittest(

Modified: python/branches/py3k-importhook/Python/import.c
==============================================================================
--- python/branches/py3k-importhook/Python/import.c	(original)
+++ python/branches/py3k-importhook/Python/import.c	Thu Jan 10 23:10:03 2008
@@ -260,6 +260,14 @@
 static long import_lock_thread = -1;
 static int import_lock_level = 0;
 
+#define UNLOCK_IMPORT do {					\
+		if (unlock_import() < 0) {			\
+			PyErr_SetString(PyExc_RuntimeError,	\
+				"not holding the import lock");	\
+			return NULL;				\
+		}					\
+	} while(0)
+
 static void
 lock_import(void)
 {
@@ -317,6 +325,7 @@
 
 #define lock_import()
 #define unlock_import() 0
+#define UNLOCK_IMPORT
 
 #endif
 
@@ -344,11 +353,7 @@
 imp_release_lock(PyObject *self, PyObject *noargs)
 {
 #ifdef WITH_THREAD
-	if (unlock_import() < 0) {
-		PyErr_SetString(PyExc_RuntimeError,
-				"not holding the import lock");
-		return NULL;
-	}
+    	UNLOCK_IMPORT;
 #endif
 	Py_INCREF(Py_None);
 	return Py_None;
@@ -657,6 +662,8 @@
 
 /* Notify that a module as been loaded
  * Must be called with the import hook acquired
+ * The function *STEALS* a reference to module when an error occurs, otherwise
+ * it returns the module.
  */
 PyObject *
 PyImport_NotifyModuleLoaded(PyObject *module)
@@ -752,6 +759,57 @@
 	}
 }
 
+/* notify by name
+ * notify_byname("a.b.c") calls PyImport_NotifyModuleLoaded() for "a", "a.b"
+ * and "a.b.c". The modules are taken from sys.modules. If a module can't be
+ * retrieved an exception is raised otherwise the module 'modname' is returned
+ */
+static PyObject *
+notify_byname(const char *modname)
+{
+	PyObject *modules, *mod = NULL;
+	int status = -1;
+	const char *pmodname = modname;
+	char name[MAXPATHLEN+1];
+	Py_ssize_t pos;
+
+	modules = PyImport_GetModuleDict();
+	if (modules == NULL) {
+		goto error;
+	}
+	for (; *pmodname != '\0'; pmodname++) {
+		if (*pmodname != '.')
+			continue;
+		pos = pmodname - modname;
+		if (pos == 0) {
+			PyErr_SetString(PyExc_ValueError,
+				"module name can't starts with a dot.");
+			return NULL;
+		}
+		strncpy(name, modname, pos);
+		name[pos] = '\0';
+		mod = PyDict_GetItemString(modules, name);
+		Py_INCREF(mod);
+		mod = PyImport_NotifyModuleLoaded(mod);
+		if (mod == NULL) {
+			goto error;
+		}
+		Py_DECREF(mod);
+	}
+	mod = PyDict_GetItemString(modules, modname);
+	Py_INCREF(mod);
+	mod = PyImport_NotifyModuleLoaded(mod);
+
+	status = 0;
+    error:
+	if (status == 0) {
+		return mod;
+	}
+	else {
+		return NULL;
+	}
+}
+
 /* register a new hook for a module
    PyImport_RegisterPostImportHook acquires the global import look
  */
@@ -831,12 +889,8 @@
 	Py_XDECREF(hooks);
 	Py_XDECREF(mod_name);
 	if (locked) {
-		if (unlock_import() < 0) {
-			PyErr_SetString(PyExc_RuntimeError,
-					"not holding the import lock");
-			return NULL;
-		}
-	}
+		UNLOCK_IMPORT;
+        }
 	if (status < 0) {
 		return NULL;
 	}
@@ -2287,12 +2341,7 @@
 	lock_import();
 	result = import_module_level(name, globals, locals, fromlist, level);
 	/* result = PyImport_NotifyModuleLoaded(result); */
-	if (unlock_import() < 0) {
-		Py_XDECREF(result);
-		PyErr_SetString(PyExc_RuntimeError,
-				"not holding the import lock");
-		return NULL;
-	}
+	UNLOCK_IMPORT;
 	return result;
 }
 
@@ -3218,18 +3267,19 @@
 imp_notify_module_loaded(PyObject *self, PyObject *args)
 {
 	PyObject *mod, *o;
+	char *name;
+
+        if (PyArg_ParseTuple(args, "s:notify_module_loaded", &name)) {
+		return notify_byname(name);
+	}
 
         if (!PyArg_ParseTuple(args, "O:notify_module_loaded", &mod))
-                return NULL;
+		return NULL;
 
 	Py_INCREF(mod);
 	lock_import();
 	o = PyImport_NotifyModuleLoaded(mod);
-	if (unlock_import() < 0) {
-		PyErr_SetString(PyExc_RuntimeError,
-				"not holding the import lock");
-		return NULL;
-	}
+	UNLOCK_IMPORT;
 	return o;
 }
 


More information about the Python-3000-checkins mailing list