[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