From 4b59ba259fd3a11357814e05a7691f5cd76b1b56 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Thu, 11 Jul 2024 13:29:47 -0400 Subject: [PATCH 01/24] build: bump version --- CHANGES.rst | 6 ++++++ coverage/version.py | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 13e3c1eb9..ff40f698c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -20,6 +20,12 @@ upgrading your version of coverage.py. .. Version 9.8.1 — 2027-07-27 .. -------------------------- +Unreleased +---------- + +Nothing yet. + + .. scriv-start-here .. _changes_7-6-0: diff --git a/coverage/version.py b/coverage/version.py index f1f2993ba..9ce5e35a7 100644 --- a/coverage/version.py +++ b/coverage/version.py @@ -8,8 +8,8 @@ # version_info: same semantics as sys.version_info. # _dev: the .devN suffix if any. -version_info = (7, 6, 0, "final", 0) -_dev = 0 +version_info = (7, 6, 1, "alpha", 0) +_dev = 1 def _make_version( From 4fbdf3fc2a94e4e5c561906a8f5a02107a989141 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 13 Jul 2024 19:11:42 -0400 Subject: [PATCH 02/24] chore: bump github/codeql-action from 3.25.11 to 3.25.12 (#1815) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.11 to 3.25.12. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/b611370bb5703a7efb587f9d136a52ea24c5c38c...4fa2a7953630fd2f3fb380f21be14ede0169dd4f) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 0934c2528..f699d6917 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -49,7 +49,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3 + uses: github/codeql-action/init@4fa2a7953630fd2f3fb380f21be14ede0169dd4f # v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -60,7 +60,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3 + uses: github/codeql-action/autobuild@4fa2a7953630fd2f3fb380f21be14ede0169dd4f # v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -74,4 +74,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3 + uses: github/codeql-action/analyze@4fa2a7953630fd2f3fb380f21be14ede0169dd4f # v3 From 45cde52c1f5ea1aa1a9cdaee5725b3719cdda09d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 13 Jul 2024 19:25:52 -0400 Subject: [PATCH 03/24] chore: bump actions/dependency-review-action from 4.3.3 to 4.3.4 (#1816) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.3.3 to 4.3.4. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/72eb03d02c7872a771aacd928f3123ac62ad6d3a...5a2ce3f5b92ee19cbb1541a4984c76d921601d7c) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 912e215f5..c578fafec 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -26,7 +26,7 @@ jobs: uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: 'Dependency Review' - uses: actions/dependency-review-action@72eb03d02c7872a771aacd928f3123ac62ad6d3a # v4.3.3 + uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4 with: base-ref: ${{ github.event.pull_request.base.sha || 'master' }} head-ref: ${{ github.event.pull_request.head.sha || github.ref }} From 8381e42c3f57ac5f4fd60b53242cc93c4f4e0675 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jul 2024 13:05:24 -0400 Subject: [PATCH 04/24] chore: bump sigstore/gh-action-sigstore-python from 2.1.1 to 3.0.0 (#1818) Bumps [sigstore/gh-action-sigstore-python](https://github.com/sigstore/gh-action-sigstore-python) from 2.1.1 to 3.0.0. - [Release notes](https://github.com/sigstore/gh-action-sigstore-python/releases) - [Changelog](https://github.com/sigstore/gh-action-sigstore-python/blob/main/CHANGELOG.md) - [Commits](https://github.com/sigstore/gh-action-sigstore-python/compare/61f6a500bbfdd9a2a339cf033e5421951fbc1cd2...f514d46b907ebcd5bedc05145c03b69c1edd8b46) --- updated-dependencies: - dependency-name: sigstore/gh-action-sigstore-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/kit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/kit.yml b/.github/workflows/kit.yml index a54bdbc01..19254c328 100644 --- a/.github/workflows/kit.yml +++ b/.github/workflows/kit.yml @@ -286,7 +286,7 @@ jobs: merge-multiple: true - name: "Sign artifacts" - uses: sigstore/gh-action-sigstore-python@61f6a500bbfdd9a2a339cf033e5421951fbc1cd2 # v2.1.1 + uses: sigstore/gh-action-sigstore-python@f514d46b907ebcd5bedc05145c03b69c1edd8b46 # v3.0.0 with: inputs: coverage-*.* From 1da3ee126d829d399b1e4fde908c09c79dd639c4 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Thu, 18 Jul 2024 13:12:27 -0400 Subject: [PATCH 05/24] build: configure dependabot to make grouped pr's once a week --- .github/dependabot.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3408e4455..c6841b18a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,7 +7,11 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: - # Check for updates to GitHub Actions every weekday - interval: "daily" + # Check for updates to GitHub Actions once a week + interval: "weekly" + groups: + action-dependencies: + patterns: + - "*" commit-message: prefix: "chore" From 7fb846e8c12b33f9f82964bbb1cef7cc2795d42d Mon Sep 17 00:00:00 2001 From: Ask Hjorth Larsen Date: Fri, 19 Jul 2024 19:14:28 +0200 Subject: [PATCH 06/24] fix: runpy.run_path(path) crashes with pathlib.Path (#1819) * fix: runpy.run_path(path) crashes with pathlib.Path * Revert "fix: runpy.run_path(path) crashes with pathlib.Path" This reverts commit 2d1eabda2710415aa02166529238e7ce6257678c. * fix: runpy.run_path(path) crashes with pathlib.Path * test: runpy.run_path(path) with being pathlib.Path * finish up #1819 * test both str and Path --------- Co-authored-by: Ned Batchelder --- CHANGES.rst | 6 +++++- CONTRIBUTORS.txt | 1 + coverage/inorout.py | 3 ++- tests/test_python.py | 21 +++++++++++++++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index ff40f698c..139d4d5ab 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -23,7 +23,11 @@ upgrading your version of coverage.py. Unreleased ---------- -Nothing yet. +- Fix: coverage used to fail when measuring code using :func:`runpy.run_path + ` with a :class:`Path ` argument. + This is now fixed, thanks to `Ask Hjorth Larsen `_. + +.. _pull 1819: https://github.com/nedbat/coveragepy/pull/1819/files .. scriv-start-here diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 728f2fb1d..e44920ce2 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -25,6 +25,7 @@ Artem Dayneko Arthur Deygin Arthur Rio Asher Foa +Ask Hjorth Larsen Ben Carlsson Ben Finney Benjamin Parzella diff --git a/coverage/inorout.py b/coverage/inorout.py index 5ea29edf1..4df54b2b4 100644 --- a/coverage/inorout.py +++ b/coverage/inorout.py @@ -321,7 +321,8 @@ def nope(disp: TFileDisposition, reason: str) -> TFileDisposition: # co_filename value. dunder_file = frame.f_globals and frame.f_globals.get("__file__") if dunder_file: - filename = source_for_file(dunder_file) + # Danger: __file__ can (rarely?) be of type Path. + filename = source_for_file(str(dunder_file)) if original_filename and not original_filename.startswith("<"): orig = os.path.basename(original_filename) if orig != os.path.basename(filename): diff --git a/tests/test_python.py b/tests/test_python.py index ee0268ffc..6a8362919 100644 --- a/tests/test_python.py +++ b/tests/test_python.py @@ -63,3 +63,24 @@ def test_source_for_file_windows(tmp_path: pathlib.Path) -> None: # If both pyw and py exist, py is preferred a_py.write_text("") assert source_for_file(src + 'c') == src + + +class RunpyTest(CoverageTest): + """Tests using runpy.""" + + @pytest.mark.parametrize("convert_to", ["str", "Path"]) + def test_runpy_path(self, convert_to: str) -> None: + # Ensure runpy.run_path(path) works when path is pathlib.Path or str. + # + # runpy.run_path(pathlib.Path(...)) causes __file__ to be a Path, + # which may make source_for_file() stumble (#1819) with: + # + # AttributeError: 'PosixPath' object has no attribute 'endswith' + + self.check_coverage(f"""\ + import runpy + from pathlib import Path + pyfile = Path('script.py') + pyfile.write_text('') + runpy.run_path({convert_to}(pyfile)) + """) From 35d1fbe623f52ac732f7038cd270329408e86ae4 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sat, 20 Jul 2024 07:46:22 -0400 Subject: [PATCH 07/24] chore: make upgrade --- requirements/dev.pip | 36 +++++++++++++++++----------------- requirements/kit.pip | 16 +++++++-------- requirements/light-threads.pip | 2 +- requirements/mypy.pip | 8 ++++---- requirements/pip-tools.pip | 6 +++--- requirements/pip.pip | 6 +++--- requirements/pytest.pip | 4 ++-- requirements/tox.pip | 8 ++++---- 8 files changed, 43 insertions(+), 43 deletions(-) diff --git a/requirements/dev.pip b/requirements/dev.pip index 2f4634e77..4f6523db3 100644 --- a/requirements/dev.pip +++ b/requirements/dev.pip @@ -4,7 +4,7 @@ # # make upgrade # -astroid==3.2.2 +astroid==3.2.3 # via pylint attrs==23.2.0 # via hypothesis @@ -12,9 +12,9 @@ backports-tarfile==1.2.0 # via jaraco-context build==1.2.1 # via check-manifest -cachetools==5.3.3 +cachetools==5.4.0 # via tox -certifi==2024.6.2 +certifi==2024.7.4 # via requests chardet==5.2.0 # via tox @@ -35,13 +35,13 @@ distlib==0.3.8 # via virtualenv docutils==0.20.1 # via readme-renderer -exceptiongroup==1.2.1 +exceptiongroup==1.2.2 # via # hypothesis # pytest execnet==2.1.1 # via pytest-xdist -filelock==3.15.3 +filelock==3.15.4 # via # tox # virtualenv @@ -49,11 +49,11 @@ flaky==3.8.1 # via -r requirements/pytest.in greenlet==3.0.3 # via -r requirements/dev.in -hypothesis==6.103.2 +hypothesis==6.108.2 # via -r requirements/pytest.in idna==3.7 # via requests -importlib-metadata==7.2.0 +importlib-metadata==8.0.0 # via # build # keyring @@ -86,7 +86,7 @@ more-itertools==10.3.0 # via # jaraco-classes # jaraco-functools -nh3==0.2.17 +nh3==0.2.18 # via readme-renderer packaging==24.1 # via @@ -97,7 +97,7 @@ packaging==24.1 # tox parso==0.8.4 # via jedi -pkginfo==1.11.1 +pkginfo==1.10.0 # via twine platformdirs==4.2.2 # via @@ -108,7 +108,7 @@ pluggy==1.5.0 # via # pytest # tox -pudb==2024.1 +pudb==2024.1.1 # via -r requirements/dev.in pygments==2.18.0 # via @@ -116,7 +116,7 @@ pygments==2.18.0 # pudb # readme-renderer # rich -pylint==3.2.3 +pylint==3.2.5 # via -r requirements/dev.in pyproject-api==1.7.1 # via tox @@ -155,15 +155,15 @@ tomli==2.0.1 # pyproject-api # pytest # tox -tomlkit==0.12.5 +tomlkit==0.13.0 # via pylint -tox==4.15.1 +tox==4.16.0 # via # -r requirements/tox.in # tox-gh -tox-gh==1.3.1 +tox-gh==1.3.2 # via -r requirements/tox.in -twine==5.1.0 +twine==5.1.1 # via -r requirements/dev.in typing-extensions==4.12.2 # via @@ -175,7 +175,7 @@ urllib3==2.2.2 # via # requests # twine -urwid==2.6.14 +urwid==2.6.15 # via # pudb # urwid-readline @@ -193,9 +193,9 @@ zipp==3.19.2 # importlib-resources # The following packages are considered to be unsafe in a requirements file: -pip==24.1 +pip==24.1.2 # via -r requirements/pip.in -setuptools==70.1.0 +setuptools==71.0.4 # via # -r requirements/pip.in # check-manifest diff --git a/requirements/kit.pip b/requirements/kit.pip index 076da7a57..75858a982 100644 --- a/requirements/kit.pip +++ b/requirements/kit.pip @@ -14,23 +14,23 @@ bracex==2.4 # via cibuildwheel build==1.2.1 # via -r requirements/kit.in -certifi==2024.6.2 +certifi==2024.7.4 # via # cibuildwheel # requests charset-normalizer==3.3.2 # via requests -cibuildwheel==2.19.1 +cibuildwheel==2.19.2 # via -r requirements/kit.in colorama==0.4.6 # via -r requirements/kit.in docutils==0.20.1 # via readme-renderer -filelock==3.15.3 +filelock==3.15.4 # via cibuildwheel idna==3.7 # via requests -importlib-metadata==7.2.0 +importlib-metadata==8.0.0 # via # build # keyring @@ -53,14 +53,14 @@ more-itertools==10.3.0 # via # jaraco-classes # jaraco-functools -nh3==0.2.17 +nh3==0.2.18 # via readme-renderer packaging==24.1 # via # auditwheel # build # cibuildwheel -pkginfo==1.11.1 +pkginfo==1.10.0 # via twine platformdirs==4.2.2 # via cibuildwheel @@ -88,7 +88,7 @@ tomli==2.0.1 # via # build # cibuildwheel -twine==5.1.0 +twine==5.1.1 # via -r requirements/kit.in typing-extensions==4.12.2 # via @@ -106,5 +106,5 @@ zipp==3.19.2 # importlib-resources # The following packages are considered to be unsafe in a requirements file: -setuptools==70.1.0 +setuptools==71.0.4 # via -r requirements/kit.in diff --git a/requirements/light-threads.pip b/requirements/light-threads.pip index e371af3c6..77cbae290 100644 --- a/requirements/light-threads.pip +++ b/requirements/light-threads.pip @@ -25,7 +25,7 @@ zope-interface==6.4.post2 # via gevent # The following packages are considered to be unsafe in a requirements file: -setuptools==70.1.0 +setuptools==71.0.4 # via # zope-event # zope-interface diff --git a/requirements/mypy.pip b/requirements/mypy.pip index 4d6477309..6e804c9df 100644 --- a/requirements/mypy.pip +++ b/requirements/mypy.pip @@ -8,7 +8,7 @@ attrs==23.2.0 # via hypothesis colorama==0.4.6 # via -r requirements/pytest.in -exceptiongroup==1.2.1 +exceptiongroup==1.2.2 # via # hypothesis # pytest @@ -16,11 +16,11 @@ execnet==2.1.1 # via pytest-xdist flaky==3.8.1 # via -r requirements/pytest.in -hypothesis==6.103.2 +hypothesis==6.108.2 # via -r requirements/pytest.in iniconfig==2.0.0 # via pytest -mypy==1.10.0 +mypy==1.11.0 # via -r requirements/mypy.in mypy-extensions==1.0.0 # via mypy @@ -42,7 +42,7 @@ tomli==2.0.1 # via # mypy # pytest -types-requests==2.32.0.20240622 +types-requests==2.32.0.20240712 # via -r requirements/mypy.in types-tabulate==0.9.0.20240106 # via -r requirements/mypy.in diff --git a/requirements/pip-tools.pip b/requirements/pip-tools.pip index ba853807c..e017048c2 100644 --- a/requirements/pip-tools.pip +++ b/requirements/pip-tools.pip @@ -8,7 +8,7 @@ build==1.2.1 # via pip-tools click==8.1.7 # via pip-tools -importlib-metadata==7.2.0 +importlib-metadata==8.0.0 # via build packaging==24.1 # via build @@ -28,7 +28,7 @@ zipp==3.19.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: -pip==24.1 +pip==24.1.2 # via pip-tools -setuptools==70.1.0 +setuptools==71.0.4 # via pip-tools diff --git a/requirements/pip.pip b/requirements/pip.pip index fe6819374..9ad0ff579 100644 --- a/requirements/pip.pip +++ b/requirements/pip.pip @@ -6,7 +6,7 @@ # distlib==0.3.8 # via virtualenv -filelock==3.15.3 +filelock==3.15.4 # via virtualenv platformdirs==4.2.2 # via virtualenv @@ -14,7 +14,7 @@ virtualenv==20.26.3 # via -r requirements/pip.in # The following packages are considered to be unsafe in a requirements file: -pip==24.1 +pip==24.1.2 # via -r requirements/pip.in -setuptools==70.1.0 +setuptools==71.0.4 # via -r requirements/pip.in diff --git a/requirements/pytest.pip b/requirements/pytest.pip index b2da89ddc..358278fbc 100644 --- a/requirements/pytest.pip +++ b/requirements/pytest.pip @@ -8,7 +8,7 @@ attrs==23.2.0 # via hypothesis colorama==0.4.6 # via -r requirements/pytest.in -exceptiongroup==1.2.1 +exceptiongroup==1.2.2 # via # hypothesis # pytest @@ -16,7 +16,7 @@ execnet==2.1.1 # via pytest-xdist flaky==3.8.1 # via -r requirements/pytest.in -hypothesis==6.103.2 +hypothesis==6.108.2 # via -r requirements/pytest.in iniconfig==2.0.0 # via pytest diff --git a/requirements/tox.pip b/requirements/tox.pip index 80366621a..7bec3da1c 100644 --- a/requirements/tox.pip +++ b/requirements/tox.pip @@ -4,7 +4,7 @@ # # make upgrade # -cachetools==5.3.3 +cachetools==5.4.0 # via tox chardet==5.2.0 # via tox @@ -14,7 +14,7 @@ colorama==0.4.6 # tox distlib==0.3.8 # via virtualenv -filelock==3.15.3 +filelock==3.15.4 # via # tox # virtualenv @@ -34,11 +34,11 @@ tomli==2.0.1 # via # pyproject-api # tox -tox==4.15.1 +tox==4.16.0 # via # -r requirements/tox.in # tox-gh -tox-gh==1.3.1 +tox-gh==1.3.2 # via -r requirements/tox.in virtualenv==20.26.3 # via tox From 694cd6e58934d02b0dfc16e6b8c4d501df6d9c61 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sat, 20 Jul 2024 09:19:15 -0400 Subject: [PATCH 08/24] test: silence some new mypy errors I'm not sure why these are happening with the new mypy, but trying to narrow the type `ast.AST` to `ast.stmt` caused even more problems and I can't be bothered. --- coverage/parser.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/coverage/parser.py b/coverage/parser.py index 19267a718..0f7e353a3 100644 --- a/coverage/parser.py +++ b/coverage/parser.py @@ -678,7 +678,7 @@ class NodeList(ast.AST): """ def __init__(self, body: Sequence[ast.AST]) -> None: self.body = body - self.lineno = body[0].lineno + self.lineno = body[0].lineno # type: ignore[attr-defined] # TODO: Shouldn't the cause messages join with "and" instead of "or"? @@ -824,7 +824,7 @@ def line_for_node(self, node: ast.AST) -> TLineNo: if handler is not None: return handler(node) else: - return node.lineno + return node.lineno # type: ignore[attr-defined, no-any-return] # First lines: _line__* # @@ -1020,10 +1020,10 @@ def _missing__While(self, node: ast.While) -> ast.AST | None: if not body_nodes: return None # Make a synthetic While-true node. - new_while = ast.While() - new_while.lineno = body_nodes.lineno - new_while.test = ast.Name() - new_while.test.lineno = body_nodes.lineno + new_while = ast.While() # type: ignore[call-arg] + new_while.lineno = body_nodes.lineno # type: ignore[attr-defined] + new_while.test = ast.Name() # type: ignore[call-arg] + new_while.test.lineno = body_nodes.lineno # type: ignore[attr-defined] new_while.test.id = "True" assert hasattr(body_nodes, "body") new_while.body = body_nodes.body From 1f08ea1cffbe28840e06720832fc1bd53e147cf6 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sat, 20 Jul 2024 16:01:46 -0400 Subject: [PATCH 09/24] refactor: move core information to its own class and file This simplifies calling into Collector, and will make core information available in more places. --- coverage/cmdline.py | 2 +- coverage/collector.py | 92 ++++++------------------------------------- coverage/control.py | 16 +++++--- coverage/core.py | 90 ++++++++++++++++++++++++++++++++++++++++++ coverage/pytracer.py | 4 +- coverage/sysmon.py | 4 +- coverage/tracer.pyi | 4 +- coverage/types.py | 2 +- 8 files changed, 120 insertions(+), 94 deletions(-) create mode 100644 coverage/core.py diff --git a/coverage/cmdline.py b/coverage/cmdline.py index 9f9c06559..7c01ccbf0 100644 --- a/coverage/cmdline.py +++ b/coverage/cmdline.py @@ -19,9 +19,9 @@ import coverage from coverage import Coverage from coverage import env -from coverage.collector import HAS_CTRACER from coverage.config import CoverageConfig from coverage.control import DEFAULT_DATAFILE +from coverage.core import HAS_CTRACER from coverage.data import combinable_files, debug_data_file from coverage.debug import info_header, short_stack, write_formatted_info from coverage.exceptions import _BaseCoverageException, _ExceptionDuringRun, NoSource diff --git a/coverage/collector.py b/coverage/collector.py index 93860e43c..1dacae474 100644 --- a/coverage/collector.py +++ b/coverage/collector.py @@ -17,38 +17,19 @@ from coverage import env from coverage.config import CoverageConfig +from coverage.core import Core from coverage.data import CoverageData from coverage.debug import short_stack -from coverage.disposition import FileDisposition from coverage.exceptions import ConfigError from coverage.misc import human_sorted_items, isolate_module from coverage.plugin import CoveragePlugin -from coverage.pytracer import PyTracer -from coverage.sysmon import SysMonitor from coverage.types import ( - TArc, TFileDisposition, TTraceData, TTraceFn, TracerCore, TWarnFn, + TArc, TFileDisposition, TTraceData, TTraceFn, Tracer, TWarnFn, ) os = isolate_module(os) -try: - # Use the C extension code when we can, for speed. - from coverage.tracer import CTracer, CFileDisposition - HAS_CTRACER = True -except ImportError: - # Couldn't import the C extension, maybe it isn't built. - if os.getenv("COVERAGE_CORE") == "ctrace": # pragma: part covered - # During testing, we use the COVERAGE_CORE environment variable - # to indicate that we've fiddled with the environment to test this - # fallback code. If we thought we had a C tracer, but couldn't import - # it, then exit quickly and clearly instead of dribbling confusing - # errors. I'm using sys.exit here instead of an exception because an - # exception here causes all sorts of other noise in unittest. - sys.stderr.write("*** COVERAGE_CORE is 'ctrace' but can't import CTracer!\n") - sys.exit(1) - HAS_CTRACER = False - T = TypeVar("T") @@ -78,15 +59,14 @@ class Collector: def __init__( self, + core: Core, should_trace: Callable[[str, FrameType], TFileDisposition], check_include: Callable[[str, FrameType], bool], should_start_context: Callable[[FrameType], str | None] | None, file_mapper: Callable[[str], str], - timid: bool, branch: bool, warn: TWarnFn, concurrency: list[str], - metacov: bool, ) -> None: """Create a collector. @@ -105,11 +85,6 @@ def __init__( filename. The result is the name that will be recorded in the data file. - If `timid` is true, then a slower simpler trace function will be - used. This is important for some environments where manipulation of - tracing functions make the faster more sophisticated trace function not - operate properly. - If `branch` is true, then branches will be measured. This involves collecting data on which statements followed each other (arcs). Use `get_arc_data` to get the arc data. @@ -124,6 +99,7 @@ def __init__( Other values are ignored. """ + self.core = core self.should_trace = should_trace self.check_include = check_include self.should_start_context = should_start_context @@ -143,52 +119,6 @@ def __init__( self.concur_id_func = None - self._trace_class: type[TracerCore] - self.file_disposition_class: type[TFileDisposition] - - core: str | None - if timid: - core = "pytrace" - else: - core = os.getenv("COVERAGE_CORE") - - if core == "sysmon" and not env.PYBEHAVIOR.pep669: - self.warn("sys.monitoring isn't available, using default core", slug="no-sysmon") - core = None - - if not core: - # Once we're comfortable with sysmon as a default: - # if env.PYBEHAVIOR.pep669 and self.should_start_context is None: - # core = "sysmon" - if HAS_CTRACER: - core = "ctrace" - else: - core = "pytrace" - - if core == "sysmon": - self._trace_class = SysMonitor - self._core_kwargs = {"tool_id": 3 if metacov else 1} - self.file_disposition_class = FileDisposition - self.supports_plugins = False - self.packed_arcs = False - self.systrace = False - elif core == "ctrace": - self._trace_class = CTracer - self._core_kwargs = {} - self.file_disposition_class = CFileDisposition - self.supports_plugins = True - self.packed_arcs = True - self.systrace = True - elif core == "pytrace": - self._trace_class = PyTracer - self._core_kwargs = {} - self.file_disposition_class = FileDisposition - self.supports_plugins = False - self.packed_arcs = False - self.systrace = True - else: - raise ConfigError(f"Unknown core value: {core!r}") - # We can handle a few concurrency options here, but only one at a time. concurrencies = set(self.concurrency) unknown = concurrencies - CoverageConfig.CONCURRENCY_CHOICES @@ -222,7 +152,7 @@ def __init__( msg = f"Couldn't trace with concurrency={tried}, the module isn't installed." raise ConfigError(msg) from ex - if self.concur_id_func and not hasattr(self._trace_class, "concur_id_func"): + if self.concur_id_func and not hasattr(core.tracer_class, "concur_id_func"): raise ConfigError( "Can't support concurrency={} with {}, only threads are supported.".format( tried, self.tracer_name(), @@ -249,7 +179,7 @@ def use_data(self, covdata: CoverageData, context: str | None) -> None: def tracer_name(self) -> str: """Return the class name of the tracer we're using.""" - return self._trace_class.__name__ + return self.core.tracer_class.__name__ def _clear_data(self) -> None: """Clear out existing data, but stay ready for more collection.""" @@ -305,7 +235,7 @@ def reset(self) -> None: self.should_trace_cache = {} # Our active Tracers. - self.tracers: list[TracerCore] = [] + self.tracers: list[Tracer] = [] self._clear_data() @@ -321,7 +251,7 @@ def unlock_data(self) -> None: def _start_tracer(self) -> TTraceFn | None: """Start a new Tracer object, and store it in self.tracers.""" - tracer = self._trace_class(**self._core_kwargs) + tracer = self.core.tracer_class(**self.core.tracer_kwargs) tracer.data = self.data tracer.lock_data = self.lock_data tracer.unlock_data = self.unlock_data @@ -403,7 +333,7 @@ def start(self) -> None: # Install our installation tracer in threading, to jump-start other # threads. - if self.systrace and self.threading: + if self.core.systrace and self.threading: self.threading.settrace(self._installation_trace) def stop(self) -> None: @@ -440,7 +370,7 @@ def resume(self) -> None: """Resume tracing after a `pause`.""" for tracer in self.tracers: tracer.start() - if self.systrace: + if self.core.systrace: if self.threading: self.threading.settrace(self._installation_trace) else: @@ -523,7 +453,7 @@ def flush_data(self) -> bool: return False if self.branch: - if self.packed_arcs: + if self.core.packed_arcs: # Unpack the line number pairs packed into integers. See # tracer.c:CTracer_record_pair for the C code that creates # these packed ints. diff --git a/coverage/control.py b/coverage/control.py index 583fed946..ca757e9e1 100644 --- a/coverage/control.py +++ b/coverage/control.py @@ -26,9 +26,10 @@ from coverage import env from coverage.annotate import AnnotateReporter -from coverage.collector import Collector, HAS_CTRACER +from coverage.collector import Collector from coverage.config import CoverageConfig, read_coverage_config from coverage.context import should_start_context_test_function, combine_context_switchers +from coverage.core import Core, HAS_CTRACER from coverage.data import CoverageData, combine_parallel_data from coverage.debug import ( DebugControl, NoDebugging, short_stack, write_formatted_info, relevant_environment_display, @@ -262,6 +263,7 @@ def __init__( # pylint: disable=too-many-arguments self._inorout: InOrOut | None = None self._plugins: Plugins = Plugins() self._data: CoverageData | None = None + self._core: Core | None = None self._collector: Collector | None = None self._metacov = False @@ -532,16 +534,20 @@ def _init_for_start(self) -> None: should_start_context = combine_context_switchers(context_switchers) + self._core = Core( + warn=self._warn, + timid=self.config.timid, + metacov=self._metacov, + ) self._collector = Collector( + core=self._core, should_trace=self._should_trace, check_include=self._check_include_omit_etc, should_start_context=should_start_context, file_mapper=self._file_mapper, - timid=self.config.timid, branch=self.config.branch, warn=self._warn, concurrency=concurrency, - metacov=self._metacov, ) suffix = self._data_suffix_specified @@ -563,7 +569,7 @@ def _init_for_start(self) -> None: self._collector.use_data(self._data, self.config.context) # Early warning if we aren't going to be able to support plugins. - if self._plugins.file_tracers and not self._collector.supports_plugins: + if self._plugins.file_tracers and not self._core.supports_plugins: self._warn( "Plugin file tracers ({}) aren't supported with {}".format( ", ".join( @@ -584,7 +590,7 @@ def _init_for_start(self) -> None: include_namespace_packages=self.config.include_namespace_packages, ) self._inorout.plugins = self._plugins - self._inorout.disp_class = self._collector.file_disposition_class + self._inorout.disp_class = self._core.file_disposition_class # It's useful to write debug info after initing for start. self._should_write_debug = True diff --git a/coverage/core.py b/coverage/core.py new file mode 100644 index 000000000..89e49c49b --- /dev/null +++ b/coverage/core.py @@ -0,0 +1,90 @@ +# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 +# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt + +"""Management of core choices.""" + +from __future__ import annotations + +import os +import sys +from typing import Any + +from coverage import env +from coverage.disposition import FileDisposition +from coverage.exceptions import ConfigError +from coverage.pytracer import PyTracer +from coverage.sysmon import SysMonitor +from coverage.types import TFileDisposition, Tracer, TWarnFn + + +try: + # Use the C extension code when we can, for speed. + from coverage.tracer import CTracer, CFileDisposition + HAS_CTRACER = True +except ImportError: + # Couldn't import the C extension, maybe it isn't built. + if os.getenv("COVERAGE_CORE") == "ctrace": # pragma: part covered + # During testing, we use the COVERAGE_CORE environment variable + # to indicate that we've fiddled with the environment to test this + # fallback code. If we thought we had a C tracer, but couldn't import + # it, then exit quickly and clearly instead of dribbling confusing + # errors. I'm using sys.exit here instead of an exception because an + # exception here causes all sorts of other noise in unittest. + sys.stderr.write("*** COVERAGE_CORE is 'ctrace' but can't import CTracer!\n") + sys.exit(1) + HAS_CTRACER = False + + +class Core: + """Information about the central technology enabling execution measurement.""" + + tracer_class: type[Tracer] + tracer_kwargs: dict[str, Any] + file_disposition_class: type[TFileDisposition] + supports_plugins: bool + packed_arcs: bool + systrace: bool + + def __init__(self, warn: TWarnFn, timid: bool, metacov: bool) -> None: + core_name: str | None + if timid: + core_name = "pytrace" + else: + core_name = os.getenv("COVERAGE_CORE") + + if core_name == "sysmon" and not env.PYBEHAVIOR.pep669: + warn("sys.monitoring isn't available, using default core", slug="no-sysmon") + core_name = None + + if not core_name: + # Once we're comfortable with sysmon as a default: + # if env.PYBEHAVIOR.pep669 and self.should_start_context is None: + # core_name = "sysmon" + if HAS_CTRACER: + core_name = "ctrace" + else: + core_name = "pytrace" + + if core_name == "sysmon": + self.tracer_class = SysMonitor + self.tracer_kwargs = {"tool_id": 3 if metacov else 1} + self.file_disposition_class = FileDisposition + self.supports_plugins = False + self.packed_arcs = False + self.systrace = False + elif core_name == "ctrace": + self.tracer_class = CTracer + self.tracer_kwargs = {} + self.file_disposition_class = CFileDisposition + self.supports_plugins = True + self.packed_arcs = True + self.systrace = True + elif core_name == "pytrace": + self.tracer_class = PyTracer + self.tracer_kwargs = {} + self.file_disposition_class = FileDisposition + self.supports_plugins = False + self.packed_arcs = False + self.systrace = True + else: + raise ConfigError(f"Unknown core value: {core_name!r}") diff --git a/coverage/pytracer.py b/coverage/pytracer.py index 00cacea15..339df60bb 100644 --- a/coverage/pytracer.py +++ b/coverage/pytracer.py @@ -17,7 +17,7 @@ from coverage import env from coverage.types import ( TArc, TFileDisposition, TLineNo, TTraceData, TTraceFileData, TTraceFn, - TracerCore, TWarnFn, + Tracer, TWarnFn, ) # We need the YIELD_VALUE opcode below, in a comparison-friendly form. @@ -36,7 +36,7 @@ THIS_FILE = __file__.rstrip("co") -class PyTracer(TracerCore): +class PyTracer(Tracer): """Python implementation of the raw data tracer.""" # Because of poor implementations of trace-function-manipulating tools, diff --git a/coverage/sysmon.py b/coverage/sysmon.py index 0c9e795c6..c113c20e7 100644 --- a/coverage/sysmon.py +++ b/coverage/sysmon.py @@ -31,7 +31,7 @@ TLineNo, TTraceData, TTraceFileData, - TracerCore, + Tracer, TWarnFn, ) @@ -171,7 +171,7 @@ def bytes_to_lines(code: CodeType) -> dict[int, int]: return b2l -class SysMonitor(TracerCore): +class SysMonitor(Tracer): """Python implementation of the raw data tracer for PEP669 implementations.""" # One of these will be used across threads. Be careful. diff --git a/coverage/tracer.pyi b/coverage/tracer.pyi index 58dd69f94..d850493ed 100644 --- a/coverage/tracer.pyi +++ b/coverage/tracer.pyi @@ -5,7 +5,7 @@ from typing import Any, Dict -from coverage.types import TFileDisposition, TTraceData, TTraceFn, TracerCore +from coverage.types import TFileDisposition, TTraceData, TTraceFn, Tracer class CFileDisposition(TFileDisposition): """CFileDisposition is in ctracer/filedisp.c""" @@ -18,7 +18,7 @@ class CFileDisposition(TFileDisposition): trace: Any def __init__(self) -> None: ... -class CTracer(TracerCore): +class CTracer(Tracer): """CTracer is in ctracer/tracer.c""" check_include: Any concur_id_func: Any diff --git a/coverage/types.py b/coverage/types.py index ff5c59cda..a219b022b 100644 --- a/coverage/types.py +++ b/coverage/types.py @@ -78,7 +78,7 @@ class TFileDisposition(Protocol): TTraceData = Dict[str, TTraceFileData] -class TracerCore(Protocol): +class Tracer(Protocol): """Anything that can report on Python execution.""" data: TTraceData From f5951d8257bcd0d1c51229ce5277e7fd691b22a9 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sat, 20 Jul 2024 16:29:15 -0400 Subject: [PATCH 10/24] docs: the illustrator would prefer to be anonymous --- doc/sleepy.rst | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/doc/sleepy.rst b/doc/sleepy.rst index ceee6f392..2bb6b8d6b 100644 --- a/doc/sleepy.rst +++ b/doc/sleepy.rst @@ -7,15 +7,10 @@ Sleepy Snake ============ -Coverage.py's mascot is Sleepy Snake, drawn by Ben Batchelder. Ben's art can -be found on `Instagram`_ and at `artofbatch.com`_. Some details of Sleepy's +Coverage.py's mascot is Sleepy Snake. Some details of Sleepy's creation are on `Ned's blog`__. __ https://nedbatchelder.com/blog/201912/sleepy_snake.html .. image:: media/sleepy-snake-600.png :alt: Sleepy Snake, cozy in his snake-shaped bed. - - -.. _Instagram: https://instagram.com/artofbatch -.. _artofbatch.com: https://artofbatch.com From c2f35887ef58da7efda30edaf949a138e2205d76 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sat, 20 Jul 2024 17:40:00 -0400 Subject: [PATCH 11/24] refactor: convenient names for oft-mentioned function arguments --- coverage/collector.py | 16 ++++++++++++---- coverage/context.py | 8 +++++--- coverage/pytracer.py | 16 ++++++++++++---- coverage/sysmon.py | 6 ++++-- coverage/types.py | 9 +++++++-- 5 files changed, 40 insertions(+), 15 deletions(-) diff --git a/coverage/collector.py b/coverage/collector.py index 1dacae474..470d3a7e3 100644 --- a/coverage/collector.py +++ b/coverage/collector.py @@ -24,7 +24,15 @@ from coverage.misc import human_sorted_items, isolate_module from coverage.plugin import CoveragePlugin from coverage.types import ( - TArc, TFileDisposition, TTraceData, TTraceFn, Tracer, TWarnFn, + TArc, + TCheckIncludeFn, + TFileDisposition, + TShouldStartContextFn, + TShouldTraceFn, + TTraceData, + TTraceFn, + Tracer, + TWarnFn, ) os = isolate_module(os) @@ -60,9 +68,9 @@ class Collector: def __init__( self, core: Core, - should_trace: Callable[[str, FrameType], TFileDisposition], - check_include: Callable[[str, FrameType], bool], - should_start_context: Callable[[FrameType], str | None] | None, + should_trace: TShouldTraceFn, + check_include: TCheckIncludeFn, + should_start_context: TShouldStartContextFn | None, file_mapper: Callable[[str], str], branch: bool, warn: TWarnFn, diff --git a/coverage/context.py b/coverage/context.py index c8ee71271..630d3d25a 100644 --- a/coverage/context.py +++ b/coverage/context.py @@ -6,12 +6,14 @@ from __future__ import annotations from types import FrameType -from typing import cast, Callable, Sequence +from typing import cast, Sequence + +from coverage.types import TShouldStartContextFn def combine_context_switchers( - context_switchers: Sequence[Callable[[FrameType], str | None]], -) -> Callable[[FrameType], str | None] | None: + context_switchers: Sequence[TShouldStartContextFn], +) -> TShouldStartContextFn | None: """Create a single context switcher from multiple switchers. `context_switchers` is a list of functions that take a frame as an diff --git a/coverage/pytracer.py b/coverage/pytracer.py index 339df60bb..8144e6566 100644 --- a/coverage/pytracer.py +++ b/coverage/pytracer.py @@ -16,8 +16,16 @@ from coverage import env from coverage.types import ( - TArc, TFileDisposition, TLineNo, TTraceData, TTraceFileData, TTraceFn, - Tracer, TWarnFn, + TArc, + TFileDisposition, + TLineNo, + TShouldStartContextFn, + TShouldTraceFn, + TTraceData, + TTraceFileData, + TTraceFn, + TWarnFn, + Tracer, ) # We need the YIELD_VALUE opcode below, in a comparison-friendly form. @@ -64,9 +72,9 @@ def __init__(self) -> None: # Attributes set from the collector: self.data: TTraceData self.trace_arcs = False - self.should_trace: Callable[[str, FrameType], TFileDisposition] + self.should_trace: TShouldTraceFn self.should_trace_cache: dict[str, TFileDisposition | None] - self.should_start_context: Callable[[FrameType], str | None] | None = None + self.should_start_context: TShouldStartContextFn | None = None self.switch_context: Callable[[str | None], None] | None = None self.lock_data: Callable[[], None] self.unlock_data: Callable[[], None] diff --git a/coverage/sysmon.py b/coverage/sysmon.py index c113c20e7..ef54292f3 100644 --- a/coverage/sysmon.py +++ b/coverage/sysmon.py @@ -29,6 +29,8 @@ TArc, TFileDisposition, TLineNo, + TShouldStartContextFn, + TShouldTraceFn, TTraceData, TTraceFileData, Tracer, @@ -180,11 +182,11 @@ def __init__(self, tool_id: int) -> None: # Attributes set from the collector: self.data: TTraceData self.trace_arcs = False - self.should_trace: Callable[[str, FrameType], TFileDisposition] + self.should_trace: TShouldTraceFn self.should_trace_cache: dict[str, TFileDisposition | None] # TODO: should_start_context and switch_context are unused! # Change tests/testenv.py:DYN_CONTEXTS when this is updated. - self.should_start_context: Callable[[FrameType], str | None] | None = None + self.should_start_context: TShouldStartContextFn | None = None self.switch_context: Callable[[str | None], None] | None = None self.lock_data: Callable[[], None] self.unlock_data: Callable[[], None] diff --git a/coverage/types.py b/coverage/types.py index a219b022b..bfd2a4d15 100644 --- a/coverage/types.py +++ b/coverage/types.py @@ -78,14 +78,19 @@ class TFileDisposition(Protocol): TTraceData = Dict[str, TTraceFileData] +# Functions passed into collectors. +TShouldTraceFn = Callable[[str, FrameType], TFileDisposition] +TCheckIncludeFn = Callable[[str, FrameType], bool] +TShouldStartContextFn = Callable[[FrameType], Union[str, None]] + class Tracer(Protocol): """Anything that can report on Python execution.""" data: TTraceData trace_arcs: bool - should_trace: Callable[[str, FrameType], TFileDisposition] + should_trace: TShouldTraceFn should_trace_cache: Mapping[str, TFileDisposition | None] - should_start_context: Callable[[FrameType], str | None] | None + should_start_context: TShouldStartContextFn | None switch_context: Callable[[str | None], None] | None lock_data: Callable[[], None] unlock_data: Callable[[], None] From fb0ba11ceba59473ff965312d2129094c9f70b83 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Mon, 22 Jul 2024 12:53:11 +0200 Subject: [PATCH 12/24] docs: update link to Django plugin. (#1821) The docs were pointing to an outdated projected (not updated) since 2013. Change to the active plugin project. --- doc/other.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/other.rst b/doc/other.rst index d0998b37f..8c8f71003 100644 --- a/doc/other.rst +++ b/doc/other.rst @@ -53,9 +53,9 @@ Language plugins Coverage.py plugins to enable coverage measurement of other languages. -* `django-coverage`__ measures the coverage of Django templates. +* `django-coverage-plugin`__ measures the coverage of Django templates. - __ https://pypi.org/project/django-coverage/ + __ https://pypi.org/project/django-coverage-plugin/ * `Cython`__ provides a plugin for measuring Cythonized code. From 9d0eb0237359978b3a650f9da444e7f3ae7233e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 08:24:36 -0400 Subject: [PATCH 13/24] chore: bump the action-dependencies group with 2 updates (#1822) Bumps the action-dependencies group with 2 updates: [github/codeql-action](https://github.com/github/codeql-action) and [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action). Updates `github/codeql-action` from 3.25.12 to 3.25.13 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/4fa2a7953630fd2f3fb380f21be14ede0169dd4f...2d790406f505036ef40ecba973cc774a50395aac) Updates `docker/setup-qemu-action` from 3.1.0 to 3.2.0 - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/5927c834f5b4fdf503fca6f4c7eccda82949e1ee...49b3bc8e6bdd4a60e6116a5414239cba5943d3cf) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch dependency-group: action-dependencies - dependency-name: docker/setup-qemu-action dependency-type: direct:production update-type: version-update:semver-minor dependency-group: action-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/kit.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index f699d6917..fbb600a5d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -49,7 +49,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@4fa2a7953630fd2f3fb380f21be14ede0169dd4f # v3 + uses: github/codeql-action/init@2d790406f505036ef40ecba973cc774a50395aac # v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -60,7 +60,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@4fa2a7953630fd2f3fb380f21be14ede0169dd4f # v3 + uses: github/codeql-action/autobuild@2d790406f505036ef40ecba973cc774a50395aac # v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -74,4 +74,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@4fa2a7953630fd2f3fb380f21be14ede0169dd4f # v3 + uses: github/codeql-action/analyze@2d790406f505036ef40ecba973cc774a50395aac # v3 diff --git a/.github/workflows/kit.yml b/.github/workflows/kit.yml index 19254c328..7962b42a3 100644 --- a/.github/workflows/kit.yml +++ b/.github/workflows/kit.yml @@ -143,7 +143,7 @@ jobs: steps: - name: "Setup QEMU" if: matrix.os == 'ubuntu' - uses: docker/setup-qemu-action@5927c834f5b4fdf503fca6f4c7eccda82949e1ee # v3.1.0 + uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 with: platforms: arm64 From 2a7d9779add1e8fa3425a784347316f5d28a510d Mon Sep 17 00:00:00 2001 From: devdanzin <74280297+devdanzin@users.noreply.github.com> Date: Sun, 28 Jul 2024 12:30:19 -0300 Subject: [PATCH 14/24] build: remove usage of distutils in setup.py. (#1823) --- setup.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/setup.py b/setup.py index cc5f7ed1a..4ce5d34f0 100644 --- a/setup.py +++ b/setup.py @@ -3,17 +3,14 @@ """Code coverage measurement for Python""" -# Distutils setup for coverage.py +# Setuptools setup for coverage.py # This file is used unchanged under all versions of Python. import os import sys -# Setuptools has to be imported before distutils, or things break. -from setuptools import setup -from distutils.core import Extension # pylint: disable=wrong-import-order +from setuptools import Extension, errors, setup from setuptools.command.build_ext import build_ext # pylint: disable=wrong-import-order -from distutils import errors # pylint: disable=wrong-import-order # Get or massage our metadata. We exec coverage/version.py so we can avoid # importing the product code into setup.py. @@ -131,12 +128,11 @@ ext_errors = ( errors.CCompilerError, - errors.DistutilsExecError, - errors.DistutilsPlatformError, + errors.ExecError, + errors.PlatformError, ) if sys.platform == "win32": - # distutils.msvc9compiler can raise an IOError when failing to - # find the compiler + # IOError can be raised when failing to find the compiler ext_errors += (IOError,) @@ -155,7 +151,7 @@ def run(self): """Wrap `run` with `BuildFailed`.""" try: build_ext.run(self) - except errors.DistutilsPlatformError as exc: + except errors.PlatformError as exc: raise BuildFailed() from exc def build_extension(self, ext): From 9c5027077e478d0996639445ea1e2554edaf3295 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Fri, 2 Aug 2024 06:32:26 -0400 Subject: [PATCH 15/24] chore: make upgrade --- requirements/dev.pip | 18 +++++++++--------- requirements/kit.pip | 6 +++--- requirements/light-threads.pip | 2 +- requirements/mypy.pip | 6 +++--- requirements/pip-tools.pip | 6 +++--- requirements/pip.pip | 4 ++-- requirements/pytest.pip | 4 ++-- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/requirements/dev.pip b/requirements/dev.pip index 4f6523db3..f32af6dfc 100644 --- a/requirements/dev.pip +++ b/requirements/dev.pip @@ -4,7 +4,7 @@ # # make upgrade # -astroid==3.2.3 +astroid==3.2.4 # via pylint attrs==23.2.0 # via hypothesis @@ -49,11 +49,11 @@ flaky==3.8.1 # via -r requirements/pytest.in greenlet==3.0.3 # via -r requirements/dev.in -hypothesis==6.108.2 +hypothesis==6.108.5 # via -r requirements/pytest.in idna==3.7 # via requests -importlib-metadata==8.0.0 +importlib-metadata==8.2.0 # via # build # keyring @@ -68,7 +68,7 @@ jaraco-classes==3.4.0 # via keyring jaraco-context==5.3.0 # via keyring -jaraco-functools==4.0.1 +jaraco-functools==4.0.2 # via keyring jedi==0.19.1 # via pudb @@ -108,7 +108,7 @@ pluggy==1.5.0 # via # pytest # tox -pudb==2024.1.1 +pudb==2024.1.2 # via -r requirements/dev.in pygments==2.18.0 # via @@ -116,13 +116,13 @@ pygments==2.18.0 # pudb # readme-renderer # rich -pylint==3.2.5 +pylint==3.2.6 # via -r requirements/dev.in pyproject-api==1.7.1 # via tox pyproject-hooks==1.1.0 # via build -pytest==8.2.2 +pytest==8.3.2 # via # -r requirements/pytest.in # pytest-xdist @@ -193,9 +193,9 @@ zipp==3.19.2 # importlib-resources # The following packages are considered to be unsafe in a requirements file: -pip==24.1.2 +pip==24.2 # via -r requirements/pip.in -setuptools==71.0.4 +setuptools==72.1.0 # via # -r requirements/pip.in # check-manifest diff --git a/requirements/kit.pip b/requirements/kit.pip index 75858a982..ddbcc90fb 100644 --- a/requirements/kit.pip +++ b/requirements/kit.pip @@ -30,7 +30,7 @@ filelock==3.15.4 # via cibuildwheel idna==3.7 # via requests -importlib-metadata==8.0.0 +importlib-metadata==8.2.0 # via # build # keyring @@ -41,7 +41,7 @@ jaraco-classes==3.4.0 # via keyring jaraco-context==5.3.0 # via keyring -jaraco-functools==4.0.1 +jaraco-functools==4.0.2 # via keyring keyring==25.2.1 # via twine @@ -106,5 +106,5 @@ zipp==3.19.2 # importlib-resources # The following packages are considered to be unsafe in a requirements file: -setuptools==71.0.4 +setuptools==72.1.0 # via -r requirements/kit.in diff --git a/requirements/light-threads.pip b/requirements/light-threads.pip index 77cbae290..68dda2f89 100644 --- a/requirements/light-threads.pip +++ b/requirements/light-threads.pip @@ -25,7 +25,7 @@ zope-interface==6.4.post2 # via gevent # The following packages are considered to be unsafe in a requirements file: -setuptools==71.0.4 +setuptools==72.1.0 # via # zope-event # zope-interface diff --git a/requirements/mypy.pip b/requirements/mypy.pip index 6e804c9df..ff7c5314d 100644 --- a/requirements/mypy.pip +++ b/requirements/mypy.pip @@ -16,11 +16,11 @@ execnet==2.1.1 # via pytest-xdist flaky==3.8.1 # via -r requirements/pytest.in -hypothesis==6.108.2 +hypothesis==6.108.5 # via -r requirements/pytest.in iniconfig==2.0.0 # via pytest -mypy==1.11.0 +mypy==1.11.1 # via -r requirements/mypy.in mypy-extensions==1.0.0 # via mypy @@ -30,7 +30,7 @@ pluggy==1.5.0 # via pytest pygments==2.18.0 # via -r requirements/pytest.in -pytest==8.2.2 +pytest==8.3.2 # via # -r requirements/pytest.in # pytest-xdist diff --git a/requirements/pip-tools.pip b/requirements/pip-tools.pip index e017048c2..60fdce03f 100644 --- a/requirements/pip-tools.pip +++ b/requirements/pip-tools.pip @@ -8,7 +8,7 @@ build==1.2.1 # via pip-tools click==8.1.7 # via pip-tools -importlib-metadata==8.0.0 +importlib-metadata==8.2.0 # via build packaging==24.1 # via build @@ -28,7 +28,7 @@ zipp==3.19.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: -pip==24.1.2 +pip==24.2 # via pip-tools -setuptools==71.0.4 +setuptools==72.1.0 # via pip-tools diff --git a/requirements/pip.pip b/requirements/pip.pip index 9ad0ff579..04ccf1cce 100644 --- a/requirements/pip.pip +++ b/requirements/pip.pip @@ -14,7 +14,7 @@ virtualenv==20.26.3 # via -r requirements/pip.in # The following packages are considered to be unsafe in a requirements file: -pip==24.1.2 +pip==24.2 # via -r requirements/pip.in -setuptools==71.0.4 +setuptools==72.1.0 # via -r requirements/pip.in diff --git a/requirements/pytest.pip b/requirements/pytest.pip index 358278fbc..8a64177c3 100644 --- a/requirements/pytest.pip +++ b/requirements/pytest.pip @@ -16,7 +16,7 @@ execnet==2.1.1 # via pytest-xdist flaky==3.8.1 # via -r requirements/pytest.in -hypothesis==6.108.2 +hypothesis==6.108.5 # via -r requirements/pytest.in iniconfig==2.0.0 # via pytest @@ -26,7 +26,7 @@ pluggy==1.5.0 # via pytest pygments==2.18.0 # via -r requirements/pytest.in -pytest==8.2.2 +pytest==8.3.2 # via # -r requirements/pytest.in # pytest-xdist From 9aaa404e9606e9f9784eac1400d3b2ce9ef2902d Mon Sep 17 00:00:00 2001 From: Kenshin <1427518212@qq.com> Date: Sat, 3 Aug 2024 23:14:36 +0800 Subject: [PATCH 16/24] fix: properly handle backslash before multi-line string (#1828) Co-authored-by: LiuYinCarl --- coverage/phystokens.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/coverage/phystokens.py b/coverage/phystokens.py index ec8959fb6..37aeee81f 100644 --- a/coverage/phystokens.py +++ b/coverage/phystokens.py @@ -57,7 +57,15 @@ def _phys_tokens(toks: TokenInfos) -> TokenInfos: if last_ttext.endswith("\\"): inject_backslash = False elif ttype == token.STRING: - if "\n" in ttext and ttext.split("\n", 1)[0][-1] == "\\": + if last_line.endswith(last_ttext+"\\\n"): + # Deal with special cases like such code:: + # + # a = ["aaa",\ + # "bbb \ + # ccc"] + # + pass + elif "\n" in ttext and ttext.split("\n", 1)[0][-1] == "\\": # It's a multi-line string and the first line ends with # a backslash, so we don't need to inject another. inject_backslash = False From dc819ff4d2333dfbf01c37406bb73ff1aceb8b3a Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Thu, 1 Aug 2024 19:39:36 -0400 Subject: [PATCH 17/24] test: two tests for #1828 --- coverage/phystokens.py | 4 ++-- tests/test_html.py | 22 ++++++++++++++++++++++ tests/test_phystokens.py | 19 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/coverage/phystokens.py b/coverage/phystokens.py index 37aeee81f..9fc36ecda 100644 --- a/coverage/phystokens.py +++ b/coverage/phystokens.py @@ -57,14 +57,14 @@ def _phys_tokens(toks: TokenInfos) -> TokenInfos: if last_ttext.endswith("\\"): inject_backslash = False elif ttype == token.STRING: - if last_line.endswith(last_ttext+"\\\n"): + if last_line.endswith(last_ttext + "\\\n"): # Deal with special cases like such code:: # # a = ["aaa",\ # "bbb \ # ccc"] # - pass + inject_backslash = True elif "\n" in ttext and ttext.split("\n", 1)[0][-1] == "\\": # It's a multi-line string and the first line ends with # a backslash, so we don't need to inject another. diff --git a/tests/test_html.py b/tests/test_html.py index f2d9bcbb3..c7cee1f98 100644 --- a/tests/test_html.py +++ b/tests/test_html.py @@ -1131,6 +1131,28 @@ def test_tabbed(self) -> None: doesnt_contain("out/tabbed_py.html", "\t") + def test_bug_1828(self) -> None: + # https://github.com/nedbat/coveragepy/pull/1828 + self.make_file("backslashes.py", """\ + a = ["aaa",\\ + "bbb \\ + ccc"] + """) + + cov = coverage.Coverage() + backslashes = self.start_import_stop(cov, "backslashes") + cov.html_report(backslashes, directory="out") + + contains( + "out/backslashes_py.html", + # line 2 is `"bbb \` + r'2' + + r' "bbb \', + # line 3 is `ccc"]` + r'3' + + r' ccc"]', + ) + def test_unicode(self) -> None: surrogate = "\U000e0100" diff --git a/tests/test_phystokens.py b/tests/test_phystokens.py index 063e517d6..0a863ab6e 100644 --- a/tests/test_phystokens.py +++ b/tests/test_phystokens.py @@ -98,6 +98,24 @@ def test_tokenize_real_file(self) -> None: real_file = os.path.join(TESTS_DIR, "test_coverage.py") self.check_file_tokenization(real_file) + def test_1828(self) -> None: + # https://github.com/nedbat/coveragepy/pull/1828 + tokens = list(source_token_lines(textwrap.dedent(""" + x = \ + 1 + a = ["aaa",\\ + "bbb \\ + ccc"] + """))) + assert tokens == [ + [], + [('nam', 'x'), ('ws', ' '), ('op', '='), ('ws', ' '), ('num', '1')], + [('nam', 'a'), ('ws', ' '), ('op', '='), ('ws', ' '), + ('op', '['), ('str', '"aaa"'), ('op', ','), ('xx', '\\')], + [('ws', ' '), ('str', '"bbb \\')], + [('str', ' ccc"'), ('op', ']')], + ] + @pytest.mark.parametrize("fname", [ "stress_phystoken.tok", "stress_phystoken_dos.tok", @@ -113,6 +131,7 @@ def test_stress(self, fname: str) -> None: with open(stress) as fstress: assert re.search(r"(?m) $", fstress.read()), f"{stress} needs a trailing space." + @pytest.mark.skipif(not env.PYBEHAVIOR.soft_keywords, reason="Soft keywords are new in Python 3.10") class SoftKeywordTest(CoverageTest): """Tests the tokenizer handling soft keywords.""" From da1682fdbedba7dd99d5b7c635c47e33ce8f207c Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sat, 3 Aug 2024 11:09:35 -0400 Subject: [PATCH 18/24] docs: changelog and contributor for #1828 --- CHANGES.rst | 6 +++++- CONTRIBUTORS.txt | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 139d4d5ab..61b2f4f9e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -27,7 +27,11 @@ Unreleased ` with a :class:`Path ` argument. This is now fixed, thanks to `Ask Hjorth Larsen `_. -.. _pull 1819: https://github.com/nedbat/coveragepy/pull/1819/files +- Fix: backslashes preceding a multi-line backslashed string could confuse the + HTML report. This is now fixed, thanks to `LiuYinCarl `_. + +.. _pull 1819: https://github.com/nedbat/coveragepy/pull/1819 +.. _pull 1828: https://github.com/nedbat/coveragepy/pull/1828 .. scriv-start-here diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index e44920ce2..9097546ea 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -135,6 +135,7 @@ Leonardo Pistone Lewis Gaul Lex Berezhny Liam DeVoe +LiuYinCarl Loïc Dachary Lorenzo Micò Louis Heredero From 2b53664329903a80af78a1f5de1a40ecbd8f6cfb Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sat, 3 Aug 2024 13:11:33 -0400 Subject: [PATCH 19/24] build: include gil/nogil in the version banner --- igor.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/igor.py b/igor.py index 5037cb503..dc21ae344 100644 --- a/igor.py +++ b/igor.py @@ -321,6 +321,9 @@ def print_banner(label): if rev: version += f" (rev {rev})" + gil = "gil" if getattr(sys, '_is_gil_enabled', lambda: True)() else "nogil" + version += f" ({gil})" + try: which_python = os.path.relpath(sys.executable) except ValueError: From 7a27f401d10a5a55ba46f4bc726cac261aa7708e Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Tue, 30 Jul 2024 07:23:16 -0400 Subject: [PATCH 20/24] test: fix a test on free-threading, use abiflags to get site-packages path correct --- .github/workflows/python-nightly.yml | 1 + tests/test_debug.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/python-nightly.yml b/.github/workflows/python-nightly.yml index fb4341e27..a91e58c41 100644 --- a/.github/workflows/python-nightly.yml +++ b/.github/workflows/python-nightly.yml @@ -104,6 +104,7 @@ jobs: set -xe python -VV python -m site + python -m sysconfig python -c "import sys; print('GIL:', getattr(sys, '_is_gil_enabled', lambda: True)())" python -m coverage debug sys python -m coverage debug pybehave diff --git a/tests/test_debug.py b/tests/test_debug.py index c818f9308..bdf98a5f7 100644 --- a/tests/test_debug.py +++ b/tests/test_debug.py @@ -376,7 +376,7 @@ def test_short_stack_full(self) -> None: else: py = "pypy" if env.PYPY else "python" majv, minv = sys.version_info[:2] - pylib = f"lib{s}{py}{majv}.{minv}" + pylib = f"lib{s}{py}{majv}.{minv}{sys.abiflags}" assert len(re_lines(fr"{s}{pylib}{s}site-packages{s}_pytest", stack_text)) > 3 assert len(re_lines(fr"{s}{pylib}{s}site-packages{s}pluggy", stack_text)) > 3 assert not re_lines(r" 0x[0-9a-fA-F]+", stack_text) # No frame ids From 3872525ab8d0757b4b38f210c61977f319f094b3 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sun, 4 Aug 2024 07:42:15 -0400 Subject: [PATCH 21/24] chore: make upgrade --- requirements/dev.pip | 6 +++--- requirements/kit.pip | 6 +++--- requirements/mypy.pip | 4 ++-- requirements/pytest.pip | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/requirements/dev.pip b/requirements/dev.pip index f32af6dfc..f276cfd8d 100644 --- a/requirements/dev.pip +++ b/requirements/dev.pip @@ -6,7 +6,7 @@ # astroid==3.2.4 # via pylint -attrs==23.2.0 +attrs==24.1.0 # via hypothesis backports-tarfile==1.2.0 # via jaraco-context @@ -49,7 +49,7 @@ flaky==3.8.1 # via -r requirements/pytest.in greenlet==3.0.3 # via -r requirements/dev.in -hypothesis==6.108.5 +hypothesis==6.108.7 # via -r requirements/pytest.in idna==3.7 # via requests @@ -72,7 +72,7 @@ jaraco-functools==4.0.2 # via keyring jedi==0.19.1 # via pudb -keyring==25.2.1 +keyring==25.3.0 # via twine libsass==0.23.0 # via -r requirements/dev.in diff --git a/requirements/kit.pip b/requirements/kit.pip index ddbcc90fb..aa1e9a21a 100644 --- a/requirements/kit.pip +++ b/requirements/kit.pip @@ -10,7 +10,7 @@ backports-tarfile==1.2.0 # via jaraco-context bashlex==0.18 # via cibuildwheel -bracex==2.4 +bracex==2.5 # via cibuildwheel build==1.2.1 # via -r requirements/kit.in @@ -20,7 +20,7 @@ certifi==2024.7.4 # requests charset-normalizer==3.3.2 # via requests -cibuildwheel==2.19.2 +cibuildwheel==2.20.0 # via -r requirements/kit.in colorama==0.4.6 # via -r requirements/kit.in @@ -43,7 +43,7 @@ jaraco-context==5.3.0 # via keyring jaraco-functools==4.0.2 # via keyring -keyring==25.2.1 +keyring==25.3.0 # via twine markdown-it-py==3.0.0 # via rich diff --git a/requirements/mypy.pip b/requirements/mypy.pip index ff7c5314d..42b7f5a66 100644 --- a/requirements/mypy.pip +++ b/requirements/mypy.pip @@ -4,7 +4,7 @@ # # make upgrade # -attrs==23.2.0 +attrs==24.1.0 # via hypothesis colorama==0.4.6 # via -r requirements/pytest.in @@ -16,7 +16,7 @@ execnet==2.1.1 # via pytest-xdist flaky==3.8.1 # via -r requirements/pytest.in -hypothesis==6.108.5 +hypothesis==6.108.7 # via -r requirements/pytest.in iniconfig==2.0.0 # via pytest diff --git a/requirements/pytest.pip b/requirements/pytest.pip index 8a64177c3..af95dfb21 100644 --- a/requirements/pytest.pip +++ b/requirements/pytest.pip @@ -4,7 +4,7 @@ # # make upgrade # -attrs==23.2.0 +attrs==24.1.0 # via hypothesis colorama==0.4.6 # via -r requirements/pytest.in @@ -16,7 +16,7 @@ execnet==2.1.1 # via pytest-xdist flaky==3.8.1 # via -r requirements/pytest.in -hypothesis==6.108.5 +hypothesis==6.108.7 # via -r requirements/pytest.in iniconfig==2.0.0 # via pytest From ebbb6a2d334f67925b78200d9da2e5fb2b0e02fb Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sun, 4 Aug 2024 11:02:00 -0400 Subject: [PATCH 22/24] build: wheels for 3.13rc1 --- .github/workflows/kit.yml | 27 +++++++++++++++++++-------- .github/workflows/publish.yml | 4 ++-- CHANGES.rst | 2 ++ howto.txt | 1 - 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/.github/workflows/kit.yml b/.github/workflows/kit.yml index 7962b42a3..d9e485bab 100644 --- a/.github/workflows/kit.yml +++ b/.github/workflows/kit.yml @@ -77,10 +77,9 @@ jobs: # "macos": ["arm64", "x86_64"], # "windows": ["x86", "AMD64"], # } - # # PYVERSIONS. Available versions: - # # https://github.com/actions/python-versions/blob/main/versions-manifest.json + # # PYVERSIONS. Available versions: https://pypi.org/project/cibuildwheel/ # # PyPy versions are handled further below in the "pypy" step. - # pys = ["cp38", "cp39", "cp310", "cp311", "cp312"] + # pys = ["cp38", "cp39", "cp310", "cp311", "cp312", "cp313"] # # # Some OS/arch combinations need overrides for the Python versions: # os_arch_pys = { @@ -107,37 +106,44 @@ jobs: - {"os": "ubuntu", "py": "cp310", "arch": "x86_64"} - {"os": "ubuntu", "py": "cp311", "arch": "x86_64"} - {"os": "ubuntu", "py": "cp312", "arch": "x86_64"} + - {"os": "ubuntu", "py": "cp313", "arch": "x86_64"} - {"os": "ubuntu", "py": "cp38", "arch": "i686"} - {"os": "ubuntu", "py": "cp39", "arch": "i686"} - {"os": "ubuntu", "py": "cp310", "arch": "i686"} - {"os": "ubuntu", "py": "cp311", "arch": "i686"} - {"os": "ubuntu", "py": "cp312", "arch": "i686"} + - {"os": "ubuntu", "py": "cp313", "arch": "i686"} - {"os": "ubuntu", "py": "cp38", "arch": "aarch64"} - {"os": "ubuntu", "py": "cp39", "arch": "aarch64"} - {"os": "ubuntu", "py": "cp310", "arch": "aarch64"} - {"os": "ubuntu", "py": "cp311", "arch": "aarch64"} - {"os": "ubuntu", "py": "cp312", "arch": "aarch64"} + - {"os": "ubuntu", "py": "cp313", "arch": "aarch64"} - {"os": "macos", "py": "cp38", "arch": "arm64", "os-version": "13"} - {"os": "macos", "py": "cp39", "arch": "arm64", "os-version": "13"} - {"os": "macos", "py": "cp310", "arch": "arm64", "os-version": "13"} - {"os": "macos", "py": "cp311", "arch": "arm64", "os-version": "13"} - {"os": "macos", "py": "cp312", "arch": "arm64", "os-version": "13"} + - {"os": "macos", "py": "cp313", "arch": "arm64", "os-version": "13"} - {"os": "macos", "py": "cp38", "arch": "x86_64", "os-version": "13"} - {"os": "macos", "py": "cp39", "arch": "x86_64", "os-version": "13"} - {"os": "macos", "py": "cp310", "arch": "x86_64", "os-version": "13"} - {"os": "macos", "py": "cp311", "arch": "x86_64", "os-version": "13"} - {"os": "macos", "py": "cp312", "arch": "x86_64", "os-version": "13"} + - {"os": "macos", "py": "cp313", "arch": "x86_64", "os-version": "13"} - {"os": "windows", "py": "cp38", "arch": "x86"} - {"os": "windows", "py": "cp39", "arch": "x86"} - {"os": "windows", "py": "cp310", "arch": "x86"} - {"os": "windows", "py": "cp311", "arch": "x86"} - {"os": "windows", "py": "cp312", "arch": "x86"} + - {"os": "windows", "py": "cp313", "arch": "x86"} - {"os": "windows", "py": "cp38", "arch": "AMD64"} - {"os": "windows", "py": "cp39", "arch": "AMD64"} - {"os": "windows", "py": "cp310", "arch": "AMD64"} - {"os": "windows", "py": "cp311", "arch": "AMD64"} - {"os": "windows", "py": "cp312", "arch": "AMD64"} - # [[[end]]] (checksum: 16ed28c185d540b2d9972a0217864472) + - {"os": "windows", "py": "cp313", "arch": "AMD64"} + # [[[end]]] (checksum: e0cd49f4a0028c4fdf1036e9bc843075) fail-fast: false steps: @@ -164,10 +170,11 @@ jobs: - name: "Build wheels" env: - CIBW_BUILD: ${{ matrix.py }}-* + CIBW_BUILD: ${{ matrix.py }}*-* CIBW_ARCHS: ${{ matrix.arch }} CIBW_ENVIRONMENT: PIP_DISABLE_PIP_VERSION_CHECK=1 CIBW_PRERELEASE_PYTHONS: True + CIBW_FREE_THREADED_SUPPORT: True CIBW_TEST_COMMAND: python -c "from coverage.tracer import CTracer; print('CTracer OK!')" run: | python -m cibuildwheel --output-dir wheelhouse @@ -285,6 +292,12 @@ jobs: pattern: dist-* merge-multiple: true + - name: "List distributions" + run: | + ls -alR + echo "Number of dists, there should be 72:" + ls -1 coverage-* | wc -l + - name: "Sign artifacts" uses: sigstore/gh-action-sigstore-python@f514d46b907ebcd5bedc05145c03b69c1edd8b46 # v3.0.0 with: @@ -299,7 +312,5 @@ jobs: with: name: signatures path: | - *.crt - *.sig - *.sigstore + *.sigstore.json retention-days: 7 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c4d5746d1..35ae00e28 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -68,7 +68,7 @@ jobs: - name: "What did we get?" run: | ls -alR - echo "Number of dists:" + echo "Number of dists, should be 72:" ls -1 dist | wc -l - name: "Generate attestations" @@ -107,7 +107,7 @@ jobs: - name: "What did we get?" run: | ls -alR - echo "Number of dists:" + echo "Number of dists, should be 72:" ls -1 dist | wc -l - name: "Generate attestations" diff --git a/CHANGES.rst b/CHANGES.rst index 61b2f4f9e..b76665bb7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -30,6 +30,8 @@ Unreleased - Fix: backslashes preceding a multi-line backslashed string could confuse the HTML report. This is now fixed, thanks to `LiuYinCarl `_. +- Now we publish wheels for Python 3.13, both regular and free-threaded. + .. _pull 1819: https://github.com/nedbat/coveragepy/pull/1819 .. _pull 1828: https://github.com/nedbat/coveragepy/pull/1828 diff --git a/howto.txt b/howto.txt index 6cba5ba98..785a6157c 100644 --- a/howto.txt +++ b/howto.txt @@ -52,7 +52,6 @@ - Kits: - Wait for kits to finish: - https://github.com/nedbat/coveragepy/actions/workflows/kit.yml - - there should be 52 - test the pypi upload: $ make test_upload - you'll need to approve the action From 9b829f1dcb57e724054e153d2ab0a2fec5d52122 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sun, 4 Aug 2024 15:03:36 -0400 Subject: [PATCH 23/24] docs: prep for 7.6.1 --- CHANGES.rst | 10 ++++++---- README.rst | 2 +- coverage/version.py | 4 ++-- doc/conf.py | 6 +++--- doc/index.rst | 2 +- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index b76665bb7..573cbdefe 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -20,8 +20,12 @@ upgrading your version of coverage.py. .. Version 9.8.1 — 2027-07-27 .. -------------------------- -Unreleased ----------- +.. scriv-start-here + +.. _changes_7-6-1: + +Version 7.6.1 — 2024-08-04 +-------------------------- - Fix: coverage used to fail when measuring code using :func:`runpy.run_path ` with a :class:`Path ` argument. @@ -36,8 +40,6 @@ Unreleased .. _pull 1828: https://github.com/nedbat/coveragepy/pull/1828 -.. scriv-start-here - .. _changes_7-6-0: Version 7.6.0 — 2024-07-11 diff --git a/README.rst b/README.rst index 04df255ff..203f8357c 100644 --- a/README.rst +++ b/README.rst @@ -25,7 +25,7 @@ Coverage.py runs on these versions of Python: .. PYVERSIONS -* Python 3.8 through 3.12, and 3.13.0b3. +* Python 3.8 through 3.12, and 3.13.0rc1, including free-threading. * PyPy3 versions 3.8 through 3.10. Documentation is on `Read the Docs`_. Code repository and issue tracker are on diff --git a/coverage/version.py b/coverage/version.py index 9ce5e35a7..ffefd8e00 100644 --- a/coverage/version.py +++ b/coverage/version.py @@ -8,8 +8,8 @@ # version_info: same semantics as sys.version_info. # _dev: the .devN suffix if any. -version_info = (7, 6, 1, "alpha", 0) -_dev = 1 +version_info = (7, 6, 1, "final", 0) +_dev = 0 def _make_version( diff --git a/doc/conf.py b/doc/conf.py index 3886abb7f..030a1a1c1 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -67,11 +67,11 @@ # @@@ editable copyright = "2009–2024, Ned Batchelder" # pylint: disable=redefined-builtin # The short X.Y.Z version. -version = "7.6.0" +version = "7.6.1" # The full version, including alpha/beta/rc tags. -release = "7.6.0" +release = "7.6.1" # The date of release, in "monthname day, year" format. -release_date = "July 11, 2024" +release_date = "August 4, 2024" # @@@ end rst_epilog = f""" diff --git a/doc/index.rst b/doc/index.rst index 748b963af..100823ada 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -18,7 +18,7 @@ supported on: .. PYVERSIONS -* Python 3.8 through 3.12, and 3.13.0b3. +* Python 3.8 through 3.12, and 3.13.0rc1, including free-threading. * PyPy3 versions 3.8 through 3.10. .. ifconfig:: prerelease From 29f5898c571aac9d6380203179ba9d6c28195c62 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sun, 4 Aug 2024 15:04:17 -0400 Subject: [PATCH 24/24] docs: sample HTML for 7.6.1 --- doc/sample_html/class_index.html | 8 ++++---- doc/sample_html/function_index.html | 8 ++++---- doc/sample_html/index.html | 8 ++++---- doc/sample_html/status.json | 2 +- doc/sample_html/z_7b071bdc2a35fa80___init___py.html | 8 ++++---- doc/sample_html/z_7b071bdc2a35fa80___main___py.html | 8 ++++---- doc/sample_html/z_7b071bdc2a35fa80_cogapp_py.html | 8 ++++---- doc/sample_html/z_7b071bdc2a35fa80_makefiles_py.html | 8 ++++---- doc/sample_html/z_7b071bdc2a35fa80_test_cogapp_py.html | 8 ++++---- doc/sample_html/z_7b071bdc2a35fa80_test_makefiles_py.html | 8 ++++---- .../z_7b071bdc2a35fa80_test_whiteutils_py.html | 8 ++++---- doc/sample_html/z_7b071bdc2a35fa80_utils_py.html | 8 ++++---- doc/sample_html/z_7b071bdc2a35fa80_whiteutils_py.html | 8 ++++---- 13 files changed, 49 insertions(+), 49 deletions(-) diff --git a/doc/sample_html/class_index.html b/doc/sample_html/class_index.html index ddcea11fd..244ce8666 100644 --- a/doc/sample_html/class_index.html +++ b/doc/sample_html/class_index.html @@ -56,8 +56,8 @@

Classes

- coverage.py v7.6.0, - created at 2024-07-11 12:38 -0400 + coverage.py v7.6.1, + created at 2024-08-04 15:03 -0400

@@ -537,8 +537,8 @@

- coverage.py v7.6.0, - created at 2024-07-11 12:38 -0400 + coverage.py v7.6.1, + created at 2024-08-04 15:03 -0400

diff --git a/doc/sample_html/z_7b071bdc2a35fa80_makefiles_py.html b/doc/sample_html/z_7b071bdc2a35fa80_makefiles_py.html index 8d7d719c1..01df01b73 100644 --- a/doc/sample_html/z_7b071bdc2a35fa80_makefiles_py.html +++ b/doc/sample_html/z_7b071bdc2a35fa80_makefiles_py.html @@ -66,8 +66,8 @@

^ index     » next       - coverage.py v7.6.0, - created at 2024-07-11 12:38 -0400 + coverage.py v7.6.1, + created at 2024-08-04 15:03 -0400