Skip to content

Remove BaseState._get_attribute #7302

Description

@masenf

Problem

Every attribute access on a state instance goes through BaseState._get_attribute (__getattribute__), and every write through BaseState.__setattr__. Together they route inherited vars to the parent instance, keep backend vars in a side dict (_backend_vars), wrap mutables in MutableProxy, bind event handlers, track dirtiness, and enforce name-collision rules. That makes state access slow and couples all var behavior to BaseState.

Measured on Python 3.14 (current → bare descriptor prototype):

op today descriptor
read var 1050 ns 255 ns
read inherited var 1550 ns 305 ns
read method 410 ns 45 ns
write var 9760 ns 290 ns

Plan

Make Field, ComputedVar and EventHandler real descriptors that own their behavior.

  • Field: data descriptor bound to the state class that stores it (owner). Class access returns the Var; instance access walks parent_state to the owner instance, reads __dict__, lazily materializes defaults, wraps mutables. __set__ stores and marks dirty (dirty set, parents' dirty_substates, dependent computed var caches). _x fields are backend: tracked, persisted, never sent to the client.
  • ComputedVar: same owner resolution, so inherited computed vars cache on the owner.
  • EventHandler: __get__ returns itself on the class, a bound method on the owner instance.
  • Inheritance follows the MRO. Fields from mixins / BaseState are rebound per concrete state. A substate redeclaring a field gets its own independent field.
  • Collisions: keep the class-definition reserved-name check; drop the var-vs-var shadow errors.
  • Typo guard: SetUndefinedStateVarError kept via a guard-only __setattr__ installed outside prod mode; prod has no __setattr__.
  • Deltas: get_delta and friends move to reflex/istate/delta.py; BaseState.get_delta becomes a deprecated wrapper.
  • Dependency graph moves onto the descriptors.

Removes _get_attribute, __setattr__ routing, _backend_vars/backend_vars/inherited_vars/inherited_backend_vars, get_skip_vars, _fast_attr_names, is_backend_base_variable, and the shadow checks. Estimated ~700 lines removed, ~200 added.

Also fixes: in a background task on a substate, in-place mutation of an inherited mutable var marks the substate dirty instead of the owner, so the change is never sent or persisted.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions