diff --git a/.github/workflows/check-test-release.yml b/.github/workflows/check-test-release.yml index 1b8d6d4..161bf3e 100644 --- a/.github/workflows/check-test-release.yml +++ b/.github/workflows/check-test-release.yml @@ -26,10 +26,10 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v7 with: fetch-depth: 0 @@ -44,7 +44,7 @@ jobs: - run: pytest - name: "Upload coverage to Codecov" - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v7 with: fail_ci_if_error: false token: ${{ secrets.CODECOV_TOKEN }} @@ -59,12 +59,12 @@ jobs: id-token: write runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v7 with: fetch-depth: 0 - uses: actions/setup-python@v6 with: - python-version: '3.13' + python-version: '3.14' - run: pip install build twine - run: python -m build diff --git a/gto/api.py b/gto/api.py index a7fdd75..b437471 100644 --- a/gto/api.py +++ b/gto/api.py @@ -364,6 +364,7 @@ def format_hexsha(hexsha): d["version"], ] + [d["stage"][name] for name in stages], + strict=True, ), ) for name, d in sorted(models_state.items()) diff --git a/pyproject.toml b/pyproject.toml index fb7a128..ff36dd6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,15 +12,17 @@ keywords = ["git", "repo", "repository", "artifact", "registry", "developer-tool classifiers = [ "Development Status :: 2 - Pre-Alpha", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", ] -requires-python = ">=3.9" +requires-python = ">=3.10" dynamic = ["version"] dependencies = [ + # gto imports click directly, so declare it explicitly + "click>=8,<9", "entrypoints", "funcy", "pydantic>=2", @@ -30,7 +32,10 @@ dependencies = [ "scmrepo>=3,<4", "semver>=2.13.0", "tabulate>=0.8.10", - "typer>=0.4.1", + # typer>=0.26 vendors click and is incompatible with gto's click-based + # CLI machinery (subclassing click.Command, @click.pass_context, etc.): + # the CLI crashes on startup. Migration tracked separately. + "typer>=0.4.1,<0.26", ] [project.urls] @@ -48,11 +53,8 @@ tests = [ ] dev = [ "gto[tests]", - "mypy==1.17.1; python_version > '3.9'", - # mypy>=1.11.0 crashes when used with pydantic-settings on Python 3.9, - # see: https://github.com/python/mypy/issues/17535 - "mypy<1.11.0; python_version <= '3.9'", - "pylint==3.3.8", + "mypy==2.2.0", + "pylint==4.0.6", "types-PyYAML", "types-filelock", "types-freezegun", diff --git a/tests/conftest.py b/tests/conftest.py index c6ada54..d2c69d3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,4 @@ # pylint: disable=redefined-outer-name -import inspect import os import sys from time import sleep @@ -19,13 +18,7 @@ class Runner: def __init__(self): - # Older versions of CliRunner need this - # Can we removed when we drop Py 3.9 support - init_sig = inspect.signature(CliRunner.__init__) - if "mix_stderr" in init_sig.parameters: - self._runner = CliRunner(mix_stderr=False) # pylint: disable=unexpected-keyword-arg - else: - self._runner = CliRunner() + self._runner = CliRunner() def invoke(self, *args, **kwargs) -> Result: return self._runner.invoke(app, *args, **kwargs) diff --git a/tests/test_api.py b/tests/test_api.py index 5d980b0..579df0a 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -298,6 +298,7 @@ def test_check_ref_catch_the_bug(scm: Git): for assignment, tag in zip( [assignment1, assignment2, assignment3], [f"{NAME}#staging#1", f"{NAME}#prod#2", f"{NAME}#dev#3"], + strict=True, ): events = gto.api.check_ref(scm, tag) assert len(events) == 1, events diff --git a/tests/test_registry.py b/tests/test_registry.py index fd9a516..b7ab6e4 100644 --- a/tests/test_registry.py +++ b/tests/test_registry.py @@ -431,6 +431,7 @@ def test_registry_state_tag_tag(tmp_dir: TmpDir): for appeared, expected in zip( iter_over(appeared_state["artifacts"][artifact]["versions"]), iter_over(expected_state["artifacts"][artifact]["versions"]), + strict=True, ): check_obj(appeared, expected, exclude["versions"]) @@ -438,6 +439,7 @@ def test_registry_state_tag_tag(tmp_dir: TmpDir): for a, e in zip( iter_over(appeared[key]), iter_over(expected[key]), + strict=True, ): check_obj(a, e, exclude[key])