Skip to content

refactor(reflex-base): consolidate BaseContext into context.base (#6514)#6553

Open
BABTUNA wants to merge 2 commits into
reflex-dev:mainfrom
BABTUNA:issue-6514-consolidate-basecontext
Open

refactor(reflex-base): consolidate BaseContext into context.base (#6514)#6553
BABTUNA wants to merge 2 commits into
reflex-dev:mainfrom
BABTUNA:issue-6514-consolidate-basecontext

Conversation

@BABTUNA
Copy link
Copy Markdown
Contributor

@BABTUNA BABTUNA commented May 21, 2026

Summary

  • Removes the duplicate BaseContext defined in reflex_base.plugins.compiler and points PageContext / CompileContext at the canonical reflex_base.context.base.BaseContext.
  • Reworks BaseContext from a frozen dataclass into a plain class with __slots__ = () so frozen subclasses (RegistrationContext, EventContext) and non-frozen subclasses (PageContext, CompileContext) can both inherit. Ports the async __aenter__ / __aexit__ helpers over from the removed copy.
  • Pins identity equality on the base via __eq__ = object.__eq__ / __hash__ = object.__hash__, and propagates eq=False to the (formerly compiler-local) dataclass subclasses.

Closes #6514.

Test plan

  • uv run pytest tests/units/reflex_base/context/test_base.py tests/units/compiler/test_plugins.py
  • uv run pytest tests/units (full unit suite)
  • uv run ruff check . && uv run ruff format --check .
  • uv run pyright reflex tests

…lex-dev#6514)

Removes the duplicate BaseContext defined in plugins/compiler.py and
makes PageContext/CompileContext inherit from reflex_base.context.base.
Converts BaseContext from a frozen dataclass to a plain class with
__slots__ = () so frozen (RegistrationContext, EventContext) and
non-frozen (PageContext, CompileContext) subclasses can both inherit.
Ports the async __aenter__/__aexit__ helpers over from the removed
copy, and pins identity equality on the base via object.__eq__ /
object.__hash__.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@BABTUNA BABTUNA requested a review from a team as a code owner May 21, 2026 23:17
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 21, 2026

Merging this PR will not alter performance

✅ 24 untouched benchmarks


Comparing BABTUNA:issue-6514-consolidate-basecontext (94c05d2) with main (6bb44d5)

Open in CodSpeed

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 21, 2026

Greptile Summary

This PR consolidates the duplicate BaseContext class by removing the one in reflex_base.plugins.compiler and pointing PageContext and CompileContext at the canonical reflex_base.context.base.BaseContext. The base class is reworked from a frozen dataclass to a plain class with __slots__ = (), allowing both frozen and non-frozen dataclass subclasses to coexist, and identity equality is pinned via __eq__ = object.__eq__ / __hash__ = object.__hash__ with eq=False propagated to the two compiler dataclasses.

  • Removes ~90 lines of duplicated context-manager boilerplate from compiler.py and adds async __aenter__/__aexit__ to the canonical base.
  • ensure_context_attached in the new base only checks _attached_context_token (was the instance entered?), whereas the old compiler.py implementation additionally verified cls.get() is self (is this instance currently active?). This makes the safety guard in CompileContext.compile() slightly weaker.
  • Test coverage for the new identity-equality and async-context-manager behaviour is added to test_base.py; test_plugins.py is updated to match the new exception types and attribute names.

Confidence Score: 4/5

Safe to merge; the consolidation is straightforward and the test suite covers the important paths.

The refactor is clean and well-tested. The one substantive concern is that ensure_context_attached now only confirms the instance was entered rather than also verifying it is the currently active value in the ContextVar. Normal single-compile-context usage is unaffected.

packages/reflex-base/src/reflex_base/context/base.py — specifically the ensure_context_attached method and whether the weaker check is intentional.

Important Files Changed

Filename Overview
packages/reflex-base/src/reflex_base/context/base.py Reworked from a frozen dataclass to a plain class with __slots__ = (); adds async context-manager support and identity equality. The ensure_context_attached guard is slightly weaker than the old compiler.py version — it only checks the token dict, not the live ContextVar value.
packages/reflex-base/src/reflex_base/plugins/compiler.py Removes the local BaseContext duplicate and redirects PageContext/CompileContext to the canonical reflex_base.context.base.BaseContext; adds eq=False to both dataclass decorators to preserve identity equality.
tests/units/reflex_base/context/test_base.py Adds three new tests covering identity equality, isolated attachment state, and the async context manager. test_async_context_manager is an async def without @pytest.mark.asyncio, but the project's asyncio_mode = "auto" covers it.
tests/units/compiler/test_plugins.py Updates exception-type assertions from RuntimeError to LookupError to match the new ContextVar.get() behaviour, and updates the context-var attribute name from __context_var__ to _context_var.

Comments Outside Diff (1)

  1. packages/reflex-base/src/reflex_base/context/base.py, line 118-126 (link)

    P2 ensure_context_attached no longer verifies self is the active context

    The old compiler.py implementation performed two checks: (1) that a context is currently active at all, and (2) that current is self. The new implementation only checks _attached_context_token.get(self) is not None, which merely confirms self.__enter__ was called and not yet exited — it does not verify self is still the context actually visible in the current ContextVar.

    Concretely: if a nested CompileContext instance is pushed via another __enter__ call (or an explicit cls.set(other)), the outer instance's ensure_context_attached() silently passes while CompileContext.get() would return the inner instance. CompileContext.compile() calls this as a safety guard, so a false pass here means the method proceeds with the wrong context active.

Reviews (1): Last reviewed commit: "refactor(reflex-base): consolidate BaseC..." | Re-trigger Greptile

The remaining "must be entered with 'with' or 'async with'" regex in
test_compile_context_requires_attached_context didn't match the
consolidated BaseContext's "must be entered before calling this method"
message, so all 10 unit-tests jobs failed on CI. Loosen the regex to
match the prefix shared by the new wording.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consolidate reflex_base.plugins.compiler.BaseContext and reflex_base.context.base.BaseContext

1 participant