Wouldn't a better approach be a way to customize the type of the module? That would allow people to define behavior for almost anything (__call__, __getattr__, __setattr__, __dir__, various operators etc). This question shouldn't exist "why can't I customize behavior X in a module when I can do it for a class". Why go half-way.
Thanks, -- Ionel Cristian Mărieș, http://blog.ionelmc.ro On Sun, Sep 10, 2017 at 9:48 PM, Ivan Levkivskyi <levkivs...@gmail.com> wrote: > I have written a short PEP as a complement/alternative to PEP 549. > I will be grateful for comments and suggestions. The PEP should > appear online soon. > > -- > Ivan > > *********************************************************** > > PEP: 562 > Title: Module __getattr__ > Author: Ivan Levkivskyi <levkivs...@gmail.com> > Status: Draft > Type: Standards Track > Content-Type: text/x-rst > Created: 09-Sep-2017 > Python-Version: 3.7 > Post-History: 09-Sep-2017 > > > Abstract > ======== > > It is proposed to support ``__getattr__`` function defined on modules to > provide basic customization of module attribute access. > > > Rationale > ========= > > It is sometimes convenient to customize or otherwise have control over > access to module attributes. A typical example is managing deprecation > warnings. Typical workarounds are assigning ``__class__`` of a module > object > to a custom subclass of ``types.ModuleType`` or substituting > ``sys.modules`` > item with a custom wrapper instance. It would be convenient to simplify > this > procedure by recognizing ``__getattr__`` defined directly in a module that > would act like a normal ``__getattr__`` method, except that it will be > defined > on module *instances*. For example:: > > # lib.py > > from warnings import warn > > deprecated_names = ["old_function", ...] > > def _deprecated_old_function(arg, other): > ... > > def __getattr__(name): > if name in deprecated_names: > warn(f"{name} is deprecated", DeprecationWarning) > return globals()[f"_deprecated_{name}"] > raise AttributeError(f"module {__name__} has no attribute {name}") > > # main.py > > from lib import old_function # Works, but emits the warning > > There is a related proposal PEP 549 that proposes to support instance > properties for a similar functionality. The difference is this PEP proposes > a faster and simpler mechanism, but provides more basic customization. > An additional motivation for this proposal is that PEP 484 already defines > the use of module ``__getattr__`` for this purpose in Python stub files, > see [1]_. > > > Specification > ============= > > The ``__getattr__`` function at the module level should accept one argument > which is a name of an attribute and return the computed value or raise > an ``AttributeError``:: > > def __getattr__(name: str) -> Any: ... > > This function will be called only if ``name`` is not found in the module > through the normal attribute lookup. > > The reference implementation for this PEP can be found in [2]_. > > > Backwards compatibility and impact on performance > ================================================= > > This PEP may break code that uses module level (global) name > ``__getattr__``. > The performance implications of this PEP are minimal, since ``__getattr__`` > is called only for missing attributes. > > > References > ========== > > .. [1] PEP 484 section about ``__getattr__`` in stub files > (https://www.python.org/dev/peps/pep-0484/#stub-files) > > .. [2] The reference implementation > (https://github.com/ilevkivskyi/cpython/pull/3/files) > > > Copyright > ========= > > This document has been placed in the public domain. > > _______________________________________________ > Python-ideas mailing list > Python-ideas@python.org > https://mail.python.org/mailman/listinfo/python-ideas > Code of Conduct: http://python.org/psf/codeofconduct/ > >
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/