FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

build(pyproject,scripts,workflows): migrate development tooling from pip to uv by Adebowale-Morakinyo · Pull Request #47 · pythonnative/pythonnative · GitHub

Repository navigation

build(pyproject,scripts,workflows): migrate development tooling from pip to uv - #47

Merged
owenthcarey merged 5 commits into
pythonnative:mainfrom
Adebowale-Morakinyo:build/migrate-pip-to-uv
Sep 2, 2026
Merged

owenthcarey merged 5 commits into
pythonnative:mainfrom
Adebowale-Morakinyo:build/migrate-pip-to-uv

Conversation

Copy link
Copy Markdown
Contributor

What

Contributor tooling and CI move from pip to uv: PEP 735 dependency groups replacing the dev,
ci, and docs extras, a committed uv.lock, all four workflows on astral-sh/setup-uv with
uv sync / uv run / uv build, and scripts/check.sh on uv sync --locked --group dev.

Nothing changes for end users. pip install pythonnative and pip install 'pythonnative[build]'
are untouched, and the build backend stays setuptools.

Closes #28.

Why

scripts/check.sh promised "if this script is green, CI should be green too" while installing
with a different resolver than CI used. There was no lockfile, so an unrelated tool release could
turn a PR red. And dev and ci were byte-identical extras publishing contributor tooling as
part of the package.

Two departures from "nothing changes," both deliberate

pip>=24.0 is added to the dev group. A pip dependency in the migrate-away-from-pip PR
needs explaining. uv sync doesn't seed pip the way uv venv --seed did, and pn run ios
shells out to sys.executable -m pip to vendor rubicon-objc (project/builder.py:341), which
the test suite exercises. Without it the clean-checkout run fails with No module named pip,
and e2e-ios would have failed the same way. The alternative was changing builder.py, which
is runtime behavior and out of scope. Caught only by running the acceptance criterion literally
rather than testing against an existing venv.

astral-sh/setup-uv is pinned to v10.0.1, not a major tag. Every other action here is
pinned to a major, but setup-uv publishes no floating v10 — gh api .../git/ref/tags/v10
returns 404. Happy to change it if you'd rather.

Task 3's premise didn't hold, so nothing was added for it

The task expects mypy to want stubs (likely types-requests) and says --install-types "breaks
outright in a uv-managed venv, which doesn't include pip." Neither holds. Verified in a clean
venv with no pip and no types-*: both plain mypy and mypy --install-types --non-interactive
print Success: no issues found in 125 source files and exit 0. mypy only shells out to pip when
it has stubs to install, and it has none — mypy.ini:4 sets ignore_missing_imports = True, and
requests is imported nowhere under src/, tests/, or examples/. With that flag off, the
only missing imports are java and rubicon.objc, platform-only modules with no stub packages
in existence.

The flags are still removed, since they were an unpinned install path inside an otherwise locked
build. But no types-* entry was needed, which is why that task looks half-done in the diff.

Beyond the literal scope list

  • scripts/run-e2e.sh:29,67 — a comment and the "pn not found" error string both told
    contributors to pip install -e .. They're in scripts/, which the acceptance criterion
    covers, and :67 is the message a contributor sees at exactly the moment this PR changes the
    answer.
  • A bash -lc 'command -v uv && uv --version' preflight before the Android emulator step. See
    below.
  • CONTRIBUTING.md:338 used a bare python scripts/check-e2e-coverage.py. That worked under the
    old flow because contributors activated a venv; removing activation breaks it.

The Android preflight

Debian/Ubuntu's /etc/profile assigns PATH outright, so a login shell can discard
GITHUB_PATH additions. Run 33332191983 shows the mechanism survives in this job:
run-e2e.sh hard-guards command -v maestro, maestro reaches PATH only via
echo "$HOME/.maestro/bin" >> $GITHUB_PATH, and all four Android shards passed. That
demonstrates GITHUB_PATH additions are honored inside this bash -lc.

It does not prove setup-uv's own directory is reachable — that run predates setup-uv entirely.
The preflight closes the gap in two seconds instead of after a multi-minute emulator boot, and
stays as a regression guard.

Testing

./scripts/check.sh passes from a fresh clone with no .venv and only uv installed — the
acceptance criterion, run literally rather than against an existing environment.
mkdocs build --strict passes from a clean site/.

The lock resolves and every CI command passes under real 3.10, 3.11, and 3.12 interpreters. The
resolved set was compared against a fresh pip install -e ".[ci]" on main: same 25 packages,
no version moved, nothing on only one side.

Every command block in CONTRIBUTING.md was executed in a clean clone with a PATH scrubbed of
any venv, since a working-tree .venv silently rescues broken commands. Three failures were
found and fixed that way: bare pn --help exited 127, uv run mkdocs serve exited 2 in a
dev-only environment, and the CLI block's cd sequence left the reader in the wrong directory.

The same treatment was applied to inline commands, not just fenced blocks: CONTRIBUTING.md:338
and the two PR-checklist lines at :250-251 all invoked bare python, pytest, ruff, and
black, which worked under the old activate-a-venv flow and exit 127 under this one. Neither
check.sh nor mkdocs --strict would ever catch those.

scripts/check.sh was mutation-checked by injecting a failure at each of its seven steps in a
temp copy, confirming it stops at that step every time.

For release.yml, the exact uv tool install ... --with "gitpython<3.1.60" resolves GitPython
3.1.59 with Actor.name_email_regex present; a bare second positional fails loudly, and --with gitpython unpinned selects 3.1.61. A simulated release — version stamped to 0.31.1, then the
literal build_command — updated and staged uv.lock and produced both artifacts.

Two things most worth your eye

--with in uv tool install. uv tool install takes one positional package, so
uv tool install "python-semantic-release==9.21.2" "gitpython<3.1.60" errors. The pin only binds
through --with. A wrong-but-parsing spelling silently resolves GitPython unpinned and
reproduces the crash the pin exists to prevent — discoverable only on a real release.

The pin may now be obsolete. GitPython 3.1.61 restored Actor.name_email_regex as deprecated
rather than removed, and PSR 9.21.2 loads this repo's config fine against it. I've carried the
pin over unchanged, but the TEMPORARY comment's premise has partly expired. Worth a follow-up
to drop the pin and restore the upstream PSR action.

What only CI can confirm

Opening as a draft for this reason.

setup-uv's cache behavior, install location, and interaction with the matrix python-version;
the bash -lc PATH question; Ubuntu-vs-macOS lock resolution, which matters since e2e-ios is
macos-15; the emulator and simulator paths; and essentially all of release.yml, which PR CI
never exercises since it triggers on push to main. That last one is both unverifiable here and
where the most damaging mistakes would live, which is why it got the most scrutiny above.

Known and not fixed

uv build produces the sdist and wheel but doesn't install them, so the old pip install .
smoke test isn't replaced. That follows the issue's instruction; noting the coverage loss so it's
a decision rather than an oversight.

Following the docs literally scaffolds my_app/ into the repository root, after which
ruff check . lints it and reports D100. Pre-existing — main's CONTRIBUTING.md does the
same at line 27, and [tool.ruff] extend-exclude doesn't cover it. Left alone.

Adebowale-Morakinyo and others added 5 commits September 1, 2026 09:42
The dev and ci extras were byte-identical copies, and dev tooling
shouldn't be published as package extras at all. Both become a single
PEP 735 dev group; docs moves to a docs group. ios and build stay
extras, since those are user-facing.

Adds a committed uv.lock so PR CI is deterministic and dependency
upgrades become deliberate. No version bound changed: the lock pins
whatever currently resolves.

pip>=24.0 joins the dev group. uv sync doesn't seed pip the way
uv venv --seed did, and pn run ios shells out to sys.executable -m pip
to vendor rubicon-objc, which the test suite exercises. Without it a
clean checkout fails with "No module named pip".

Adds the semantic-release build_command from the PSR uv integration
guide, so the release commit carries a refreshed lockfile.
Re-lock uv.lock for the v0.32.0 release. main released v0.32.0 after
this branch was cut, so the merge commit's pyproject.toml no longer
matched the lockfile and `uv sync --locked` failed in every CI job.
The only lock change is this project's own version entry.
owenthcarey merged commit c90bbcb into pythonnative:main Sep 2, 2026
15 checks passed

Adebowale-Morakinyo commented Sep 2, 2026 •
edited
Loading

Copy link
Copy Markdown
Contributor Author

@owenthcarey Thanks for sorting the lockfile - I see you re-locked before merging. For the record, the cause: uv.lock records the project's own version, so any branch open across a release goes stale against main's bumped pyproject.toml, and the PR merge commit fails --locked. Mine was cut before v0.32.0.

That'll hit any contributor whose PR is open when a release lands, and the fix isn't obvious from the error. Happy to open an issue and follow up with either a line in CONTRIBUTING.md ("rebase on main and run uv lock if a release landed while your PR was open") or --frozen in CI, which installs from the lock without the freshness check. Your call on which - --frozen is friendlier but gives up part of what the lockfile is for.

Also, apologies for the red CI - I'd left it as a draft for that reason.

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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.

Migrate development tooling and CI from pip to uv

2 participants


Back | FazBrowse Home | New Git URL