Skip to content

make pydantic optional - #6786

Merged
masenf merged 8 commits into
reflex-dev:mainfrom
benedikt-bartscher:make-pydantic-optional
Aug 6, 2026
Merged

make pydantic optional#6786
masenf merged 8 commits into
reflex-dev:mainfrom
benedikt-bartscher:make-pydantic-optional

Conversation

@benedikt-bartscher

Copy link
Copy Markdown
Contributor

No description provided.

@codspeed-hq

codspeed-hq Bot commented Jul 16, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 26 untouched benchmarks
⏩ 8 skipped benchmarks1


Comparing benedikt-bartscher:make-pydantic-optional (02f7152) with main (7ba00b4)

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.

@greptile-apps

greptile-apps Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR makes pydantic an optional dependency of both reflex and reflex-base. The hot-path pydantic check in base_state_processor.py is moved from per-call find_spec to a single module-level probe (with the result cached as BaseModelV2 = None when absent), which is a good performance improvement. A new subprocess-based test verifies that core import, state, component render, and serializer functionality all work without pydantic present.

  • packages/reflex-base/pyproject.toml: pydantic removed from hard deps, added as [project.optional-dependencies] pydantic.
  • pyproject.toml: new pydantic = ["reflex-base[pydantic]"] extra; db extra retains a direct pydantic pin.
  • tests/units/test_optional_pydantic.py: subprocess test with sys.meta_path filter + sys.modules purge to simulate a pydantic-free environment.

Confidence Score: 5/5

  • This PR is safe to merge — the changes are narrowly scoped to dependency declarations and a single import-time guard, with no functional regressions for users who have pydantic installed.
  • The pydantic guard is moved from per-call to module-level with a clear null sentinel, the test simulates a pydantic-free environment correctly (including the sys.modules purge that was previously missing), and the breaking change is documented. No defects were found in the changed paths.
  • No files require special attention.

Important Files Changed

Filename Overview
packages/reflex-base/src/reflex_base/event/processor/base_state_processor.py Moves the pydantic find_spec check from per-event to module-import time, setting BaseModelV2 = None when pydantic is absent; hot-path guard is correct and well-commented.
packages/reflex-base/pyproject.toml Moves pydantic from hard dependency to [project.optional-dependencies]; version constraint preserved.
pyproject.toml Adds pydantic = ["reflex-base[pydantic]"] extra; db extra keeps pydantic as a direct dependency.
tests/units/test_optional_pydantic.py New subprocess-based test that blocks pydantic via sys.meta_path filter + sys.modules purge, verifying core reflex functionality works without pydantic; well-structured isolation mechanism.
news/+pydantic-optional.breaking.md Breaking change note documenting the removal of pydantic as a hard dependency and the new reflex[pydantic] extra.
uv.lock Lockfile updated to reflect pydantic becoming optional; also includes an aiohttp version downgrade from 3.14.3 to 3.14.1.

Reviews (8): Last reviewed commit: "Resolve pydantic presence once instead o..." | Re-trigger Greptile

Comment thread tests/units/test_optional_pydantic.py

@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.

interesting; i thought we had pydantic as optional for some time now, but i guess not...

@benedikt-bartscher
benedikt-bartscher marked this pull request as ready for review July 17, 2026 16:35
@benedikt-bartscher
benedikt-bartscher requested a review from a team as a code owner July 17, 2026 16:35
@benedikt-bartscher

Copy link
Copy Markdown
Contributor Author

interesting; i thought we had pydantic as optional for some time now, but i guess not...

I remember reading some git commits or changelogs which mentioned this as well - however somehow it currently isn't optional.

I guess this is ready for review now.

benedikt-bartscher and others added 5 commits July 17, 2026 18:46
With pydantic optional, find_spec("pydantic") in _transform_event_arg
does a full sys.path scan on every dict-payload argument when pydantic
is absent (measured 85us per call; 0.64us after hoisting). Bind the
BaseModel reference once at import, like the other guarded sites.
@FarhanAliRaza

Copy link
Copy Markdown
Contributor

Validated this end to end in a real app: installed the branch's packages into a clean venv (confirmed nothing pulls pydantic transitively — 40 packages, no pydantic), ran a counter app, and exercised state events in the browser — compile, hydration, and event round-trips all work without pydantic. Also confirmed the [pydantic] extra resolves and re-activates model serialization / MUTABLE_TYPES / ObjectVar support.

One perf issue surfaced and is fixed in 02f7152: _transform_event_arg called find_spec("pydantic") per dict-payload event argument. That was harmless while pydantic was a hard dep (sys.modules hit, ~125ns), but with pydantic absent every call did a full sys.path scan — measured 85.3µs per argument, and 0.64µs after hoisting the check to import time like the other guarded sites.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 7 files

Re-trigger cubic

@masenf
masenf merged commit d8a132b into reflex-dev:main Aug 6, 2026
108 checks passed
masenf pushed a commit that referenced this pull request Aug 28, 2026
pydantic_optional (#6786): bare/pydantic/db extras and the in-place
upgrade path all verified end-to-end in the browser; no regressions vs
0.9.8. Two low-severity error-message papercuts recorded.

typing_python (#6944/#6890/#6846): PEP 695 aliases compile and render on
3.11-3.14, and Python 3.14 builtin-annotation handling passes fully.
Found: runtime assignment to an alias-annotated state var raises
TypeError in State.__setattr__ (high — mutating handlers die), and an
uncalled handler with an alias-annotated arg crashes page compile.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EMjBXPozsNeQNSBZecNH8x
masenf pushed a commit that referenced this pull request Aug 28, 2026
A ~29s 1920x1080 motion graphic covering the end-user-facing changes in
0.9.9, sourced from the 0.9.9a1 and 0.9.9a2 changelog entries across
reflex, reflex-base, the component packages and reflex-hosting-cli.

Nine beats: the dev-mode main-thread win (#6905), call-site
auto-memoization of @rx.memo (#6949), the move to React Router 8 (#6854),
DevTools component naming (#6945), stdlib logging with --json plus the
client_error report (#6863, #6865, #6827), the cloud CLI's whoami/token
and autoscaling flags (#6918, #6884, #6948), and a grid of the smaller
fixes a user would notice (#6786, #6593, #6944, #6971, #6790, #6920).

Styled to match reflex.dev by reusing its design system rather than
approximating it: the dark violet/slate scales, wave-line motif, radial
bloom and type scale come from reflex-site-shared, and the fonts are the
same @fontsource-variable Instrument Sans and JetBrains Mono files the
site serves.

Source only — the rendered mp4 is a build artifact, regenerated by
`npm run build` and ignored. Lives outside the packaged tree (hatch only
includes /reflex), so it does not affect the published wheel or sdist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016arkVKmoogzUtZNfZZSvSo
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.

3 participants