From a5da277a8653ecaf5fdc905f67b6503732e7dba7 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sat, 2 Oct 2021 23:13:14 -0400 Subject: [PATCH 1/9] build: bump version --- CHANGES.rst | 6 ++++++ coverage/version.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index d9fcc2b8c..909ccde25 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -21,6 +21,12 @@ want to know what's different in 5.0 since 4.5.x, see :ref:`whatsnew5x`. .. Version 9.8.1 --- 2027-07-27 .. ---------------------------- +Unreleased +---------- + +Nothing yet. + + .. _changes_60: Version 6.0 --- 2021-10-03 diff --git a/coverage/version.py b/coverage/version.py index 98bbda8b5..cad69ce79 100644 --- a/coverage/version.py +++ b/coverage/version.py @@ -5,7 +5,7 @@ # This file is exec'ed in setup.py, don't import anything! # Same semantics as sys.version_info. -version_info = (6, 0, 0, "final", 0) +version_info = (6, 0, 1, "alpha", 0) def _make_version(major, minor, micro, releaselevel, serial): From fb21f8e8f33e9737b2e7f237d203773cda1c6567 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Mon, 4 Oct 2021 08:55:06 -0400 Subject: [PATCH 2/9] docs: the 5.0 change summary shouldn't be so prominent anymore --- CHANGES.rst | 7 ++++--- doc/index.rst | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 909ccde25..50a81aaf3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -9,9 +9,7 @@ These changes are listed in decreasing version number order. Note this can be different from a strict chronological order when there are two branches in development at the same time, such as 4.5.x and 5.0. -This list is detailed and covers changes in each pre-release version. If you -want to know what's different in 5.0 since 4.5.x, see :ref:`whatsnew5x`. - +This list is detailed and covers changes in each pre-release version. .. When updating the "Unreleased" header to a specific version, use this .. format. Don't forget the jump target: @@ -468,6 +466,9 @@ Version 5.0 --- 2019-12-14 Nothing new beyond 5.0b2. +A summary of major changes in 5.0 since 4.5.x is in see :ref:`whatsnew5x`. + + .. _changes_50b2: diff --git a/doc/index.rst b/doc/index.rst index 2b4a6a45c..927248e47 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -222,6 +222,5 @@ More information contributing trouble faq - whatsnew5x changes sleepy From 62116801c3ae2f7bfc6302836e46bdfac681c1a5 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Tue, 5 Oct 2021 06:43:24 -0400 Subject: [PATCH 3/9] build: 3.10.0 is out --- .github/workflows/coverage.yml | 2 +- .github/workflows/kit.yml | 1 + .github/workflows/testsuite.yml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5686493e2..c305477bc 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -37,7 +37,7 @@ jobs: - "3.7" - "3.8" - "3.9" - - "3.10.0-rc.2" + - "3.10" - "pypy3" exclude: # Windows PyPy doesn't seem to work? diff --git a/.github/workflows/kit.yml b/.github/workflows/kit.yml index 726cefaca..c6b9e43da 100644 --- a/.github/workflows/kit.yml +++ b/.github/workflows/kit.yml @@ -122,6 +122,7 @@ jobs: prerel: name: "Build ${{ matrix.python-version }} wheels on ${{ matrix.os }}" + if: ${{ false }} # disable for now, since there are no pre-rel Python versions. runs-on: ${{ matrix.os }} strategy: matrix: diff --git a/.github/workflows/testsuite.yml b/.github/workflows/testsuite.yml index 49df01e6e..6b0de1b3d 100644 --- a/.github/workflows/testsuite.yml +++ b/.github/workflows/testsuite.yml @@ -35,7 +35,7 @@ jobs: - "3.7" - "3.8" - "3.9" - - "3.10.0-rc.2" + - "3.10" - "pypy3" exclude: # Windows PyPy doesn't seem to work? From 613446ca9da592c6925329b869b9ef785d83f76e Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Tue, 5 Oct 2021 19:43:00 -0400 Subject: [PATCH 4/9] fix: pretend we didn't import third-party packages we use. #1228 tomli couldn't use coverage themselves because we imported it early. Cleaning sys.modules means their own imports will actually execute after coverage has started, so their files will be properly measured. --- CHANGES.rst | 5 ++++- coverage/misc.py | 27 +++++++++++++++++++++++++++ coverage/tomlconfig.py | 7 ++----- tests/test_misc.py | 20 +++++++++++++++++++- 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 50a81aaf3..937d2d0fa 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -22,7 +22,10 @@ This list is detailed and covers changes in each pre-release version. Unreleased ---------- -Nothing yet. +- Changed an internal detail of how tomli is imported, so that tomli can use + coverage.py for their own test suite (`issue 1228`_). + +.. _issue 1228: https://github.com/nedbat/coveragepy/issues/1228 .. _changes_60: diff --git a/coverage/misc.py b/coverage/misc.py index 11dad23e0..cd4a77401 100644 --- a/coverage/misc.py +++ b/coverage/misc.py @@ -5,6 +5,7 @@ import errno import hashlib +import importlib import importlib.util import inspect import locale @@ -43,6 +44,32 @@ def isolate_module(mod): os = isolate_module(os) +def import_third_party(modname): + """Import a third-party module we need, but might not be installed. + + This also cleans out the module after the import, so that coverage won't + appear to have imported it. This lets the third party use coverage for + their own tests. + + Arguments: + modname (str): the name of the module to import. + + Returns: + The imported module, or None if the module couldn't be imported. + + """ + try: + mod = importlib.import_module(modname) + except ImportError: + mod = None + + imported = [m for m in sys.modules if m.startswith(modname)] + for name in imported: + del sys.modules[name] + + return mod + + def dummy_decorator_with_args(*args_unused, **kwargs_unused): """Dummy no-op implementation of a decorator with arguments.""" def _decorator(func): diff --git a/coverage/tomlconfig.py b/coverage/tomlconfig.py index 203192c93..3301acc8e 100644 --- a/coverage/tomlconfig.py +++ b/coverage/tomlconfig.py @@ -8,13 +8,10 @@ import re from coverage.exceptions import CoverageException -from coverage.misc import substitute_variables +from coverage.misc import import_third_party, substitute_variables # TOML support is an install-time extra option. -try: - import tomli -except ImportError: # pragma: not covered - tomli = None +tomli = import_third_party("tomli") class TomlDecodeError(Exception): diff --git a/tests/test_misc.py b/tests/test_misc.py index 3858c4f8b..077c24344 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -3,11 +3,13 @@ """Tests of miscellaneous stuff.""" +import sys + import pytest from coverage.exceptions import CoverageException from coverage.misc import contract, dummy_decorator_with_args, file_be_gone -from coverage.misc import Hasher, one_of, substitute_variables +from coverage.misc import Hasher, one_of, substitute_variables, import_third_party from coverage.misc import USE_CONTRACTS from tests.coveragetest import CoverageTest @@ -155,3 +157,19 @@ def test_substitute_variables_errors(text): substitute_variables(text, VARS) assert text in str(exc_info.value) assert "Variable NOTHING is undefined" in str(exc_info.value) + + +class ImportThirdPartyTest(CoverageTest): + """Test import_third_party.""" + + run_in_temp_dir = False + + def test_success(self): + mod = import_third_party("pytest") + assert mod.__name__ == "pytest" + assert "pytest" not in sys.modules + + def test_failure(self): + mod = import_third_party("xyzzy") + assert mod is None + assert "xyzzy" not in sys.modules From 19545b7d78fb91a82088517681e20cf4ffcd8c63 Mon Sep 17 00:00:00 2001 From: glacials Date: Fri, 6 Aug 2021 14:17:26 -0700 Subject: [PATCH 5/9] Fix an incompatibility with pyarmor --- coverage/context.py | 2 +- tests/test_context.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/coverage/context.py b/coverage/context.py index 45e86a5c1..43d2b1cc7 100644 --- a/coverage/context.py +++ b/coverage/context.py @@ -48,7 +48,7 @@ def qualname_from_frame(frame): fname = co.co_name method = None if co.co_argcount and co.co_varnames[0] == "self": - self = frame.f_locals["self"] + self = frame.f_locals.get("self", None) method = getattr(self, fname, None) if method is None: diff --git a/tests/test_context.py b/tests/test_context.py index 3f80803bd..de972819f 100644 --- a/tests/test_context.py +++ b/tests/test_context.py @@ -5,6 +5,7 @@ import inspect import os.path +from unittest import mock import coverage from coverage.context import qualname_from_frame @@ -275,3 +276,8 @@ def test_bug_829(self): # A class with a name like a function shouldn't confuse qualname_from_frame. class test_something: # pylint: disable=unused-variable assert get_qualname() is None + + def test_bug_1210(self): + co = mock.Mock(co_name="a_co_name", co_argcount=1, co_varnames=["self"]) + frame = mock.Mock(f_code = co, f_locals={}) + assert qualname_from_frame(frame) == "unittest.mock.a_co_name" From f33b733e92a2422d64cb7f4ba2a64898e1e4f336 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Wed, 6 Oct 2021 16:55:18 -0400 Subject: [PATCH 6/9] docs: note #1210 in the changelog --- CHANGES.rst | 5 +++++ CONTRIBUTORS.txt | 1 + tests/test_context.py | 4 +++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 937d2d0fa..784fa5c29 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -25,7 +25,12 @@ Unreleased - Changed an internal detail of how tomli is imported, so that tomli can use coverage.py for their own test suite (`issue 1228`_). +- Defend against an obscure possibility under code obfuscation, where a + function can have an argument called "self", but no local named "self" + (`pull request 1210`_). Thanks, Ben Carlsson. + .. _issue 1228: https://github.com/nedbat/coveragepy/issues/1228 +.. _pull request 1210: https://github.com/nedbat/coveragepy/pull/1210 .. _changes_60: diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 2642e6b1a..1c1fe0e9c 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -20,6 +20,7 @@ Arcadiy Ivanov Aron Griffis Artem Dayneko Arthur Deygin +Ben Carlsson Ben Finney Bernát Gábor Bill Hart diff --git a/tests/test_context.py b/tests/test_context.py index de972819f..36eff2f0d 100644 --- a/tests/test_context.py +++ b/tests/test_context.py @@ -278,6 +278,8 @@ class test_something: # pylint: disable=unused-variable assert get_qualname() is None def test_bug_1210(self): + # Under pyarmor (an obfuscator), a function can have a "self" argument, + # but then not have a "self" local. co = mock.Mock(co_name="a_co_name", co_argcount=1, co_varnames=["self"]) - frame = mock.Mock(f_code = co, f_locals={}) + frame = mock.Mock(f_code=co, f_locals={}) assert qualname_from_frame(frame) == "unittest.mock.a_co_name" From a309f08287e3bc3f50e2c97feaa44e6b2523d355 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Wed, 6 Oct 2021 20:31:19 -0400 Subject: [PATCH 7/9] fix: make exceptions importable from coverage.misc again. #1226 --- CHANGES.rst | 9 ++++++++- coverage/misc.py | 5 +++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 784fa5c29..3dea0df17 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -22,6 +22,12 @@ This list is detailed and covers changes in each pre-release version. Unreleased ---------- +- In 6.0, the coverage.py exceptions moved from coverage.misc to + coverage.exceptions. These exceptions are not part of the public supported + API, CoverageException is. But a number of other third-party packages were + importing the exceptions from coverage.misc, so they are now available from + there again (`issue 1226`_). + - Changed an internal detail of how tomli is imported, so that tomli can use coverage.py for their own test suite (`issue 1228`_). @@ -29,8 +35,9 @@ Unreleased function can have an argument called "self", but no local named "self" (`pull request 1210`_). Thanks, Ben Carlsson. -.. _issue 1228: https://github.com/nedbat/coveragepy/issues/1228 .. _pull request 1210: https://github.com/nedbat/coveragepy/pull/1210 +.. _issue 1226: https://github.com/nedbat/coveragepy/issues/1226 +.. _issue 1228: https://github.com/nedbat/coveragepy/issues/1228 .. _changes_60: diff --git a/coverage/misc.py b/coverage/misc.py index cd4a77401..0f985be0e 100644 --- a/coverage/misc.py +++ b/coverage/misc.py @@ -20,6 +20,11 @@ from coverage import env from coverage.exceptions import CoverageException +# In 6.0, the exceptions moved from misc.py to exceptions.py. But a number of +# other packages were importing the exceptions from misc, so import them here. +# pylint: disable=unused-wildcard-import +from coverage.exceptions import * # pylint: disable=wildcard-import + ISOLATED_MODULES = {} From 72200e21e58bf358884a28e77f6169a04b206f0f Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Wed, 6 Oct 2021 20:41:02 -0400 Subject: [PATCH 8/9] docs: this document isn't in a toc, and that's ok --- doc/whatsnew5x.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/whatsnew5x.rst b/doc/whatsnew5x.rst index bf0fe6cae..f49739ef0 100644 --- a/doc/whatsnew5x.rst +++ b/doc/whatsnew5x.rst @@ -1,6 +1,8 @@ .. Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 .. For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt +:orphan: + .. _whatsnew5x: ==================== From 78a9c68a969465cd7197c40405bf6b90d4767c34 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Wed, 6 Oct 2021 20:42:39 -0400 Subject: [PATCH 9/9] build: prep for 6.0.1 --- CHANGES.rst | 6 ++++-- coverage/version.py | 2 +- doc/conf.py | 4 ++-- doc/index.rst | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 3dea0df17..9d810dbde 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -19,8 +19,10 @@ This list is detailed and covers changes in each pre-release version. .. Version 9.8.1 --- 2027-07-27 .. ---------------------------- -Unreleased ----------- +.. _changes_601: + +Version 6.0.1 --- 2021-10-06 +---------------------------- - In 6.0, the coverage.py exceptions moved from coverage.misc to coverage.exceptions. These exceptions are not part of the public supported diff --git a/coverage/version.py b/coverage/version.py index cad69ce79..c9b537e37 100644 --- a/coverage/version.py +++ b/coverage/version.py @@ -5,7 +5,7 @@ # This file is exec'ed in setup.py, don't import anything! # Same semantics as sys.version_info. -version_info = (6, 0, 1, "alpha", 0) +version_info = (6, 0, 1, "final", 0) def _make_version(major, minor, micro, releaselevel, serial): diff --git a/doc/conf.py b/doc/conf.py index 5874b6376..5109ff726 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -67,9 +67,9 @@ # The short X.Y version. version = "6.0" # CHANGEME # The full version, including alpha/beta/rc tags. -release = "6.0" # CHANGEME +release = "6.0.1" # CHANGEME # The date of release, in "monthname day, year" format. -release_date = "October 3, 2021" # CHANGEME +release_date = "October 6, 2021" # CHANGEME rst_epilog = """ .. |release_date| replace:: {release_date} diff --git a/doc/index.rst b/doc/index.rst index 927248e47..dc34c3f79 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -23,7 +23,7 @@ supported on: .. ifconfig:: prerelease **This is a pre-release build. The usual warnings about possible bugs - apply.** The latest stable version is coverage.py 6.0, `described here`_. + apply.** The latest stable version is coverage.py 6.0.1, `described here`_. .. _described here: http://coverage.readthedocs.io/