From b28b61cc01d38322a164ab9ccbd347ef51a7268b Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Thu, 16 Jan 2025 15:37:58 -0500 Subject: [PATCH] Use uv in CI and update for PEP 639. --- .github/workflows/ci.yml | 45 ++++++++++++++++---------------- noxfile.py | 56 +++++++++++++++++++++++----------------- pyproject.toml | 23 +++++++---------- uv.lock | 21 +++++++++++++++ 4 files changed, 85 insertions(+), 60 deletions(-) create mode 100644 uv.lock diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79cd93e..b719553 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,17 +7,11 @@ on: tags: - "v*" pull_request: - release: - types: [published] schedule: # Daily at 7:37 - cron: "37 7 * * *" workflow_dispatch: -env: - PIP_DISABLE_PIP_VERSION_CHECK: "1" - PIP_NO_PYTHON_VERSION_WARNING: "1" - jobs: list: runs-on: ubuntu-latest @@ -25,17 +19,20 @@ jobs: noxenvs: ${{ steps.noxenvs-matrix.outputs.noxenvs }} steps: - uses: actions/checkout@v4 - - name: Set up nox - uses: wntrblm/nox@2024.10.09 + - name: Set up uv + uses: astral-sh/setup-uv@v5 + with: + enable-cache: true - id: noxenvs-matrix run: | echo >>$GITHUB_OUTPUT noxenvs=$( - nox --list-sessions --json | jq '[.[].session]' + uvx nox --list-sessions --json | jq '[.[].session]' ) ci: needs: list runs-on: ${{ matrix.os }} + strategy: fail-fast: false matrix: @@ -44,7 +41,7 @@ jobs: posargs: [""] include: - os: ubuntu-latest - noxenv: "tests-3.11" + noxenv: tests-3.13 posargs: coverage github steps: @@ -59,17 +56,21 @@ jobs: uses: actions/setup-python@v5 with: python-version: | - 3.8 3.9 3.10 3.11 3.12 + 3.13 pypy3.10 allow-prereleases: true - - name: Set up nox - uses: wntrblm/nox@2024.10.09 + + - name: Set up uv + uses: astral-sh/setup-uv@v5 + with: + enable-cache: true + - name: Run nox - run: nox -s "${{ matrix.noxenv }}" -- ${{ matrix.posargs }} + run: uvx nox -s "${{ matrix.noxenv }}" -- ${{ matrix.posargs }} packaging: needs: ci @@ -77,21 +78,21 @@ jobs: environment: name: PyPI url: https://pypi.org/p/jsonschema-lexer + permissions: contents: write id-token: write steps: - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 + - name: Set up uv + uses: astral-sh/setup-uv@v5 with: - cache: pip - python-version: "3.x" - - name: Install dependencies - run: python -m pip install build - - name: Create packages - run: python -m build . + enable-cache: true + + - name: Build our distributions + run: uv run --frozen --with 'build[uv]' -m build --installer=uv + - name: Publish to PyPI if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/noxfile.py b/noxfile.py index 1e98cf0..8747edb 100644 --- a/noxfile.py +++ b/noxfile.py @@ -12,14 +12,14 @@ REQUIREMENTS = dict( tests=ROOT / "test-requirements.txt", ) -REQUIREMENTS_IN = { - path.parent / f"{path.stem}.in" for path in REQUIREMENTS.values() -} +REQUIREMENTS_IN = [ # this is actually ordered, as files depend on each other + (path.parent / f"{path.stem}.in", path) for path in REQUIREMENTS.values() +] - -SUPPORTED = ["pypy3.10", "3.10", "3.11", "3.12"] +SUPPORTED = ["pypy3.10", "3.10", "3.11", "3.12", "3.13"] LATEST = SUPPORTED[-1] +nox.options.default_venv_backend = "uv|virtualenv" nox.options.sessions = [] @@ -35,7 +35,7 @@ def _session(fn): @session(python=SUPPORTED) def tests(session): """ - Run the test suite. + Run the test suite with a corresponding Python version. """ session.install("-r", REQUIREMENTS["tests"]) @@ -60,7 +60,7 @@ def tests(session): stdout=summary, ) else: - session.run("python", "-m", "pytest", *session.posargs, PACKAGE) + session.run("pytest", *session.posargs, PACKAGE) @session(python=SUPPORTED) @@ -77,9 +77,15 @@ def build(session): """ Build a distribution suitable for PyPI and check its validity. """ - session.install("build", "twine") + session.install("build[uv]", "twine") with TemporaryDirectory() as tmpdir: - session.run("python", "-m", "build", ROOT, "--outdir", tmpdir) + session.run( + "pyproject-build", + "--installer=uv", + ROOT, + "--outdir", + tmpdir, + ) session.run("twine", "check", "--strict", tmpdir + "/*") @@ -95,33 +101,35 @@ def secrets(session): @session(tags=["style"]) def style(session): """ - Check for coding style. + Check Python code style. """ session.install("ruff") - session.run("ruff", "check", ROOT) + session.run("ruff", "check", ROOT, __file__) @session() def typing(session): """ - Statically check typing annotations. + Check static typing. """ session.install("pyright", ROOT) - session.run("pyright", PACKAGE) + session.run("pyright", *session.posargs, PACKAGE) @session(default=False) def requirements(session): """ - Update requirements files. + Update the project's pinned requirements. + + You should commit the result afterwards. """ - session.install("pip-tools") - for each in REQUIREMENTS_IN: - session.run( - "pip-compile", - "--resolver", - "backtracking", - "--strip-extras", - "-U", - each.relative_to(ROOT), - ) + if session.venv_backend == "uv": + cmd = ["uv", "pip", "compile"] + else: + session.install("pip-tools") + cmd = ["pip-compile", "--resolver", "backtracking", "--strip-extras"] + + for each, out in REQUIREMENTS_IN: + # otherwise output files end up with silly absolute path comments... + relative = each.relative_to(ROOT) + session.run(*cmd, "--upgrade", "--output-file", out, relative) diff --git a/pyproject.toml b/pyproject.toml index c72f6af..3b84a19 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,19 +10,21 @@ name = "jsonschema-lexer" description = "A Pygments lexer for JSON Schema" requires-python = ">=3.10" readme = "README.rst" +license = "MIT" +license-files = ["COPYING"] keywords = ["json", "jsonschema"] authors = [ { name = "Julian Berman", email = "Julian+jsonschema-lexer@GrayVines.com" }, ] classifiers = [ "Development Status :: 3 - Alpha", - "License :: OSI Approved :: MIT License", + "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.13", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: File Formats :: JSON", @@ -56,24 +58,16 @@ skip_covered = true [tool.doc8] ignore = [ - "D000", # see PyCQA/doc8#125 - "D001", # one sentence per line, so max length doesn't make sense + "D000", # see PyCQA/doc8#125 + "D001", # one sentence per line, so max length doesn't make sense ] -[tool.isort] -combine_as_imports = true -ensure_newline_before_comments = true -from_first = true -include_trailing_comma = true -multi_line_output = 3 -use_parentheses = true - [tool.pyright] reportUnnecessaryTypeIgnoreComment = true strict = ["**/*.py"] exclude = [ - "**/tests/__init__.py", - "**/tests/test_*.py", + "**/tests/__init__.py", + "**/tests/test_*.py", ] [tool.ruff] @@ -85,6 +79,7 @@ ignore = [ "A001", # It's fine to shadow builtins "A002", "A003", + "A005", "ARG", # This is all wrong whenever an interface is involved "ANN", # Just let the type checker do this "B006", # Mutable arguments require care but are OK if you don't abuse them diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..b45df7b --- /dev/null +++ b/uv.lock @@ -0,0 +1,21 @@ +version = 1 +requires-python = ">=3.10" + +[[package]] +name = "jsonschema-lexer" +source = { editable = "." } +dependencies = [ + { name = "pygments" }, +] + +[package.metadata] +requires-dist = [{ name = "pygments", specifier = ">=2.17.2" }] + +[[package]] +name = "pygments" +version = "2.19.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, +]