Skip to content

Fix build config to exclude sibling packages from distributions - #6966

Merged
masenf merged 7 commits into
mainfrom
claude/reflex-pyi-duplication-d1nxt7
Aug 28, 2026
Merged

Fix build config to exclude sibling packages from distributions#6966
masenf merged 7 commits into
mainfrom
claude/reflex-pyi-duplication-d1nxt7

Conversation

@masenf

@masenf masenf commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Type of change

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

Description

This PR fixes the Hatch build configuration to prevent sibling workspace packages and test fixtures from being included in published wheels and sdists. The main reflex package was inadvertently shipping files from packages/ subdirectories and test golden files, bloating distributions unnecessarily.

Changes:

  1. Root pyproject.toml: Updated [tool.hatch.build] to use anchored include patterns (/reflex, /scripts/hatch_build.py) that only match at the repo root, preventing nested packages/*/src/ directories from being included. Moved the build hook to targets.sdist.include so it's only shipped in sdists (needed to build wheels from sdists), not in wheels themselves.

  2. All packages/*/pyproject.toml: Standardized artifact patterns from *.pyi (which matched anywhere) to /src/**/*.pyi (anchored to each package's root), ensuring each package only ships its own generated stubs.

  3. Tests: Added comprehensive test suite (tests/units/test_build_config.py) that validates:

    • Core reflex files are included
    • Sibling package files are excluded
    • Test fixtures are excluded
    • Build hook is only in sdists, not wheels
    • Each workspace package only ships its own stubs
  4. Documentation: Updated AGENTS.md with changelog fragment guidelines and adjusted the pre-submission checklist.

  5. Changelog: Added news fragment documenting the size reduction.

Test Plan

Added 114 lines of unit tests covering all build configuration scenarios:

  • test_build_selects_reflex_files: Verifies core reflex files are included
  • test_build_skips_files_outside_reflex: Verifies sibling packages and fixtures are excluded
  • test_build_walks_only_the_reflex_tree: Validates no unexpected files are included
  • test_sdist_ships_the_build_hook / test_wheel_omits_the_build_hook: Ensures correct hook distribution
  • test_package_ships_only_its_own_stubs: Validates each workspace package's isolation

All tests pass for both SdistBuilder and WheelBuilder.

Checklist

  • Tests pass with adequate coverage
  • uv run ruff check . and uv run ruff format . clean
  • uv run pyright reflex tests passes
  • News fragment added for user-facing changes

https://claude.ai/code/session_014sgS35XWLy5xpVZqgHXupg

Review in cubic

masenf added 4 commits August 28, 2026 07:00
Hatchling matches `include` and `artifacts` with gitignore semantics, so an
unanchored pattern matches at any depth, and `artifacts` is checked before
`include` and bypasses it entirely.

Both mattered here. `artifacts = ["*.pyi"]` swept in every generated stub in
the workspace -- 163 files under packages/, each already bundled by the
package that owns it, plus the 12 pyi_generator golden fixtures under tests/.
And `include = ["reflex", ...]` matched the nested
packages/reflex-base/src/reflex_base/.templates/web/components/reflex/
directory, dragging a stray .js file along with it.

The wheel therefore installed a top-level `packages/` directory next to
`reflex/` in site-packages. Anchoring both patterns to the repository root
drops the sdist and wheel from 308 files to 132, and the wheel from 770 KB to
280 KB.

Add tests that assert both builders select nothing outside reflex/ and the
build hook, checked against the config we ship rather than a copy of it.
…acts

Two follow-ups in the same vein as anchoring the root patterns.

`scripts/hatch_build.py` only needs to reach the sdist, so that a wheel can be
built from it. Shipping it in the wheel installed a top-level `scripts`
directory into site-packages -- a far more collision-prone name than the
`packages` one just removed. Moving it to `targets.sdist.include` leaves the
wheel with `reflex/` alone.

The 14 packages that generate stubs still declared `artifacts = ["*.pyi"]`.
That is harmless today only because each build root is the package's own
directory; the pattern is the same footgun that let the root config reach into
packages/. Anchor them to `/src/**/*.pyi` and collapse the two identical
per-target keys into one.

Tests cover both: the walk test now distinguishes the two targets, and every
stub-generating package is checked to select its own `src` stubs and nothing
beside them. Discovery keys off the `reflex-pyi` build hook so that removing a
package's patterns fails its assertions rather than dropping it from the
parametrization.
The news fragment was written for a reviewer: it explained hatchling's pattern
semantics, counted the files, and narrated the two bugs. All of that is a click
away in the PR. Cut it to what a downstream user needs to know.

Document that expectation in AGENTS.md so the next fragment starts there, and
add the fragment to the submission checklist.

The per-package build comment repeated a paragraph of hatchling semantics
across 14 files. One line is enough; the reason the two per-target keys collapse
into one is that both targets want the same patterns, and a build-level
`artifacts` applies to every target.
The brevity rule was easy to read as "never more than two sentences", which
would cut the one thing a deprecation entry is most useful for: showing the
supported form beside the old one. Say what the rule is actually about, and
where the cutoff to docs falls.
@masenf
masenf requested a review from a team as a code owner August 28, 2026 07:43
@greptile-apps

greptile-apps Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR narrows Hatch build selection so the main and workspace distributions exclude sibling packages and test artifacts.

  • Anchors root and workspace-package artifact patterns to their intended source trees.
  • Keeps the custom build hook in the source distribution while omitting it from wheels.
  • Adds tests for distribution boundaries and package isolation.
  • Documents the user-visible distribution-size reduction and changelog-fragment conventions.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
pyproject.toml Anchors the main package build inputs and limits the custom build hook to source distributions.
tests/units/test_build_config.py Adds coverage for root package selection, build-hook inclusion, and workspace-package isolation.
packages/reflex-components-core/pyproject.toml Restricts generated stub artifacts to the package-local source tree.
AGENTS.md Adds changelog-fragment guidance and updates the pre-submission checklist.

Reviews (3): Last reviewed commit: "Merge branch 'main' into claude/reflex-p..." | Re-trigger Greptile

Comment thread tests/units/test_build_config.py
@codspeed-hq

codspeed-hq Bot commented Aug 28, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 27 untouched benchmarks
⏩ 8 skipped benchmarks1


Comparing claude/reflex-pyi-duplication-d1nxt7 (acd74c7) with main (fba9cc5)

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.

tomllib is stdlib only on 3.11+, so collection failed on the 3.10 leg of the
matrix. The repo's fallback elsewhere is `import tomli as tomllib`, but there
is no second parser to reach for here: the builder already exposes the parsed
`[tool.hatch.build]` table, and it is the same parse the assertions run
against.

Verified on 3.10 and 3.14.
@masenf masenf added this to the v0.9.9 milestone Aug 28, 2026
@masenf
masenf merged commit a5cf92a into main Aug 28, 2026
112 checks passed
@masenf
masenf deleted the claude/reflex-pyi-duplication-d1nxt7 branch August 28, 2026 18:58
masenf pushed a commit that referenced this pull request Aug 28, 2026
…-context-refactor-jv3pig

Picks up #6971, #6959 and #6966 — upload filename sanitization, Vite plugin
imports, and packaging excludes. Clean auto-merge; main's ``templates.py`` edit
is in the Vite config template, well away from ``render_iterable_tag``.
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.

1 participant