proj/pkgcore/snakeoil:master commit in: /, src/snakeoil/klass/

"Arthur Zamarin" <[email protected]>
Newsgroups gmane.linux.gentoo.cvs
Message-ID <1786137609.9ea8b9d99bf77a8b7cffc9a1c3cba8abafd9b9ec.arthurzam@gentoo>
commit:     9ea8b9d99bf77a8b7cffc9a1c3cba8abafd9b9ec
Author:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
AuthorDate: Fri Aug  7 21:20:09 2026 +0000
Commit:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
CommitDate: Fri Aug  7 21:20:09 2026 +0000
URL:        https://gitweb.gentoo.org/proj/pkgcore/snakeoil.git/commit/?id=9ea8b9d9

klass.immutable: inline the mutation block into the autowrapper

__allow_mutation_wrapper__ entered __allow_mutation__ via `with`, so every
auto wrapped __init__ built a generator, drove it through __enter__ and
__exit__, and tore it down - all to set one contextvar and reset it. Do
that directly in the wrapper instead. __allow_mutation__ itself is
untouched and still the way to open a mutation block by hand; nothing
overrides it, so the wrapper was it's only caller.

Semantics are identical: same contextvar, same id(instance), same reset in
a finally. Construction of small immutable instances gets cheaper, the
saving being a fixed cost per call rather than per attribute:

    StrExactMatch            0.047s -> 0.031s   1.53x
    PackageRestriction       0.128s -> 0.111s   1.16x
    atom                     0.212s -> 0.195s   1.09x
    19602 restriction trees  0.270s -> 0.236s   1.15x

Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org>

 NEWS.rst                        | 4 ++++
 src/snakeoil/klass/immutable.py | 7 ++++++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/NEWS.rst b/NEWS.rst
index 9898052..556a36d 100644
--- a/NEWS.rst
+++ b/NEWS.rst
@@ -23,6 +23,10 @@ snakeoil 0.11.4 (unreleased)
   serialization.  Dropping it makes serializing slotted objects ~4x faster
   (Arthur Zamarin, #117)
 
+- ``snakeoil.klass.immutable.Simple``: methods auto wrapped in a mutation block
+  no longer build and drive a ``@contextmanager`` generator per call.  Creating
+  small immutable instances is up to 1.5x faster (Arthur Zamarin)
+
 
 snakeoil 0.11.3 (2026-07-30)
 ----------------------------

diff --git a/src/snakeoil/klass/immutable.py b/src/snakeoil/klass/immutable.py
index 8d0c972..e47d967 100644
--- a/src/snakeoil/klass/immutable.py
+++ b/src/snakeoil/klass/immutable.py
@@ -122,8 +122,13 @@ class Simple:
     def __allow_mutation_wrapper__(cls, functor):
         @functools.wraps(functor)
         def f(instance, *args, **kwargs):
-            with cls.__allow_mutation__(instance):
+            # __allow_mutation__ inlined; building and driving it's generator is
+            # the dominant cost of creating small immutable instances.
+            last = _immutable_allow_mutations.set(id(instance))
+            try:
                 return functor(instance, *args, **kwargs)
+            finally:
+                _immutable_allow_mutations.reset(last)
 
         f.__disable_mutation_autowrapping__ = True  # pyright: ignore[reportAttributeAccessIssue] # it's already wrapped.
         return f
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.