diff --git a/.cookiecutterrc b/.cookiecutterrc index 29789c1..1d621f1 100644 --- a/.cookiecutterrc +++ b/.cookiecutterrc @@ -1,9 +1,6 @@ # Generated by cookiepatcher, a small shim around cookiecutter (pip install cookiepatcher) default_context: - allow_tests_inside_package: 'no' - c_extension_function: '-' - c_extension_module: '-' c_extension_optional: 'yes' c_extension_support: 'yes' codacy: 'no' @@ -17,17 +14,19 @@ default_context: email: contact@ionelmc.ro formatter_quote_style: single full_name: Ionel Cristian Mărieș + function_name: compute github_actions: 'yes' github_actions_osx: 'yes' github_actions_windows: 'yes' license: BSD 2-Clause License + module_name: cext package_name: lazy_object_proxy pre_commit: 'yes' project_name: lazy-object-proxy project_short_description: A fast and thorough lazy object proxy. pypi_badge: 'yes' pypi_disable_upload: 'no' - release_date: '2023-01-04' + release_date: '2023-12-15' repo_hosting: github.com repo_hosting_domain: github.com repo_main_branch: master @@ -38,10 +37,11 @@ default_context: sphinx_docs: 'yes' sphinx_docs_hosting: https://python-lazy-object-proxy.readthedocs.io/ sphinx_doctest: 'no' - sphinx_theme: sphinx-py3doc-enhanced-theme + sphinx_theme: furo test_matrix_separate_coverage: 'yes' + tests_inside_package: 'no' version: 1.10.0 version_manager: bump2version website: https://blog.ionelmc.ro year_from: '2014' - year_to: '2023' + year_to: '2024' diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index f1366a9..a507797 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -1,5 +1,5 @@ name: build -on: [push, pull_request] +on: [push, pull_request, workflow_dispatch] jobs: test: name: ${{ matrix.name }} @@ -19,89 +19,6 @@ jobs: toxpython: 'python3.11' tox_env: 'docs' os: 'ubuntu-latest' - - name: 'py38-cover (ubuntu/x86_64)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-cover' - cover: true - cibw_arch: 'x86_64' - cibw_build: false - os: 'ubuntu-latest' - - name: 'py38-cover (windows/AMD64)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-cover' - cover: true - cibw_arch: 'AMD64' - cibw_build: false - os: 'windows-latest' - - name: 'py38-cover (macos/x86_64)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-cover' - cover: true - cibw_arch: 'x86_64' - cibw_build: false - os: 'macos-latest' - - name: 'py38-nocov (ubuntu/x86_64/manylinux)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-nocov' - cibw_arch: 'x86_64' - cibw_build: 'cp38-*manylinux*' - os: 'ubuntu-latest' - - name: 'py38-nocov (ubuntu/x86_64/musllinux)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-nocov' - cibw_arch: 'x86_64' - cibw_build: 'cp38-*musllinux*' - os: 'ubuntu-latest' - - name: 'py38-nocov (ubuntu/aarch64/manylinux)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-nocov' - cibw_arch: 'aarch64' - cibw_build: 'cp38-*manylinux*' - os: 'ubuntu-latest' - - name: 'py38-nocov (ubuntu/aarch64/musllinux)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-nocov' - cibw_arch: 'aarch64' - cibw_build: 'cp38-*musllinux*' - os: 'ubuntu-latest' - - name: 'py38-nocov (windows/AMD64)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-nocov' - cibw_arch: 'AMD64' - cibw_build: 'cp38-*' - os: 'windows-latest' - - name: 'py38-nocov (windows/x86)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x86' - tox_env: 'py38-nocov' - cibw_arch: 'x86' - cibw_build: 'cp38-*' - os: 'windows-latest' - - name: 'py38-nocov (macos/x86_64)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-nocov' - cibw_arch: 'x86_64' - cibw_build: 'cp38-*' - os: 'macos-latest' - name: 'py39-cover (ubuntu/x86_64)' python: '3.9' toxpython: 'python3.9' @@ -120,13 +37,13 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'py39-cover (macos/x86_64)' + - name: 'py39-cover (macos/arm64)' python: '3.9' toxpython: 'python3.9' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'py39-cover' cover: true - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' - name: 'py39-nocov (ubuntu/x86_64/manylinux)' @@ -169,20 +86,12 @@ jobs: cibw_arch: 'AMD64' cibw_build: 'cp39-*' os: 'windows-latest' - - name: 'py39-nocov (windows/x86)' + - name: 'py39-nocov (macos/arm64)' python: '3.9' toxpython: 'python3.9' - python_arch: 'x86' + python_arch: 'arm64' tox_env: 'py39-nocov' - cibw_arch: 'x86' - cibw_build: 'cp39-*' - os: 'windows-latest' - - name: 'py39-nocov (macos/x86_64)' - python: '3.9' - toxpython: 'python3.9' - python_arch: 'x64' - tox_env: 'py39-nocov' - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: 'cp39-*' os: 'macos-latest' - name: 'py310-cover (ubuntu/x86_64)' @@ -203,13 +112,13 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'py310-cover (macos/x86_64)' + - name: 'py310-cover (macos/arm64)' python: '3.10' toxpython: 'python3.10' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'py310-cover' cover: true - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' - name: 'py310-nocov (ubuntu/x86_64/manylinux)' @@ -252,20 +161,12 @@ jobs: cibw_arch: 'AMD64' cibw_build: 'cp310-*' os: 'windows-latest' - - name: 'py310-nocov (windows/x86)' + - name: 'py310-nocov (macos/arm64)' python: '3.10' toxpython: 'python3.10' - python_arch: 'x86' + python_arch: 'arm64' tox_env: 'py310-nocov' - cibw_arch: 'x86' - cibw_build: 'cp310-*' - os: 'windows-latest' - - name: 'py310-nocov (macos/x86_64)' - python: '3.10' - toxpython: 'python3.10' - python_arch: 'x64' - tox_env: 'py310-nocov' - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: 'cp310-*' os: 'macos-latest' - name: 'py311-cover (ubuntu/x86_64)' @@ -286,13 +187,13 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'py311-cover (macos/x86_64)' + - name: 'py311-cover (macos/arm64)' python: '3.11' toxpython: 'python3.11' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'py311-cover' cover: true - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' - name: 'py311-nocov (ubuntu/x86_64/manylinux)' @@ -335,20 +236,12 @@ jobs: cibw_arch: 'AMD64' cibw_build: 'cp311-*' os: 'windows-latest' - - name: 'py311-nocov (windows/x86)' + - name: 'py311-nocov (macos/arm64)' python: '3.11' toxpython: 'python3.11' - python_arch: 'x86' + python_arch: 'arm64' tox_env: 'py311-nocov' - cibw_arch: 'x86' - cibw_build: 'cp311-*' - os: 'windows-latest' - - name: 'py311-nocov (macos/x86_64)' - python: '3.11' - toxpython: 'python3.11' - python_arch: 'x64' - tox_env: 'py311-nocov' - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: 'cp311-*' os: 'macos-latest' - name: 'py312-cover (ubuntu/x86_64)' @@ -369,13 +262,13 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'py312-cover (macos/x86_64)' + - name: 'py312-cover (macos/arm64)' python: '3.12' toxpython: 'python3.12' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'py312-cover' cover: true - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' - name: 'py312-nocov (ubuntu/x86_64/manylinux)' @@ -418,72 +311,13 @@ jobs: cibw_arch: 'AMD64' cibw_build: 'cp312-*' os: 'windows-latest' - - name: 'py312-nocov (windows/x86)' + - name: 'py312-nocov (macos/arm64)' python: '3.12' toxpython: 'python3.12' - python_arch: 'x86' + python_arch: 'arm64' tox_env: 'py312-nocov' - cibw_arch: 'x86' + cibw_arch: 'arm64' cibw_build: 'cp312-*' - os: 'windows-latest' - - name: 'py312-nocov (macos/x86_64)' - python: '3.12' - toxpython: 'python3.12' - python_arch: 'x64' - tox_env: 'py312-nocov' - cibw_arch: 'x86_64' - cibw_build: 'cp312-*' - os: 'macos-latest' - - name: 'pypy38-cover (ubuntu/x86_64)' - python: 'pypy-3.8' - toxpython: 'pypy3.8' - python_arch: 'x64' - tox_env: 'pypy38-cover' - cover: true - cibw_arch: 'x86_64' - cibw_build: false - os: 'ubuntu-latest' - - name: 'pypy38-cover (windows/AMD64)' - python: 'pypy-3.8' - toxpython: 'pypy3.8' - python_arch: 'x64' - tox_env: 'pypy38-cover' - cover: true - cibw_arch: 'AMD64' - cibw_build: false - os: 'windows-latest' - - name: 'pypy38-cover (macos/x86_64)' - python: 'pypy-3.8' - toxpython: 'pypy3.8' - python_arch: 'x64' - tox_env: 'pypy38-cover' - cover: true - cibw_arch: 'x86_64' - cibw_build: false - os: 'macos-latest' - - name: 'pypy38-nocov (ubuntu/x86_64/manylinux)' - python: 'pypy-3.8' - toxpython: 'pypy3.8' - python_arch: 'x64' - tox_env: 'pypy38-nocov' - cibw_arch: 'x86_64' - cibw_build: false - os: 'ubuntu-latest' - - name: 'pypy38-nocov (windows/AMD64)' - python: 'pypy-3.8' - toxpython: 'pypy3.8' - python_arch: 'x64' - tox_env: 'pypy38-nocov' - cibw_arch: 'AMD64' - cibw_build: false - os: 'windows-latest' - - name: 'pypy38-nocov (macos/x86_64)' - python: 'pypy-3.8' - toxpython: 'pypy3.8' - python_arch: 'x64' - tox_env: 'pypy38-nocov' - cibw_arch: 'x86_64' - cibw_build: false os: 'macos-latest' - name: 'pypy39-cover (ubuntu/x86_64)' python: 'pypy-3.9' @@ -503,13 +337,13 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'pypy39-cover (macos/x86_64)' + - name: 'pypy39-cover (macos/arm64)' python: 'pypy-3.9' toxpython: 'pypy3.9' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'pypy39-cover' cover: true - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' - name: 'pypy39-nocov (ubuntu/x86_64/manylinux)' @@ -528,12 +362,12 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'pypy39-nocov (macos/x86_64)' + - name: 'pypy39-nocov (macos/arm64)' python: 'pypy-3.9' toxpython: 'pypy3.9' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'pypy39-nocov' - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' - name: 'pypy310-cover (ubuntu/x86_64)' @@ -554,13 +388,13 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'pypy310-cover (macos/x86_64)' + - name: 'pypy310-cover (macos/arm64)' python: 'pypy-3.10' toxpython: 'pypy3.10' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'pypy310-cover' cover: true - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' - name: 'pypy310-nocov (ubuntu/x86_64/manylinux)' @@ -579,12 +413,12 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'pypy310-nocov (macos/x86_64)' + - name: 'pypy310-nocov (macos/arm64)' python: 'pypy-3.10' toxpython: 'pypy3.10' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'pypy310-nocov' - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' steps: @@ -606,11 +440,6 @@ jobs: pip --version tox --version pip list --format=freeze - - name: install dependencies (gdb) - if: > - !matrix.cibw_build && matrix.os == 'ubuntu' - run: > - sudo apt-get install gdb - name: cibw build and test if: matrix.cibw_build run: cibuildwheel @@ -662,3 +491,6 @@ jobs: - uses: coverallsapp/github-action@v2 with: parallel-finished: true + - uses: codecov/codecov-action@v3 + with: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0a737a5..2124ee7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,16 +6,13 @@ exclude: '^(\.tox|ci/templates|\.bumpversion\.cfg)(/|$)' # Note the order is intentional to avoid multiple passes of the hooks repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.7 + rev: v0.7.4 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix, --show-fixes] - - repo: https://github.com/psf/black - rev: 23.12.0 - hooks: - - id: black + - id: ruff-format - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v5.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer diff --git a/LICENSE b/LICENSE index 07630f9..b56dc6d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 2-Clause License -Copyright (c) 2014-2023, Ionel Cristian Mărieș. All rights reserved. +Copyright (c) 2014-2024, Ionel Cristian Mărieș. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.rst b/README.rst index cac8bba..e429753 100644 --- a/README.rst +++ b/README.rst @@ -10,13 +10,11 @@ Overview * - docs - |docs| * - tests - - | |github-actions| - | |coveralls| |codecov| + - |github-actions| |coveralls| |codecov| * - package - - | |version| |wheel| |supported-versions| |supported-implementations| - | |commits-since| + - |version| |wheel| |supported-versions| |supported-implementations| |commits-since| .. |docs| image:: https://readthedocs.org/projects/python-lazy-object-proxy/badge/?style=flat - :target: https://python-lazy-object-proxy.readthedocs.io/ + :target: https://readthedocs.org/projects/python-lazy-object-proxy/ :alt: Documentation Status .. |github-actions| image:: https://github.com/ionelmc/python-lazy-object-proxy/actions/workflows/github-actions.yml/badge.svg @@ -91,11 +89,18 @@ Installation pip install lazy-object-proxy +You can also install the in-development version with:: + + pip install https://github.com/ionelmc/python-lazy-object-proxy/archive/master.zip + + Documentation ============= + https://python-lazy-object-proxy.readthedocs.io/ + Development =========== diff --git a/ci/requirements.txt b/ci/requirements.txt index a1708f4..b4f1852 100644 --- a/ci/requirements.txt +++ b/ci/requirements.txt @@ -1,6 +1,5 @@ virtualenv>=16.6.0 pip>=19.1.1 setuptools>=18.0.1 -six>=1.14.0 tox twine diff --git a/ci/templates/.github/workflows/github-actions.yml b/ci/templates/.github/workflows/github-actions.yml index 55e98d3..fb89fec 100644 --- a/ci/templates/.github/workflows/github-actions.yml +++ b/ci/templates/.github/workflows/github-actions.yml @@ -1,5 +1,5 @@ name: build -on: [push, pull_request] +on: [push, pull_request, workflow_dispatch] jobs: test: name: {{ '${{ matrix.name }}' }} @@ -36,8 +36,7 @@ jobs: ['ubuntu', 'x64', 'aarch64', '*manylinux*', False], ['ubuntu', 'x64', 'aarch64', '*musllinux*', False], ['windows', 'x64', 'AMD64', '*', True], - ['windows', 'x86', 'x86', '*', False], - ['macos', 'x64', 'x86_64', '*', True], + ['macos', 'arm64', 'arm64', '*', True], ] %} {% if include_cover or ('nocov' in env and not prefix.startswith('pypy')) %} {% set wheel_suffix = 'nocov' in env and wheel_arch.strip('*') %} @@ -135,3 +134,6 @@ jobs: - uses: coverallsapp/github-action@v2 with: parallel-finished: true + - uses: codecov/codecov-action@v3 + with: + CODECOV_TOKEN: {% raw %}${{ secrets.CODECOV_TOKEN }}{% endraw %} diff --git a/docs/conf.py b/docs/conf.py index f6d031a..18f3f99 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,7 +1,3 @@ -import traceback - -import sphinx_py3doc_enhanced_theme - extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.autosummary', @@ -16,7 +12,7 @@ source_suffix = '.rst' master_doc = 'index' project = 'lazy-object-proxy' -year = '2014-2023' +year = '2014-2024' author = 'Ionel Cristian Mărieș' copyright = f'{year}, {author}' try: @@ -24,17 +20,19 @@ version = release = get_distribution('lazy_object_proxy').version except Exception: + import traceback + traceback.print_exc() version = release = '1.10.0' pygments_style = 'trac' templates_path = ['.'] extlinks = { - 'issue': ('https://github.com/ionelmc/python-lazy-object-proxy/issues/%s', '#'), - 'pr': ('https://github.com/ionelmc/python-lazy-object-proxy/pull/%s', 'PR #'), + 'issue': ('https://github.com/ionelmc/python-lazy-object-proxy/issues/%s', '#%s'), + 'pr': ('https://github.com/ionelmc/python-lazy-object-proxy/pull/%s', 'PR #%s'), } -html_theme = 'sphinx_py3doc_enhanced_theme' -html_theme_path = [sphinx_py3doc_enhanced_theme.get_html_theme_path()] + +html_theme = 'furo' html_theme_options = { 'githuburl': 'https://github.com/ionelmc/python-lazy-object-proxy/', } @@ -42,9 +40,6 @@ html_use_smartypants = True html_last_updated_fmt = '%b %d, %Y' html_split_index = False -html_sidebars = { - '**': ['searchbox.html', 'globaltoc.html', 'sourcelink.html'], -} html_short_title = f'{project}-{version}' napoleon_use_ivar = True diff --git a/docs/requirements.txt b/docs/requirements.txt index 62bc14e..c03e307 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,2 +1,2 @@ sphinx>=1.3 -sphinx-py3doc-enhanced-theme +furo diff --git a/pyproject.toml b/pyproject.toml index f84e2f2..6632079 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,11 +7,16 @@ build-backend = "setuptools.build_meta" [tool.setuptools_scm] -[tool.ruff.per-file-ignores] -"ci/*" = ["S"] - [tool.ruff] extend-exclude = ["static", "ci/templates"] +line-length = 140 +src = ["src", "tests"] +target-version = "py39" + +[tool.ruff.lint.per-file-ignores] +"ci/*" = ["S"] + +[tool.ruff.lint] ignore = [ "RUF001", # ruff-specific rules ambiguous-unicode-character-string "S101", # flake8-bandit assert @@ -23,7 +28,6 @@ ignore = [ "B004", "S102", ] -line-length = 140 select = [ "B", # flake8-bugbear "C4", # flake8-comprehensions @@ -38,28 +42,20 @@ select = [ "PLE", # pylint errors "PT", # flake8-pytest-style "PTH", # flake8-use-pathlib - "Q", # flake8-quotes "RSE", # flake8-raise "RUF", # ruff-specific rules "S", # flake8-bandit "UP", # pyupgrade "W", # pycodestyle warnings ] -src = ["src", "tests"] -target-version = "py38" -[tool.ruff.flake8-pytest-style] +[tool.ruff.lint.flake8-pytest-style] fixture-parentheses = false mark-parentheses = false -[tool.ruff.isort] +[tool.ruff.lint.isort] forced-separate = ["conftest"] force-single-line = true -[tool.black] -line-length = 140 -target-version = ["py38"] -skip-string-normalization = true - -[tool.ruff.flake8-quotes] -inline-quotes = "single" +[tool.ruff.format] +quote-style = "single" diff --git a/setup.py b/setup.py index 30f84c6..d7a0044 100755 --- a/setup.py +++ b/setup.py @@ -105,7 +105,6 @@ def read(*names, **kwargs): 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3 :: Only', - 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', @@ -126,14 +125,14 @@ def read(*names, **kwargs): keywords=[ # eg: "keyword1", "keyword2", "keyword3", ], - python_requires='>=3.8', + python_requires='>=3.9', install_requires=[ # eg: "aspectlib==1.1.1", "six>=1.7", ], extras_require={ # eg: # "rst": ["docutils>=0.11"], - # ":python_version=="2.6"": ["argparse"], + # ":python_version=='3.8'": ["backports.zoneinfo"], }, setup_requires=[ 'setuptools_scm>=3.3.1', diff --git a/tox.ini b/tox.ini index 57f7222..37b2254 100644 --- a/tox.ini +++ b/tox.ini @@ -14,16 +14,14 @@ envlist = clean, check, docs, - {py38,py39,py310,py311,py312,pypy38,pypy39,pypy310}-{cover,nocov}, + {py39,py310,py311,py312,pypy39,pypy310}-{cover,nocov}, report ignore_basepython_conflict = true [testenv] basepython = - pypy38: {env:TOXPYTHON:pypy3.8} pypy39: {env:TOXPYTHON:pypy3.9} pypy310: {env:TOXPYTHON:pypy3.10} - py38: {env:TOXPYTHON:python3.8} py39: {env:TOXPYTHON:python3.9} py310: {env:TOXPYTHON:python3.10} py311: {env:TOXPYTHON:python3.11} @@ -84,7 +82,10 @@ commands = coverage html [testenv:clean] -commands = coverage erase +commands = + python setup.py clean + coverage erase skip_install = true deps = + setuptools coverage