Updates following recent discussions (#470)
This commit is contained in:
parent
2a0cc286f2
commit
8f2d854856
65
pep-0562.rst
65
pep-0562.rst
|
@ -1,5 +1,5 @@
|
||||||
PEP: 562
|
PEP: 562
|
||||||
Title: Module __getattr__
|
Title: Module __getattr__ and __dir__
|
||||||
Author: Ivan Levkivskyi <levkivskyi@gmail.com>
|
Author: Ivan Levkivskyi <levkivskyi@gmail.com>
|
||||||
Status: Draft
|
Status: Draft
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
|
@ -12,8 +12,9 @@ Post-History: 09-Sep-2017
|
||||||
Abstract
|
Abstract
|
||||||
========
|
========
|
||||||
|
|
||||||
It is proposed to support a ``__getattr__`` function defined on modules to
|
It is proposed to support a ``__getattr__`` and ``__dir__`` functions defined
|
||||||
provide basic customization of module attribute access.
|
+on modules to provide basic customization of module attribute access.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Rationale
|
Rationale
|
||||||
|
@ -79,6 +80,29 @@ An additional motivation for this proposal is that PEP 484 already defines
|
||||||
the use of module ``__getattr__`` for this purpose in Python stub files,
|
the use of module ``__getattr__`` for this purpose in Python stub files,
|
||||||
see [1]_.
|
see [1]_.
|
||||||
|
|
||||||
|
In addition, to allow modifying result of a ``dir()`` call on a module
|
||||||
|
to show deprecated and other dynamically generated attributes, it is
|
||||||
|
proposed to support module level ``__dir__`` function. For example::
|
||||||
|
|
||||||
|
# lib.py
|
||||||
|
|
||||||
|
deprecated_names = ["old_function", ...]
|
||||||
|
__all__ = ["new_function_one", "new_function_two", ...]
|
||||||
|
|
||||||
|
def new_function_one(arg, other):
|
||||||
|
...
|
||||||
|
def new_function_two(arg, other):
|
||||||
|
...
|
||||||
|
|
||||||
|
def __dir__():
|
||||||
|
return sorted(__all__ + deprecated_names)
|
||||||
|
|
||||||
|
# main.py
|
||||||
|
|
||||||
|
import lib
|
||||||
|
|
||||||
|
dir(lib) # prints ["new_function_one", "new_function_two", "old_function", ...]
|
||||||
|
|
||||||
|
|
||||||
Specification
|
Specification
|
||||||
=============
|
=============
|
||||||
|
@ -92,15 +116,44 @@ an ``AttributeError``::
|
||||||
This function will be called only if ``name`` is not found in the module
|
This function will be called only if ``name`` is not found in the module
|
||||||
through the normal attribute lookup.
|
through the normal attribute lookup.
|
||||||
|
|
||||||
|
The ``__dir__`` function should accept no arguments, and return
|
||||||
|
a list of strings that represents the names accessible on module::
|
||||||
|
|
||||||
|
def __dir__() -> List[str]: ...
|
||||||
|
|
||||||
|
If present, this function overrides the standard ``dir()`` search on
|
||||||
|
a module.
|
||||||
|
|
||||||
The reference implementation for this PEP can be found in [2]_.
|
The reference implementation for this PEP can be found in [2]_.
|
||||||
|
|
||||||
|
|
||||||
Backwards compatibility and impact on performance
|
Backwards compatibility and impact on performance
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
This PEP may break code that uses module level (global) name ``__getattr__``.
|
This PEP may break code that uses module level (global) names ``__getattr__``
|
||||||
The performance implications of this PEP are minimal, since ``__getattr__``
|
and ``__dir__``. The performance implications of this PEP are minimal,
|
||||||
is called only for missing attributes.
|
since ``__getattr__`` is called only for missing attributes.
|
||||||
|
|
||||||
|
|
||||||
|
Discussion
|
||||||
|
==========
|
||||||
|
|
||||||
|
Note that the use of module ``__getattr__`` requires care to keep the referred
|
||||||
|
objects pickleable. For example, the ``__name__`` attribute of a function
|
||||||
|
should correspond to the name with which it is accessible via
|
||||||
|
``__getattr__``::
|
||||||
|
|
||||||
|
def keep_pickleable(func):
|
||||||
|
func.__name__ = func.__name__.replace('_deprecated_', '')
|
||||||
|
func.__qualname__ = func.__qualname__.replace('_deprecated_', '')
|
||||||
|
return func
|
||||||
|
|
||||||
|
@keep_pickleable
|
||||||
|
def _deprecated_old_function(arg, other):
|
||||||
|
...
|
||||||
|
|
||||||
|
One should be also careful to avoid recursion as one would do with
|
||||||
|
a class level ``__getattr__``.
|
||||||
|
|
||||||
|
|
||||||
References
|
References
|
||||||
|
|
Loading…
Reference in New Issue