Skip to content

Commit

Permalink
Replace PDM with uv (#111)
Browse files Browse the repository at this point in the history
This PR replaces PDM with uv while removing dependency groups to
simplify dev dependencies as well as noxfile logic.
  • Loading branch information
SRv6d authored Sep 13, 2024
1 parent bbda356 commit a66dbea
Show file tree
Hide file tree
Showing 11 changed files with 926 additions and 2,295 deletions.
7 changes: 1 addition & 6 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
{
"name": "Python 3",
"image": "mcr.microsoft.com/devcontainers/python:0-3.11",
"features": {
"ghcr.io/devcontainers-contrib/features/pdm:2": {},
"ghcr.io/devcontainers-contrib/features/nox:2": {}
},
"postCreateCommand": "pdm install",
"image": "ghcr.io/astral-sh/uv:python3.11-bookworm",
"customizations": {
"vscode": {
"extensions": [
Expand Down
4 changes: 2 additions & 2 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ For users of IDEs with support for devcontainers, it's usage is recommended.

### Other

Ensure you have Python 3.11 or greater with recent versions of [pdm] and [nox] in your environment.
Ensure you have Python 3.11 or greater with recent versions of [uv] and [nox] in your environment.

## Coding Standards

Expand Down Expand Up @@ -87,7 +87,7 @@ as well as [mypy] for static type checks.
assert stderr == b""
```

[pdm]: https://github.com/pdm-project/pdm
[uv]: https://github.com/astral-sh/uv
[nox]: https://github.com/wntrblm/nox
[ruff]: https://github.com/astral-sh/ruff
[mypy]: https://github.com/python/mypy
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pdm-project/setup-pdm@v4
- uses: astral-sh/setup-uv@v2
with:
cache: true
enable-cache: true
- name: Build
run: pdm build
run: uv build
- name: Attest Build Provenance
uses: actions/attest-build-provenance@v1
with:
Expand Down
22 changes: 17 additions & 5 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
name: Publish

on:
release:
types: [published]
workflow_run:
workflows: [Build]
types: [completed]
workflow_dispatch:

permissions:
Expand All @@ -15,6 +16,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pdm-project/setup-pdm@v4
- name: Publish to PyPI
run: pdm publish
- uses: actions/setup-python@v5
with:
python-version: "3.x"

- name: Create Dist Directory
run: mkdir dist

- name: Download Relase Sdist and Wheel
run: gh release download ${GITHUB_REF_NAME} --pattern "anycastd-*" --dir dist
env:
GITHUB_TOKEN: ${{ github.token }}

- name: Publish distribution to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
13 changes: 6 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ permissions:
id-token: write

jobs:
test:
name: test with Python ${{ matrix.python_version }}
pytest:
name: pytest (Python ${{ matrix.python_version }})
runs-on: ubuntu-latest
strategy:
matrix:
Expand All @@ -29,12 +29,11 @@ jobs:
PYTHON: ${{ matrix.python_version }}
steps:
- uses: actions/checkout@v4
- uses: pdm-project/setup-pdm@v4
- uses: astral-sh/setup-uv@v2
with:
python-version: ${{ matrix.python_version }}
cache: true
- run: pip3 install nox
- run: nox -s test
enable-cache: true
- run: uv python install ${{ matrix.python_version }}
- run: uvx nox -s test
- name: Upload coverage reports to Codecov
uses: codecov/[email protected]
with:
Expand Down
27 changes: 12 additions & 15 deletions .github/workflows/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,29 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pdm-project/setup-pdm@v4
- uses: astral-sh/setup-uv@v2
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: true
- run: pip3 install nox
- run: nox -s lint
enable-cache: true
- run: uv python install ${{ env.PYTHON_VERSION }}
- run: uvx nox -s lint
check-lockfile:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pdm-project/setup-pdm@v4
- uses: astral-sh/setup-uv@v2
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: true
- run: pip3 install nox
- run: nox -s lockfile
enable-cache: true
- run: uv python install ${{ env.PYTHON_VERSION }}
- run: uvx nox -s lockfile
type-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pdm-project/setup-pdm@v4
- uses: astral-sh/setup-uv@v2
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: true
- run: pip3 install nox
- run: nox -s mypy
enable-cache: true
- run: uv python install ${{ env.PYTHON_VERSION }}
- run: uvx nox -s mypy
spellcheck:
runs-on: ubuntu-latest
steps:
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
<a>
<img src="https://img.shields.io/badge/v3.11+-black?style=flat&color=FFFF00&label=Python" alt="python version">
</a>
<a href="https://pdm.fming.dev">
<img src="https://img.shields.io/badge/pdm-managed-blueviolet" alt="pdm">
<a href="https://github.com/astral-sh/uv">
<img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json" alt="uv">
</a>
</div>
<br>
Expand Down
110 changes: 45 additions & 65 deletions noxfile.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os
import shutil
from typing import List, Optional
from typing import Sequence

import nox

Expand All @@ -12,64 +12,49 @@
FRR_LATEST_MAJOR_VERSION = "9.1.0"

nox.options.sessions = SESSIONS
os.environ.update({"PDM_IGNORE_SAVED_PYTHON": "1"})


def pdm_sync(
def uv_run(
session: nox.Session,
*,
self: bool = False,
default: bool = False,
editable: bool = True,
groups: Optional[List[str]] = None,
command: str,
args: Sequence[str],
) -> None:
"""Install dependencies using PDM.
"""Use uv to run a command provided by a Python package.
Args:
session: The nox session.
self: Whether to install the package itself.
default: Whether to install the default dependencies.
editable: Whether to install packages in editable mode.
groups: The dependency groups to install.
command: The command to run.
args: The command arguments.
"""
cmd = ["pdm", "sync"]
if not self:
cmd.append("--no-self")
if not default:
cmd.append("--no-default")
if not editable:
cmd.append("--no-editable")
if groups:
for group in groups:
cmd.append("-G")
cmd.append(group)

session.run(*cmd, external=True)
session.run("uv", "run", command, *args, external=True)


@nox.session(python=PYTHON)
def lockfile(session: nox.Session) -> None:
"""Check if the lockfile is up-to-date."""
session.run("pdm", "lock", "--check", external=True)
session.run("uv", "lock", "--locked", external=True)


@nox.session(python=PYTHON)
@nox.session(python=PYTHON, venv_backend="uv")
def lint(session: nox.Session) -> None:
"""Lint code and check formatting using ruff."""
pdm_sync(session, groups=["lint"])
session.run("ruff", "check", "src", "tests")
uv_run(session, command="ruff", args=["check", "src", "tests"])
# Use ruff to check that formatting conforms to black.
session.run("ruff", "format", "--check", "src", "tests")
uv_run(
session,
command="ruff",
args=["format", "--check", "src", "tests"],
)


@nox.session(python=PYTHON)
@nox.session(python=PYTHON, venv_backend="uv")
def mypy(session: nox.Session) -> None:
"""Validate static types using mypy."""
pdm_sync(session, default=True, groups=["typecheck", "type_stubs"])
session.run("mypy", "src")
uv_run(session, command="mypy", args=["src"])


@nox.session(python=PYTHON)
@nox.session(python=PYTHON, venv_backend="uv")
def test(session: nox.Session) -> None:
"""Run tests without external dependencies if not running in CI.
Expand All @@ -80,18 +65,17 @@ def test(session: nox.Session) -> None:
pytest_no_external_dependencies(session)
else:
pytest_full(session)
session.run("coverage", "xml")
uv_run(session, command="coverage", args=["xml"])


@nox.session(python=PYTHON)
@nox.session(python=PYTHON, venv_backend="uv")
def pytest_no_external_dependencies(session: nox.Session) -> None:
"""Run pytest tests that have no external dependencies.
This session only runs tests that do not require external dependencies
such as real databases, Docker, etc. and thus should be able to run
on any developer machine.
"""
pdm_sync(session, self=True, default=True, groups=["test"])
session.warn(
"Skipping the following test marker(s) "
"since they require external dependencies: {}.\n"
Expand All @@ -107,57 +91,53 @@ def pytest_no_external_dependencies(session: nox.Session) -> None:
else:
markexpr += f" and not {marker}"

session.run("pytest", "tests", "-m", markexpr, *session.posargs)
uv_run(session, command="pytest", args=["tests", "-m", markexpr, *session.posargs])


@nox.session(python=PYTHON)
@nox.session(python=PYTHON, venv_backend="uv")
def pytest_full(session: nox.Session) -> None:
"""Run all pytest tests.
This session includes all tests and is intended to be
run in CI or before a commit.
"""
pdm_sync(session, self=True, default=True, groups=["test"])
args = session.posargs if not CI else ["--cov"]
session.run(
"pytest",
"tests",
"-m",
# FRRouting tests that run against a FRRouting daemon have their own session
"not frrouting_daemon_required",
*args,
uv_run(
session,
command="pytest",
args=[
"tests",
"-m",
# FRRouting tests that run against a FRRouting daemon have their own session
"not frrouting_daemon_required",
*args,
],
)
session.notify("pytest_frrouting_daemon_required")


@nox.session(python=PYTHON)
@nox.session(python=PYTHON, venv_backend="uv")
def pytest_frrouting_daemon_required(session: nox.Session) -> None:
"""Run pytest FRRouting integration tests against a FRRouting daemon.
This session runs the integration tests that run against a local FRRouting instance
using the FRRouting docker image.
"""
pdm_sync(session, self=True, default=True, groups=["test"])
if shutil.which("docker") is None:
session.error("This session requires Docker to be installed")
# If the FRR container version is not set in the environment, use the latest version
# defined at the top of this file.
if not session.env.get("FRR_VERSION"):
session.env["FRR_VERSION"] = FRR_LATEST_MAJOR_VERSION
session.run(
"pytest",
"tests",
"-m",
"frrouting_daemon_required",
"--cov",
"--cov-append",
*session.posargs,
uv_run(
session,
command="pytest",
args=[
"tests",
"-m",
"frrouting_daemon_required",
"--cov",
"--cov-append",
*session.posargs,
],
)


@nox.session(python=PYTHON)
def safety(session: nox.Session) -> None:
"""Scan dependencies for known security vulnerabilities using safety."""
session.install("safety")
session.run("pdm", "export", "-o", "requirements.txt", external=True)
session.run("safety", "check", "--file=requirements.txt", "--full-report")
Loading

0 comments on commit a66dbea

Please sign in to comment.