diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 516cf99..a1dea54 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: matrix: python-version: ["3.9", "3.10", "3.11", "3.12"] # Empty is latest, head is latest from GitHub - pdm-version: ["", "head", "2.7.4", "2.8.2", "2.9.3", "2.10.4", "2.11.2", "2.12.2"] + pdm-version: [""] steps: - uses: actions/checkout@v4 @@ -30,13 +30,12 @@ jobs: with: cache: true python-version: ${{ matrix.python-version }} # Version range or exact version of a Python version to use, the same as actions/setup-python - architecture: x64 # The target architecture (x86, x64) of the Python interpreter. the same as actions/setup-python version: ${{ matrix.pdm-version }} # The version of PDM to install. Leave it as empty to use the latest version from PyPI, or 'head' to use the latest version from GitHub prerelease: true # Allow prerelease versions of PDM to be installed - enable-pep582: false # Enable PEP 582 package loading globally allow-python-prereleases: true # Allow prerelease versions of Python to be installed. For example if only 3.12-dev is available, 3.12 will fall back to 3.12-dev - name: Set Cache Variables id: set_variables + shell: bash run: | echo "PIP_CACHE=$(pip cache dir)" >> $GITHUB_OUTPUT echo "PDM_CACHE=$(pdm config cache_dir)" >> $GITHUB_OUTPUT @@ -50,24 +49,11 @@ jobs: - name: Install dependencies run: | - pdm config venv.with_pip True pdm install -G :all --dev - pdm venv activate in-project - source .venv/bin/activate - # Get the pip command to run depending on matrix.pdm-version - # We force reinstall of pdm in the virtualenv - if [[ "${{ matrix.pdm-version }}" == "head" ]]; then - pip install "pdm @ git+https://github.com/pdm-project/pdm" - elif [[ "${{ matrix.pdm-version }}" == "" ]]; then - pip install pdm - else - pip install pdm==${{ matrix.pdm-version }} - fi + - name: Run Test with tox + run: pdm run tox - - name: Test with pytest - run: | - pdm run test-cov - name: Upload coverage to Codecov uses: codecov/codecov-action@v4 with: @@ -86,3 +72,7 @@ jobs: pdm build # Do not upload to PyPI, here we only want to check that the build works # XXX Check valid wheels? + + + - name: Check Python package + uses: hynek/build-and-inspect-python-package@v2 diff --git a/pdm.lock b/pdm.lock index fa3073f..d162c9a 100644 --- a/pdm.lock +++ b/pdm.lock @@ -2,10 +2,10 @@ # It is not intended for manual editing. [metadata] -groups = ["default", "dev", "pdm", "poetry"] +groups = ["default", "dev", "pdm", "poetry", "testtox"] strategy = ["cross_platform"] lock_version = "4.4.1" -content_hash = "sha256:ae0c87bb7d27e2116e0b8c440b6d395aedb838958aeece5b1b703a8d070e4903" +content_hash = "sha256:038ebe3c53dc2805fa29f2d8d0d66579327abe4e0b940097135365b54ba275fa" [[package]] name = "anyio" @@ -79,6 +79,16 @@ files = [ {file = "cachecontrol-0.14.0.tar.gz", hash = "sha256:7db1195b41c81f8274a7bbd97c956f44e8348265a1bc7641c37dfebc39f0c938"}, ] +[[package]] +name = "cachetools" +version = "5.3.3" +requires_python = ">=3.7" +summary = "Extensible memoizing collections and decorators" +files = [ + {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, + {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, +] + [[package]] name = "certifi" version = "2024.2.2" @@ -154,6 +164,16 @@ files = [ {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, ] +[[package]] +name = "chardet" +version = "5.2.0" +requires_python = ">=3.7" +summary = "Universal encoding detector for Python 3" +files = [ + {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, + {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, +] + [[package]] name = "charset-normalizer" version = "3.3.2" @@ -853,27 +873,27 @@ files = [ [[package]] name = "pbs-installer" -version = "2024.3.27" +version = "2024.4.1" requires_python = ">=3.8" summary = "Installer for Python Build Standalone" files = [ - {file = "pbs_installer-2024.3.27-py3-none-any.whl", hash = "sha256:6299ca01a91cc87033fa4176106a977da16e2484b4094ef4bacb576f822c0392"}, - {file = "pbs_installer-2024.3.27.tar.gz", hash = "sha256:30a368d14710a5e38a57401006b4c1061f030ed06d42d69c8f5e8dd20ee25d58"}, + {file = "pbs_installer-2024.4.1-py3-none-any.whl", hash = "sha256:762e1b5b95a48389051205c48fcd4635e946b48ab3252d2c79a8a77dc87e91ff"}, + {file = "pbs_installer-2024.4.1.tar.gz", hash = "sha256:1f2aca82511fb9e1973b14708d7386780a8c56d111b680ae5786b3f430fa918a"}, ] [[package]] name = "pbs-installer" -version = "2024.3.27" +version = "2024.4.1" extras = ["install"] requires_python = ">=3.8" summary = "Installer for Python Build Standalone" dependencies = [ - "pbs-installer==2024.3.27", + "pbs-installer==2024.4.1", "zstandard>=0.21.0", ] files = [ - {file = "pbs_installer-2024.3.27-py3-none-any.whl", hash = "sha256:6299ca01a91cc87033fa4176106a977da16e2484b4094ef4bacb576f822c0392"}, - {file = "pbs_installer-2024.3.27.tar.gz", hash = "sha256:30a368d14710a5e38a57401006b4c1061f030ed06d42d69c8f5e8dd20ee25d58"}, + {file = "pbs_installer-2024.4.1-py3-none-any.whl", hash = "sha256:762e1b5b95a48389051205c48fcd4635e946b48ab3252d2c79a8a77dc87e91ff"}, + {file = "pbs_installer-2024.4.1.tar.gz", hash = "sha256:1f2aca82511fb9e1973b14708d7386780a8c56d111b680ae5786b3f430fa918a"}, ] [[package]] @@ -1058,6 +1078,20 @@ files = [ {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, ] +[[package]] +name = "pyproject-api" +version = "1.6.1" +requires_python = ">=3.8" +summary = "API to interact with the python pyproject.toml based projects" +dependencies = [ + "packaging>=23.1", + "tomli>=2.0.1; python_version < \"3.11\"", +] +files = [ + {file = "pyproject_api-1.6.1-py3-none-any.whl", hash = "sha256:4c0116d60476b0786c88692cf4e325a9814965e2469c5998b830bba16b183675"}, + {file = "pyproject_api-1.6.1.tar.gz", hash = "sha256:1817dc018adc0d1ff9ca1ed8c60e1623d5aaca40814b953af14a9cf9a5cae538"}, +] + [[package]] name = "pyproject-hooks" version = "1.0.0" @@ -1446,6 +1480,55 @@ files = [ {file = "tomlkit-0.12.4.tar.gz", hash = "sha256:7ca1cfc12232806517a8515047ba66a19369e71edf2439d0f5824f91032b6cc3"}, ] +[[package]] +name = "tox" +version = "4.14.2" +requires_python = ">=3.8" +summary = "tox is a generic virtualenv management and test command line tool" +dependencies = [ + "cachetools>=5.3.2", + "chardet>=5.2", + "colorama>=0.4.6", + "filelock>=3.13.1", + "packaging>=23.2", + "platformdirs>=4.1", + "pluggy>=1.3", + "pyproject-api>=1.6.1", + "tomli>=2.0.1; python_version < \"3.11\"", + "virtualenv>=20.25", +] +files = [ + {file = "tox-4.14.2-py3-none-any.whl", hash = "sha256:2900c4eb7b716af4a928a7fdc2ed248ad6575294ed7cfae2ea41203937422847"}, + {file = "tox-4.14.2.tar.gz", hash = "sha256:0defb44f6dafd911b61788325741cc6b2e12ea71f987ac025ad4d649f1f1a104"}, +] + +[[package]] +name = "tox-gh" +version = "1.3.1" +requires_python = ">=3.7" +summary = "Seamless integration of tox into GitHub Actions." +dependencies = [ + "tox>=4.6", +] +files = [ + {file = "tox_gh-1.3.1-py3-none-any.whl", hash = "sha256:c671c62ce23ae519a557c3da81e9aa7e35b3a66c69bad71908e595921f83e82d"}, + {file = "tox_gh-1.3.1.tar.gz", hash = "sha256:594af90b740c14735c41b914b41db2d2aa0360929a1746af32bda4b9fef9bf3d"}, +] + +[[package]] +name = "tox-pdm" +version = "0.7.2" +requires_python = ">=3.7" +summary = "A plugin for tox that utilizes PDM as the package manager and installer" +dependencies = [ + "tomli; python_version < \"3.11\"", + "tox>=4.0", +] +files = [ + {file = "tox_pdm-0.7.2-py3-none-any.whl", hash = "sha256:12f6215416b7acd00a80a9e7128f3dc3e3c89308d60707f5d0a24abdf83ac104"}, + {file = "tox_pdm-0.7.2.tar.gz", hash = "sha256:a841a7e1e942a71805624703b9a6d286663bd6af79bba6130ba756975c315308"}, +] + [[package]] name = "trove-classifiers" version = "2024.3.25" diff --git a/pyproject.toml b/pyproject.toml index cfa6a60..c4e2f06 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,7 @@ dynamic = [ dependencies = [ "strictyaml>=1.7.3", 'tomli>=2; python_version < "3.11"', + 'typing-extensions; python_version < "3.10"', ] [project.optional-dependencies] pdm = [ @@ -69,7 +70,7 @@ test-cov = {cmd="pytest --junitxml=junit/test-results.xml --cov --cov-report=xml [tool.pdm.dev-dependencies] dev = [ - "PyYAML>=6.0", + "PyYAML>=6.0.1", "mypy>=1.4.1", "ruff>=0.0.275", "types-PyYAML>=6.0.12.10", @@ -78,6 +79,15 @@ dev = [ "pytest-cov>=4.1.0", "pre-commit>=3.3.3", "tomli>=2.0.1", + "tox-gh>=1.3.1", + "tox-pdm>=0.7.2", + "tox>=4.14.2", +] +testtox = [ + "pytest>=8.1.1", + "pytest-cov>=5.0.0", + "pytest-mock>=3.14.0", + "PyYAML>=6.0.1", ] [tool.ruff] @@ -93,14 +103,20 @@ minversion = "7.0" testpaths = ["tests"] norecursedirs = "*.egg .eggs dist build docs .tox .git __pycache__ node_modules .venv __pypackages__" +[tool.coverage.paths] +source =[ + "src" +] [tool.coverage.run] branch = true +parallel = true include = ["src/*"] omit = ["*/tests/*"] +source = ["src", "tests"] [tool.coverage.report] -fail_under = 92.0 - +show_missing = true +precision = 2 exclude_lines = [ "def __repr__", "if TYPE_CHECKING:", diff --git a/tests/conftest.py b/tests/conftest.py index b8a4da4..253aab6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,8 @@ -pytest_plugins = [ - "pdm.pytest", -] +try: + import pdm # noqa: F401 +except ImportError: + pass +else: + pytest_plugins = [ + "pdm.pytest", + ] diff --git a/tests/test_pdm/test_pdm_plugin.py b/tests/test_pdm/test_pdm_plugin.py index c93bf32..736d283 100644 --- a/tests/test_pdm/test_pdm_plugin.py +++ b/tests/test_pdm/test_pdm_plugin.py @@ -4,6 +4,9 @@ from unittest import mock import pytest + +pdm_module = pytest.importorskip("pdm") +# ruff: noqa: E402 from pdm.cli.hooks import HookManager from pdm.core import Core from pdm.models.candidates import Candidate diff --git a/tests/test_pdm/test_pdm_sync_pre_commit_hook.py b/tests/test_pdm/test_pdm_sync_pre_commit_hook.py index 6f349a5..5d467e6 100644 --- a/tests/test_pdm/test_pdm_sync_pre_commit_hook.py +++ b/tests/test_pdm/test_pdm_sync_pre_commit_hook.py @@ -2,6 +2,9 @@ from unittest.mock import MagicMock, patch import pytest + +pdm_module = pytest.importorskip("pdm") +# ruff: noqa: E402 from pdm.core import Core from pdm.models.candidates import Candidate from pdm.models.requirements import NamedRequirement diff --git a/tests/test_poetry/test_poetry_plugin.py b/tests/test_poetry/test_poetry_plugin.py index a78a37f..f4719a3 100644 --- a/tests/test_poetry/test_poetry_plugin.py +++ b/tests/test_poetry/test_poetry_plugin.py @@ -2,6 +2,9 @@ from unittest.mock import MagicMock, patch import pytest + +poetry_module = pytest.importorskip("poetry") +# ruff: noqa: E402 from cleo.events.console_terminate_event import ConsoleTerminateEvent from poetry.console.application import Application from poetry.console.commands.install import InstallCommand diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..5ef0ed8 --- /dev/null +++ b/tox.ini @@ -0,0 +1,67 @@ +[tox] +requires = + tox>=4.2 +env_list = + report + clean + py{312, 311, 310, 39}-pdm{213, 212, 211, 210, 29, 28, 27} + py{312, 311, 310, 39}-poetry{17, 16} + +[testenv] +set_env = + py{39,310,311,312}-pdm{27,28,29,210,211,212,213}: COVERAGE_FILE = .coverage.{envname} + py{39,310,311,312}-poetry{16, 17}: COVERAGE_FILE = .coverage.{envname} +commands = + pytest --cov --cov-append --cov-report=term-missing {posargs:-vv} --cov-config=pyproject.toml +depends = + report: py{312, 311, 310, 39}-pdm{213, 212, 211, 210, 29, 28, 27} + report: py{312, 311, 310, 39}-poetry{17, 16} + py{312, 311, 310, 39}-pdm{213, 212, 211, 210, 29, 28, 27}: clean + py{312, 311, 310, 39}-poetry{17, 16}: clean + +[testenv:report] +skip_install = true +commands = + coverage combine + coverage report + coverage html + coverage xml +groups = + testtox + +[testenv:clean] +skip_install = true +commands = + coverage erase +groups = + testtox + +[testenv:py{39,310,311,312}-pdm{27,28,29,210,211,212,213}] +package = editable +deps = + pdm210: pdm<2.11,>=2.10 + pdm211: pdm<2.12,>=2.11 + pdm212: pdm<2.13,>=2.12 + pdm213: pdm<2.14,>=2.13.2 + pdm27: pdm<2.8,>=2.7 + pdm28: pdm<2.9,>=2.8 + pdm29: pdm<2.10,>=2.9 +groups = + testtox + +[testenv:py{312, 311, 310, 39}-poetry{16, 17, 18}] +package = editable +deps = + poetry16: poetry<1.7,>=1.6 + poetry17: poetry<1.8,>=1.7 + poetry18: poetry<1.9,>=1.8 +groups = + testtox + +[gh] +python = + 3.9= py39-pdm{27,28,29,210,211,212,213},py39-poetry{16, 17, 18}, report, clean + 3.10= py310-pdm{27,28,29,210,211,212,213}, py310-poetry{16, 17, 18}, report, clean + 3.11= py311-pdm{27,28,29,210,211,212,213}, py311-poetry{16, 17, 18}, report, clean + 3.12= py312-pdm{27,28,29,210,211,212,213}, py312-poetry{16, 17, 18}, report, clean +fail_on_no_env = True