<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>