diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 247ad054..6c104f42 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,7 +6,12 @@ updates: schedule: interval: "weekly" labels: - - "maintenance" + - "maintenance :construction:" + groups: + # Group all pip dependencies into one PR + pip-dependencies: + patterns: + - "*" # Update via cruft ignore: - dependency-name: "mkdocs*" @@ -19,7 +24,7 @@ updates: schedule: interval: "weekly" labels: - - "maintenance" + - "maintenance :construction:" # Update via cruft ignore: - dependency-name: "actions/checkout" diff --git a/.github/workflows/post-dependabot-update.yml b/.github/workflows/post-dependabot-update.yml new file mode 100644 index 00000000..14514a5a --- /dev/null +++ b/.github/workflows/post-dependabot-update.yml @@ -0,0 +1,31 @@ +name: Post Dependabot Update +on: + pull_request: + branches: [main] + paths: + - dev/** + +jobs: + auto-update: + if: github.actor == 'dependabot[bot]' + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref }} + + - uses: hynek/setup-cached-uv@v2 + + - name: Run tests + run: uvx nox --sessions flavours-codegen + + - name: Commit changes + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add upath/_flavour_sources.py + git commit -m "Auto-update generated flavours" || echo "No changes" + git push diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index af303a83..eeb522ee 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,19 +20,10 @@ jobs: with: fetch-depth: 0 - - name: Set up Python 3.10 - uses: actions/setup-python@v5 - with: - python-version: '3.10' - - - name: Upgrade pip and nox - run: | - pip install --upgrade pip nox - pip --version - nox --version + - uses: hynek/setup-cached-uv@v2 - name: Build package - run: nox -s build + run: uvx nox -s build - name: Upload package if: github.event_name == 'release' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 92d5099b..115a286e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -59,7 +59,7 @@ jobs: - uses: hynek/setup-cached-uv@v2 - name: Run tests - run: uvx nox --sessions typesafety --python ${{ matrix.pyv }} + run: uvx nox --sessions type-safety --python ${{ matrix.pyv }} lint: runs-on: ubuntu-latest @@ -70,19 +70,10 @@ jobs: with: fetch-depth: 0 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.10' - - - name: Upgrade pip and nox - run: | - python -m pip install --upgrade pip nox - pip --version - nox --version + - uses: hynek/setup-cached-uv@v2 - name: Lint code and check dependencies - run: nox -s lint + run: uvx nox -s lint build: needs: [tests, lint] @@ -93,16 +84,7 @@ jobs: with: fetch-depth: 0 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.10' - - - name: Install dependencies - run: | - python -m pip install --upgrade pip nox - pip --version - nox --version + - uses: hynek/setup-cached-uv@v2 - name: Build package - run: nox -s build + run: uvx nox -s build diff --git a/noxfile.py b/noxfile.py index d5018acc..1a1952ce 100644 --- a/noxfile.py +++ b/noxfile.py @@ -2,22 +2,56 @@ import glob import os +import sys import nox nox.options.reuse_existing_virtualenvs = True nox.options.error_on_external_run = True -nox.needs_version = ">=2024.3.2" -nox.options.default_venv_backend = "uv|virtualenv" +nox.needs_version = ">=2024.04.15" +nox.options.default_venv_backend = "uv" -nox.options.sessions = "lint", "tests" +nox.options.sessions = "lint", "tests", "type-checking", "type-safety" locations = ("upath",) running_in_ci = os.environ.get("CI", "") != "" +SUPPORTED_PYTHONS = ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] +BASE_PYTHON = SUPPORTED_PYTHONS[-3] +MIN_PYTHON = SUPPORTED_PYTHONS[0] + + +@(lambda f: f()) +def FSSPEC_MIN_VERSION() -> str: + """Get the minimum fsspec version boundary from pyproject.toml.""" + try: + from packaging.requirements import Requirement + + if sys.version_info >= (3, 11): + from tomllib import load as toml_load + else: + from tomli import load as toml_load + except ImportError: + raise RuntimeError( + "We rely on nox>=2024.04.15 depending on `packaging` and `tomli/tomllib`." + " Please report if you see this error." + ) + + with open("pyproject.toml", "rb") as f: + pyproject_data = toml_load(f) + + for requirement in pyproject_data["project"]["dependencies"]: + req = Requirement(requirement) + if req.name == "fsspec": + for specifier in req.specifier: + if specifier.operator == ">=": + return str(specifier.version) + raise RuntimeError("Could not find fsspec minimum version in pyproject.toml") + -@nox.session(python=["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]) +@nox.session(python=SUPPORTED_PYTHONS) def tests(session: nox.Session) -> None: + """Run the test suite.""" # workaround in case no aiohttp binary wheels are available if session.python == "3.14": session.env["AIOHTTP_NO_EXTENSIONS"] = "1" @@ -36,9 +70,9 @@ def tests(session: nox.Session) -> None: ) -@nox.session(python="3.9", name="tests-minversion") +@nox.session(python=MIN_PYTHON, name="tests-minversion") def tests_minversion(session: nox.Session) -> None: - session.install("fsspec==2024.5.0", ".[tests,dev]") + session.install(f"fsspec=={FSSPEC_MIN_VERSION}", ".[tests,dev]") session.run("uv", "pip", "freeze", silent=not running_in_ci) session.run( "pytest", @@ -51,8 +85,12 @@ def tests_minversion(session: nox.Session) -> None: ) +tests_minversion.__doc__ = f"Run the test suite with fsspec=={FSSPEC_MIN_VERSION}." + + @nox.session def lint(session: nox.Session) -> None: + """Run pre-commit hooks.""" session.install("pre-commit") session.install("-e", ".[tests]") @@ -70,6 +108,7 @@ def safety(session: nox.Session) -> None: @nox.session def build(session: nox.Session) -> None: + """Build sdists and wheels.""" session.install("build", "setuptools", "twine") session.run("python", "-m", "build") dists = glob.glob("dist/*") @@ -79,31 +118,19 @@ def build(session: nox.Session) -> None: @nox.session def develop(session: nox.Session) -> None: """Sets up a python development environment for the project.""" - args = session.posargs or ("venv",) - venv_dir = os.fsdecode(os.path.abspath(args[0])) - - session.log(f"Setting up virtual environment in {venv_dir}") - session.install("virtualenv") - session.run("virtualenv", venv_dir, silent=True) + session.run("uv", "venv", external=True) - python = os.path.join(venv_dir, "bin/python") - session.run(python, "-m", "pip", "install", "-e", ".[tests,dev]", external=True) - -@nox.session -def black(session): - print("please run `nox -s lint` instead") - raise SystemExit(1) - - -@nox.session +@nox.session(name="type-checking", python=BASE_PYTHON) def type_checking(session): + """Run mypy checks.""" session.install("-e", ".[typechecking]") session.run("python", "-m", "mypy") -@nox.session(python=["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]) -def typesafety(session): +@nox.session(name="type-safety", python=SUPPORTED_PYTHONS) +def type_safety(session): + """Run typesafety tests.""" session.install("-e", ".[typechecking]") session.run( "python", @@ -119,7 +146,12 @@ def typesafety(session): ) -@nox.session(python="3.12") +@nox.session(name="flavours-upgrade-deps", python=BASE_PYTHON) +def upgrade_flavours(session): + session.run("uvx", "pur", "-r", "dev/requirements.txt") + + +@nox.session(name="flavours-codegen", python=BASE_PYTHON) def generate_flavours(session): session.install("-r", "dev/requirements.txt") with open("upath/_flavour_sources.py", "w") as target: