Skip to content

Upgrade dev tooling and fix docstring style - #6893

Merged
FarhanAliRaza merged 1 commit into
mainfrom
claude/upgrade-ruff-pyright-typer-u3z09k
Aug 25, 2026
Merged

Upgrade dev tooling and fix docstring style#6893
FarhanAliRaza merged 1 commit into
mainfrom
claude/upgrade-ruff-pyright-typer-u3z09k

Conversation

@masenf

@masenf masenf commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Changes To Core Features:

  • Have you added an explanation of what your changes do and why you'd like us to include them?

Description

This PR upgrades locked dev tooling and addresses linting issues introduced by the new versions:

Tooling upgrades:

  • ruff 0.15.12 → 0.16.2
  • pyright 1.1.408 → 1.1.411
  • typer 0.25.1 → 0.27.1

Key changes:

  1. Property docstring style (ruff D421): Updated all property docstrings from imperative form ("Get the ...", "Return the ...") to noun phrases ("The ..."). This applies across:

    • reflex/app.py
    • reflex/compiler/compiler.py
    • reflex/experimental/client_state.py
    • reflex/istate/
    • packages/reflex-base/src/reflex_base/ (vars, event, config, registry, plugins)
    • packages/reflex-components-core/src/reflex_components_core/
    • packages/reflex-docgen/src/reflex_docgen/
    • packages/reflex-components-internal/src/reflex_components_internal/
  2. Type safety improvements:

    • Added cast() calls in reflex/compiler/compiler.py and reflex/reflex.py for untyped libsass and typer APIs
    • Fixed type annotation in packages/reflex-base/src/reflex_base/vars/base.py for default_value with explanatory comment
    • Removed redundant EventSpec import from TYPE_CHECKING block in packages/reflex-base/src/reflex_base/event/processor/base_state_processor.py
    • Changed chain_updates() parameter type from EventSpec | list[EventSpec] | None to Any with updated docstring explaining runtime validation
  3. Code quality fixes:

    • Simplified condition in packages/reflex-base/src/reflex_base/utils/types.py (removed redundant cls is not None check)
    • Fixed import organization in packages/reflex-base/src/reflex_base/vars/datetime.py (moved ImportVar to correct location)
    • Improved control flow in packages/reflex-base/src/reflex_base/vars/dep_tracking.py (split compound condition for clarity)
  4. Test infrastructure:

    • Created tests/units/reflex_cli/v2/utils.py with as_click_command() helper to reduce duplication across CLI tests
    • Updated all CLI test files to use the new helper
    • Removed redundant scope="function" parameter from pytest_asyncio.fixture decorators (already set by loop_scope)
  5. Linting configuration:

    • Added ASYNC119 to ignore list (background event handlers hold async with self across yield by design)
    • Added RUF075 to ignore list (state managers deliberately skip write-back when with body raises)
    • Added RUF105 and RUF201 to ignore list (preserve noqa comment readability)

Test Plan

Existing unit tests pass. The changes are primarily:

  • Docstring style updates (no functional impact)
  • Type annotations and casts for better type checking
  • Test infrastructure refactoring (DRY principle)
  • Linting configuration updates

All changes maintain backward compatibility and improve code quality without altering runtime behavior.

https://claude.ai/code/session_01RLumacyNrCZDqvyptaVxkE

Review in cubic

@masenf
masenf requested a review from a team as a code owner August 14, 2026 23:08
@greptile-apps

greptile-apps Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR upgrades the locked development tooling and updates the codebase for the resulting lint and type-checking requirements.

  • Converts property docstrings to noun phrases for the new Ruff rule.
  • Adds type annotations and casts around field defaults, logging streams, libsass, and Typer’s vendored Click implementation.
  • Refactors CLI test command conversion into a shared helper and updates asynchronous fixture declarations.
  • Refreshes the development dependency lockfile and lint configuration.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
pyproject.toml Updates development-tool constraints and Ruff ignores to accommodate the upgraded linting behavior.
uv.lock Refreshes locked development dependencies, including Ruff, Pyright, and Typer.
reflex/reflex.py Casts Typer’s generated command to Click’s command interface for registration with the root CLI.
reflex/compiler/compiler.py Adds a type-only cast around the untyped libsass API without changing runtime behavior.
packages/reflex-base/src/reflex_base/vars/base.py Widens field default annotations to represent the existing possibility of a None default.
packages/reflex-base/src/reflex_base/vars/dep_tracking.py Restructures the IMPORT_NAME guard without changing bytecode-scanner behavior.
packages/reflex-base/src/reflex_base/event/processor/base_state_processor.py Aligns the chain_updates input annotation and documentation with its existing runtime validation.
tests/units/reflex_cli/v2/utils.py Introduces a shared helper for adapting Typer applications to Click commands in CLI tests.

Reviews (2): Last reviewed commit: "Upgrade ruff, pyright, and typer; fix th..." | Re-trigger Greptile

@codspeed-hq

codspeed-hq Bot commented Aug 14, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 27 untouched benchmarks
⏩ 8 skipped benchmarks1


Comparing claude/upgrade-ruff-pyright-typer-u3z09k (e1544df) with main (d02e452)

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.

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

All reported issues were addressed across 59 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/reflex-base/src/reflex_base/vars/base.py Outdated
FarhanAliRaza
FarhanAliRaza previously approved these changes Aug 16, 2026
uv.lock: ruff 0.15.12 -> 0.16.3, pyright 1.1.408 -> 1.1.411,
typer 0.25.1 -> 0.27.1. ruff 0.16.4 published inside the 7 day
exclude-newer window, so 0.16.3 is the newest resolvable release.

ruff 0.16 (preview rules are enabled repo-wide):

- D421 property-docstring-starts-with-verb: reword 55 property
  docstrings from "Get the X." / "Return the X." to "The X.", per the
  Google style guide the repo already follows.
- PT003: drop the redundant scope="function" from five
  pytest_asyncio.fixture calls, which 0.16 now recognizes.
- ASYNC119, RUF075: ignored. Both fire on deliberate patterns --
  background handlers hold `async with self` across `yield`, and the
  state managers skip write-back when the `with` body raises.
- RUF105, RUF201: ignored. Both are stylistic; RUF105's own docs call
  it opinionated, and migrating 190 `noqa` comments to `ruff: ignore`
  would drop them for other tooling and for older ruff. RUF201 would
  leave the config half codes, half names, since prefix selectors have
  no name form.

pyright 1.1.411 narrows `x is None` on an `Any` value to `Any | None`,
where it previously stayed `Any`. That surfaced two dead guards, both
removed: `cls is not None` in `_isinstance()` (the line above already
returns for None) and `instruction.argval is not None` in the
dependency-tracking scanner, where the check moves inside the branch so
it stops leaking None into the sibling branches. Its bundled typeshed
also types `inspect.isgenerator`/`isasyncgen` as yielding `object`, so
`chain_updates()` now declares `events: Any`, matching the runtime
validation it delegates to.

It also caught a real gap in Field: when an annotated type has no
computed default, the field is given a `None` default and its recorded
`annotated_type` is widened to match, but the static FIELD_TYPE cannot
follow. `Field.default`, `Field.default_factory`, and
`Field.default_value()` now admit None rather than asserting a type the
value need not inhabit. Also: cast untyped `sass.compile()` to str,
cast `log_file_stream()`'s eagerly-opened handler stream to TextIO, and
import `ImportVar`/`unionize` from the modules that define them rather
than re-exporting them through `reflex_base.vars.base`.

typer 0.27 vendors its own copy of click, so `typer.main.get_command()`
no longer returns a nominal `click.Command`. The objects stay
structurally compatible (`reflex cloud` and the hosting CLI tests pass),
so the conversion is cast at its two call sites; the six test modules
that duplicated the Typer-to-click preamble now share an
`as_click_command()` helper.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLumacyNrCZDqvyptaVxkE
@masenf
masenf force-pushed the claude/upgrade-ruff-pyright-typer-u3z09k branch from 08c78da to e1544df Compare August 25, 2026 18:13
@FarhanAliRaza
FarhanAliRaza merged commit 9bb64f1 into main Aug 25, 2026
134 of 135 checks passed
@FarhanAliRaza
FarhanAliRaza deleted the claude/upgrade-ruff-pyright-typer-u3z09k branch August 25, 2026 19:28
masenf pushed a commit that referenced this pull request Aug 25, 2026
…-context-refactor-jv3pig

One conflict, in `reflex/experimental/client_state.py`: main reworded a property
docstring there (#6893, the ruff/pyright/typer upgrade) while this branch had
replaced the whole file with a deprecation shim over
`reflex_base.client_state`. Resolved in favor of the shim -- the implementation
that docstring belonged to no longer exists here.

That upgrade also brought the rule behind the reword, and this branch's own
`ClientStateVar.value` tripped it. Fixed the same way main fixed theirs.

Verified against the merged base with the upgraded tooling (ruff 0.16.3,
pyright 1.1.411): pre-commit 7/7, 7762 unit tests, 40 vitest, 24 Playwright.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017DE4XVgDNtq2i89CMVspJ9
masenf added a commit that referenced this pull request Aug 27, 2026
#6918 was branched before #6939 and #6893 landed, so merging it left main
failing both pre-commit and the unit tests.

- `reflex_cli.v2.auth` imported `reflex_base.utils.log` at module scope.
  #6939 made reflex-base optional, because it does not exist on the reflex
  versions the CLI advertises support for, and `reflex_cli.v2.deployments`
  imports auth unconditionally — so importing any hosting CLI command
  raised ImportError on reflex older than 0.9, failing
  `test_cli_imports_without_reflex_base[reflex_cli.v2.deployments]`. It now
  resolves `log` through `reflex_cli.utils.log`, the shim the rest of the
  CLI uses, which falls back to its own SUCCESS level when reflex-base is
  absent. `reflex_cli.v2.auth` joins that test's module list so the guard
  names the module directly instead of catching it only through
  deployments.

- `tests/units/reflex_cli/v2/test_auth.py` resolved the CLI with an inline
  `get_command(...) if isinstance(hosting_cli, Typer)`, which types as
  `Group | Command`; since the typer upgrade in #6893 vendored click, that
  is not assignable to `click.Command`, so every `runner.invoke` call was a
  pyright error (22 in total). It now uses the `as_click_command` helper
  #6893 added for exactly this, which casts once.

No behavior change: on reflex 0.9 and up `reflex_cli.utils.log.SUCCESS` is
the same object the module imported before.


Claude-Session: https://claude.ai/code/session_01QNTSjh5JBcVFfTx7Jvn3DT

Co-authored-by: Claude <noreply@anthropic.com>
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