CINXE.COM
Extend PEP 562 with __setattr__ for modules? - Ideas - Discussions on Python.org
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Extend PEP 562 with __setattr__ for modules? - Ideas - Discussions on Python.org</title> <meta name="description" content="Since CPython 3.5 it’s possible to customize setting module attributes by setting __class__ attribute. Unfortunately, this coming with a measurable speed regression for attribute access: $ cat b.py x = 1 $ python -m ti&hellip;"> <meta name="generator" content="Discourse 3.5.0.beta3-dev - https://github.com/discourse/discourse version 67d083ede00cd0cd210f7f8ea9cd9a8401e7ed50"> <link rel="icon" type="image/png" href="https://us1.discourse-cdn.com/flex002/uploads/python1/optimized/1X/9997f0605d56c4bfecd63594f52f42cdafd6b06a_2_32x32.png"> <link rel="apple-touch-icon" type="image/png" href="https://us1.discourse-cdn.com/flex002/uploads/python1/optimized/1X/4c06143de7870c35963b818b15b395092a434991_2_180x180.png"> <meta name="theme-color" media="(prefers-color-scheme: light)" content="#fff"> <meta name="theme-color" media="(prefers-color-scheme: dark)" content="#111111"> <meta name="color-scheme" content="light dark"> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, viewport-fit=cover"> <link rel="canonical" href="https://discuss.python.org/t/extend-pep-562-with-setattr-for-modules/25506" /> <link rel="search" type="application/opensearchdescription+xml" href="https://discuss.python.org/opensearch.xml" title="Discussions on Python.org Search"> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/color_definitions_base__2_63793e0ef886931ea57b1bd3af879a1276bd113f.css?__ws=discuss.python.org" media="(prefers-color-scheme: light)" rel="stylesheet" class="light-scheme"/><link href="https://sea2.discourse-cdn.com/flex002/stylesheets/color_definitions_dark_1_2_43abcefbdd9beefcd331bc023542f97eec02aae7.css?__ws=discuss.python.org" media="(prefers-color-scheme: dark)" rel="stylesheet" class="dark-scheme" data-scheme-id="1"/> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/desktop_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="desktop" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/automation_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="automation" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/checklist_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="checklist" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-ai_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-ai" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-akismet_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-akismet" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-chat-integration_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-chat-integration" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-data-explorer_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-data-explorer" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-details_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-details" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-lazy-videos_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-lazy-videos" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-local-dates_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-local-dates" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-math_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-math" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-narrative-bot_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-narrative-bot" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-policy_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-policy" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-presence_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-presence" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-solved_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-solved" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-templates_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-templates" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-topic-voting_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-topic-voting" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-user-notes_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-user-notes" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/footnote_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="footnote" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/hosted-site_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="hosted-site" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/poll_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="poll" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/spoiler-alert_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="spoiler-alert" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-ai_desktop_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-ai_desktop" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/discourse-topic-voting_desktop_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="discourse-topic-voting_desktop" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/poll_desktop_198dd31b976770ad5c9d19c177284c74ab264d5c.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="poll_desktop" /> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/desktop_theme_4_2e811723c7b3a9d9c0b07883b47c1326e5e88f0b.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="desktop_theme" data-theme-id="4" data-theme-name="unformatted code detector"/> <link href="https://sea2.discourse-cdn.com/flex002/stylesheets/desktop_theme_2_a9849aa38830bf34f182cb074510772b69ba2039.css?__ws=discuss.python.org" media="all" rel="stylesheet" data-target="desktop_theme" data-theme-id="2" data-theme-name="light"/> <link rel="alternate nofollow" type="application/rss+xml" title="RSS feed of 'Extend PEP 562 with __setattr__ for modules?'" href="https://discuss.python.org/t/extend-pep-562-with-setattr-for-modules/25506.rss" /> <meta property="og:site_name" content="Discussions on Python.org" /> <meta property="og:type" content="website" /> <meta name="twitter:card" content="summary" /> <meta name="twitter:image" content="https://us1.discourse-cdn.com/flex002/uploads/python1/original/1X/f93ff97c4f381b5e8add5a0c163b4ded29f20ed7.png" /> <meta property="og:image" content="https://us1.discourse-cdn.com/flex002/uploads/python1/original/1X/f93ff97c4f381b5e8add5a0c163b4ded29f20ed7.png" /> <meta property="og:url" content="https://discuss.python.org/t/extend-pep-562-with-setattr-for-modules/25506" /> <meta name="twitter:url" content="https://discuss.python.org/t/extend-pep-562-with-setattr-for-modules/25506" /> <meta property="og:title" content="Extend PEP 562 with __setattr__ for modules?" /> <meta name="twitter:title" content="Extend PEP 562 with __setattr__ for modules?" /> <meta property="og:description" content="Since CPython 3.5 it’s possible to customize setting module attributes by setting __class__ attribute. Unfortunately, this coming with a measurable speed regression for attribute access: $ cat b.py x = 1 $ python -m timeit -r11 -s 'import b' 'b.x' 5000000 loops, best of 11: 48.8 nsec per loop $ cat c.py import sys, types x = 1 class _Foo(types.ModuleType): pass sys.modules[__name__].__class__ = _Foo $ python -m timeit -r11 -s 'import c' 'c.x' 2000000 loops, best of 11: 131 nsec per loop For r..." /> <meta name="twitter:description" content="Since CPython 3.5 it’s possible to customize setting module attributes by setting __class__ attribute. Unfortunately, this coming with a measurable speed regression for attribute access: $ cat b.py x = 1 $ python -m timeit -r11 -s 'import b' 'b.x' 5000000 loops, best of 11: 48.8 nsec per loop $ cat c.py import sys, types x = 1 class _Foo(types.ModuleType): pass sys.modules[__name__].__class__ = _Foo $ python -m timeit -r11 -s 'import c' 'c.x' 2000000 loops, best of 11: 131 nsec per loop For r..." /> <meta property="og:article:section" content="Ideas" /> <meta property="og:article:section:color" content="3AB54A" /> <meta name="twitter:label1" value="Reading time" /> <meta name="twitter:data1" value="7 mins 🕑" /> <meta name="twitter:label2" value="Likes" /> <meta name="twitter:data2" value="8 ❤" /> <meta property="article:published_time" content="2023-04-06T05:26:16+00:00" /> <meta property="og:ignore_canonical" content="true" /> <link rel="next" href="/t/extend-pep-562-with-setattr-for-modules/25506?page=2"> </head> <body class="crawler browser-update"> <header> <a href="/"> Discussions on Python.org </a> </header> <div id="main-outlet" class="wrap" role="main"> <div id="topic-title"> <h1> <a href="/t/extend-pep-562-with-setattr-for-modules/25506">Extend PEP 562 with __setattr__ for modules?</a> </h1> <div class="topic-category" itemscope itemtype="http://schema.org/BreadcrumbList"> <span itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"> <a href="/c/ideas/6" class="badge-wrapper bullet" itemprop="item"> <span class='badge-category-bg' style='background-color: #3AB54A'></span> <span class='badge-category clear-badge'> <span class='category-name' itemprop='name'>Ideas</span> </span> </a> <meta itemprop="position" content="1" /> </span> </div> </div> <div itemscope itemtype='http://schema.org/DiscussionForumPosting'> <meta itemprop='headline' content='Extend PEP 562 with __setattr__ for modules?'> <link itemprop='url' href='https://discuss.python.org/t/extend-pep-562-with-setattr-for-modules/25506'> <meta itemprop='datePublished' content='2023-04-06T05:26:16Z'> <meta itemprop='articleSection' content='Ideas'> <meta itemprop='keywords' content=''> <div itemprop='publisher' itemscope itemtype="http://schema.org/Organization"> <meta itemprop='name' content='Python Software Foundation'> <div itemprop='logo' itemscope itemtype="http://schema.org/ImageObject"> <meta itemprop='url' content='https://us1.discourse-cdn.com/flex002/uploads/python1/original/1X/c7591c98caf3b31d4d9c6f322f41ed9d80a50800.png'> </div> </div> <div id='post_1' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/skirpichev'><span itemprop='name'>skirpichev</span></a> (Sergey B Kirpichev) </span> <link itemprop="mainEntityOfPage" href="https://discuss.python.org/t/extend-pep-562-with-setattr-for-modules/25506"> <span class="crawler-post-infos"> <time datetime='2023-04-06T05:26:16Z' class='post-time'> April 6, 2023, 5:26am </time> <meta itemprop='dateModified' content='2023-04-06T05:26:16Z'> <span itemprop='position'>1</span> </span> </div> <div class='post' itemprop='text'> <p>Since CPython 3.5 it’s possible to customize setting module attributes by setting <code>__class__</code> attribute. Unfortunately, this coming with a measurable speed regression for attribute access:</p> <pre><code class="lang-auto">$ cat b.py x = 1 $ python -m timeit -r11 -s 'import b' 'b.x' 5000000 loops, best of 11: 48.8 nsec per loop $ cat c.py import sys, types x = 1 class _Foo(types.ModuleType): pass sys.modules[__name__].__class__ = _Foo $ python -m timeit -r11 -s 'import c' 'c.x' 2000000 loops, best of 11: 131 nsec per loop </code></pre> <p>For reading attributes this could be workarounded with <code>__getattr__</code>, but there is no similar support for <code>__setattr__</code>. Maybe it does make sense as well (or even for <code>__delattr__</code>)? If so, will this require<br> a PEP? (Draft implementation is in <a href="https://github.com/skirpichev/cpython/tree/module-setattr" class="inline-onebox" rel="noopener nofollow ugc">GitHub - skirpichev/cpython at module-setattr</a>)</p> <p>As a background story, this solution come from the mpmath issue <a href="https://github.com/mpmath/mpmath/issues/657" class="inline-onebox" rel="noopener nofollow ugc">ENH: guard against incorrect use of `mp.dps`? · Issue #657 · mpmath/mpmath · GitHub</a> In short, people are trying to set precision attributes not on the context object (mpmath.mp, e.g. mpmath.mp.dps), but on the mpmath module. Probably, this is a very special scenario, but…</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="1" /> <span class='post-likes'>1 Like</span> </div> <div class='crawler-linkback-list' itemscope itemtype='http://schema.org/ItemList'> <div itemprop='itemListElement' itemscope itemtype='http://schema.org/ListItem'> <a itemprop='url' href="https://discuss.python.org/t/pep-726-module-setattr-and-delattr/32640/18">PEP 726: Module __setattr__ and __delattr__</a> <meta itemprop='position' content='3'> </div> <div itemprop='itemListElement' itemscope itemtype='http://schema.org/ListItem'> <a itemprop='url' href="https://discuss.python.org/t/pep-713-callable-modules/26127/40">PEP 713: Callable Modules</a> <meta itemprop='position' content='4'> </div> </div> </div> <div id='post_2' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/brettcannon'><span itemprop='name'>brettcannon</span></a> (Brett Cannon) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-06T22:06:45Z' class='post-time'> April 6, 2023, 10:06pm </time> <meta itemprop='dateModified' content='2023-04-06T22:06:45Z'> <span itemprop='position'>2</span> </span> </div> <div class='post' itemprop='text'> <aside class="quote no-group" data-username="skirpichev" data-post="1" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.python.org/skirpichev/48/10996_2.png" class="avatar"> Sergey B Kirpichev:</div> <blockquote> <p>For reading attributes this could be workarounded with <code>__getattr__</code>, but there is no similar support for <code>__setattr__</code>. Maybe it does make sense as well (or even for <code>__delattr__</code>)?</p> </blockquote> </aside> <p>To be clear, this is <code>__setattr__</code> for module objects?</p> <aside class="quote no-group" data-username="skirpichev" data-post="1" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.python.org/skirpichev/48/10996_2.png" class="avatar"> Sergey B Kirpichev:</div> <blockquote> <p>will this require<br> a PEP?</p> </blockquote> </aside> <p>Not necessarily, but since it would potentially impact all modules and the setting of module attributes it could come to that in the end.</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> <div id='post_3' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/oscarbenjamin'><span itemprop='name'>oscarbenjamin</span></a> (Oscar Benjamin) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T00:48:48Z' class='post-time'> April 7, 2023, 12:48am </time> <meta itemprop='dateModified' content='2023-04-07T00:48:48Z'> <span itemprop='position'>3</span> </span> </div> <div class='post' itemprop='text'> <aside class="quote group-committers" data-username="brettcannon" data-post="2" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.python.org/brettcannon/48/21723_2.png" class="avatar"> Brett Cannon:</div> <blockquote> <p>To be clear, this is <code>__setattr__</code> for module objects?</p> </blockquote> </aside> <p>Yes.</p> <p>The context here is:</p><aside class="onebox githubissue" data-onebox-src="https://github.com/mpmath/mpmath/issues/657"> <header class="source"> <a href="https://github.com/mpmath/mpmath/issues/657" target="_blank" rel="noopener nofollow ugc">github.com/mpmath/mpmath</a> </header> <article class="onebox-body"> <div class="github-row"> <div class="github-icon-container" title="Issue" data-github-private-repo="false"> <svg width="60" height="60" class="github-icon" viewBox="0 0 14 16" aria-hidden="true"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg> </div> <div class="github-info-container"> <h4> <a href="https://github.com/mpmath/mpmath/issues/657" target="_blank" rel="noopener nofollow ugc">ENH: guard against incorrect use of `mp.dps`?</a> </h4> <div class="github-info"> <div class="date"> opened <span class="discourse-local-date" data-format="ll" data-date="2023-02-13" data-time="23:30:24" data-timezone="UTC">11:30PM - 13 Feb 23 UTC</span> </div> <div class="date"> closed <span class="discourse-local-date" data-format="ll" data-date="2024-01-05" data-time="11:36:01" data-timezone="UTC">11:36AM - 05 Jan 24 UTC</span> </div> <div class="user"> <a href="https://github.com/mdhaber" target="_blank" rel="noopener nofollow ugc"> <img alt="mdhaber" src="https://us1.discourse-cdn.com/flex002/uploads/python1/original/2X/e/e04025ba3d57b435998d34ec0d5498cfc60a014f.jpeg" class="onebox-avatar-inline" width="20" height="20" data-dominant-color="978C81"> mdhaber </a> </div> </div> <div class="labels"> <span style="display:inline-block;margin-top:2px;background-color: #B8B8B8;padding: 2px;border-radius: 4px;color: #fff;margin-left: 3px;"> enhancement </span> </div> </div> </div> <div class="github-row"> <p class="github-body-container">I am a SciPy maintainer, and we frequently use mpmath to compute reference value<span class="show-more-container"><a href="" rel="noopener" class="show-more">…</a></span><span class="excerpt hidden">s. (Thank you for your work! It's very helpful.) A common mistake is for contributors to do, e.g.: ```python3 import numpy as np import mpmath as mp # should be from mpmath import mp mp.dps = 50 a, b = mp.mpf(1e-11), mp.mpf(1.001e-11) print(np.float64(mp.ncdf(b) - mp.ncdf(a))) # 3.885780586188048e-15 ``` This suffers from catastrophic cancellation just as: ```python3 from scipy.special import ndtr a, b = 1e-11, 1.001e-11 print(ndtr(b) - ndtr(a)) # 3.885780586188048e-15 ``` does, but the fact that `mpmath` is _not_ working with 50 digits is obscured by the conversion to float. (I've run into other, subtler reasons for not noticing the problem, too.) Another example in the wild: https://github.com/scipy/scipy/issues/18088#issuecomment-1712538038 I know that this is user error and not a bug in `mpmath`, but I wonder if it is possible to guard against this. For instance, `mpmath` doesn't currently have a `dps` attribute. Perhaps it could be added as a property, and a warning (or error) could be raised if modification is attempted, directing the user to `mpmath.mp.dps`?</span></p> </div> </article> <div class="onebox-metadata"> </div> <div style="clear: both"></div> </aside> <p>Without going into the details of the issue it would be useful if there was someway to intercept a user setting an attribute on a module to either warn or raise an error. For example if a user does</p> <pre data-code-wrap="python"><code class="lang-python">import mpmath as mp mp.dps = 100 </code></pre> <p>then that will not work as intended. The correct way is</p> <pre data-code-wrap="python"><code class="lang-python">from mpmath import mp mp.dps = 100 </code></pre> <p>Here <code>mp</code> is a special non-module object that can interpret its <code>dps</code> attribute and do something useful with it.</p> <p>In the interest of communicating errors helpfully to users it would be good to be able to make it an error to set an attribute on a module so e.g. <code>mpmath.dps = 100</code> (where <code>mpmath</code> is a module) could be an error. Currently this is only possible by replacing the module object with a proxy in <code>sys.modules</code> but I expect that being able to protect a module from arbitrary attribute assignment would be a useful feature in general.</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> <div id='post_4' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/methane'><span itemprop='name'>methane</span></a> (Inada Naoki) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T01:54:20Z' class='post-time'> April 7, 2023, 1:54am </time> <meta itemprop='dateModified' content='2023-04-07T01:54:20Z'> <span itemprop='position'>4</span> </span> </div> <div class='post' itemprop='text'> <aside class="quote no-group" data-username="skirpichev" data-post="1" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.python.org/skirpichev/48/10996_2.png" class="avatar"> Sergey B Kirpichev:</div> <blockquote> <p>Since CPython 3.5 it’s possible to customize setting module attributes by setting <code>__class__</code> attribute. Unfortunately, this coming with a measurable speed regression for attribute access:</p> </blockquote> </aside> <p><code>__getattr__</code> has very little performance impact because it is called only when the attribute is not found.</p> <p>On the other hand, <code>__setattr__</code> would be called for every attribute access. So it might have performance impact like <code>__class__</code> hack.</p> <aside class="quote no-group quote-modified" data-username="skirpichev" data-post="1" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.python.org/skirpichev/48/10996_2.png" class="avatar"> Sergey B Kirpichev:</div> <blockquote> <p>As a background story, this solution come from the mpmath issue <a href="https://github.com/mpmath/mpmath/issues/657">ENH: guard against incorrect use of <code>mp.dps</code>? · Issue #657 · mpmath/mpmath · GitHub </a> In short, people are trying to set precision attributes not on the context object (mpmath.mp, e.g. mpmath.mp.dps), but on the mpmath module. Probably, this is a very special scenario, but…</p> </blockquote> </aside> <p>I agree that this is a very specail scenario.</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="1" /> <span class='post-likes'>1 Like</span> </div> </div> <div id='post_5' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/Rosuav'><span itemprop='name'>Rosuav</span></a> (Chris Angelico) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T02:07:43Z' class='post-time'> April 7, 2023, 2:07am </time> <meta itemprop='dateModified' content='2023-04-07T02:07:43Z'> <span itemprop='position'>5</span> </span> </div> <div class='post' itemprop='text'> <aside class="quote group-committers quote-modified" data-username="methane" data-post="4" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.python.org/methane/48/43_2.png" class="avatar"> Inada Naoki:</div> <blockquote> <p><code>__getattr__</code> has very little performance impact because it is called only when the attribute is not found.</p> <p>On the other hand, <code>__setattr__</code> would be called for every attribute access. So it might have performance impact like <code>__class__</code> hack.</p> <aside class="quote no-group quote-modified" data-username="skirpichev" data-post="1" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.python.org/skirpichev/48/10996_2.png" class="avatar"> skirpichev:</div> <blockquote> <p>As a background story, this solution come from the mpmath issue <a href="https://github.com/mpmath/mpmath/issues/657">ENH: guard against incorrect use of <code>mp.dps</code>? · Issue #657 · mpmath/mpmath · GitHub </a> In short, people are trying to set precision attributes not on the context object (mpmath.mp, e.g. mpmath.mp.dps), but on the mpmath module. Probably, this is a very special scenario, but…</p> </blockquote> </aside> <p>I agree that this is a very specail scenario.</p> </blockquote> </aside> <p>With a class, we can define its slots and then any new attributes are instant errors. What if modules could do the same? It wouldn’t let you fully customize the error (and thus point people to the correct way to do things), but it’d prevent the scenario of “no error, just wrong behaviour” and would give people an error that they can ask about.</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="2" /> <span class='post-likes'>2 Likes</span> </div> </div> <div id='post_6' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/stoneleaf'><span itemprop='name'>stoneleaf</span></a> (Ethan Furman) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T02:08:04Z' class='post-time'> April 7, 2023, 2:08am </time> <meta itemprop='dateModified' content='2023-04-07T02:08:04Z'> <span itemprop='position'>6</span> </span> </div> <div class='post' itemprop='text'> <aside class="quote group-committers" data-username="methane" data-post="4" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.python.org/methane/48/43_2.png" class="avatar"> Inada Naoki:</div> <blockquote> <p>On the other hand, <code>__setattr__</code> would be called for every attribute access. So it might have performance impact like <code>__class__</code> hack.</p> </blockquote> </aside> <p><code>__setattr__</code> would only be called when an assignment was attempted; <code>__getattribute__</code> is the one that’s called all the time. (Unless it’s different at the C level.)</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> <div id='post_7' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/skirpichev'><span itemprop='name'>skirpichev</span></a> (Sergey B Kirpichev) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T02:13:35Z' class='post-time'> April 7, 2023, 2:13am </time> <meta itemprop='dateModified' content='2023-04-07T02:13:35Z'> <span itemprop='position'>7</span> </span> </div> <div class='post' itemprop='text'> <aside class="quote group-committers" data-username="methane" data-post="4" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.python.org/methane/48/43_2.png" class="avatar"> Inada Naoki:</div> <blockquote> <p><code>__getattr__</code> has very little performance impact because it is called only when the attribute is not found.</p> </blockquote> </aside> <p>In the above example (wich <code>__class__</code> hack) actually neither <code>__getattr__</code> or <code>__setattr__</code> was changed. Yet attribute reading is affected (~2x speed loss).</p> <aside class="quote group-committers" data-username="methane" data-post="4" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.python.org/methane/48/43_2.png" class="avatar"> Inada Naoki:</div> <blockquote> <p>On the other hand, <code>__setattr__</code> would be called for every attribute access.</p> </blockquote> </aside> <p>Only for setting attributes, here is a test on my branch (same timings as without <code>__class__</code> hack):</p> <pre><code class="lang-auto">$ cat d.py x = 1 def __setattr__(name, value): if name == 'spam': raise AttributeError globals()[name] = value $ python -m timeit -r11 -s 'import d' 'd.x' 5000000 loops, best of 11: 48.8 nsec per loop </code></pre> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> <div id='post_8' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/methane'><span itemprop='name'>methane</span></a> (Inada Naoki) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T02:24:59Z' class='post-time'> April 7, 2023, 2:24am </time> <meta itemprop='dateModified' content='2023-04-07T02:24:59Z'> <span itemprop='position'>8</span> </span> </div> <div class='post' itemprop='text'> <p>Sorry, I meant all attribute assignment.</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> <div id='post_9' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/kknechtel'><span itemprop='name'>kknechtel</span></a> (Karl Knechtel) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T03:39:32Z' class='post-time'> April 7, 2023, 3:39am </time> <meta itemprop='dateModified' content='2023-04-07T03:39:32Z'> <span itemprop='position'>9</span> </span> </div> <div class='post' itemprop='text'> <p>This thread looks to me like there might be some miscommunication going on, so I want to try to share my understanding first.</p> <p>I think that OP is not concerned with slowing down attribute assignment here, because assigning an attribute to an imported module is much less common than looking up an attribute there. The goal is to have <em>some</em> way to intercept attribute assignment so that an exception can be raised to guard against programming errors; of course we should expect this to have <em>some</em> overhead. However, the current best solution for intercepting attribute <em>assignment</em>, means that attribute <em>lookup</em> will <em>also</em> be slowed down. (I assume this is because we now have to work through a Python implementation of the module class instead of using a built-in one.)</p> <p>However, if we add a <code>__setattr__</code> hook to the C implementation, although that doesn’t impact on attribute lookups (satisfying OP’s use case), it presumably would slow down assigning attributes to modules <em>for everybody</em>. OP isn’t bothered by this in a SciPy or mpmath context, but a change like that needs serious consideration since the overhead cost would be paid even by people who <em>don’t</em> plan to use the hook.</p> <hr> <p>Personally, my intuition is that it might still be worthwhile. It’s hard for me to imagine a popular third-party library that <em>expects</em> the user to set attributes on modules imported from the library, enough times to become a performance concern. On the other hand, a tight loop repeatedly calling some library function is pretty easy to imagine (granted, the user could trivially cache this lookup).</p> <p>On the other hand, it’s <em>commonly enough incorrect</em> to assign attributes to a <code>module</code> (after import) that I almost wonder if it needs to be supported by default. (If I had to choose, I find it more annoying not being able to set attributes on an ordinary <code>object</code> instance - that also makes it harder to teach beginners about the concept of attributes in general, at least with my teaching style).</p> <aside class="quote no-group" data-username="Rosuav" data-post="5" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.python.org/rosuav/48/3429_2.png" class="avatar"> Chris Angelico:</div> <blockquote> <p>With a class, we can define its slots and then any new attributes are instant errors. What if modules could do the same? It wouldn’t let you fully customize the error (and thus point people to the correct way to do things), but it’d prevent the scenario of “no error, just wrong behaviour” and would give people an error that they can ask about.</p> </blockquote> </aside> <p>Therefore, I like this suggestion, assuming it works as expected. It should address OP’s use case and, if anything, improve performance rather than making it worse. Meanwhile, people who want to do fancy things with setting attributes on modules still have the option of taking the performance hit of a user-defined subclass (and if they want to do <em>really</em> fancy things, the <code>__setattr__</code> hook is right there for them, because they already defined a class in Python).</p> <p>For bonus points, a bit of standard library support, along the lines of:</p> <pre><code class="lang-auto">from types import ModuleType import sys def module_setattr_hook(func=None): """ A decorator to enable custom logic for setting module attributes. Decorate a top-level function in a module, to make it implement attribute assignment for the module. It should accept three arguments: * self: types.ModuleType - the module being modified. * attr: str -> the name of the attribute being set. * value -> the new value for the attribute. Alternately, just call `module_setattr_hook()` to make it possible to set attributes with no special logic. """ module = sys.modules[func.__module__] cls = module.__class__ if cls is types.ModuleType: # base type, needs to be swapped with a user type cls = type('_UserModule', (types.ModuleType,), {}) module.__class__ = cls # otherwise, just monkey-patch the existing type if func is not None: cls.__setattr__ = func return func </code></pre> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> <div id='post_10' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/skirpichev'><span itemprop='name'>skirpichev</span></a> (Sergey B Kirpichev) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T04:41:30Z' class='post-time'> April 7, 2023, 4:41am </time> <meta itemprop='dateModified' content='2023-04-07T04:41:30Z'> <span itemprop='position'>10</span> </span> </div> <div class='post' itemprop='text'> <aside class="quote no-group" data-username="kknechtel" data-post="9" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://avatars.discourse-cdn.com/v4/letter/k/e47c2d/48.png" class="avatar"> Karl Knechtel:</div> <blockquote> <p>it presumably would slow down assigning attributes to modules <em>for everybody</em>. OP isn’t bothered by this</p> </blockquote> </aside> <p>The problem is that I don’t see a measurable difference for naive tests with timeit (~same numbers in the main and on the branch):</p> <pre><code class="lang-auto">$ cat b.py x = 1 $ python -m timeit -r11 -s 'import b' 'b.x=2' # name exists in __dict__ 5000000 loops, best of 11: 97.4 nsec per loop $ python -m timeit -r11 -s 'import b' 'b.y=2' 5000000 loops, best of 11: 97.4 nsec per loop </code></pre> <p>That’s why this obvious concern wasn’t mentioned in my top post:)</p> <p>The cost is an additional call <code>PyDict_GetItemWithError()</code> to check if there is a <code>__getattr__</code> helper.</p> <p>Also, as you pointed out, intensive using of attribute assignments for modules is a <em>very</em> exotic scenario, while reading attributes - is not. Unfortunately, the <code>__class__</code> hack affects the second case even if you are using it to customize assignment of attributes… So, slight speed regression for exotic scenarios seems to be a fair trade off.</p> <aside class="quote no-group" data-username="kknechtel" data-post="9" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://avatars.discourse-cdn.com/v4/letter/k/e47c2d/48.png" class="avatar"> Karl Knechtel:</div> <blockquote> <p>It should address OP’s use case</p> </blockquote> </aside> <p>Only partially. It lacks a user-friendly exception message.</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> <div id='post_11' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/kknechtel'><span itemprop='name'>kknechtel</span></a> (Karl Knechtel) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T06:25:19Z' class='post-time'> April 7, 2023, 6:25am </time> <meta itemprop='dateModified' content='2023-04-07T06:25:19Z'> <span itemprop='position'>11</span> </span> </div> <div class='post' itemprop='text'> <aside class="quote no-group" data-username="skirpichev" data-post="10" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.python.org/skirpichev/48/10996_2.png" class="avatar"> Sergey B Kirpichev:</div> <blockquote> <p>The problem is that I don’t see a measurable difference for naive tests with timeit (~same numbers in the main and on the branch):</p> </blockquote> </aside> <p>Well, yes; you’re comparing two use cases within the current existing functionality. If the built-in type had a <code>__setattr__</code> hook, it would have to be invoked in both cases, and doing so would take more time than the current approach, which doesn’t.</p> <aside class="quote no-group" data-username="skirpichev" data-post="10" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.python.org/skirpichev/48/10996_2.png" class="avatar"> Sergey B Kirpichev:</div> <blockquote> <p>It lacks a user-friendly exception message.</p> </blockquote> </aside> <p>Does the standard <code>AttributeError</code> not explain well enough, given the circumstance?<br> … Actually, I have some separate proposals there.</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> <div id='post_12' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/methane'><span itemprop='name'>methane</span></a> (Inada Naoki) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T07:49:12Z' class='post-time'> April 7, 2023, 7:49am </time> <meta itemprop='dateModified' content='2023-04-07T07:49:12Z'> <span itemprop='position'>12</span> </span> </div> <div class='post' itemprop='text'> <aside class="quote no-group" data-username="kknechtel" data-post="9" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://avatars.discourse-cdn.com/v4/letter/k/e47c2d/48.png" class="avatar"> Karl Knechtel:</div> <blockquote> <p>However, if we add a <code>__setattr__</code> hook to the C implementation, although that doesn’t impact on attribute lookups (satisfying OP’s use case), it presumably would slow down assigning attributes to modules <em>for everybody</em>.</p> </blockquote> </aside> <p>Not only that. It makes:</p> <ul> <li>Python semantics complex.</li> <li>Cpython and other implementation complex.</li> <li>Need special care for it when optimizing the interpreter.</li> </ul> <p>Python is very dynamic language already. I am very conservative about making Python even more dynamic.</p> <p>Emitting DeprecationWarning and lazy import are useful for many packages. That’s why I like module <code>__getattr__</code>. I don’t know how module <code>__setattr__</code> is useful for packages other than this specific case.</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> <div id='post_13' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/skirpichev'><span itemprop='name'>skirpichev</span></a> (Sergey B Kirpichev) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T08:08:25Z' class='post-time'> April 7, 2023, 8:08am </time> <meta itemprop='dateModified' content='2023-04-07T08:08:25Z'> <span itemprop='position'>13</span> </span> </div> <div class='post' itemprop='text'> <aside class="quote no-group" data-username="kknechtel" data-post="11" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://avatars.discourse-cdn.com/v4/letter/k/e47c2d/48.png" class="avatar"> Karl Knechtel:</div> <blockquote> <p>If the built-in type had a <code>__setattr__</code> hook,</p> </blockquote> </aside> <p>You meant if the module had <code>__setattr__</code> hook, right? That’s true, but we are talking about the cost for people who <em>don’t plan to use the hook</em>. In this case it should be safe to assume there is no such name in the module’s dict. From PEP 562:</p> <blockquote> <p>This PEP may break code that uses module level (global) names <code>__getattr__</code> and<br> <code>__dir__</code>. (But the language reference explicitly reserves <em>all</em> undocumented dunder<br> names, and allows “breakage without warning”</p> </blockquote> <aside class="quote no-group" data-username="kknechtel" data-post="11" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://avatars.discourse-cdn.com/v4/letter/k/e47c2d/48.png" class="avatar"> Karl Knechtel:</div> <blockquote> <p>Does the standard <code>AttributeError</code> not explain well enough</p> </blockquote> </aside> <p>Well, it certainly doesn’t show to user how to fix the problem.</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> <div id='post_14' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/ntessore'><span itemprop='name'>ntessore</span></a> (Nicolas Tessore) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T08:09:11Z' class='post-time'> April 7, 2023, 8:09am </time> <meta itemprop='dateModified' content='2023-04-07T08:09:11Z'> <span itemprop='position'>14</span> </span> </div> <div class='post' itemprop='text'> <aside class="quote group-committers" data-username="methane" data-post="12" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.python.org/methane/48/43_2.png" class="avatar"> Inada Naoki:</div> <blockquote> <p>I don’t know how module <code>__setattr__</code> is useful for packages other than this specific case.</p> </blockquote> </aside> <p>Write-protecting module constants could be useful, if <code>__setattr__</code> was called on all write access.</p> <p>PS: But more appropriate and useful would be module-level descriptors.</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> <div id='post_15' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/methane'><span itemprop='name'>methane</span></a> (Inada Naoki) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T08:13:20Z' class='post-time'> April 7, 2023, 8:13am </time> <meta itemprop='dateModified' content='2023-04-07T08:13:20Z'> <span itemprop='position'>15</span> </span> </div> <div class='post' itemprop='text'> <p>How is it important for Python future?<br> I think this change needs a PEP. The PEP can list such use cases.</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="2" /> <span class='post-likes'>2 Likes</span> </div> </div> <div id='post_16' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/kknechtel'><span itemprop='name'>kknechtel</span></a> (Karl Knechtel) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T08:23:03Z' class='post-time'> April 7, 2023, 8:23am </time> <meta itemprop='dateModified' content='2023-04-07T08:23:03Z'> <span itemprop='position'>16</span> </span> </div> <div class='post' itemprop='text'> <p>It just occurred to me, trying to control <code>__setattr__</code> on modules would also cause problems for packages. If I want to <code>import a.b</code>, it will be problematic if <code>a</code> is a <code>module</code> instance and the default <code>module</code> denies (via <code>__slots__</code>) permission to attach any attributes that weren’t defined during <code>a</code>’s creation.</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> <div id='post_17' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/Rosuav'><span itemprop='name'>Rosuav</span></a> (Chris Angelico) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T09:18:30Z' class='post-time'> April 7, 2023, 9:18am </time> <meta itemprop='dateModified' content='2023-04-07T09:18:30Z'> <span itemprop='position'>17</span> </span> </div> <div class='post' itemprop='text'> <aside class="quote no-group" data-username="kknechtel" data-post="16" data-topic="25506"> <div class="title"> <div class="quote-controls"></div> <img loading="lazy" alt="" width="24" height="24" src="https://avatars.discourse-cdn.com/v4/letter/k/e47c2d/48.png" class="avatar"> Karl Knechtel:</div> <blockquote> <p>It just occurred to me, trying to control <code>__setattr__</code> on modules would also cause problems for packages. If I want to <code>import a.b</code>, it will be problematic if <code>a</code> is a <code>module</code> instance and the default <code>module</code> denies (via <code>__slots__</code>) permission to attach any attributes that weren’t defined</p> </blockquote> </aside> <p>I think the response to that would be “don’t do that, then”. Use of <code>__slots__</code> would be incompatible with lazy loading of a package’s modules.</p> <p>(Eager loading would be no harder to handle than any other names, you just import them all and then <code>__slots__ = tuple(globals())</code> or whatever the recommended idiom is.)</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> <div id='post_18' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/kknechtel'><span itemprop='name'>kknechtel</span></a> (Karl Knechtel) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-07T10:22:54Z' class='post-time'> April 7, 2023, 10:22am </time> <meta itemprop='dateModified' content='2023-04-07T10:22:54Z'> <span itemprop='position'>18</span> </span> </div> <div class='post' itemprop='text'> <p>I misunderstood your original suggestion, then. I thought you were proposing to add such a mechanism to the builtin type.</p> <p>I figured that using <code>__slots__</code> on non-package modules is already possible, if you derive from <code>types.ModuleType</code>. However, it seems that such a declaration is ignored.</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> <div id='post_19' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/methane'><span itemprop='name'>methane</span></a> (Inada Naoki) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-24T04:35:21Z' class='post-time'> April 24, 2023, 4:35am </time> <meta itemprop='dateModified' content='2023-04-24T04:35:21Z'> <span itemprop='position'>19</span> </span> </div> <div class='post' itemprop='text'> <p>After reading PEP 713, I am +1 for both of <code>__call__</code> and <code>__setattr__</code>.</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> <div id='post_20' itemprop='comment' itemscope itemtype='http://schema.org/Comment' class='topic-body crawler-post'> <div class='crawler-post-meta'> <span class="creator" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a itemprop="url" rel='nofollow' href='https://discuss.python.org/u/skirpichev'><span itemprop='name'>skirpichev</span></a> (Sergey B Kirpichev) </span> <span class="crawler-post-infos"> <time itemprop='datePublished' datetime='2023-04-24T05:45:08Z' class='post-time'> April 24, 2023, 5:45am </time> <meta itemprop='dateModified' content='2023-04-24T05:45:08Z'> <span itemprop='position'>20</span> </span> </div> <div class='post' itemprop='text'> <p>Thanks for blessing. I’ll try to prepare a PEP. Unfortunately, probably now there is no chance that this could enter 3.12 if accepted…</p> </div> <div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="interactionType" content="http://schema.org/LikeAction"/> <meta itemprop="userInteractionCount" content="0" /> <span class='post-likes'></span> </div> </div> </div> <div role='navigation' itemscope itemtype='http://schema.org/SiteNavigationElement' class="topic-body crawler-post"> <span itemprop='name'><b><a rel="next" itemprop="url" href="/t/extend-pep-562-with-setattr-for-modules/25506?page=2">next page →</a></b></span> </div> </div> <footer class="container wrap"> <nav class='crawler-nav'> <ul> <li itemscope itemtype='http://schema.org/SiteNavigationElement'> <span itemprop='name'> <a href='/' itemprop="url">Home </a> </span> </li> <li itemscope itemtype='http://schema.org/SiteNavigationElement'> <span itemprop='name'> <a href='/categories' itemprop="url">Categories </a> </span> </li> <li itemscope itemtype='http://schema.org/SiteNavigationElement'> <span itemprop='name'> <a href='/guidelines' itemprop="url">Guidelines </a> </span> </li> <li itemscope itemtype='http://schema.org/SiteNavigationElement'> <span itemprop='name'> <a href='/tos' itemprop="url">Terms of Service </a> </span> </li> <li itemscope itemtype='http://schema.org/SiteNavigationElement'> <span itemprop='name'> <a href='/privacy' itemprop="url">Privacy Policy </a> </span> </li> </ul> </nav> <p class='powered-by-link'>Powered by <a href="https://www.discourse.org">Discourse</a>, best viewed with JavaScript enabled</p> </footer> <div class="buorg"><div>Unfortunately, <a href="https://www.discourse.org/faq/#browser">your browser is unsupported</a>. Please <a href="https://browsehappy.com">switch to a supported browser</a> to view rich content, log in and reply.</div></div> </body> </html>