diff --git a/.editorconfig b/.editorconfig index c5508b9..e4b8673 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,8 +1,8 @@ -# Generated from: -# https://github.com/zopefoundation/meta/tree/master/config/pure-python +# Generated with zope.meta (https://zopemeta.readthedocs.io/) from: +# https://github.com/zopefoundation/meta/tree/master/src/zope/meta/pure-python # # EditorConfig Configuration file, for more details see: -# http://EditorConfig.org +# https://EditorConfig.org # EditorConfig is a convention description, that could be interpreted # by multiple editors to enforce common coding conventions for specific # file types @@ -12,7 +12,7 @@ root = true -[*] # For All Files +[*] # Unix-style newlines with a newline ending every file end_of_line = lf insert_final_newline = true diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index bf22c0a..8a1cde6 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -1,5 +1,5 @@ -# Generated from: -# https://github.com/zopefoundation/meta/tree/master/config/pure-python +# Generated with zope.meta (https://zopemeta.readthedocs.io/) from: +# https://github.com/zopefoundation/meta/tree/master/src/zope/meta/pure-python name: pre-commit on: @@ -21,10 +21,10 @@ jobs: name: linting runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: - python-version: 3.x + python-version: '3.13' - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd #v3.0.1 with: extra_args: --all-files --show-diff-on-failure diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ace0d07..c458fa5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,5 +1,5 @@ -# Generated from: -# https://github.com/zopefoundation/meta/tree/master/config/pure-python +# Generated with zope.meta (https://zopemeta.readthedocs.io/) from: +# https://github.com/zopefoundation/meta/tree/master/src/zope/meta/pure-python name: tests on: @@ -25,7 +25,6 @@ jobs: config: # [Python version, tox env] - ["3.11", "release-check"] - - ["3.9", "py39"] - ["3.10", "py310"] - ["3.11", "py311"] - ["3.12", "py312"] @@ -43,12 +42,12 @@ jobs: if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name name: ${{ matrix.os[0] }}-${{ matrix.config[1] }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: persist-credentials: false - name: Install uv + caching - # astral/setup-uv@7 - uses: astral-sh/setup-uv@3259c6206f993105e3a61b142c2d97bf4b9ef83d + # astral/setup-uv@8.1.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b with: enable-cache: true cache-dependency-glob: | @@ -57,11 +56,7 @@ jobs: python-version: ${{ matrix.config[0] }} github-token: ${{ secrets.GITHUB_TOKEN }} - name: Test - if: ${{ !startsWith(runner.os, 'Mac') }} run: uvx --with tox-uv tox -e ${{ matrix.config[1] }} - - name: Test (macOS) - if: ${{ startsWith(runner.os, 'Mac') }} - run: uvx --with tox-uv tox -e ${{ matrix.config[1] }}-universal2 - name: Coverage if: matrix.config[1] == 'coverage' run: | diff --git a/.gitignore b/.gitignore index 1f321f5..188120b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -# Generated from: -# https://github.com/zopefoundation/meta/tree/master/config/pure-python +# Generated with zope.meta (https://zopemeta.readthedocs.io/) from: +# https://github.com/zopefoundation/meta/tree/master/src/zope/meta/pure-python *.dll *.egg-info/ *.profraw @@ -28,5 +28,6 @@ lib64 log/ parts/ pyvenv.cfg +share/ testing.log var/ diff --git a/.meta.toml b/.meta.toml index 04360f6..32f5cc5 100644 --- a/.meta.toml +++ b/.meta.toml @@ -1,16 +1,17 @@ -# Generated from: -# https://github.com/zopefoundation/meta/tree/master/config/pure-python +# Generated with zope.meta (https://zopemeta.readthedocs.io/) from: +# https://github.com/zopefoundation/meta/tree/master/src/zope/meta/pure-python [meta] template = "pure-python" -commit-id = "72252845" +commit-id = "ba10c93f" [python] with-pypy = false with-docs = true with-sphinx-doctests = true with-windows = true -with-future-python = true +with-future-python = false with-macos = false +with-free-threaded-python = false [tox] use-flake8 = true @@ -47,7 +48,7 @@ testenv-additional = [ " coverage combine", " coverage html", " coverage report -m --fail-under=100", - "depends = py39,py310,py311,py311-datetime,py312,py313,py314,coverage", + "depends = py310,py311,py311-datetime,py312,py313,py314,coverage", ] coverage-command = "pytest --cov=src --cov=tests --cov-report= tests {posargs}" coverage-setenv = [ @@ -55,7 +56,7 @@ coverage-setenv = [ ] [coverage] -fail-under = 97.2 +fail-under = 97.1 [isort] additional-sources = "{toxinidir}/tests" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cbb2541..d2d5029 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,9 +1,9 @@ -# Generated from: -# https://github.com/zopefoundation/meta/tree/master/config/pure-python +# Generated with zope.meta (https://zopemeta.readthedocs.io/) from: +# https://github.com/zopefoundation/meta/tree/master/src/zope/meta/pure-python minimum_pre_commit_version: '3.6' repos: - repo: https://github.com/pycqa/isort - rev: "7.0.0" + rev: "8.0.1" hooks: - id: isort - repo: https://github.com/hhatto/autopep8 @@ -12,14 +12,15 @@ repos: - id: autopep8 args: [--in-place, --aggressive, --aggressive] - repo: https://github.com/asottile/pyupgrade - rev: v3.21.0 + rev: v3.21.2 hooks: - id: pyupgrade - args: [--py39-plus] + args: [--py310-plus] - repo: https://github.com/isidentical/teyit rev: 0.4.3 hooks: - id: teyit + language_version: python3.13 - repo: https://github.com/PyCQA/flake8 rev: "7.3.0" hooks: diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 034043e..f81cabf 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,5 +1,5 @@ -# Generated from: -# https://github.com/zopefoundation/meta/tree/master/config/pure-python +# Generated with zope.meta (https://zopemeta.readthedocs.io/) from: +# https://github.com/zopefoundation/meta/tree/master/src/zope/meta/pure-python # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details diff --git a/CHANGES.rst b/CHANGES.rst index eddc785..f567534 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,10 @@ Changes 8.2 (unreleased) ---------------- -- Nothing changed yet. +- Move package metadata from setup.py to pyproject.toml. + +- Drop support for Python 3.9. + 8.1 (2025-10-19) ---------------- diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0ab12fe..ca517f4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing to zopefoundation projects diff --git a/MANIFEST.in b/MANIFEST.in index 7f0aa88..178479d 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,5 @@ -# Generated from: -# https://github.com/zopefoundation/meta/tree/master/config/pure-python +# Generated with zope.meta (https://zopemeta.readthedocs.io/) from: +# https://github.com/zopefoundation/meta/tree/master/src/zope/meta/pure-python include *.md include *.rst include *.txt diff --git a/docs/conf.py b/docs/conf.py index 1ce21d1..bb0d2ef 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -112,7 +112,6 @@ # Intersphinx Mapping for Links between different Documentations intersphinx_mapping = { 'python3': ('https://docs.python.org/3', None), - 'python39': ('https://docs.python.org/3.9', None), 'python310': ('https://docs.python.org/3.10', None), 'python311': ('https://docs.python.org/3.11', None), 'python312': ('https://docs.python.org/3.12', None), diff --git a/docs/contributing/changes_from38to39.rst b/docs/contributing/changes_from38to39.rst deleted file mode 100644 index a040b03..0000000 --- a/docs/contributing/changes_from38to39.rst +++ /dev/null @@ -1,5 +0,0 @@ -Changes from Python 3.8 to Python 3.9 -------------------------------------- - -.. literalinclude:: ast/python3_9.ast - :diff: ast/python3_8.ast diff --git a/docs/contributing/index.rst b/docs/contributing/index.rst index 69909e4..67b4f84 100644 --- a/docs/contributing/index.rst +++ b/docs/contributing/index.rst @@ -98,7 +98,6 @@ A (modified style) Copy of all Abstract Grammar Definitions for the Python versi .. toctree:: :maxdepth: 2 - changes_from38to39 changes_from39to310 changes_from310to311 changes_from311to312 @@ -241,7 +240,6 @@ Technical Backgrounds - Links to External Documentation * `Python 3.12 AST`_ (EOL 2028-10) * `Python 3.11 AST`_ (EOL 2027-10) * `Python 3.10 AST`_ (EOL 2026-10) - * `Python 3.9 AST`_ (EOL 2025-10) * `AST NodeVistiors Class`_ * `AST NodeTransformer Class`_ @@ -269,8 +267,6 @@ Todos .. _`What's new in Python 3.10`: https://docs.python.org/3.10/whatsnew/3.10.html -.. _`What's new in Python 3.9`: https://docs.python.org/3.9/whatsnew/3.9.html - .. _`Status of Python Versions`: https://devguide.python.org/versions/ .. _`Concept of Immutable Types and Python Example`: https://en.wikipedia.org/wiki/Immutable_object#Python @@ -295,8 +291,6 @@ Todos .. _`Python 3.10 AST`: https://docs.python.org/3.10/library/ast.html#abstract-grammar -.. _`Python 3.9 AST`: https://docs.python.org/3.9/library/ast.html#abstract-grammar - .. _`AST NodeVistiors Class`: https://docs.python.org/3/library/ast.html#ast.NodeVisitor .. _`AST NodeTransformer Class`: https://docs.python.org/3/library/ast.html#ast.NodeTransformer diff --git a/docs/index.rst b/docs/index.rst index 7e617d8..1ce9733 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -15,7 +15,7 @@ RestrictedPython is not a sandbox system or a secured environment, but it helps Supported Python versions ========================= -RestrictedPython supports CPython 3.9 up to 3.14. +RestrictedPython supports CPython 3.10 up to 3.14. It does _not_ support PyPy or other alternative Python implementations. Contents diff --git a/pyproject.toml b/pyproject.toml index 7b94ef6..c66658e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,5 @@ -# -# Generated from: -# https://github.com/zopefoundation/meta/tree/master/config/pure-python - +# Generated with zope.meta (https://zopemeta.readthedocs.io/) from: +# https://github.com/zopefoundation/meta/tree/master/src/zope/meta/pure-python [build-system] requires = [ "setuptools >= 78.1.1,< 81", @@ -9,12 +7,63 @@ requires = [ ] build-backend = "setuptools.build_meta" + +[project] +name = "RestrictedPython" +version = "8.2.dev0" +description = "RestrictedPython is a defined subset of the Python language which allows to provide a program input into a trusted environment." +license = "ZPL-2.1" +classifiers = [ + "Development Status :: 6 - Mature", + "Programming Language :: Python", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "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", + "Programming Language :: Python :: Implementation :: CPython", + "Topic :: Security", +] +dynamic = ["readme"] +requires-python = ">=3.10, <3.15" +authors = [ + {name = "Zope Foundation and contributors",email = "zope-dev@zope.dev"}, +] +maintainers = [ + {name = "Plone Foundation and contributors",email = "zope-dev@zope.dev"}, +] +keywords = [ + "restricted", + "execution", + "security", + "untrusted", + "code", +] + +[project.optional-dependencies] +test = [ + "pytest", + "pytest-mock", +] +docs = [ + "Sphinx", + "furo", +] + +[project.urls] +Documentation = "https://restrictedpython.readthedocs.io/" +Issues = "https://github.com/zopefoundation/RestrictedPython/issues" +Source = "https://github.com/zopefoundation/RestrictedPython" +Changelog = "https://github.com/zopefoundation/RestrictedPython/blob/master/CHANGES.rst" + [tool.coverage.run] branch = true source = ["RestrictedPython"] [tool.coverage.report] -fail_under = 97.2 +fail_under = 97.1 precision = 2 ignore_errors = true show_missing = true @@ -31,3 +80,7 @@ exclude_lines = [ [tool.coverage.html] directory = "parts/htmlcov" + +[tool.setuptools.dynamic] +readme = {file = ["README.rst", "CHANGES.rst"]} + diff --git a/setup.cfg b/setup.cfg index ae12100..3b11c8e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ -# Generated from: -# https://github.com/zopefoundation/meta/tree/master/config/pure-python +# Generated with zope.meta (https://zopemeta.readthedocs.io/) from: +# https://github.com/zopefoundation/meta/tree/master/src/zope/meta/pure-python [flake8] doctests = 1 diff --git a/setup.py b/setup.py index 9217802..2978e06 100644 --- a/setup.py +++ b/setup.py @@ -13,57 +13,8 @@ ############################################################################## """Setup for RestrictedPython package""" -import os - -from setuptools import find_packages from setuptools import setup -def read(*rnames): - with open(os.path.join(os.path.dirname(__file__), *rnames)) as f: - return f.read() - - -setup(name='RestrictedPython', - version='8.2.dev0', - url='https://github.com/zopefoundation/RestrictedPython', - license='ZPL-2.1', - description=( - 'RestrictedPython is a defined subset of the Python language which ' - 'allows to provide a program input into a trusted environment.'), - long_description=read('README.rst') + '\n' + read('CHANGES.rst'), - long_description_content_type='text/x-rst', - classifiers=[ - 'Development Status :: 6 - Mature', - 'License :: OSI Approved :: Zope Public License', - 'Programming Language :: Python', - 'Operating System :: OS Independent', - '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', - 'Programming Language :: Python :: Implementation :: CPython', - 'Topic :: Security', - ], - keywords='restricted execution security untrusted code', - author='Zope Foundation and Contributors', - author_email='zope-dev@zope.dev', - project_urls={ - "Documentation": "https://restrictedpython.readthedocs.io/", - "Source": "https://github.com/zopefoundation/RestrictedPython", - "Tracker": - "https://github.com/zopefoundation/RestrictedPython/issues", - }, - packages=find_packages('src'), - package_dir={'': 'src'}, - install_requires=[], - python_requires=">=3.9, <3.15", - extras_require={ - 'test': ['pytest', 'pytest-mock'], - 'docs': ['Sphinx', 'furo'], - }, - include_package_data=True, - zip_safe=False) +# See pyproject.toml for package metadata +setup() diff --git a/src/RestrictedPython/_compat.py b/src/RestrictedPython/_compat.py index 2c5641e..63c7fa1 100644 --- a/src/RestrictedPython/_compat.py +++ b/src/RestrictedPython/_compat.py @@ -3,7 +3,6 @@ _version = sys.version_info -IS_PY310_OR_GREATER = _version.major == 3 and _version.minor >= 10 IS_PY311_OR_GREATER = _version.major == 3 and _version.minor >= 11 IS_PY312_OR_GREATER = _version.major == 3 and _version.minor >= 12 IS_PY313_OR_GREATER = _version.major == 3 and _version.minor >= 13 diff --git a/src/RestrictedPython/transformer.py b/src/RestrictedPython/transformer.py index fa71e48..c030bb7 100644 --- a/src/RestrictedPython/transformer.py +++ b/src/RestrictedPython/transformer.py @@ -361,55 +361,6 @@ def gen_none_node(self): def gen_del_stmt(self, name_to_del): return ast.Delete(targets=[ast.Name(name_to_del, ast.Del())]) - def transform_slice(self, slice_): - """Transform slices into function parameters. - - ast.Slice nodes are only allowed within a ast.Subscript node. - To use a slice as an argument of ast.Call it has to be converted. - Conversion is done by calling the 'slice' function from builtins - """ - - if isinstance(slice_, ast.expr): - # Python 3.9+ - return slice_ - - elif isinstance(slice_, ast.Index): - return slice_.value - - elif isinstance(slice_, ast.Slice): - # Create a python slice object. - args = [] - - if slice_.lower: - args.append(slice_.lower) - else: - args.append(self.gen_none_node()) - - if slice_.upper: - args.append(slice_.upper) - else: - args.append(self.gen_none_node()) - - if slice_.step: - args.append(slice_.step) - else: - args.append(self.gen_none_node()) - - return ast.Call( - func=ast.Name('slice', ast.Load()), - args=args, - keywords=[]) - - elif isinstance(slice_, ast.ExtSlice): - dims = ast.Tuple([], ast.Load()) - for item in slice_.dims: - dims.elts.append(self.transform_slice(item)) - return dims - - else: # pragma: no cover - # Index, Slice and ExtSlice are only defined Slice types. - raise NotImplementedError(f"Unknown slice type: {slice_}") - def check_name(self, node, name, allow_magic_methods=False): """Check names if they are allowed. @@ -932,7 +883,7 @@ def visit_Subscript(self, node): if isinstance(node.ctx, ast.Load): new_node = ast.Call( func=ast.Name('_getitem_', ast.Load()), - args=[node.value, self.transform_slice(node.slice)], + args=[node.value, node.slice], keywords=[]) copy_locations(new_node, node) @@ -953,24 +904,12 @@ def visit_Subscript(self, node): raise NotImplementedError( f"Unknown ctx type: {type(node.ctx)}") - def visit_Index(self, node): - """ - - """ - return self.node_contents_visit(node) - def visit_Slice(self, node): """ """ return self.node_contents_visit(node) - def visit_ExtSlice(self, node): - """ - - """ - return self.node_contents_visit(node) - # Comprehensions def visit_ListComp(self, node): diff --git a/tests/test_NamedExpr.py b/tests/test_NamedExpr.py index 2da22ad..1fc393b 100644 --- a/tests/test_NamedExpr.py +++ b/tests/test_NamedExpr.py @@ -23,7 +23,7 @@ def test_no_private_target(self): def test_simple_only(self): # we test here that only a simple variable is allowed # as assignemt expression target - # Currently (Python 3.8, 3.9), this is enforced by the + # This is currently enforced by the # Python concrete syntax; therefore, some (``ast``) trickery is # necessary to produce a test for it. class TransformNamedExprTarget(NodeTransformer): diff --git a/tests/test_compile.py b/tests/test_compile.py index c4ea7de..379e71f 100644 --- a/tests/test_compile.py +++ b/tests/test_compile.py @@ -8,7 +8,6 @@ from RestrictedPython import compile_restricted_eval from RestrictedPython import compile_restricted_exec from RestrictedPython import compile_restricted_single -from RestrictedPython._compat import IS_PY310_OR_GREATER from RestrictedPython._compat import IS_PY311_OR_GREATER from tests.helper import restricted_eval @@ -40,10 +39,7 @@ def test_compile__compile_restricted_invalid_mode_input(): def test_compile__invalid_syntax(): with pytest.raises(SyntaxError) as err: compile_restricted(INVALID_ASSINGMENT, '', 'exec') - if IS_PY310_OR_GREATER: - assert "SyntaxError: cannot assign to literal here." in str(err.value) - else: - assert "cannot assign to literal at statement:" in str(err.value) + assert "SyntaxError: cannot assign to literal here." in str(err.value) def test_compile__compile_restricted_exec__1(): @@ -118,15 +114,10 @@ def no_exec(): def test_compile__compile_restricted_exec__10(): """It is a SyntaxError to use the `exec` statement.""" result = compile_restricted_exec(EXEC_STATEMENT) - if IS_PY310_OR_GREATER: - assert ( - 'Line 2: SyntaxError: Missing parentheses in call to \'exec\'. Did' - ' you mean exec(...)? at statement: "exec \'q = 1\'"', - ) == result.errors - else: - assert ( - 'Line 2: SyntaxError: Missing parentheses in call to \'exec\' at' - ' statement: "exec \'q = 1\'"',) == result.errors + assert ( + 'Line 2: SyntaxError: Missing parentheses in call to \'exec\'. Did' + ' you mean exec(...)? at statement: "exec \'q = 1\'"', + ) == result.errors FUNCTION_DEF = """\ diff --git a/tests/test_compile_restricted_function.py b/tests/test_compile_restricted_function.py index 0bf0437..d1454db 100644 --- a/tests/test_compile_restricted_function.py +++ b/tests/test_compile_restricted_function.py @@ -3,7 +3,6 @@ from RestrictedPython import PrintCollector from RestrictedPython import compile_restricted_function from RestrictedPython import safe_builtins -from RestrictedPython._compat import IS_PY310_OR_GREATER def test_compile_restricted_function(): @@ -211,15 +210,9 @@ def test_compile_restricted_function_handle_SyntaxError(): ) assert result.code is None - if IS_PY310_OR_GREATER: - assert result.errors == ( - "Line 1: SyntaxError: '(' was never closed at statement: 'a('", - ) - else: - assert result.errors == ( - "Line 1: SyntaxError: unexpected EOF while parsing at statement:" - " 'a('", - ) + assert result.errors == ( + "Line 1: SyntaxError: '(' was never closed at statement: 'a('", + ) def test_compile_restricted_function_invalid_syntax(): @@ -237,11 +230,6 @@ def test_compile_restricted_function_invalid_syntax(): assert len(result.errors) == 1 error_msg = result.errors[0] - if IS_PY310_OR_GREATER: - assert error_msg.startswith( - "Line 1: SyntaxError: cannot assign to literal here. Maybe " - ) - else: - assert error_msg.startswith( - "Line 1: SyntaxError: cannot assign to literal at statement:" - ) + assert error_msg.startswith( + "Line 1: SyntaxError: cannot assign to literal here. Maybe " + ) diff --git a/tox.ini b/tox.ini index 4015b3a..3439cf4 100644 --- a/tox.ini +++ b/tox.ini @@ -1,11 +1,10 @@ -# Generated from: -# https://github.com/zopefoundation/meta/tree/master/config/pure-python +# Generated with zope.meta (https://zopemeta.readthedocs.io/) from: +# https://github.com/zopefoundation/meta/tree/master/src/zope/meta/pure-python [tox] minversion = 3.18 envlist = release-check lint - py39 py310 py311 py312 @@ -20,13 +19,11 @@ envlist = usedevelop = true package = wheel wheel_build_env = .pkg -pip_pre = py314: true deps = setuptools >= 78.1.1,< 81 datetime: DateTime -cconstraints.txt pytest-cov - Sphinx setenv = COVERAGE_FILE=.coverage.{envname} commands = @@ -52,7 +49,7 @@ commands = coverage combine coverage html coverage report -m --fail-under=100 -depends = py39,py310,py311,py311-datetime,py312,py313,py314,coverage +depends = py310,py311,py311-datetime,py312,py313,py314,coverage [testenv:setuptools-latest] basepython = python3 @@ -72,12 +69,12 @@ deps = twine build check-manifest - check-python-versions >= 0.20.0 + check-python-versions >= 0.24.2 wheel commands_pre = commands = check-manifest - check-python-versions --only setup.py,tox.ini,.github/workflows/tests.yml + check-python-versions --only pyproject.toml,setup.py,tox.ini,.github/workflows/tests.yml python -m build --sdist --no-isolation twine check dist/* @@ -108,7 +105,6 @@ deps = datetime: DateTime -cconstraints.txt pytest-cov - Sphinx setenv = COVERAGE_FILE=.coverage commands =