From 0e9a8baeb20acdc1812a50a2b1876debab8659cb Mon Sep 17 00:00:00 2001 From: Martijn Pieters Date: Mon, 15 May 2023 15:20:53 +0100 Subject: [PATCH] Add tox configuration Tox manages test environments for all supported Python versions, as well as linting and formatting tools. On GitHub, the test and lint steps are kept as close as possible to the Makefile equivalents. --- .github/workflows/ci.yml | 13 ++-- Makefile | 26 ++++---- poetry.lock | 129 ++++++++++++++++++++++++++++++++++++++- pyproject.toml | 5 +- tox.ini | 47 ++++++++++++++ 5 files changed, 195 insertions(+), 25 deletions(-) create mode 100644 tox.ini diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03ecd3d..25c9b4f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,11 +32,7 @@ jobs: - name: Install linting requirements run: poetry install --no-root --with=linting --all-extras - name: Execute linters - run: | - poetry run black --check --diff . - poetry run flake8 - poetry run mypy - poetry run pyright + run: make lint test: needs: @@ -59,11 +55,10 @@ jobs: cache: poetry - name: Install testing requirements run: | - poetry install --no-root --with=dev --all-extras + poetry install --no-root --all-extras + poetry run pip install tox-gh-actions - name: Execute tests - env: - PYTHONDEVMODE: '1' - run: poetry run pytest + run: poetry run tox test-summary: name: Test matrix status diff --git a/Makefile b/Makefile index c8da942..f883ec3 100644 --- a/Makefile +++ b/Makefile @@ -1,27 +1,27 @@ -checkfiles = fastapi_cache/ examples/ tests/ -py_warn = PYTHONDEVMODE=1 - up: @poetry update deps: - @poetry install --no-root --with=linting -E all + @poetry install --no-root --with=linting --all-extras -style: deps - @isort -src $(checkfiles) - @black $(checkfiles) +format: deps + @poetry run tox run -e format -check: deps - @black $(checkfiles) || (echo "Please run 'make style' to auto-fix style issues" && false) - @flake8 $(checkfiles) - @mypy ${checkfiles} - @pyright ${checkfiles} +lint: deps + @poetry run tox run -e lint test: deps - $(py_warn) pytest + @poetry run tox + +test-parallel: deps + @poetry run tox run-parallel build: clean deps @poetry build clean: @rm -rf ./dist + +# aliases +check: lint +style: format diff --git a/poetry.lock b/poetry.lock index 028eb80..deceead 100644 --- a/poetry.lock +++ b/poetry.lock @@ -315,6 +315,18 @@ files = [ [package.dependencies] types-awscrt = "*" +[[package]] +name = "cachetools" +version = "5.3.0" +description = "Extensible memoizing collections and decorators" +category = "dev" +optional = false +python-versions = "~=3.7" +files = [ + {file = "cachetools-5.3.0-py3-none-any.whl", hash = "sha256:429e1a1e845c008ea6c85aa35d4b98b65d6a9763eeef3e37e92728a12d1de9d4"}, + {file = "cachetools-5.3.0.tar.gz", hash = "sha256:13dfddc7b8df938c21a940dfa6557ce6e94a2f1cdfa58eb90c805721d58f2c14"}, +] + [[package]] name = "certifi" version = "2023.5.7" @@ -404,6 +416,18 @@ files = [ [package.dependencies] pycparser = "*" +[[package]] +name = "chardet" +version = "5.1.0" +description = "Universal encoding detector for Python 3" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "chardet-5.1.0-py3-none-any.whl", hash = "sha256:362777fb014af596ad31334fde1e8c327dfdb076e1960d1694662d46a6917ab9"}, + {file = "chardet-5.1.0.tar.gz", hash = "sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5"}, +] + [[package]] name = "charset-normalizer" version = "3.1.0" @@ -622,6 +646,18 @@ test = ["iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-co test-randomorder = ["pytest-randomly"] tox = ["tox"] +[[package]] +name = "distlib" +version = "0.3.6" +description = "Distribution utilities" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.6-py2.py3-none-any.whl", hash = "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e"}, + {file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"}, +] + [[package]] name = "exceptiongroup" version = "1.1.1" @@ -659,6 +695,22 @@ dev = ["pre-commit (>=2.17.0,<3.0.0)", "ruff (==0.0.138)", "uvicorn[standard] (> doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "typer-cli (>=0.0.13,<0.0.14)", "typer[all] (>=0.6.1,<0.8.0)"] test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==23.1.0)", "coverage[toml] (>=6.5.0,<8.0)", "databases[sqlite] (>=0.3.2,<0.7.0)", "email-validator (>=1.1.1,<2.0.0)", "flask (>=1.1.2,<3.0.0)", "httpx (>=0.23.0,<0.24.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.982)", "orjson (>=3.2.1,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "peewee (>=3.13.3,<4.0.0)", "pytest (>=7.1.3,<8.0.0)", "python-jose[cryptography] (>=3.3.0,<4.0.0)", "python-multipart (>=0.0.5,<0.0.7)", "pyyaml (>=5.3.1,<7.0.0)", "ruff (==0.0.138)", "sqlalchemy (>=1.3.18,<1.4.43)", "types-orjson (==3.6.2)", "types-ujson (==5.7.0.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)"] +[[package]] +name = "filelock" +version = "3.12.0" +description = "A platform independent file lock." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "filelock-3.12.0-py3-none-any.whl", hash = "sha256:ad98852315c2ab702aeb628412cbf7e95b7ce8c3bf9565670b4eaecf1db370a9"}, + {file = "filelock-3.12.0.tar.gz", hash = "sha256:fc03ae43288c013d2ea83c8597001b1129db351aad9c57fe2409327916b8e718"}, +] + +[package.extras] +docs = ["furo (>=2023.3.27)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] + [[package]] name = "flake8" version = "6.0.0" @@ -1137,6 +1189,9 @@ files = [ {file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"}, ] +[package.dependencies] +typing-extensions = {version = ">=4.5", markers = "python_version < \"3.8\""} + [package.extras] docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] @@ -1249,6 +1304,26 @@ files = [ {file = "pyflakes-3.0.1.tar.gz", hash = "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"}, ] +[[package]] +name = "pyproject-api" +version = "1.5.1" +description = "API to interact with the python pyproject.toml based projects" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyproject_api-1.5.1-py3-none-any.whl", hash = "sha256:4698a3777c2e0f6b624f8a4599131e2a25376d90fe8d146d7ac74c67c6f97c43"}, + {file = "pyproject_api-1.5.1.tar.gz", hash = "sha256:435f46547a9ff22cf4208ee274fca3e2869aeb062a4834adfc99a4dd64af3cf9"}, +] + +[package.dependencies] +packaging = ">=23" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +docs = ["furo (>=2022.12.7)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] +testing = ["covdefaults (>=2.2.2)", "importlib-metadata (>=6)", "pytest (>=7.2.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "virtualenv (>=20.17.1)", "wheel (>=0.38.4)"] + [[package]] name = "pyright" version = "1.1.308" @@ -1434,6 +1509,36 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "tox" +version = "4.5.1" +description = "tox is a generic virtualenv management and test command line tool" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tox-4.5.1-py3-none-any.whl", hash = "sha256:d25a2e6cb261adc489604fafd76cd689efeadfa79709965e965668d6d3f63046"}, + {file = "tox-4.5.1.tar.gz", hash = "sha256:5a2eac5fb816779dfdf5cb00fecbc27eb0524e4626626bb1de84747b24cacc56"}, +] + +[package.dependencies] +cachetools = ">=5.3" +chardet = ">=5.1" +colorama = ">=0.4.6" +filelock = ">=3.11" +importlib-metadata = {version = ">=6.4.1", markers = "python_version < \"3.8\""} +packaging = ">=23.1" +platformdirs = ">=3.2" +pluggy = ">=1" +pyproject-api = ">=1.5.1" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.5", markers = "python_version < \"3.8\""} +virtualenv = ">=20.21" + +[package.extras] +docs = ["furo (>=2023.3.27)", "sphinx (>=6.1.3)", "sphinx-argparse-cli (>=1.11)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)", "sphinx-copybutton (>=0.5.2)", "sphinx-inline-tabs (>=2022.1.2b11)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"] +testing = ["build[virtualenv] (>=0.10)", "covdefaults (>=2.3)", "devpi-process (>=0.3)", "diff-cover (>=7.5)", "distlib (>=0.3.6)", "flaky (>=3.7)", "hatch-vcs (>=0.3)", "hatchling (>=1.14)", "psutil (>=5.9.4)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-xdist (>=3.2.1)", "re-assert (>=1.1)", "time-machine (>=2.9)", "wheel (>=0.40)"] + [[package]] name = "types-aiobotocore" version = "2.5.0.post2" @@ -1902,6 +2007,28 @@ typing-extensions = {version = "*", markers = "python_version < \"3.8\""} [package.extras] standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] +[[package]] +name = "virtualenv" +version = "20.23.0" +description = "Virtual Python Environment builder" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "virtualenv-20.23.0-py3-none-any.whl", hash = "sha256:6abec7670e5802a528357fdc75b26b9f57d5d92f29c5462ba0fbe45feacc685e"}, + {file = "virtualenv-20.23.0.tar.gz", hash = "sha256:a85caa554ced0c0afbd0d638e7e2d7b5f92d23478d05d17a76daeac8f279f924"}, +] + +[package.dependencies] +distlib = ">=0.3.6,<1" +filelock = ">=3.11,<4" +importlib-metadata = {version = ">=6.4.1", markers = "python_version < \"3.8\""} +platformdirs = ">=3.2,<4" + +[package.extras] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.7.1)", "time-machine (>=2.9)"] + [[package]] name = "wrapt" version = "1.15.0" @@ -2100,4 +2227,4 @@ redis = ["redis"] [metadata] lock-version = "2.0" python-versions = "^3.7" -content-hash = "f09d0644dfef38d2912bdd3a0e95a375a039ff312be97f21250509783b14412e" +content-hash = "edb317193b26f7b00f1a4998cb61a56b2f3fd542c15218f0c3858d8e60a33bf0" diff --git a/pyproject.toml b/pyproject.toml index e646e38..2f5e6fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,10 +42,11 @@ pytest = "*" requests = "*" coverage = "^6.5.0" httpx = "*" +tox = "^4.5.1" [build-system] -requires = ["poetry>=0.12"] -build-backend = "poetry.masonry.api" +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" [tool.poetry.extras] redis = ["redis"] diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..617bb34 --- /dev/null +++ b/tox.ini @@ -0,0 +1,47 @@ +[tox] +env_list = + py37,py38,py39,py310,py311 +minversion = 4.5.1 + +[gh-actions] +# Map Github Actions Python version to environment factors +# Requires tox-gh-actions 3.x is installed in the GitHub action +python = + 3.7: py37 + 3.8: py38 + 3.9: py39 + 3.10: py310 + 3.11: py311 + +[testenv] +description = Run the tests with pytest +package = wheel +extras = all +set_env = + # trick poetry into adopting the tox virtualenv + POETRY_VIRTUALENVS_PATH = {[tox]work_dir} +allowlist_externals = poetry +commands_pre = + poetry install --no-root --sync --all-extras +commands = + python -X dev -m pytest {tty:--color=yes} {posargs} + +[testenv:lint] +description = Run the linters +skip_install = true +commands_pre = + poetry install --no-root --with=linting --sync --all-extras +commands = + black --check --diff . + flake8 + mypy + pyright + +[testenv:format] +description = Format the code +skip_install = true +commands_pre = + poetry install --no-root --sync --with=linting +commands = + black . + isort .