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:
parent
9184614867
commit
1e61038030
93
pep-0369.txt
93
pep-0369.txt
|
@ -80,12 +80,14 @@ No hook was registered
|
||||||
|
|
||||||
sys.post_import_hooks contains no entry for the module
|
sys.post_import_hooks contains no entry for the module
|
||||||
|
|
||||||
|
|
||||||
A hook is registered and the module is not loaded yet
|
A hook is registered and the module is not loaded yet
|
||||||
'''''''''''''''''''''''''''''''''''''''''''''''''''''
|
'''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||||
|
|
||||||
The import hook registry contains an entry
|
The import hook registry contains an entry
|
||||||
sys.post_import_hooks["name"] = [hook1]
|
sys.post_import_hooks["name"] = [hook1]
|
||||||
|
|
||||||
|
|
||||||
A module is successfully loaded
|
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
|
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
|
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
|
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
|
exception. At the end the entry for the module name set to None, even
|
||||||
sys.post_import_hooks, even when an error has occured.
|
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
|
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
|
The import hooks are neither called nor removed from the registry. It
|
||||||
may be possible to load the module later.
|
may be possible to load the module later.
|
||||||
|
|
||||||
|
|
||||||
A hook is registered but the module is already loaded
|
A hook is registered but the module is already loaded
|
||||||
'''''''''''''''''''''''''''''''''''''''''''''''''''''
|
'''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||||
|
|
||||||
The hook is fired immediately.
|
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
|
C API
|
||||||
-----
|
-----
|
||||||
|
|
||||||
New PyImport_* API functions
|
New C API functions
|
||||||
''''''''''''''''''''''''''''
|
'''''''''''''''''''
|
||||||
|
|
||||||
``PyObject* PyImport_GetPostImportHooks(void)``
|
``PyObject* PyImport_GetPostImportHooks(void)``
|
||||||
Returns the dict sys.post_import_hooks or NULL
|
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
|
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)``
|
``PyObject* PyImport_RegisterPostImportHook(PyObject *callable, PyObject *mod_name)``
|
||||||
Register a new hook ``callable`` for the module ``mod_name``
|
Register a new hook ``callable`` for the module ``mod_name``
|
||||||
|
|
||||||
The ``PyImport_PostImportNotify()`` method is called by
|
``int PyModule_GetNotified(PyObject *module)``
|
||||||
``PyImport_ImportModuleLevel()``::
|
Returns the status of the ``__notified__`` slot / attribute.
|
||||||
|
|
||||||
PyImport_ImportModuleLevel(...)
|
``int PyModule_SetNotified(PyObject *module, int status)``
|
||||||
{
|
Set the status of the ``__notified__`` slot / attribute.
|
||||||
...
|
|
||||||
result = import_module_level(name, globals, locals, fromlist, level);
|
|
||||||
result = PyImport_PostImportNotify(result);
|
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
|
Python API
|
||||||
|
@ -142,16 +192,21 @@ Python API
|
||||||
The import hook registry and two new API methods are exposed through the
|
The import hook registry and two new API methods are exposed through the
|
||||||
``sys`` and ``imp`` module.
|
``sys`` and ``imp`` module.
|
||||||
|
|
||||||
sys.post_import_hooks
|
``sys.post_import_hooks``
|
||||||
The dict contains the post import hooks: {"name" : [hook1, hook2], ...}
|
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*
|
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
|
Notify the system that a module has been loaded. The method is provided
|
||||||
for compatibility with existing lazy / deferred import extensions.
|
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,
|
The when_imported function decorator is also in the imp module,
|
||||||
which is equivalent to::
|
which is equivalent to::
|
||||||
|
|
||||||
|
|
17
pep-0370.txt
17
pep-0370.txt
|
@ -57,14 +57,14 @@ user site directory
|
||||||
``~/Library/Python/2.6/site-packages``
|
``~/Library/Python/2.6/site-packages``
|
||||||
Unix
|
Unix
|
||||||
``~/.local/lib/python2.6/site-packages``
|
``~/.local/lib/python2.6/site-packages``
|
||||||
|
|
||||||
Windows
|
Windows
|
||||||
``%APPDATA%/Python/Python26/site-packages``
|
``%APPDATA%/Python/Python26/site-packages``
|
||||||
|
|
||||||
user configuration directory
|
user data directory
|
||||||
|
|
||||||
Usually the parent directory of the user site directory. It's meant
|
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
|
Mac
|
||||||
``~/Library/Python/2.6``
|
``~/Library/Python/2.6``
|
||||||
|
@ -81,7 +81,6 @@ user base directory
|
||||||
|
|
||||||
Mac
|
Mac
|
||||||
``~/Library/Python``
|
``~/Library/Python``
|
||||||
|
|
||||||
Unix
|
Unix
|
||||||
``~/.local``
|
``~/.local``
|
||||||
Windows
|
Windows
|
||||||
|
@ -107,7 +106,7 @@ too. [8]_
|
||||||
|
|
||||||
On Linux ``~/.local`` was chosen in favor over ``~/.python`` because the
|
On Linux ``~/.local`` was chosen in favor over ``~/.python`` because the
|
||||||
directory is already used by several other programs in analogy to
|
directory is already used by several other programs in analogy to
|
||||||
``/usr/local``. [7]_
|
``/usr/local``. [7]_ [11]_
|
||||||
|
|
||||||
|
|
||||||
Implementation
|
Implementation
|
||||||
|
@ -171,6 +170,9 @@ Open Questions
|
||||||
* Should the Windows installer add ``%APPDATA%/Python/Scripts`` to
|
* Should the Windows installer add ``%APPDATA%/Python/Scripts`` to
|
||||||
``PATH``?
|
``PATH``?
|
||||||
|
|
||||||
|
* Should the base directory be configurable with an environment variable
|
||||||
|
like ``PYTHONUSERHOME``?
|
||||||
|
|
||||||
|
|
||||||
Reference Implementation
|
Reference Implementation
|
||||||
========================
|
========================
|
||||||
|
@ -199,6 +201,7 @@ References
|
||||||
|
|
||||||
.. [4] reference implementation
|
.. [4] reference implementation
|
||||||
http://bugs.python.org/issue1799
|
http://bugs.python.org/issue1799
|
||||||
|
http://svn.python.org/view/sandbox/trunk/pep370
|
||||||
|
|
||||||
.. [5] MSDN: CSIDL
|
.. [5] MSDN: CSIDL
|
||||||
http://msdn2.microsoft.com/en-us/library/bb762494.aspx
|
http://msdn2.microsoft.com/en-us/library/bb762494.aspx
|
||||||
|
@ -218,7 +221,9 @@ References
|
||||||
.. [10] Discussion about the bin directory
|
.. [10] Discussion about the bin directory
|
||||||
http://permalink.gmane.org/gmane.comp.python.devel/91095
|
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:
|
Local Variables:
|
||||||
mode: indented-text
|
mode: indented-text
|
||||||
|
|
Loading…
Reference in New Issue