<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <p><br>
    </p>
    <br>
    <div class="moz-cite-prefix">On 09/06/2017 08:26 AM, Guido van
      Rossum wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAP7+vJK2XY2mYMSNnOcVqeQye7inB5Mz85wfmyymvBppndMiiA@mail.gmail.com">
      <div dir="ltr">
        <div>So we've seen a real use case for __class__ assignment:
          deprecating things on access. That use case could also be
          solved if modules natively supported defining __getattr__
          (with the same "only used if attribute not found otherwise"
          semantics as it has on classes), but it couldn't be solved
          using @property (or at least it would be quite hacky).<br>
        </div>
      </div>
    </blockquote>
    <br>
    I guess it's a matter of perspective.  I solved this problem using
    @property, and I don't think it's particularly hacky.  (See my
    implementation at the bottom of this email).  The worst thing it
    does is look up the current module via sys.modules[__name__]...
    which Nathaniel's code also must do.<br>
    <br>
    My example is a lot simpler than Nathaniel's code but it's just a
    proof-of-concept.  Nathaniel's code does much more.  In particular,
    I didn't override __dir__ to hide the deprecated attributes; doing
    that would mean assigning to __class__ just as Nathaniel does.  (If
    you're actually curious to see it I could add that to the
    proof-of-concept.)<br>
    <br>
    IMO my PEP strikes the right balance.  @property is far more popular
    than __getattr__ or __getattribute__; 19 times out of 20, people use
    @property.  Meanwhile, people for whom @property is insufficient
    (like Nathaniel) can already assign to module.__class__ and override
    __getattr__, __getattribute__, __del__, or any other existing magic
    method.  In other words: the commonplace is easy, and the unusual is
    possible.  Perfect!<br>
    <br>
    <br>
    <i>/arry<br>
      <br>
      -----<br>
      <br>
    </i>test_deprecated.py:<br>
    <blockquote><tt>import depmod<br>
        <br>
        print(depmod.depr1) # throws an exception</tt><br>
    </blockquote>
    <br>
    depmod.py:<br>
    <blockquote><tt># module with deprecated properties<br>
        import sys<br>
        <br>
        _deprecated_properies = (<br>
            ("depr1", 33),<br>
            ("depr2", 44),<br>
            )<br>
        <br>
        __module__ = sys.modules[__name__]<br>
        def set_deprecated_property(name, value):<br>
            @property<br>
            def prop(self):<br>
                raise RuntimeError(f"property '{name}' is deprecated")<br>
                return value<br>
            setattr(__module__, name, prop)<br>
        <br>
        for name, value in _deprecated_properies:<br>
            set_deprecated_property(name, value)</tt><br>
    </blockquote>
    <br>
  </body>
</html>