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

build(pyproject,scripts,workflows): migrate development tooling from … · pythonnative/pythonnative@c90bbcb · GitHub

Repository navigation

Commit c90bbcb

Browse files
build(pyproject,scripts,workflows): migrate development tooling from pip to uv (#47)
Refs: #28
1 parent 3223619 commit c90bbcb

9 files changed

Lines changed: 1699 additions & 100 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,37 +17,29 @@ jobs:
1717
- name: Checkout
1818
uses: actions/checkout@v4
1919

20-
- name: Set up Python ${{ matrix.python-version }}
21-
uses: actions/setup-python@v5
20+
- name: Set up uv (Python ${{ matrix.python-version }})
21+
uses: astral-sh/setup-uv@v10.0.1
2222
with:
23+
enable-cache: true
2324
python-version: ${{ matrix.python-version }}
2425

25-
- name: Install tools
26-
run: |
27-
python -m pip install --upgrade pip
28-
pip install -e ".[ci]"
26+
- name: Install dependencies
27+
run: uv sync --locked --group dev
2928

3029
- name: Lint (Ruff)
31-
run: |
32-
ruff check .
30+
run: uv run ruff check .
3331

3432
- name: Format check (Black)
35-
run: |
36-
black --check src examples tests
33+
run: uv run black --check src examples tests
3734

3835
- name: Type check (MyPy)
39-
run: |
40-
mypy --install-types --non-interactive
41-
42-
- name: Install package
43-
run: |
44-
pip install .
36+
run: uv run mypy
4537

38+
# Produces the sdist and wheel through the setuptools backend. Note
39+
# this builds but does not install them, so the previous non-editable
40+
# install smoke test is not replaced.
4641
- name: Build package
47-
run: |
48-
pip install build
49-
python -m build
42+
run: uv build
5043

5144
- name: Run tests
52-
run: |
53-
pytest -q
45+
run: uv run pytest -q

‎.github/workflows/docs.yml‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@ jobs:
1414
runs-on: ubuntu-latest
1515
steps:
1616
- uses: actions/checkout@v4
17-
- uses: actions/setup-python@v5
17+
- uses: astral-sh/setup-uv@v10.0.1
1818
with:
19+
enable-cache: true
1920
python-version: '3.11'
21+
# `uv sync` installs the project itself, which mkdocstrings needs in
22+
# order to import and introspect it.
2023
- name: Install docs deps
21-
run: |
22-
python -m pip install --upgrade pip
23-
pip install -e ".[docs]"
24+
run: uv sync --locked --group docs
2425
- name: Build site
25-
run: |
26-
python -m mkdocs build --strict
26+
run: uv run mkdocs build --strict
2727
- name: Deploy to GitHub Pages
2828
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
2929
uses: peaceiris/actions-gh-pages@v3

‎.github/workflows/e2e.yml‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@ jobs:
6060
- name: Checkout
6161
uses: actions/checkout@v4
6262

63-
- name: Set up Python
64-
uses: actions/setup-python@v5
63+
- name: Set up uv
64+
uses: astral-sh/setup-uv@v10.0.1
6565
with:
66+
enable-cache: true
6667
python-version: '3.11'
6768

6869
- name: Set up Java 17
@@ -72,7 +73,7 @@ jobs:
7273
java-version: '17'
7374

7475
- name: Install PythonNative
75-
run: pip install -e .
76+
run: uv sync --locked
7677

7778
- name: Install Maestro
7879
run: |
@@ -85,12 +86,18 @@ jobs:
8586
sudo udevadm control --reload-rules
8687
sudo udevadm trigger --name-match=kvm
8788
89+
# The emulator step runs its script through a login shell, which
90+
# sources /etc/profile and can rewrite PATH. Confirm uv survives that
91+
# here, in seconds, rather than after a multi-minute emulator boot.
92+
- name: Verify uv is reachable in a login shell
93+
run: bash -lc 'command -v uv && uv --version'
94+
8895
- name: Build, install, and run E2E tests
8996
uses: reactivecircus/android-emulator-runner@v2
9097
with:
9198
api-level: 31
9299
arch: x86_64
93-
script: bash -lc "./scripts/run-e2e.sh android ${{ matrix.suites }}"
100+
script: bash -lc "uv run ./scripts/run-e2e.sh android ${{ matrix.suites }}"
94101

95102
# Maestro writes per-flow debug output (command log, view-hierarchy
96103
# dumps, failure screenshots) under ~/.maestro/tests. Surface it when
@@ -149,13 +156,14 @@ jobs:
149156
- name: Checkout
150157
uses: actions/checkout@v4
151158

152-
- name: Set up Python
153-
uses: actions/setup-python@v5
159+
- name: Set up uv
160+
uses: astral-sh/setup-uv@v10.0.1
154161
with:
162+
enable-cache: true
155163
python-version: '3.11'
156164

157165
- name: Install PythonNative
158-
run: pip install -e .
166+
run: uv sync --locked
159167

160168
# Maestro drives iOS simulators with its own bundled XCTest
161169
# runner; idb-companion (once installed here) hasn't been needed
@@ -167,7 +175,7 @@ jobs:
167175
echo "$HOME/.maestro/bin" >> $GITHUB_PATH
168176
169177
- name: Build and run E2E tests
170-
run: ./scripts/run-e2e.sh ios ${{ matrix.suites }}
178+
run: uv run ./scripts/run-e2e.sh ios ${{ matrix.suites }}
171179
env:
172180
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
173181

‎.github/workflows/release.yml‎

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,12 @@ jobs:
2222
with:
2323
fetch-depth: 0
2424

25-
- name: Set up Python
26-
uses: actions/setup-python@v5
25+
- name: Set up uv
26+
uses: astral-sh/setup-uv@v10.0.1
2727
with:
28+
enable-cache: true
2829
python-version: '3.12'
2930

30-
- name: Install build tools
31-
run: python -m pip install -U pip build
32-
3331
# TEMPORARY: inlined replacement for the
3432
# python-semantic-release/python-semantic-release@v9 action. That
3533
# action builds its Docker image at job time with GitPython
@@ -46,7 +44,7 @@ jobs:
4644
run: |
4745
git config user.name "github-actions"
4846
git config user.email "actions@github.com"
49-
pip install "python-semantic-release==9.21.2" "gitpython<3.1.60"
47+
uv tool install "python-semantic-release==9.21.2" --with "gitpython<3.1.60"
5048
tags_before=$(git tag | wc -l)
5149
semantic-release -v version
5250
tags_after=$(git tag | wc -l)
@@ -56,10 +54,9 @@ jobs:
5654
echo "released=false" >> "$GITHUB_OUTPUT"
5755
fi
5856
59-
- name: Build package
60-
if: steps.release.outputs.released == 'true'
61-
run: python -m build
62-
57+
# The distributions come from `build_command` in
58+
# [tool.semantic_release], which runs `uv build` after PSR stamps the
59+
# new version, so there is no separate build step here.
6360
- name: Publish to PyPI
6461
if: steps.release.outputs.released == 'true'
6562
uses: pypa/gh-action-pypi-publish@release/v1

‎CONTRIBUTING.md‎

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,49 @@ Thanks for your interest in contributing. This repository contains the PythonNat
44

55
## Quick start
66

7-
Development uses Python ≥ 3.10.
7+
Development uses Python ≥ 3.10 and [uv](https://docs.astral.sh/uv/) as the
8+
only prerequisite. `uv sync` creates and updates `.venv` itself, so there's no
9+
virtual environment to make and nothing to activate.
810

911
```bash
10-
# one-shot: creates .venv, syncs CI deps, runs every CI check
11-
# (requires uv: https://docs.astral.sh/uv/getting-started/installation/)
12+
# install the project and its dev tooling into .venv, exactly as CI does
13+
uv sync --locked --group dev
14+
15+
# one-shot: runs every CI check, in the same order
1216
./scripts/check.sh
1317

14-
# Run individual steps if you only want one
15-
pytest -q
16-
ruff check .
17-
black src examples tests
18+
# run individual steps if you only want one
19+
uv run pytest -q
20+
uv run ruff check .
21+
uv run black src examples tests
1822
```
1923

20-
Common library and CLI entry points:
24+
Dependencies are pinned in `uv.lock`, which is committed, so local runs and CI
25+
resolve identically. `--locked` fails rather than silently re-resolving if the
26+
lockfile has drifted from `pyproject.toml`. Upgrading a dependency is a
27+
deliberate `uv lock --upgrade-package <name>` in its own commit.
28+
29+
Common library and CLI entry points. `uv run` puts `.venv/bin` on the path
30+
for one command, so `pn` resolves without activating anything. Each block
31+
starts from the repository root.
2132

2233
```bash
2334
# CLI help
24-
pn --help
35+
uv run pn --help
2536

26-
# create a new sample app from the bundled templates
27-
pn init my_app
37+
# scaffold a sample app into ./my_app/, then work inside it
38+
uv run pn init my_app
2839
cd my_app
40+
uv run pn run android
41+
```
2942

43+
`uv run` looks upward for the nearest project, so it keeps using the
44+
repository's `.venv` from a subdirectory. The bundled example works the same
45+
way:
46+
47+
```bash
3048
# run the Hello World example
31-
cd examples/hello-world && pn run android
49+
cd examples/hello-world && uv run pn run android
3250
```
3351

3452
## Claiming an issue
@@ -70,10 +88,12 @@ Unsolicited pull requests for issues that are already assigned or already have a
7088
Common commands:
7189

7290
```bash
73-
./scripts/check.sh # run all CI checks (mirrors ci.yml)
74-
pytest -q # run tests
75-
ruff check . # lint
76-
black src examples tests # format
91+
./scripts/check.sh # run all CI checks (mirrors ci.yml)
92+
uv sync --locked --group dev # install/refresh .venv from the lockfile
93+
uv run pytest -q # run tests
94+
uv run ruff check . # lint
95+
uv run black src examples tests # format
96+
uv run --group docs mkdocs serve # preview the docs site locally
7797
```
7898

7999
## Conventional Commits
@@ -237,8 +257,8 @@ Co-authored-by: Name <email>
237257
## Pull request checklist
238258

239259
- PR title: Conventional Commits format (CI-enforced by `pr-lint.yml`).
240-
- Tests: added/updated; `pytest` passes.
241-
- Lint/format: `ruff check .`, `black` pass.
260+
- Tests: added/updated; `uv run pytest` passes.
261+
- Lint/format: `uv run ruff check .` and `uv run black --check src examples tests` pass.
242262
- Docs: update `README.md` if behavior changes.
243263
- Templates: update `src/pythonnative/templates/` if generator output changes.
244264
- No generated artifacts committed.
@@ -302,17 +322,17 @@ Build and run everything via the convenience script:
302322

303323
```bash
304324
# Android (emulator must be running)
305-
./scripts/run-e2e.sh android
325+
uv run ./scripts/run-e2e.sh android
306326

307327
# iOS (simulator must be running)
308-
./scripts/run-e2e.sh ios
328+
uv run ./scripts/run-e2e.sh ios
309329
```
310330

311331
For tight iteration, run a single category instead of the full pass:
312332

313333
```bash
314-
./scripts/run-e2e.sh android hooks
315-
./scripts/run-e2e.sh ios components
334+
uv run ./scripts/run-e2e.sh android hooks
335+
uv run ./scripts/run-e2e.sh ios components
316336
```
317337

318338
Available categories: `components`, `hooks`, `navigation`, `layout`, `styling`, `animations`, `misc`.
@@ -325,7 +345,7 @@ When you add a new public symbol you must also:
325345
2. Append a `DemoEntry` in `examples/e2e-suite/app/registry.py`.
326346
3. Add a Maestro flow at `tests/e2e/flows/<category>/<name>.yaml`.
327347
4. Append the flow to the top-level `tests/e2e/android.yaml`, `tests/e2e/ios.yaml`, and the matching `tests/e2e/suites/<category>.yaml`.
328-
5. Confirm `python scripts/check-e2e-coverage.py` exits 0.
348+
5. Confirm `uv run python scripts/check-e2e-coverage.py` exits 0.
329349

330350
`tests/e2e/AGENTS.md` is the deeper reference (label conventions, failure triage, naming rules); AI agents should read it before touching the suite. The `e2e.yml` workflow runs the suite automatically on pushes to `main` and PRs.
331351

‎pyproject.toml‎

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,28 +35,28 @@ ios = [
3535
build = [
3636
"Pillow>=10.0",
3737
]
38-
docs = [
39-
"mkdocs>=1.5",
40-
"mkdocs-material[imaging]>=9.5",
41-
"mkdocstrings[python]>=0.24",
42-
"mkdocs-autorefs>=1.0",
43-
"pymdown-extensions>=10.7",
44-
]
38+
39+
# Contributor tooling, not published as package extras (PEP 735). Install
40+
# with `uv sync --group dev` or `--group docs`; `uv sync` alone gets `dev`.
41+
[dependency-groups]
4542
dev = [
4643
"black>=24.0",
4744
"ruff>=0.5",
4845
"mypy>=1.10",
4946
"pytest>=8.0",
5047
"pytest-asyncio>=0.23",
5148
"Pillow>=10.0",
49+
# `pn run ios` shells out to `sys.executable -m pip` to vendor
50+
# rubicon-objc (project/builder.py), and the test suite exercises that
51+
# path. `uv sync` does not seed pip the way `uv venv --seed` did.
52+
"pip>=24.0",
5253
]
53-
ci = [
54-
"black>=24.0",
55-
"ruff>=0.5",
56-
"mypy>=1.10",
57-
"pytest>=8.0",
58-
"pytest-asyncio>=0.23",
59-
"Pillow>=10.0",
54+
docs = [
55+
"mkdocs>=1.5",
56+
"mkdocs-material[imaging]>=9.5",
57+
"mkdocstrings[python]>=0.24",
58+
"mkdocs-autorefs>=1.0",
59+
"pymdown-extensions>=10.7",
6060
]
6161

6262
[project.scripts]
@@ -144,6 +144,15 @@ asyncio_mode = "auto"
144144
# ── Semantic Release ────────────────────────────────────────────────
145145

146146
[tool.semantic_release]
147+
# PSR stamps the new version into pyproject.toml before running this, so
148+
# `--upgrade-package` re-syncs only this project's own version in the lock
149+
# (never dependency upgrades), and the staged uv.lock lands in the release
150+
# commit. This also replaces the workflow's separate `python -m build`.
151+
build_command = """
152+
uv lock --upgrade-package pythonnative
153+
git add uv.lock
154+
uv build
155+
"""
147156
version_toml = ["pyproject.toml:project.version"]
148157
version_variables = ["src/pythonnative/__init__.py:__version__"]
149158
commit_message = "chore(release): v{version}"

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL