Some updates on PEP 369 and 370.

PEP 369 still doesn't reflect all changes but it's more up to date
This commit is contained in:
Christian Heimes 2008-01-16 10:21:03 +00:00
parent 9184614867
commit 1e61038030
2 changed files with 85 additions and 25 deletions

View File

@ -80,12 +80,14 @@ No hook was registered
sys.post_import_hooks contains no entry for the module
A hook is registered and the module is not loaded yet
'''''''''''''''''''''''''''''''''''''''''''''''''''''
The import hook registry contains an entry
sys.post_import_hooks["name"] = [hook1]
A module is successfully loaded
'''''''''''''''''''''''''''''''
@ -93,8 +95,14 @@ The import machinery checks if sys.post_import_hooks contains post import
hooks for the newly loaded module. If hooks are found then the hooks are
called in the order they were registered with the module instance as first
argument. The processing of the hooks is stopped when a method raises an
exception. At the end the entry for the module name is removed from
sys.post_import_hooks, even when an error has occured.
exception. At the end the entry for the module name set to None, even
when an error has occured.
Additionally the new ``__notified__`` slot of the module object is set
to ``True`` in order to prevent infinity recursions when the notification
method is called inside a hook. For object which don't subclass from
``PyModule`` a new attribute is added instead.
A module can't be loaded
''''''''''''''''''''''''
@ -102,38 +110,80 @@ A module can't be loaded
The import hooks are neither called nor removed from the registry. It
may be possible to load the module later.
A hook is registered but the module is already loaded
'''''''''''''''''''''''''''''''''''''''''''''''''''''
The hook is fired immediately.
Invariants
----------
The import hook system guarentees certain invariants. XXX
Sample Python implementation
----------------------------
A Python implemenation may look like::
def notify(name):
try:
module = sys.modules[name]
except KeyError:
raise ImportError("Module %s has not been imported" % (name,))
if module.__notified__:
return
try:
module.__notified__ = True
if '.' in name:
notify(name[:name.rfind('.')])
for callback in post_import_hooks[name]:
callback(module)
finally:
post_import_hooks[name] = None
XXX
C API
-----
New PyImport_* API functions
''''''''''''''''''''''''''''
New C API functions
'''''''''''''''''''
``PyObject* PyImport_GetPostImportHooks(void)``
Returns the dict sys.post_import_hooks or NULL
``PyObject* PyImport_NotifyModuleLoaded(PyObject *module)``
``PyObject* PyImport_NotifyLoadedByModule(PyObject *module)``
Notify the post import system that a module was requested. Returns the
module or NULL if an error has occured.
a borrowed reference to the same module object or NULL if an error has
occured. The function calls only the hooks for the module itself an not
its parents. The function must be called with the import lock acquired.
``PyObject* PyImport_NotifyLoadedByName(const char *name)``
``PyImport_NotifyLoadedByName("a.b.c")`` calls
``PyImport_NotifyLoadedByModule()`` for ``a``, ``a.b`` and ``a.b.c``
in that particular order. The modules are retrieved from
``sys.modules``. If a module can't be retrieved, an exception is raised
otherwise the a borrowed reference to ``modname`` is returned.
The hook calls always start with the prime parent module.
The caller of PyImport_NotifyLoadedByName() must hold the import lock!
``PyObject* PyImport_RegisterPostImportHook(PyObject *callable, PyObject *mod_name)``
Register a new hook ``callable`` for the module ``mod_name``
The ``PyImport_PostImportNotify()`` method is called by
``PyImport_ImportModuleLevel()``::
``int PyModule_GetNotified(PyObject *module)``
Returns the status of the ``__notified__`` slot / attribute.
PyImport_ImportModuleLevel(...)
{
...
result = import_module_level(name, globals, locals, fromlist, level);
result = PyImport_PostImportNotify(result);
...
}
``int PyModule_SetNotified(PyObject *module, int status)``
Set the status of the ``__notified__`` slot / attribute.
The ``PyImport_NotifyLoadedByModule()`` method is called inside
``import_submodule()``. The import system makes sure that the import lock
is acquired and the hooks for the parent modules are already called.
Python API
@ -142,16 +192,21 @@ Python API
The import hook registry and two new API methods are exposed through the
``sys`` and ``imp`` module.
sys.post_import_hooks
The dict contains the post import hooks: {"name" : [hook1, hook2], ...}
``sys.post_import_hooks``
The dict contains the post import hooks::
imp.register_post_import_hook(hook: "callable", name: str)
{"name" : [hook1, hook2], ...}
``imp.register_post_import_hook(hook: "callable", name: str)``
Register a new hook *hook* for the module *name*
imp.notify_module_loaded(module: "module instance") -> module
``imp.notify_module_loaded(module: "module instance") -> module``
Notify the system that a module has been loaded. The method is provided
for compatibility with existing lazy / deferred import extensions.
``module.__notified__``
A slot of a module instance. XXX
The when_imported function decorator is also in the imp module,
which is equivalent to::

View File

@ -57,14 +57,14 @@ user site directory
``~/Library/Python/2.6/site-packages``
Unix
``~/.local/lib/python2.6/site-packages``
Windows
``%APPDATA%/Python/Python26/site-packages``
user configuration directory
user data directory
Usually the parent directory of the user site directory. It's meant
for Python version specific data like config files.
for Python version specific data like config files, docs, images
and translations.
Mac
``~/Library/Python/2.6``
@ -81,7 +81,6 @@ user base directory
Mac
``~/Library/Python``
Unix
``~/.local``
Windows
@ -107,7 +106,7 @@ too. [8]_
On Linux ``~/.local`` was chosen in favor over ``~/.python`` because the
directory is already used by several other programs in analogy to
``/usr/local``. [7]_
``/usr/local``. [7]_ [11]_
Implementation
@ -171,6 +170,9 @@ Open Questions
* Should the Windows installer add ``%APPDATA%/Python/Scripts`` to
``PATH``?
* Should the base directory be configurable with an environment variable
like ``PYTHONUSERHOME``?
Reference Implementation
========================
@ -199,6 +201,7 @@ References
.. [4] reference implementation
http://bugs.python.org/issue1799
http://svn.python.org/view/sandbox/trunk/pep370
.. [5] MSDN: CSIDL
http://msdn2.microsoft.com/en-us/library/bb762494.aspx
@ -218,7 +221,9 @@ References
.. [10] Discussion about the bin directory
http://permalink.gmane.org/gmane.comp.python.devel/91095
.. [11] freedesktop.org XGD basedir specs mentions ~/.local
http://www.freedesktop.org/wiki/Specifications/basedir-spec
..
Local Variables:
mode: indented-text