<div dir="ltr"><div class="gmail_default" style="font-family:trebuchet ms,sans-serif">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.<br></div></div><div class="gmail_extra"><br clear="all"><div><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div><span style="font-family:trebuchet ms,sans-serif"><span style="color:rgb(51,51,51)"><br><font size="2"><span style="color:rgb(51,51,51)">Thanks,</span><br><span style="color:rgb(153,153,153)">-- Ionel</span></font></span><font size="2"><font style="color:rgb(153,153,153)"> Cristian Mărieș, <a href="http://blog.ionelmc.ro" target="_blank">http://blog.ionelmc.ro</a><br></font></font></span></div></div></div></div></div></div></div>
<br><div class="gmail_quote">On Sun, Sep 10, 2017 at 9:48 PM, Ivan Levkivskyi <span dir="ltr"><<a href="mailto:levkivskyi@gmail.com" target="_blank">levkivskyi@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">I have written a short PEP as a complement/alternative to PEP 549.<br>I will be grateful for comments and suggestions. The PEP should<br>appear online soon.<br><br>--<br>Ivan<br><br>******************************<wbr>*****************************<br><br>PEP: 562<br>Title: Module __getattr__<br>Author: Ivan Levkivskyi <<a href="mailto:levkivskyi@gmail.com" target="_blank">levkivskyi@gmail.com</a>><br>Status: Draft<br>Type: Standards Track<br>Content-Type: text/x-rst<br>Created: 09-Sep-2017<br>Python-Version: 3.7<br>Post-History: 09-Sep-2017<br><br><br>Abstract<br>========<br><br>It is proposed to support ``__getattr__`` function defined on modules to<br>provide basic customization of module attribute access.<br><br><br>Rationale<br>=========<br><br>It is sometimes convenient to customize or otherwise have control over<br>access to module attributes. A typical example is managing deprecation<br>warnings. Typical workarounds are assigning ``__class__`` of a module object<br>to a custom subclass of ``types.ModuleType`` or substituting ``sys.modules``<br>item with a custom wrapper instance. It would be convenient to simplify this<br>procedure by recognizing ``__getattr__`` defined directly in a module that<br>would act like a normal ``__getattr__`` method, except that it will be defined<br>on module *instances*. For example::<br><br>  # lib.py<br><br>  from warnings import warn<br><br>  deprecated_names = ["old_function", ...]<br><br>  def _deprecated_old_function(arg, other):<br>      ...<br><br>  def __getattr__(name):<br>      if name in deprecated_names:<br>          warn(f"{name} is deprecated", DeprecationWarning)<br>          return globals()[f"_deprecated_{name}<wbr>"]<br>      raise AttributeError(f"module {__name__} has no attribute {name}")<br><br>  # main.py<br><br>  from lib import old_function  # Works, but emits the warning<br><br>There is a related proposal PEP 549 that proposes to support instance<br>properties for a similar functionality. The difference is this PEP proposes<br>a faster and simpler mechanism, but provides more basic customization.<br>An additional motivation for this proposal is that PEP 484 already defines<br>the use of module ``__getattr__`` for this purpose in Python stub files,<br>see [1]_.<br><br><br>Specification<br>=============<br><br>The ``__getattr__`` function at the module level should accept one argument<br>which is a name of an attribute and return the computed value or raise<br>an ``AttributeError``::<br><br>  def __getattr__(name: str) -> Any: ...<br><br>This function will be called only if ``name`` is not found in the module<br>through the normal attribute lookup.<br><br>The reference implementation for this PEP can be found in [2]_.<br><br><br>Backwards compatibility and impact on performance<br>==============================<wbr>===================<br><br>This PEP may break code that uses module level (global) name ``__getattr__``.<br>The performance implications of this PEP are minimal, since ``__getattr__``<br>is called only for missing attributes.<br><br><br>References<br>==========<br><br>.. [1] PEP 484 section about ``__getattr__`` in stub files<br>   (<a href="https://www.python.org/dev/peps/pep-0484/#stub-files" target="_blank">https://www.python.org/dev/<wbr>peps/pep-0484/#stub-files</a>)<br><br>.. [2] The reference implementation<br>   (<a href="https://github.com/ilevkivskyi/cpython/pull/3/files" target="_blank">https://github.com/<wbr>ilevkivskyi/cpython/pull/3/<wbr>files</a>)<br><br><br>Copyright<br>=========<br><br>This document has been placed in the public domain.</div>
<br>______________________________<wbr>_________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/<wbr>mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/<wbr>codeofconduct/</a><br>
<br></blockquote></div><br></div>