Author: christian.heimes
Date: Mon Jan 14 00:14:07 2008
New Revision: 59941
Modified:
python/branches/py3k-importhook/Lib/test/test_imp.py
python/branches/py3k-importhook/Python/import.c
Log:
Implemented a queue for registrations. It's filled while hooks are processed
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 Mon Jan 14
00:14:07 2008
@@ -105,20 +105,29 @@
import imp
def callback(mod):
- imp.test_callbacks.append(("pih_test%s", mod.__name__))
+ info = ("pih_test%(info)s", mod.__name__)
+ imp.test_callbacks.append(info)
+
+def callback_added(mod):
+ info = ("ADDED in pih_test%(info)s", mod.__name__)
+ imp.test_callbacks.append(info)
+
+def callback_add(mod):
+ callback(mod)
+ imp.register_post_import_hook(callback_added, "pih_test.a")
imp.register_post_import_hook(callback, "pih_test")
-imp.register_post_import_hook(callback, "pih_test.a")
+imp.register_post_import_hook(callback_add, "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 __init__", mod_callback % {'info':''}),
("pih_test a", None),
- ("pih_test a __init__", mod_callback % '.a'),
+ ("pih_test a __init__", mod_callback % {'info':'.a'}),
("pih_test a b", None),
- ("pih_test a b __init__", mod_callback % '.a.b'),
+ ("pih_test a b __init__", mod_callback % {'info':'.a.b'}),
]
class CallBack:
@@ -240,11 +249,12 @@
self.assertEqual(callback.names,
["pih_test", "pih_test.a", "pih_test.a.b"])
- def test_hook_hirarchie(self):
+ def test_hook_hirarchie_withregister(self):
self.tmpdir = mkhier(hier_withregister)
def callback(mod):
- imp.test_callbacks.append(('', mod.__name__))
+ info = ('', mod.__name__)
+ imp.test_callbacks.append(info)
imp.register_post_import_hook(callback, "pih_test")
imp.register_post_import_hook(callback, "pih_test.a")
@@ -263,11 +273,16 @@
expected.append(("", "pih_test.a"))
expected.append(("pih_test", "pih_test.a"))
expected.append(("pih_test.a", "pih_test.a"))
+ # delayed
+ expected.append(("ADDED in pih_test", "pih_test.a"))
+ expected.append(("ADDED in 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"))
+ # This one is called immediately because pih_test.a is already laoded
+ expected.append(("ADDED in 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"))
Modified: python/branches/py3k-importhook/Python/import.c
==============================================================================
--- python/branches/py3k-importhook/Python/import.c (original)
+++ python/branches/py3k-importhook/Python/import.c Mon Jan 14 00:14:07 2008
@@ -111,6 +111,14 @@
{0, 0}
};
+/* Queue for the post import hook system */
+static PyObject *register_queue = NULL;
+static int notification_in_progress = 0;
+
+static PyObject *notify_byname(const char *);
+static int queue_registration(PyObject *, PyObject *);
+static int process_registration_queue(void);
+
/* Initialize things */
@@ -241,8 +249,8 @@
void
_PyImport_Fini(void)
{
- Py_XDECREF(extensions);
- extensions = NULL;
+ Py_CLEAR(extensions);
+ Py_CLEAR(register_queue);
PyMem_DEL(_PyImport_Filetab);
_PyImport_Filetab = NULL;
}
@@ -639,7 +647,10 @@
"sys.modules failed");
}
-/* post import hook API */
+/* **************************************************************************
+ * post import hook API
+ */
+
PyObject *
PyImport_GetPostImportHooks(void)
{
@@ -732,6 +743,8 @@
if ((it = PyObject_GetIter(hooks)) == NULL) {
goto error;
}
+
+ notification_in_progress = 1;
while ((hook = PyIter_Next(it)) != NULL) {
o = PyObject_CallFunctionObjArgs(hook, module, NULL);
Py_DECREF(hook);
@@ -750,6 +763,11 @@
if (PyDict_SetItem(registry, mod_name, Py_None) < 0) {
status = -1;
}
+ notification_in_progress = 0;
+ /* register queued hooks */
+ if (process_registration_queue()) {
+ goto removehooks;
+ }
error:
Py_XDECREF(mod_name);
Py_XDECREF(it);
@@ -832,6 +850,13 @@
goto error;
}
+ if (notification_in_progress) {
+ if (queue_registration(callable, mod_name) != 0) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+ }
+
registry = PyImport_GetPostImportHooks();
modules = PyImport_GetModuleDict();
if (registry == NULL || modules == NULL) {
@@ -846,8 +871,9 @@
/* module may be already loaded, get the module object from sys */
if (hooks == NULL || hooks == Py_None) {
PyObject *module = NULL;
-
- if ((module = PyDict_GetItem(modules, mod_name)) != NULL) {
+
+ module = PyDict_GetItem(modules, mod_name);
+ if (module != NULL) {
/* module is already loaded, fire hook immediately */
PyObject *o;
@@ -904,6 +930,84 @@
}
}
+static int
+queue_registration(PyObject *callable, PyObject *mod_name)
+{
+
+ PyObject *tup;
+
+ if (register_queue == NULL) {
+ register_queue = PyList_New(0);
+ if (register_queue == NULL)
+ return -1;
+ }
+ assert(notification_in_progress);
+ tup = PyTuple_New(2);
+ if (tup == NULL) {
+ return -1;
+ }
+ Py_INCREF(callable);
+ Py_INCREF(mod_name);
+ PyTuple_SetItem(tup, 0, callable);
+ PyTuple_SetItem(tup, 1, mod_name);
+ if (PyList_Append(register_queue, tup)) {
+ Py_DECREF(tup);
+ return -1;
+ }
+ Py_DECREF(tup);
+ return 0;
+}
+
+static int
+process_registration_queue(void)
+{
+ PyObject *modules;
+ PyObject *mod_name, *hook, *module, *o;
+ PyObject *it = NULL, *tup = NULL;
+ int rc = -1;
+
+ if (notification_in_progress)
+ return 0;
+
+ if (register_queue == NULL || PyList_Size(register_queue) == 0) {
+ return 0;
+ }
+
+ if ((modules = PyImport_GetModuleDict()) == NULL) {
+ goto error;
+ }
+
+ while (Py_SIZE(register_queue)) {
+ tup = PyObject_CallMethod(register_queue, "pop", "i", 0);
+ if ((hook = PyTuple_GetItem(tup, 0)) == NULL) {
+ goto error;
+ }
+ if ((mod_name = PyTuple_GetItem(tup, 1)) == NULL) {
+ goto error;
+ }
+ if ((module = PyDict_GetItem(modules, mod_name)) == NULL) {
+ goto error;
+ }
+ o = PyImport_RegisterPostImportHook(hook, mod_name);
+ if (o == NULL) {
+ goto error;
+ }
+ Py_DECREF(o);
+ Py_CLEAR(tup);
+ }
+ if (PyErr_Occurred()) {
+ goto error;
+ }
+
+ rc = 0;
+ error:
+ Py_XDECREF(it);
+ Py_XDECREF(tup);
+ return rc;
+}
+
+/* end of post import hook */
+
static PyObject * get_sourcefile(const char *file);
/* Execute a code object in a module and return the module object
_______________________________________________
Python-3000-checkins mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-3000-checkins