Skip to content

Commit f3c60ab

Browse files
Merge pull request #561 from Backblaze/uv
Migrate from pdm to uv. Clean project dependency structure
2 parents 504859f + a8ef09d commit f3c60ab

File tree

9 files changed

+2480
-110
lines changed

9 files changed

+2480
-110
lines changed

.github/workflows/cd.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ on:
66

77
env:
88
PYTHON_DEFAULT_VERSION: "3.12"
9+
UV_VERSION: "0.8.24"
910

1011
jobs:
1112
deploy:
@@ -26,13 +27,17 @@ jobs:
2627
uses: actions/setup-python@v6
2728
with:
2829
python-version: ${{ env.PYTHON_DEFAULT_VERSION }}
30+
- uses: astral-sh/setup-uv@v7
31+
with:
32+
version: ${{ env.UV_VERSION }}
33+
enable-cache: true
2934
- name: Display Python version
3035
run: python -c "import sys; print(sys.version)"
3136
- name: Install dependencies
32-
run: python -m pip install --upgrade nox pdm==2.26.2
37+
run: uv sync --only-group nox --locked
3338
- name: Build the distribution
3439
id: build
35-
run: nox -vs build
40+
run: uv run nox -vs build
3641
- name: Read the Changelog
3742
id: read-changelog
3843
uses: mindsers/changelog-reader-action@v2

.github/workflows/ci.yml

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ on:
88

99
env:
1010
PYTHON_DEFAULT_VERSION: "3.12"
11+
UV_VERSION: "0.8.24"
1112

1213
jobs:
1314
lint:
@@ -24,17 +25,20 @@ jobs:
2425
uses: actions/setup-python@v6
2526
with:
2627
python-version: ${{ env.PYTHON_DEFAULT_VERSION }}
27-
cache: "pip"
28+
- uses: astral-sh/setup-uv@v7
29+
with:
30+
version: ${{ env.UV_VERSION }}
31+
enable-cache: true
2832
- name: Install dependencies
29-
run: python -m pip install --upgrade nox pdm==2.26.2
33+
run: uv sync --only-group nox --locked
3034
- name: Run linters
31-
run: nox -vs lint
35+
run: uv run nox -vs lint
3236
- name: Validate new changelog entries
3337
if: (contains(github.event.pull_request.labels.*.name, '-changelog') == false) && (github.event.pull_request.base.ref != '')
3438
run: if [ -z "$(git diff --diff-filter=A --name-only origin/${{ github.event.pull_request.base.ref }} changelog.d)" ];
3539
then echo no changelog item added; exit 1; fi
3640
- name: Changelog validation
37-
run: nox -vs towncrier_check
41+
run: uv run nox -vs towncrier_check
3842
build:
3943
timeout-minutes: 30
4044
needs: lint
@@ -47,11 +51,14 @@ jobs:
4751
uses: actions/setup-python@v6
4852
with:
4953
python-version: ${{ env.PYTHON_DEFAULT_VERSION }}
50-
cache: "pip"
54+
- uses: astral-sh/setup-uv@v7
55+
with:
56+
version: ${{ env.UV_VERSION }}
57+
enable-cache: true
5158
- name: Install dependencies
52-
run: python -m pip install --upgrade nox pdm==2.26.2
59+
run: uv sync --only-group nox --locked
5360
- name: Build the distribution
54-
run: nox -vs build
61+
run: uv run nox -vs build
5562
cleanup_buckets:
5663
timeout-minutes: 30
5764
needs: lint
@@ -69,13 +76,17 @@ jobs:
6976
uses: actions/setup-python@v6
7077
with:
7178
python-version: ${{ env.PYTHON_DEFAULT_VERSION }}
72-
cache: "pip"
79+
- uses: astral-sh/setup-uv@v7
80+
if: ${{ env.B2_TEST_APPLICATION_KEY != '' && env.B2_TEST_APPLICATION_KEY_ID != '' }} # TODO: skip this whole job instead
81+
with:
82+
version: ${{ env.UV_VERSION }}
83+
enable-cache: true
7384
- name: Install dependencies
7485
if: ${{ env.B2_TEST_APPLICATION_KEY != '' && env.B2_TEST_APPLICATION_KEY_ID != '' }} # TODO: skip this whole job instead
75-
run: python -m pip install --upgrade nox pdm==2.26.2
86+
run: uv sync --only-group nox --locked
7687
- name: Find and remove old buckets
7788
if: ${{ env.B2_TEST_APPLICATION_KEY != '' && env.B2_TEST_APPLICATION_KEY_ID != '' }} # TODO: skip this whole job instead
78-
run: nox -vs cleanup_old_buckets
89+
run: uv run nox -vs cleanup_old_buckets
7990
test:
8091
timeout-minutes: 90
8192
needs: cleanup_buckets
@@ -107,14 +118,17 @@ jobs:
107118
uses: actions/setup-python@v6
108119
with:
109120
python-version: ${{ matrix.python-version }}
110-
cache: "pip"
121+
- uses: astral-sh/setup-uv@v7
122+
with:
123+
version: ${{ env.UV_VERSION }}
124+
enable-cache: true
111125
- name: Install dependencies
112-
run: python -m pip install --upgrade nox pdm==2.26.2
126+
run: uv sync --only-group nox --locked
113127
- name: Run unit tests
114-
run: nox -vs unit -- -v
128+
run: uv run nox -vs unit -- -v
115129
- name: Run integration tests
116130
if: ${{ env.B2_TEST_APPLICATION_KEY != '' && env.B2_TEST_APPLICATION_KEY_ID != '' }}
117-
run: nox -vs integration -- --dont-cleanup-old-buckets -v
131+
run: uv run nox -vs integration -- --dont-cleanup-old-buckets -v
118132
doc:
119133
timeout-minutes: 30
120134
needs: build
@@ -127,13 +141,17 @@ jobs:
127141
uses: actions/setup-python@v6
128142
with:
129143
python-version: ${{ env.PYTHON_DEFAULT_VERSION }}
130-
cache: "pip"
131-
- name: Install dependencies
144+
- uses: astral-sh/setup-uv@v7
145+
with:
146+
version: ${{ env.UV_VERSION }}
147+
enable-cache: true
148+
- name: Install system dependencies
132149
env:
133150
DEBIAN_FRONTEND: noninteractive
134151
run: |
135152
sudo apt-get update -y
136153
sudo apt-get install -y graphviz plantuml
137-
python -m pip install --upgrade nox pdm==2.26.2
154+
- name: Install dependencies
155+
run: uv sync --only-group nox --locked
138156
- name: Build the docs
139-
run: nox --non-interactive -vs doc
157+
run: uv run nox --non-interactive -vs doc

.readthedocs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ build:
1313
- graphviz
1414
jobs:
1515
post_create_environment:
16-
- pip install pdm
17-
- pdm export --format requirements --group doc --output requirements-doc.txt
16+
- python -m pip install uv==0.8.4
17+
- uv export --format requirements-txt --group doc --output-file requirements-doc.txt
1818

1919
# Build documentation in the docs/ directory with Sphinx
2020
sphinx:

CONTRIBUTING.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ for a given github issue).
5555

5656
## Developer Info
5757

58-
You'll need to have [nox](https://github.com/theacodes/nox) and [pdm](https://pdm-project.org/) installed:
58+
You'll need to have [nox](https://github.com/theacodes/nox) and [uv](https://docs.astral.sh/uv/) installed:
5959

60-
* `pip install nox pdm`
60+
* `pip install nox uv`
6161

6262
With `nox`, you can run different sessions (default are `lint` and `test`):
6363

@@ -99,11 +99,11 @@ Given Python interpreters should be installed in the operating system or via [py
9999

100100
## Managing dependencies
101101

102-
We use [pdm](https://pdm-project.org/) for managing dependencies and developing locally.
102+
We use [uv](https://docs.astral.sh/uv/) for managing dependencies and developing locally.
103103
If you want to change any of the project requirements (or requirement bounds) in `pyproject.toml`,
104-
make sure that `pdm.lock` file reflects those changes by using `pdm add`, `pdm update` or other
105-
commands - see [documentation](https://pdm-project.org/latest/). You can verify that lock file
106-
is up to date by running the linter.
104+
make sure that `uv.lock` file reflects those changes by using `uv add`, `uv lock` or other
105+
commands - see [documentation](https://docs.astral.sh/uv/). You can verify that the lock file
106+
is up to date by running `uv lock --check`.
107107

108108
## Linting
109109

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Use a separate nox dependency group for reprocible installs of nox in ci / cd.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Migrate from pdm to uv.

noxfile.py

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919

2020
UPSTREAM_REPO_URL = '[email protected]:Backblaze/b2-sdk-python.git'
2121

22-
# Required for PDM to use nox's virtualenvs
23-
os.environ.update({'PDM_IGNORE_SAVED_PYTHON': '1'})
24-
2522
CI = os.environ.get('CI') is not None
2623
NOX_PYTHONS = os.environ.get('NOX_PYTHONS')
2724
_NOX_EXTRAS = os.environ.get('NOX_EXTRAS')
@@ -59,20 +56,27 @@ def _detect_python_nox_id() -> str:
5956

6057
PY_PATHS = ['b2sdk', 'test', 'noxfile.py']
6158

62-
nox.options.reuse_existing_virtualenvs = True
59+
nox.options.default_venv_backend = 'uv'
60+
nox.options.reuse_existing_virtualenvs = False
6361
nox.options.sessions = [
6462
'lint',
6563
'test',
6664
]
6765

6866

69-
def pdm_install(session: nox.Session, *args: str, dev: bool = True) -> None:
70-
# dev dependencies are installed by default
71-
prod_args = [] if dev else ['--prod']
72-
group_args = []
73-
for group in args:
74-
group_args.extend(['--group', group])
75-
session.run('pdm', 'install', *prod_args, *group_args, external=True)
67+
def uv_install(
68+
session: nox.Session, *, groups: tuple[str, ...] = (), extras: tuple[str, ...] = ()
69+
) -> None:
70+
args = ['sync', '--locked']
71+
for group in groups:
72+
if group:
73+
args.extend(['--group', group])
74+
for extra in extras:
75+
if extra:
76+
args.extend(['--extra', extra])
77+
uv_env = getattr(session.virtualenv, 'location', os.getenv('VIRTUAL_ENV'))
78+
79+
session.run_install('uv', *args, env={'UV_PROJECT_ENVIRONMENT': uv_env})
7680

7781

7882
def skip_coverage(python_version: str | None) -> bool:
@@ -82,7 +86,7 @@ def skip_coverage(python_version: str | None) -> bool:
8286
@nox.session(name='format', python=PYTHON_DEFAULT_VERSION)
8387
def format_(session):
8488
"""Lint the code and apply fixes in-place whenever possible."""
85-
pdm_install(session, 'lint')
89+
uv_install(session, groups=('format',))
8690
session.run('ruff', 'check', '--fix', *PY_PATHS)
8791
session.run('ruff', 'format', *PY_PATHS)
8892
# session.run(
@@ -99,7 +103,7 @@ def format_(session):
99103
def lint(session):
100104
"""Run linters in readonly mode."""
101105
# We need to install 'doc' group because liccheck needs to inspect it.
102-
pdm_install(session, 'doc', 'lint', 'full')
106+
uv_install(session, groups=('doc', 'lint'), extras=('full',))
103107
session.run('ruff', 'check', *PY_PATHS)
104108
session.run('ruff', 'format', *PY_PATHS)
105109
# session.run(
@@ -114,15 +118,12 @@ def lint(session):
114118
session.run('pytest', 'test/static')
115119
session.run('liccheck', '-s', 'pyproject.toml')
116120

117-
# Check if the lockfile is up to date
118-
session.run('pdm', 'lock', '--check', external=True)
119-
120121

121122
@nox.session(python=PYTHON_VERSIONS)
122123
@nox.parametrize('extras', NOX_EXTRAS)
123124
def unit(session, extras):
124125
"""Run unit tests."""
125-
pdm_install(session, 'test', *extras)
126+
uv_install(session, groups=('test',), extras=tuple(extras))
126127
args = ['--doctest-modules', '-n', 'auto']
127128
if not skip_coverage(session.python):
128129
args += ['--cov=b2sdk', '--cov-branch', '--cov-report=xml']
@@ -142,14 +143,14 @@ def unit(session, extras):
142143
@nox.parametrize('extras', NOX_EXTRAS)
143144
def integration(session, extras):
144145
"""Run integration tests."""
145-
pdm_install(session, 'test', *extras)
146+
uv_install(session, groups=('test',), extras=tuple(extras))
146147
session.run('pytest', '-s', *session.posargs, 'test/integration')
147148

148149

149150
@nox.session(python=PYTHON_DEFAULT_VERSION)
150151
def cleanup_old_buckets(session):
151152
"""Remove buckets from previous test runs."""
152-
pdm_install(session, 'test')
153+
uv_install(session, groups=('test',))
153154
session.run('python', '-m', 'test.integration.cleanup_buckets')
154155

155156

@@ -167,15 +168,15 @@ def test(session):
167168
@nox.session
168169
def cover(session):
169170
"""Perform coverage analysis."""
170-
pdm_install(session, 'test')
171+
uv_install(session, groups=('test',))
171172
session.run('coverage', 'report', '--fail-under=75', '--show-missing', '--skip-covered')
172173
session.run('coverage', 'erase')
173174

174175

175176
@nox.session(python=PYTHON_DEFAULT_VERSION)
176177
def build(session):
177178
"""Build the distribution."""
178-
session.run('pdm', 'build', external=True)
179+
session.run('uv', 'build', external=True)
179180

180181
# Set outputs for GitHub Actions
181182
if CI:
@@ -191,7 +192,7 @@ def build(session):
191192
@nox.session(python=PYTHON_DEFAULT_VERSION)
192193
def doc(session):
193194
"""Build the documentation."""
194-
pdm_install(session, 'doc')
195+
uv_install(session, groups=('doc',))
195196
session.cd('doc')
196197
sphinx_args = ['-b', 'html', '-T', '-W', 'source', 'build/html']
197198
session.run('rm', '-rf', 'build', external=True)
@@ -216,7 +217,7 @@ def doc(session):
216217
@nox.session
217218
def doc_cover(session):
218219
"""Perform coverage analysis for the documentation."""
219-
pdm_install(session, 'doc')
220+
uv_install(session, groups=('doc',))
220221
session.cd('doc')
221222
sphinx_args = ['-b', 'coverage', '-T', '-W', 'source', 'build/coverage']
222223
report_file = 'build/coverage/python.txt'
@@ -253,7 +254,7 @@ def make_release_commit(session):
253254
if current_branch != 'master':
254255
session.log('WARNING: releasing from a branch different than master')
255256

256-
pdm_install(session, 'release')
257+
uv_install(session, groups=('release',))
257258
session.run('towncrier', 'build', '--yes', '--version', version)
258259

259260
session.log(

0 commit comments

Comments
 (0)