Skip to content

Commit e72d996

Browse files
committed
chore(python): use uv for package management
1 parent bc3beb4 commit e72d996

19 files changed

+1933
-258
lines changed

.github/workflows/build.yml

+27-25
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ jobs:
137137
- uses: actions/setup-node@v4
138138
with:
139139
node-version: 22.x
140+
- uses: astral-sh/setup-uv@v5
141+
with:
142+
enable-cache: false
140143
- name: Set up Python ${{ matrix.python-version }}
141144
uses: actions/setup-python@v5
142145
with:
@@ -145,19 +148,18 @@ jobs:
145148
- name: Setup tmate session
146149
uses: mxschmitt/action-tmate@v3
147150
if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
148-
- name: Install Python packaging/test tools
149-
run: pip install tox nox wheel numpy -r python/requirements-test.txt
150-
- run: nox -s lint format mypy
151+
- run: uvx nox -s lint format mypy
151152
- name: Check for dirty working directory
152153
run: git diff --exit-code
153-
- name: Test with tox
154-
run: tox -e ${{ fromJSON('["skip-browser-tests","firefox-xvfb"]')[runner.os == 'Linux'] }}
154+
- name: Run python tests (skip browser tests)
155+
run: uvx nox -s test -- --skip-browser-tests
156+
if: ${{ runner.os != 'Linux' }}
157+
- name: Run python tests (include browser tests)
158+
run: uvx nox -s test_xvfb -- --browser firefox
159+
if: ${{ runner.os == 'Linux' }}
155160
# Verify that editable install works
156-
- name: Install in editable form
157-
run: pip install -e . --config-settings editable_mode=strict
158-
- name: Run Python tests against editable install (excluding WebGL)
159-
working-directory: python/tests
160-
run: pytest -vv --skip-browser-tests
161+
- name: Test in editable form
162+
run: uvx nox -s test_editable
161163

162164
python-build-package:
163165
strategy:
@@ -185,34 +187,33 @@ jobs:
185187
with:
186188
node-version: 22.x
187189
cache: "npm"
190+
- uses: astral-sh/setup-uv@v5
191+
with:
192+
enable-cache: false
188193
- name: Set up Python
189194
uses: actions/setup-python@v5
190195
with:
191196
python-version: 3.x
192-
- name: Get pip cache dir
193-
id: pip-cache
197+
- name: Get uv cache dir
198+
id: uv-cache
194199
run: |
195-
echo "dir=$(pip cache dir)" >> "$GITHUB_OUTPUT"
200+
echo "dir=$(uv cache dir)" >> "$GITHUB_OUTPUT"
196201
- run: npm ci
197202
- run: |
198203
build_info="{'tag':'$(git describe --always --tags)', 'url':'https://github.com/google/neuroglancer/commit/$(git rev-parse HEAD)', 'timestamp':'$(date)'}"
199204
npm run build-python -- --no-typecheck --no-lint --define NEUROGLANCER_BUILD_INFO="${build_info}"
200205
shell: bash
201206
- name: Check for dirty working directory
202207
run: git diff --exit-code
203-
- name: Install setuptools
204-
run: pip install setuptools
205208
- name: Build Python source distribution (sdist)
206-
run: python setup.py sdist --format gztar
209+
run: uv build --sdist
207210
if: ${{ runner.os == 'Linux' }}
208-
- name: Install cibuildwheel
209-
run: pip install cibuildwheel
210211
- name: Build Python wheels
211-
run: bash -xve ./python/build_tools/cibuildwheel.sh
212+
run: uvx nox -s cibuildwheel
212213
env:
213-
# On Linux, share pip cache with manylinux docker containers
214-
CIBW_ENVIRONMENT_LINUX: PIP_CACHE_DIR=/host${{ steps.pip-cache.outputs.dir }}
215-
CIBW_BEFORE_ALL_LINUX: /project/python/build_tools/cibuildwheel_linux_cache_setup.sh /host${{ steps.pip-cache.outputs.dir }}
214+
# On Linux, share uv cache with manylinux docker containers
215+
CIBW_ENVIRONMENT_LINUX: UV_CACHE_DIR=/host${{ steps.uv-cache.outputs.dir }}
216+
CIBW_BEFORE_ALL_LINUX: /project/python/build_tools/cibuildwheel_linux_cache_setup.sh /host${{ steps.uv-cache.outputs.dir }}
216217
CIBW_BUILD: ${{ matrix.cibw_build }}
217218
- name: Upload wheels as artifacts
218219
uses: actions/upload-artifact@v4
@@ -226,6 +227,9 @@ jobs:
226227
runs-on: ubuntu-latest
227228
steps:
228229
- uses: actions/checkout@v4
230+
- uses: astral-sh/setup-uv@v5
231+
with:
232+
enable-cache: false
229233
- name: Set up Python
230234
uses: actions/setup-python@v5
231235
with:
@@ -234,10 +238,8 @@ jobs:
234238
uses: ts-graphviz/setup-graphviz@b1de5da23ed0a6d14e0aeee8ed52fdd87af2363c # v2.0.2
235239
with:
236240
macos-skip-brew-update: "true"
237-
- name: Install nox
238-
run: pip install nox
239241
- name: Build docs
240-
run: nox -s docs
242+
run: uvx nox -s docs
241243
- name: Upload docs as artifact
242244
uses: actions/upload-artifact@v4
243245
with:

.github/workflows/build_docs_preview.yml

+5-4
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,19 @@ jobs:
99

1010
steps:
1111
- uses: actions/checkout@v4
12+
- uses: astral-sh/setup-uv@v5
13+
with:
14+
enable-cache: false
1215
- name: Set up Python ${{ matrix.python-version }}
1316
uses: actions/setup-python@v5
1417
with:
15-
python-version: 3.12
18+
python-version: 3.13
1619
- name: Setup Graphviz
1720
uses: ts-graphviz/setup-graphviz@b1de5da23ed0a6d14e0aeee8ed52fdd87af2363c # v2.0.2
1821
with:
1922
macos-skip-brew-update: "true"
20-
- name: Install nox
21-
run: pip install nox
2223
- name: Build documentation
23-
run: nox -s docs
24+
run: uvx nox -s docs
2425
- name: Upload client as artifact
2526
uses: actions/upload-artifact@v4
2627
with:

docs/requirements.txt

-7
This file was deleted.

dprint.json

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"plugins": [
3+
// specify plugin urls here
4+
"https://plugins.dprint.dev/toml-0.6.3.wasm"
5+
]
6+
}

noxfile.py

+132-8
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,64 @@
22

33
import nox
44

5+
nox.options.default_venv_backend = "uv"
56
nox.options.reuse_existing_virtualenvs = True
67
nox.options.error_on_external_run = True
78

89

910
@nox.session
1011
def lint(session):
11-
session.install("-r", "python/requirements-lint.txt")
12-
session.run("ruff", "check", ".")
12+
session.run_install(
13+
"uv",
14+
"sync",
15+
"--only-group",
16+
"ruff",
17+
env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location},
18+
)
19+
session.run("ruff", "check", ".", *session.posargs)
1320

1421

1522
@nox.session
1623
def format(session):
17-
session.install("-r", "python/requirements-lint.txt")
18-
session.run("ruff", "format", ".")
24+
session.run_install(
25+
"uv",
26+
"sync",
27+
"--only-group",
28+
"ruff",
29+
env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location},
30+
)
31+
session.run("ruff", "format", ".", *session.posargs)
1932

2033

2134
@nox.session
2235
def mypy(session):
23-
session.install("-r", "python/requirements-mypy.txt")
24-
session.run("mypy", ".")
36+
session.run_install(
37+
"uv",
38+
"sync",
39+
"--no-install-workspace",
40+
"--no-default-groups",
41+
"--group",
42+
"mypy",
43+
"--extra",
44+
"webdriver",
45+
"--group",
46+
"test",
47+
env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location},
48+
)
49+
session.run("mypy", ".", *session.posargs)
2550

2651

2752
@nox.session
28-
def docs(session):
29-
session.install("-r", "docs/requirements.txt")
53+
def docs(session: nox.Session):
54+
session.run_install(
55+
"uv",
56+
"sync",
57+
"--no-default-groups",
58+
"--group",
59+
"docs",
60+
"--no-install-workspace",
61+
env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location},
62+
)
3063
session.run(
3164
"sphinx-build",
3265
"docs",
@@ -37,7 +70,98 @@ def docs(session):
3770
"-T",
3871
"-W",
3972
"--keep-going",
73+
*session.posargs,
4074
env={
4175
"PYTHONPATH": os.path.join(os.path.dirname(__file__), "python"),
4276
},
4377
)
78+
79+
80+
@nox.session
81+
def test(session: nox.Session):
82+
session.run_install(
83+
"uv",
84+
"sync",
85+
"--no-default-groups",
86+
"--group",
87+
"test",
88+
"--extra",
89+
"webdriver",
90+
"--no-editable",
91+
env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location},
92+
)
93+
session.chdir("python/tests")
94+
session.run("pytest", "-vv", "-s", *session.posargs)
95+
96+
97+
@nox.session
98+
def test_xvfb(session: nox.Session):
99+
session.run_install(
100+
"uv",
101+
"sync",
102+
"--no-default-groups",
103+
"--group",
104+
"test",
105+
"--extra",
106+
"webdriver",
107+
"--no-editable",
108+
env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location},
109+
)
110+
session.chdir("python/tests")
111+
session.run(
112+
"xvfb-run",
113+
"-e",
114+
"/dev/stderr",
115+
"--auto-servernum",
116+
"--server-args",
117+
"-screen 0 1024x768x24",
118+
"pytest",
119+
"-vv",
120+
"-s",
121+
*session.posargs,
122+
external=True,
123+
env={"PATH": os.environ["PATH"]},
124+
include_outer_env=False,
125+
)
126+
127+
128+
@nox.session
129+
def test_editable(session: nox.Session):
130+
session.run_install(
131+
"uv",
132+
"sync",
133+
"--no-default-groups",
134+
"--group",
135+
"test",
136+
"--extra",
137+
"webdriver",
138+
env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location},
139+
)
140+
session.chdir("python/tests")
141+
session.run("pytest", "-vv", "-s", "--skip-browser-tests", *session.posargs)
142+
143+
144+
@nox.session(python=False)
145+
def cibuildwheel(session: nox.Session):
146+
session.run(
147+
"uv",
148+
"run",
149+
"--only-group",
150+
"cibuildwheel",
151+
"cibuildwheel",
152+
"--output-dir",
153+
"dist",
154+
*session.posargs,
155+
env={
156+
"CIBW_BUILD_FRONTEND": "build[uv]",
157+
"CIBW_ARCHS_MACOS": "x86_64 arm64",
158+
"CIBW_SKIP": "pp* *_i686 *-win32 *-musllinux*",
159+
"CIBW_TEST_GROUPS": "test",
160+
"CIBW_TEST_COMMAND": "python -m pytest {project}/python/tests -vv -s --skip-browser-tests",
161+
"CIBW_MANYLINUX_X86_64_IMAGE": "manylinux2014",
162+
# Assume the client bundle was already built. The github actions workflow builds
163+
# the client with specific defines to include the build stamp, and that would be
164+
# lost if setup.py rebuilds the client.
165+
"CIBW_ENVIRONMENT": "NEUROGLANCER_PREBUILT_CLIENT=1",
166+
},
167+
)

0 commit comments

Comments
 (0)