[Python-3000-checkins] r59890 - in python/branches/py3k-importhook: Lib/test/test_imp.py Python/import.c
christian.heimes
python-3000-checkins at python.org
Thu Jan 10 18:39:27 CET 2008
Author: christian.heimes
Date: Thu Jan 10 18:39:27 2008
New Revision: 59890
Modified:
python/branches/py3k-importhook/Lib/test/test_imp.py
python/branches/py3k-importhook/Python/import.c
Log:
sys.post_import_hooks[name] is set to None during and after the callbacks are called (as proposed by PJE)
imp_notify_module_loaded() is protected by the importer lock
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 18:39:27 2008
@@ -111,8 +111,7 @@
self.assert_("sys" in callback.mods, callback.mods)
self.assert_(callback.mods["sys"] is sys, callback.mods)
self.failIf("telnetlib" in callback.mods, callback.mods)
- regc = sys.post_import_hooks.get("sys", False)
- self.assert_(regc is False, regc)
+ self.assertEqual(sys.post_import_hooks["sys"], None)
def test_register_callback_new(self):
callback = CallBack()
@@ -129,11 +128,15 @@
import telnetlib
self.assert_("telnetlib" in callback.mods, callback.mods)
self.assert_(callback.mods["telnetlib"] is telnetlib, callback.mods)
+ self.assertEqual(sys.post_import_hooks["telnetlib"], None)
def test_post_import_notify(self):
imp.notify_module_loaded(sys)
self.failUnlessRaises(TypeError, imp.notify_module_loaded, None)
self.failUnlessRaises(TypeError, imp.notify_module_loaded, object())
+ # Should this fail?
+ mod = imp.new_module("post_import_test_module")
+ imp.notify_module_loaded(mod)
def test_main():
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 18:39:27 2008
@@ -655,6 +655,9 @@
return pihr;
}
+/* Notify that a module as been loaded
+ * Must be called with the import hook acquired
+ */
PyObject *
PyImport_NotifyModuleLoaded(PyObject *module)
{
@@ -673,8 +676,7 @@
if (module == NULL) {
return NULL;
}
-
- /* Should I allow all kinds of objects ? */
+ /* Should I allow all kinds of objects? */
if (!PyModule_Check(module)) {
PyErr_Format(PyExc_TypeError,
"A module object was expected, got '%.200s'",
@@ -683,15 +685,12 @@
}
/* XXX check if module is in sys.modules ? */
- registry = PyImport_GetPostImportHooks();
- if (registry == NULL) {
+ if ((registry = PyImport_GetPostImportHooks()) == NULL) {
/* warn about invalid registry? */
PyErr_Clear();
return module;
}
-
- mod_name = PyObject_GetAttr(module, name);
- if (mod_name == NULL) {
+ if ((mod_name = PyObject_GetAttr(module, name)) == NULL) {
goto error;
}
if (!PyUnicode_Check(mod_name)) {
@@ -707,12 +706,15 @@
goto error;
}
- hooks = PyDict_GetItem(registry, mod_name);
- if (hooks == NULL) {
+ if ((hooks = PyDict_GetItem(registry, mod_name)) == NULL) {
/* Either no hooks are defined or they are already fired */
PyErr_Clear();
goto end;
}
+ 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'",
@@ -721,8 +723,7 @@
}
/* fire hooks */
- it = PyObject_GetIter(hooks);
- if (it == NULL) {
+ if ((it = PyObject_GetIter(hooks)) == NULL) {
goto error;
}
while ((hook = PyIter_Next(it)) != NULL) {
@@ -734,16 +735,12 @@
Py_DECREF(o);
}
- /* Mark hooks as fired */
- if (PyDict_DelItem(registry, mod_name) < 0) {
- goto error;
- }
-
end:
status = 0;
error:
Py_XDECREF(mod_name);
Py_XDECREF(it);
+ Py_XDECREF(hooks);
if (status < 0) {
Py_XDECREF(module);
return NULL;
@@ -753,10 +750,13 @@
}
}
+/* register a new hook for a module
+ PyImport_RegisterPostImportHook acquires the global import look
+ */
PyObject *
PyImport_RegisterPostImportHook(PyObject *callable, PyObject *mod_name)
{
- PyObject *registry = NULL, *hooks = NULL;
+ PyObject *registry = NULL, *hooks = NULL, *modules;
int status = -1, locked = 0;
if (!PyCallable_Check(callable)) {
@@ -769,7 +769,8 @@
}
registry = PyImport_GetPostImportHooks();
- if (registry == NULL) {
+ modules = PyImport_GetModuleDict();
+ if (registry == NULL || modules == NULL) {
goto error;
}
@@ -778,43 +779,43 @@
hooks = PyDict_GetItem(registry, mod_name);
/* module may be already loaded, get the module object from sys */
- if (hooks == NULL) {
- PyObject *o, *modules;
+ if (hooks == NULL || hooks == Py_None) {
PyObject *module = NULL;
- modules = PyImport_GetModuleDict();
- if (modules == NULL) {
- goto error;
- }
- module = PyDict_GetItem(modules, mod_name);
- if (module != NULL) {
+ if ((module = PyDict_GetItem(modules, mod_name)) != NULL) {
/* module is already loaded, fire hook immediately */
+ PyObject *o;
+
o = PyObject_CallFunctionObjArgs(callable, module, NULL);
+ Py_XDECREF(o);
+ if (hooks == NULL) {
+ if (PyDict_SetItem(registry, mod_name, Py_None) < 0) {
+ goto error;
+ }
+ }
if (o == NULL) {
goto error;
}
- Py_DECREF(o);
goto end;
}
- }
- /* no hook registered so far */
- if (hooks == NULL) {
- PyErr_Clear();
- hooks = PyList_New(0);
- if (hooks == NULL) {
- goto error;
- }
- if (PyDict_SetItem(registry, mod_name, hooks) < 0) {
- goto error;
+ else {
+ /* no hook has been registered so far */
+ PyErr_Clear();
+ assert(hooks != Py_None);
+ hooks = PyList_New(0);
+ if (hooks == NULL) {
+ goto error;
+ }
+ if (PyDict_SetItem(registry, mod_name, hooks) < 0) {
+ goto error;
+ }
}
}
- else {
- if (!PyList_Check(hooks)) {
+ if (!PyList_Check(hooks)) {
PyErr_Format(PyExc_TypeError,
"expected list of hooks, got '%.200s'",
Py_TYPE(hooks)->tp_name);
goto error;
- }
}
/* append a new callable */
if (PyList_Append(hooks, callable) < 0) {
@@ -3212,13 +3213,20 @@
static PyObject *
imp_notify_module_loaded(PyObject *self, PyObject *args)
{
- PyObject *mod;
+ PyObject *mod, *o;
if (!PyArg_ParseTuple(args, "O:notify_module_loaded", &mod))
return NULL;
Py_INCREF(mod);
- return PyImport_NotifyModuleLoaded(mod);
+ lock_import();
+ o = PyImport_NotifyModuleLoaded(mod);
+ if (unlock_import() < 0) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "not holding the import lock");
+ return NULL;
+ }
+ return o;
}
static PyObject *
@@ -3285,7 +3293,9 @@
"register_post_import_hook(callable, module_name) -> None");
PyDoc_STRVAR(doc_notify_module_loaded,
-"notify_module_loaded(module) -> module");
+"notify_module_loaded(module) -> module\n\
+Notifies the system that a module has been loaded. The method is\n\
+with the global import locker.");
static PyMethodDef imp_methods[] = {
More information about the Python-3000-checkins
mailing list