Skip to content

ENG-9860 fix(vars): preserve custom Field attributes in state metaclass#6726

Open
FarhanAliRaza wants to merge 2 commits into
reflex-dev:mainfrom
FarhanAliRaza:farhan/eng-9860-state-metaclass-should-preserve-custom-attributes-on-field
Open

ENG-9860 fix(vars): preserve custom Field attributes in state metaclass#6726
FarhanAliRaza wants to merge 2 commits into
reflex-dev:mainfrom
FarhanAliRaza:farhan/eng-9860-state-metaclass-should-preserve-custom-attributes-on-field

Conversation

@FarhanAliRaza

Copy link
Copy Markdown
Contributor

BaseStateMeta rebuilt Field instances for state annotations, discarding any custom attributes callers had set. Copy over attrs the rebuilt field did not recompute via Field._copy_custom_attrs_from so subclassed or customized fields keep their extra state.

All Submissions:

  • Have you followed the guidelines stated in CONTRIBUTING.md file?
  • Have you checked to ensure there aren't any other open Pull Requests for the desired changed?

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)

New Feature Submission:

  • Does your submission pass the tests?
  • Have you linted your code locally prior to submission?

Changes To Core Features:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your core changes, as applicable?
  • Have you successfully ran tests with your changes locally?

BaseStateMeta rebuilt Field instances for state annotations, discarding
any custom attributes callers had set. Copy over attrs the rebuilt field
did not recompute via Field._copy_custom_attrs_from so subclassed or
customized fields keep their extra state.
@FarhanAliRaza FarhanAliRaza requested a review from a team as a code owner July 9, 2026 13:39
@FarhanAliRaza FarhanAliRaza added the reflex-enterprise For issues related to `reflex-enterprise` label Jul 9, 2026
@greptile-apps

greptile-apps Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes BaseStateMeta silently discarding custom attributes set on Field instances when it rebuilds them during state class construction. The fix adds a source_field parameter to Field.__init__ that deep-copies any non-reserved attributes from the original field after the rebuilt field has been fully initialized.

  • base.py: Adds _RESERVED_FIELD_ATTRS = frozenset({\"annotation\"}) and a source_field parameter; the copy loop runs after all standard init processing so it cannot overwrite default, default_factory, type attrs, or is_var. Three BaseStateMeta rebuild sites now pass source_field=value.
  • test_base.py: Five new tests cover annotated rebuild, type-inferred rebuild, factory rebuild, annotation exclusion, and deep-copy isolation of mutable attributes.

Confidence Score: 5/5

Safe to merge — the change is additive, well-contained, and backed by targeted tests.

The copy loop runs strictly after all standard Field.init processing so it cannot overwrite computed type or default attrs. The annotation guard correctly prevents the one known duck-typing hazard. copy.deepcopy per-attribute handles the mutable aliasing edge case. All three rebuild sites in BaseStateMeta were updated consistently, and five tests cover the key scenarios.

No files require special attention.

Important Files Changed

Filename Overview
packages/reflex-base/src/reflex_base/vars/base.py Adds source_field parameter to Field.__init__ that deep-copies non-reserved custom attributes after full init; _RESERVED_FIELD_ATTRS correctly guards annotation so pydantic duck-typing via get_field_type is not broken.
tests/units/reflex_base/vars/test_base.py New test suite covering annotated rebuild, unannotated type-inferred rebuild, unannotated factory rebuild, annotation exclusion guard, and mutable deep-copy isolation.
packages/reflex-base/news/6726.bugfix.md Changelog entry correctly describes the fix.
tests/units/reflex_base/vars/init.py Empty __init__.py added to make the new test directory a package.

Reviews (2): Last reviewed commit: "fix(vars): deep-copy custom Field attrs ..." | Re-trigger Greptile

Comment thread tests/units/reflex_base/vars/test_base.py
Comment thread packages/reflex-base/src/reflex_base/vars/base.py Outdated
@codspeed-hq

codspeed-hq Bot commented Jul 9, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 26 untouched benchmarks
⏩ 8 skipped benchmarks1


Comparing FarhanAliRaza:farhan/eng-9860-state-metaclass-should-preserve-custom-attributes-on-field (c577490) with main (948c619)2

Open in CodSpeed

Footnotes

  1. 8 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (3b97060) during the generation of this report, so 948c619 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3f368d27a9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/reflex-base/src/reflex_base/vars/base.py Outdated

@masenf masenf left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this copying functionality should be part of __init__; you can add another optional param source_field and apply the copying of extra values from there.

what greptile says about deepcopying the values makes sense to me, we don't want to have shared references to mutable types across different Field instances.

having a list of reserved attributes also makes sense to avoid misidentification with pydantic fields.

add changelog entry

Fold custom-attribute copying into Field.__init__ via a source_field
parameter instead of the post-hoc _copy_custom_attrs_from helper.
Copied attrs are now deep-copied so mutable values aren't shared
between the original and rebuilt fields, and the reserved `annotation`
attribute is never carried over — get_field_type duck-types pydantic
fields on `.annotation`, so copying it would shadow the real class
annotation.
@FarhanAliRaza FarhanAliRaza requested a review from masenf July 10, 2026 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

reflex-enterprise For issues related to `reflex-enterprise`

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants