Latest Results
support async context for mutable proxies (#6691)
* support async context for mutable proxies
* preserve nested mutable proxy context targets
* Fix mutable proxy async context test typing
* Address mutable proxy async context review
* Handle mutable proxy enter failures
* Optimize mutable proxy iteration path tracking
* Clear mutable proxy context after cleanup failure
* Fix dict method mutable proxy paths
* Use strict zip for mutable proxy slice paths
* Reduce mutable proxy iteration overhead
* Optimize dataclass mutable proxy cache
* fix: harden mutable proxy async context refresh from review findings
Review fixes on top of #6691:
- Treat structural changes (deleted key, removed attr, changed container
type) during proxy refresh as the documented RuntimeError instead of
leaking raw KeyError/AttributeError/TypeError.
- Rename the "iter" path sentinel to "unrefreshable" (it also marks
missing dict.get defaults) and reject unrefreshable proxies before
taking the state lock; mark list index/slice proxies unrefreshable
since positions are not stable identities.
- Catch BaseException in __aenter__ so KeyboardInterrupt cannot leak
the state lock; drop the IterPath dynamic-subclass optimization.
- Skip the wrapping machinery for non-mutable element reads and split
_wrap_recursive/_wrap_mutable so mutability is checked exactly once:
dict element reads ~4.5x faster, list iteration ~8.6x faster than
main; iterating all-mutable elements ~13% slower from path tracking.
- Move mutable proxy tests to tests/units/istate/test_proxy.py and add
coverage: attr paths, plain-state no-op enter, deleted-key refresh,
shifted list items, BaseException cleanup.
- Document refresh-by-path semantics and unrefreshable cases in the
background events docs.
* perf(proxy): recover mutable element wrap cost from path tracking
The async-context path tracking added in this PR made iterating an
all-mutable list (test_var_access[mutable_dataclass_list]) ~10% slower
on CodSpeed. Two changes recover it (+25% local walltime, 28.5ms ->
22.8ms):
- Store _self_state/_self_field_name/_self_path in __init__ via
object.__setattr__, skipping the Python-level __setattr__ prefix
dispatch and wrapt's C setattro (which ends in a generic setattr for
_self_* names anyway) on the per-element construction hot path.
- Pass the full child path to _wrap_mutable instead of a segment, so
__iter__ builds the shared child path tuple once per iteration
rather than allocating an identical tuple per element.
* fix(proxy): use base proxy setattr for internal attrs, not object.__setattr__
object.__setattr__ fails with "can't apply this __setattr__ to
ItemMutableProxy object" on Python <= 3.13: the interpreter rejects it
for instances whose static base (wrapt's C ObjectProxy) overrides
tp_setattro. It only worked on the local 3.14 interpreter, so CI unit
and integration jobs on 3.10-3.12 failed across the board.
Bind super().__setattr__ once in __init__ instead — the same sanctioned
wrapt path as before, still skipping the per-store Python-level
MutableProxy.__setattr__ dispatch. Local CodSpeed walltime keeps +18%
on test_var_access[mutable_dataclass_list] vs the pre-optimization
baseline (28.5ms -> 24.1ms).
* fix(proxy): reject read-only and type-changing refreshes in async context
- MutableProxy.__aenter__ now raises ImmutableStateError when bound to a
ReadOnlyStateProxy, instead of entering it and silently making the
read-only state mutable.
- Refreshing a dataclass-backed proxy raises the refresh error when the
field's value was concurrently replaced with a different type, since
the generated proxy class carries the original type's
__dataclass_fields__.
---------
Co-authored-by: Harsh Thakare <harsh@pybex.io>
Co-authored-by: Farhan <www.mfarvirus@gmail.com> Latest Branches
0%
claude/release-process-changelog-sot-tqmdpd ×3.4
harsh21234i:fix/mutable-proxy-async-context-6689 0%
gaurav0107:fix/6483-default-template-radix-themes-plugin © 2026 CodSpeed Technology