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 Python-3000-checkins@python.org http://mail.python.org/mailman/listinfo/python-3000-checkins