From aa10190a55c5bbce5f4c57149f9261dd247e76f0 Mon Sep 17 00:00:00 2001 From: Oleh Prypin Date: Fri, 7 Oct 2022 23:18:05 +0200 Subject: [PATCH] Migrate from Tox to Hatch as test runner (#2991) --- .github/workflows/{tox.yml => ci.yml} | 52 ++++++------ docs/about/contributing.md | 10 +-- mkdocs/tests/integration.py | 12 +-- pyproject.toml | 113 ++++++++++++++++++++++++++ requirements/lint.txt | 10 --- requirements/packaging.txt | 8 -- requirements/project-min.txt | 21 ----- requirements/project.txt | 21 ----- requirements/test.txt | 2 - tox.ini | 86 -------------------- 10 files changed, 150 insertions(+), 185 deletions(-) rename .github/workflows/{tox.yml => ci.yml} (72%) delete mode 100644 requirements/lint.txt delete mode 100644 requirements/packaging.txt delete mode 100644 requirements/project-min.txt delete mode 100644 requirements/project.txt delete mode 100644 requirements/test.txt delete mode 100644 tox.ini diff --git a/.github/workflows/tox.yml b/.github/workflows/ci.yml similarity index 72% rename from .github/workflows/tox.yml rename to .github/workflows/ci.yml index 064c46f9..7c4321d7 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/ci.yml @@ -11,15 +11,15 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] include: - python-version: 3.7 - tox-env: py37 + py: py37 - python-version: 3.8 - tox-env: py38 + py: py38 - python-version: 3.9 - tox-env: py39 + py: py39 - python-version: '3.10' - tox-env: py310 + py: py310 - python-version: pypy-3.7-v7.x - tox-env: pypy3 + py: pypy3 # Just to slim down the test matrix: exclude: - python-version: 3.8 @@ -28,8 +28,6 @@ jobs: os: windows-latest - python-version: 3.9 os: ubuntu-latest - env: - TOXENV: ${{ matrix.tox-env }}-{unittests,min-req,integration,integration-no-babel} runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 @@ -39,10 +37,13 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - python -m pip install --upgrade pip tox - - name: Run tox + python -m pip install --upgrade hatch + - name: Run tests run: | - python -m tox --discover $(which python) + hatch run +py=${{ matrix.py }} +type= test:with-coverage + - name: Run integration tests + run: | + hatch run +py=${{ matrix.py }} +type= integration:test shell: bash - name: Upload Codecov Results if: success() @@ -50,7 +51,7 @@ jobs: with: file: ./coverage.xml flags: unittests - name: ${{ matrix.os }}/${{ matrix.tox-env }} + name: ${{ matrix.os }}/${{ matrix.py }} fail_ci_if_error: false lint: @@ -63,35 +64,32 @@ jobs: python-version: '3.10' - name: Install Python dependencies run: | - python -m pip install --upgrade pip tox + python -m pip install --upgrade hatch - name: Setup Node uses: actions/setup-node@v1 with: node-version: 16 - - name: Check with isort + - name: Check with black + isort if: always() - run: python -m tox -e isort && git diff --exit-code - - name: Check with black - if: always() - run: python -m tox -e black && git diff --exit-code + run: hatch run style:format && git diff --exit-code - name: Check with flake8 if: always() - run: python -m tox -e flake8 + run: hatch run style:lint - name: Check with mypy if: always() - run: python -m tox -e mypy - - name: Check with markdown-lint + run: hatch run types:check + - name: Check Markdown style if: always() - run: python -m tox -e markdown-lint - - name: Check with jshint + run: hatch run lint:markdown + - name: Check JS style if: always() - run: python -m tox -e jshint - - name: Check with csslint + run: hatch run lint:js + - name: Check CSS style if: always() - run: python -m tox -e csslint - - name: Check with codespell + run: hatch run lint:css + - name: Check spelling if: always() - run: python -m tox -e codespell + run: hatch run lint:spelling package: runs-on: ubuntu-latest diff --git a/docs/about/contributing.md b/docs/about/contributing.md index 8d21e434..22648415 100644 --- a/docs/about/contributing.md +++ b/docs/about/contributing.md @@ -53,14 +53,14 @@ to the git repository. ## Running the tests -To run the tests, it is recommended that you use [tox]. +To run the tests, it is recommended that you use [Hatch]. -Install Tox using [pip] by running the command `pip install tox`. -Then the test suite can be run for MkDocs by running the command `tox` in the +Install Hatch using [pip] by running the command `pip install hatch`. +Then the test suite can be run for MkDocs by running the command `hatch run all` in the root of your MkDocs repository. It will attempt to run the tests against all of the Python versions we -support. So don't be concerned if you are missing some and they fail. The rest +support. So don't be concerned if you are missing some. The rest will be verified by [GitHub Actions] when you submit a pull request. ## Translating themes @@ -105,7 +105,7 @@ file so that everything is ready for translators to do their job. [virtualenv]: https://virtualenv.pypa.io/en/latest/user_guide.html [pip]: https://pip.pypa.io/en/stable/ -[tox]: https://tox.readthedocs.io/en/latest/ +[Hatch]: https://hatch.pypa.io/ [GitHub Actions]: https://docs.github.com/actions [PyPA Code of Conduct]: https://www.pypa.io/en/latest/code-of-conduct/ [Translating Themes]: ../dev-guide/translations.md diff --git a/mkdocs/tests/integration.py b/mkdocs/tests/integration.py index a2927912..8f3fdc37 100644 --- a/mkdocs/tests/integration.py +++ b/mkdocs/tests/integration.py @@ -18,16 +18,15 @@ TODOs import logging import os import subprocess +import tempfile import click -from mkdocs import utils - log = logging.getLogger('mkdocs') DIR = os.path.dirname(__file__) MKDOCS_CONFIG = os.path.abspath(os.path.join(DIR, '../../mkdocs.yml')) -MKDOCS_THEMES = utils.get_theme_names() +MKDOCS_THEMES = ['mkdocs', 'readthedocs'] TEST_PROJECTS = os.path.abspath(os.path.join(DIR, 'integration')) @@ -36,9 +35,12 @@ TEST_PROJECTS = os.path.abspath(os.path.join(DIR, 'integration')) '--output', help="The output directory to use when building themes", type=click.Path(file_okay=False, writable=True), - required=True, ) def main(output=None): + if output is None: + directory = tempfile.TemporaryDirectory(prefix='mkdocs_integration-') + output = directory.name + log.propagate = False stream = logging.StreamHandler() formatter = logging.Formatter("\033[1m\033[1;32m *** %(message)s *** \033[0m") @@ -46,7 +48,7 @@ def main(output=None): log.addHandler(stream) log.setLevel(logging.DEBUG) - base_cmd = ['mkdocs', 'build', '-s', '--site-dir'] + base_cmd = ['mkdocs', 'build', '-q', '-s', '--site-dir'] log.debug("Building installed themes.") for theme in sorted(MKDOCS_THEMES): diff --git a/pyproject.toml b/pyproject.toml index 34711d8e..233eb4aa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,22 @@ dependencies = [ i18n = [ "babel >=2.9.0", ] +min-versions = [ + "click ==7.0", + "Jinja2 ==2.11.1", + "markupsafe ==2.0.1", + "Markdown ==3.2.1", + "PyYAML ==5.1", + "watchdog ==2.0", + "ghp-import ==1.0", + "pyyaml_env_tag ==0.1", + "importlib_metadata ==4.3; python_version < '3.10'", + "typing_extensions ==3.10; python_version < '3.8'", + "packaging ==20.5", + "mergedeep ==1.3.4", + "colorama ==0.4; platform_system == 'Windows'", + "babel ==2.9.0", +] [project.urls] Documentation = "https://www.mkdocs.org/" @@ -80,6 +96,103 @@ dependencies = [ "babel", ] +[tool.hatch.envs.default.scripts] +all = [ + "hatch run types:check", + "hatch run test:test", + "hatch run style:check", + "hatch run lint:check", + "hatch run +type=default +py= integration:test", +] + +[tool.hatch.envs.test] +features = ["i18n"] +dependencies = [ + "coverage", +] +[tool.hatch.envs.test.scripts] +test = "coverage run --source=mkdocs --omit 'mkdocs/tests/*' -m unittest discover -p '*tests.py' mkdocs --top-level-directory ." +_coverage = ["test", "coverage xml", "coverage report --show-missing"] +with-coverage = "test" +[[tool.hatch.envs.test.matrix]] +python = ["py37", "py38", "py39", "py310", "pypy3"] +type = ["default", "min-req"] +[tool.hatch.envs.test.overrides] +matrix.type.features = [ + { value = "min-versions", if = ["min-req"] }, +] +matrix.type.scripts = [ + { key = "with-coverage", value = "_coverage", if = ["default"] }, +] + +[tool.hatch.envs.integration] +template = "docs" +[tool.hatch.envs.integration.scripts] +test = "python -m mkdocs.tests.integration" +[[tool.hatch.envs.integration.matrix]] +python = ["py37", "py38", "py39", "py310", "pypy3"] +type = ["default", "no-babel"] +[tool.hatch.envs.integration.overrides] +matrix.type.features = [ + { value = "i18n", if = ["default"] }, +] + +[tool.hatch.envs.types] +dependencies = [ + "mypy", + "types-Jinja2", + "types-Markdown", + "types-PyYAML", + "types-setuptools", + "typing-extensions", +] +[tool.hatch.envs.types.scripts] +check = "mypy mkdocs" + +[tool.hatch.envs.style] +detached = true +dependencies = [ + "black", + "isort", + "flake8", +] +[tool.hatch.envs.style.scripts] +lint = [ + "flake8 mkdocs", +] +check = [ + "isort --check-only --diff mkdocs", + "black -q --check --diff mkdocs", + "lint", +] +format = [ + "isort -q mkdocs", + "black -q mkdocs", +] + +[tool.hatch.envs.lint] +detached = true +dependencies = [ + "codespell", +] +[tool.hatch.envs.lint.scripts] +spelling = "codespell mkdocs docs *.* -S LC_MESSAGES -S '*.min.js' -S 'lunr*.js' -S fontawesome-webfont.svg -S tinyseg.js" +markdown = "npm exec --yes -- markdownlint-cli README.md CONTRIBUTING.md docs/ --ignore docs/CNAME" +js = "npm exec --yes -- jshint mkdocs/" +css = "npm exec --yes -- csslint --quiet mkdocs/" +check = ["markdown", "js", "css", "spelling"] + +[tool.hatch.envs.docs] +dependencies = [ + "Markdown >=3.3.3", + "mdx_gh_links >=0.2", + "markdown-callouts >=0.3.0", + "mkdocs-literate-nav >=0.5.0", + "mkdocs-redirects >=1.0.1", + "pymdown-extensions >=8.0.1", + "mkdocstrings-python >=0.7.1", +] + [tool.black] line-length = 100 target-version = ["py37"] diff --git a/requirements/lint.txt b/requirements/lint.txt deleted file mode 100644 index c9704506..00000000 --- a/requirements/lint.txt +++ /dev/null @@ -1,10 +0,0 @@ -black -isort -flake8 -mypy -typing-extensions -types-setuptools -types-PyYAML -types-Markdown -types-Jinja2 -codespell diff --git a/requirements/packaging.txt b/requirements/packaging.txt deleted file mode 100644 index acd60dab..00000000 --- a/requirements/packaging.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Wheel for PyPI installs. -wheel==0.24.0 - -# Twine for secured PyPI uploads. -twine==1.5.0 - -# Babel for messages.po localization compilation -babel==2.9.0 diff --git a/requirements/project-min.txt b/requirements/project-min.txt deleted file mode 100644 index dca726f0..00000000 --- a/requirements/project-min.txt +++ /dev/null @@ -1,21 +0,0 @@ -click==7.0 -Jinja2==2.11.1 -markupsafe==2.0.1 -Markdown==3.3.3 -PyYAML==5.1 -watchdog==2.0.0 -ghp-import==1.0 -pyyaml_env_tag==0.1 -importlib_metadata==4.3; python_version < "3.10" -typing_extensions==3.10; python_version < "3.8" -packaging==20.5 -mergedeep==1.3.4 -colorama==0.4; platform_system == 'Windows' -babel==2.9.0 - -mdx_gh_links==0.2 -markdown-callouts==0.3.0 -mkdocs-literate-nav==0.5.0 -mkdocs-redirects==1.0.1 -pymdown-extensions==8.0.1 -mkdocstrings-python==0.7.1 diff --git a/requirements/project.txt b/requirements/project.txt deleted file mode 100644 index 77e8f823..00000000 --- a/requirements/project.txt +++ /dev/null @@ -1,21 +0,0 @@ -click>=7.0 -Jinja2>=2.11.1 -markupsafe>=2.0.1 -Markdown>=3.3 -PyYAML>=5.1 -watchdog>=2.0.0 -ghp-import>=1.0 -pyyaml_env_tag>=0.1 -importlib_metadata>=4.3; python_version < "3.10" -typing_extensions>=3.10; python_version < "3.8" -packaging>=20.5 -mergedeep>=1.3.4 -colorama>=0.4; platform_system == 'Windows' -babel>=2.9.0 - -mdx_gh_links>=0.2 -markdown-callouts>=0.3.0 -mkdocs-literate-nav>=0.5.0 -mkdocs-redirects>=1.0.1 -pymdown-extensions>=8.0.1 -mkdocstrings-python>=0.7.1 diff --git a/requirements/test.txt b/requirements/test.txt deleted file mode 100644 index 3dea5a3c..00000000 --- a/requirements/test.txt +++ /dev/null @@ -1,2 +0,0 @@ -coverage -babel>=2.9.0 diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 1b181c34..00000000 --- a/tox.ini +++ /dev/null @@ -1,86 +0,0 @@ -[tox] -isolated_build = true -envlist = - py{37,38,39,310,py3}-{unittests,min-req,integration,integration-no-babel}, - black, isort, flake8, markdown-lint, linkchecker, jshint, csslint, nobabel, codespell - -[testenv] -passenv = LANG -deps= - py{37,38,39,310,py3}-integration: -rrequirements/project.txt - py{37,38,39,310,py3}-min-req: -rrequirements/project-min.txt - py{37,38,39,310,py3}-{unittests,min-req}: -rrequirements/test.txt -commands= - {envpython} --version - py{37,38,39,310,py3}-{unittests,min-req}: {envbindir}/coverage run --source=mkdocs --omit 'mkdocs/tests/*' -m unittest discover -p '*tests.py' mkdocs --top-level-directory . - py{37,38,39,310,py3}-unittests: {envbindir}/coverage xml - py{37,38,39,310,py3}-unittests: {envbindir}/coverage report --show-missing - py{37,38,39,310,py3}-integration: {envpython} -m mkdocs.tests.integration --output={envtmpdir}/builds - -[testenv:black] -deps=black -skip_install=true -commands={envbindir}/black mkdocs - -[testenv:isort] -deps=isort -skip_install=true -commands={envbindir}/isort mkdocs - -[testenv:flake8] -deps=flake8 -skip_install=true -commands={envbindir}/flake8 mkdocs - -[testenv:mypy] -deps= - mypy - typing-extensions - types-setuptools - types-PyYAML - types-Markdown - types-Jinja2 -commands={envbindir}/mypy mkdocs - -[testenv:markdown-lint] -whitelist_externals=npm -skip_install=true -passenv=* -commands= - npm exec --yes -- markdownlint-cli README.md CONTRIBUTING.md docs/ --ignore docs/CNAME - -[testenv:codespell] -deps=codespell -skip_install=true -commands= - {envbindir}/codespell mkdocs docs *.* -S .tox -S LC_MESSAGES -S '*.min.js' -S 'lunr*.js' -S fontawesome-webfont.svg -S tinyseg.js - -[testenv:linkchecker] -basepython = python2.7 -passenv=* -deps= - mdx_gh_links - requests<=2.9.0 - LinkChecker -commands= - {envpython} -m mkdocs.tests.integration --output={envtmpdir}/builds - linkchecker {envtmpdir}/builds/ - -[testenv:jshint] -whitelist_externals=npm -skip_install=true -passenv=* -commands=npm exec --yes -- jshint mkdocs/ - -[testenv:csslint] -whitelist_externals=npm -skip_install=true -passenv=* -commands=npm exec --yes -- csslint mkdocs/ - -[testenv:py{37,38,39,310,py3}-integration-no-babel] -passenv = LANG -deps=-rrequirements/project.txt -commands= - pip uninstall -y babel - {envpython} -m mkdocs.tests.integration --output={envtmpdir}/builds