diff --git a/0001-make-data-collection-operations-thread-safe.patch b/0001-make-data-collection-operations-thread-safe.patch new file mode 100644 index 0000000..c01e98b --- /dev/null +++ b/0001-make-data-collection-operations-thread-safe.patch @@ -0,0 +1,140 @@ +From e36b42e2db46e892d9347ba0408c99b187ba8cb8 Mon Sep 17 00:00:00 2001 +From: Ned Batchelder +Date: Mon, 3 May 2021 07:56:05 -0400 +Subject: [PATCH] fix: make data collection operations thread-safe + +--- + CHANGES.rst | 3 +++ + coverage/sqldata.py | 20 ++++++++++++++++++++ + tests/test_data.py | 7 ++++++- + 3 files changed, 29 insertions(+), 1 deletion(-) + +#diff --git a/CHANGES.rst b/CHANGES.rst +#index 29af7340..3c65e5d8 100644 +#--- a/CHANGES.rst +#+++ b/CHANGES.rst +#@@ -26,6 +26,9 @@ Unreleased +# +# - Dropped support for Python 2.7, PyPy 2, and Python 3.5. +# +#+- Data collection is now thread-safe. There may have been rare instances of +#+ exceptions raised in multi-threaded programs. +#+ +# - Plugins (like the `Django coverage plugin`_) were generating "Already +# imported a file that will be measured" warnings about Django itself. These +# have been fixed, closing `issue 1150`_. +Index: coverage-5.5/coverage/sqldata.py +=================================================================== +--- coverage-5.5.orig/coverage/sqldata.py ++++ coverage-5.5/coverage/sqldata.py +@@ -8,12 +8,14 @@ + + import collections + import datetime ++import functools + import glob + import itertools + import os + import re + import sqlite3 + import sys ++import threading + import zlib + + from coverage import env +@@ -179,6 +181,10 @@ class CoverageData(SimpleReprMixin): + Data in a :class:`CoverageData` can be serialized and deserialized with + :meth:`dumps` and :meth:`loads`. + ++ The methods used during the coverage.py collection phase ++ (:meth:`add_lines`, :meth:`add_arcs`, :meth:`set_context`, and ++ :meth:`add_file_tracers`) are thread-safe. Other methods may not be. ++ + """ + + def __init__(self, basename=None, suffix=None, no_disk=False, warn=None, debug=None): +@@ -207,6 +213,8 @@ class CoverageData(SimpleReprMixin): + # Maps thread ids to SqliteDb objects. + self._dbs = {} + self._pid = os.getpid() ++ # Synchronize the operations used during collection. ++ self._lock = threading.Lock() + + # Are we in sync with the data file? + self._have_used = False +@@ -218,6 +226,15 @@ class CoverageData(SimpleReprMixin): + self._current_context_id = None + self._query_context_ids = None + ++ def _locked(method): # pylint: disable=no-self-argument ++ """A decorator for methods that should hold self._lock.""" ++ @functools.wraps(method) ++ def _wrapped(self, *args, **kwargs): ++ with self._lock: ++ # pylint: disable=not-callable ++ return method(self, *args, **kwargs) ++ return _wrapped ++ + def _choose_filename(self): + """Set self._filename based on inited attributes.""" + if self._no_disk: +@@ -381,6 +398,7 @@ class CoverageData(SimpleReprMixin): + else: + return None + ++ @_locked + def set_context(self, context): + """Set the current context for future :meth:`add_lines` etc. + +@@ -422,6 +440,7 @@ class CoverageData(SimpleReprMixin): + """ + return self._filename + ++ @_locked + def add_lines(self, line_data): + """Add measured line data. + +@@ -454,6 +473,7 @@ class CoverageData(SimpleReprMixin): + (file_id, self._current_context_id, linemap), + ) + ++ @_locked + def add_arcs(self, arc_data): + """Add measured arc data. + +@@ -498,6 +518,7 @@ class CoverageData(SimpleReprMixin): + ('has_arcs', str(int(arcs))) + ) + ++ @_locked + def add_file_tracers(self, file_tracers): + """Add per-file plugin information. + +Index: coverage-5.5/tests/test_data.py +=================================================================== +--- coverage-5.5.orig/tests/test_data.py ++++ coverage-5.5/tests/test_data.py +@@ -488,10 +488,14 @@ class CoverageDataTest(DataTestHelpers, + + def test_thread_stress(self): + covdata = CoverageData() ++ exceptions = [] + + def thread_main(): + """Every thread will try to add the same data.""" +- covdata.add_lines(LINES_1) ++ try: ++ covdata.add_lines(LINES_1) ++ except Exception as ex: ++ exceptions.append(ex) + + threads = [threading.Thread(target=thread_main) for _ in range(10)] + for t in threads: +@@ -500,6 +504,7 @@ class CoverageDataTest(DataTestHelpers, + t.join() + + self.assert_lines1_data(covdata) ++ assert exceptions == [] + + + class CoverageDataTestInTempDir(DataTestHelpers, CoverageTest): diff --git a/change__file__report-dir.patch b/change__file__report-dir.patch new file mode 100644 index 0000000..e557dc0 --- /dev/null +++ b/change__file__report-dir.patch @@ -0,0 +1,36 @@ +From 01cbb8751f98e5a7de79699444cbc03647691616 Mon Sep 17 00:00:00 2001 +From: Ned Batchelder +Date: Tue, 11 May 2021 19:32:32 -0400 +Subject: [PATCH] fix: Python 3.8.10 changed how __file__ is reported when + running directories + +--- + coverage/execfile.py | 5 +++++ + tests/test_process.py | 2 +- + 2 files changed, 6 insertions(+), 1 deletion(-) + +--- a/coverage/execfile.py ++++ b/coverage/execfile.py +@@ -176,6 +176,11 @@ class PyRunner(object): + # directory. + for ext in [".py", ".pyc", ".pyo"]: + try_filename = os.path.join(self.arg0, "__main__" + ext) ++ # 3.8.10 changed how files are reported when running a ++ # directory. But I'm not sure how far this change is going to ++ # spread, so I'll just hard-code it here for now. ++ if env.PYVERSION >= (3, 8, 10): ++ try_filename = os.path.abspath(try_filename) + if os.path.exists(try_filename): + self.arg0 = try_filename + break +--- a/tests/test_process.py ++++ b/tests/test_process.py +@@ -852,7 +852,7 @@ class EnvironmentTest(CoverageTest): + expected = re_lines(expected, r'\s+"argv0":', match=False) + actual = re_lines(actual, r'\s+"argv0":', match=False) + +- assert expected == actual ++ assert actual == expected + + def test_coverage_run_is_like_python(self): + with open(TRY_EXECFILE) as f: diff --git a/coverage-5.4.tar.gz b/coverage-5.4.tar.gz deleted file mode 100644 index ebabbeb..0000000 --- a/coverage-5.4.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6d2e262e5e8da6fa56e774fb8e2643417351427604c2b177f8e8c5f75fc928ca -size 687727 diff --git a/coverage-5.5.tar.gz b/coverage-5.5.tar.gz new file mode 100644 index 0000000..98fb769 --- /dev/null +++ b/coverage-5.5.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c +size 691258 diff --git a/python-coverage.changes b/python-coverage.changes index 38d956c..ff38641 100644 --- a/python-coverage.changes +++ b/python-coverage.changes @@ -1,3 +1,50 @@ +------------------------------------------------------------------- +Wed May 12 09:29:03 UTC 2021 - Matej Cepl + +- Add change__file__report-dir.patch to fix another issue repored + in gh#nedbat/coveragepy#1161. + +------------------------------------------------------------------- +Tue May 11 10:44:16 UTC 2021 - Antonio Larrosa + +- Add a patch from upstream (slightly rebased) to make data + collection operations thread safe: + * 0001-make-data-collection-operations-thread-safe.patch + +------------------------------------------------------------------- +Sun May 9 22:27:19 UTC 2021 - Matej Cepl + +- Add traced_file_absolute.patch to fix gh#nedbat/coveragepy#1161. + +------------------------------------------------------------------- +Sat May 8 18:47:01 UTC 2021 - Matej Cepl + +- Switch off test_debug_trace started to avoid failure + (gh#nedbat/coveragepy#1161). + +------------------------------------------------------------------- +Sat May 8 14:15:04 UTC 2021 - Matej Cepl + +- Update to 5.5: + - coverage combine has a new option, --keep to keep the original data + files after combining them. The default is still to delete the files + after they have been combined. This was requested in issue 1108 and + implemented in pull request 1110. Thanks, Éric Larivière. + - When reporting missing branches in coverage report, branches aren’t + reported that jump to missing lines. This adds to the long-standing + behavior of not reporting branches from missing lines. Now branches + are only reported if both the source and destination lines are + executed. Closes both issue 1065 and issue 955. + - Minor improvements to the HTML report: + - The state of the line visibility selector buttons is saved in + local storage so you don’t have to fiddle with them so often, + fixing issue 1123. + - It has a little more room for line numbers so that 4-digit numbers + work well, fixing issue 1124. + - Improved the error message when combining line and branch data, so + that users will be more likely to understand what’s happening, + closing issue 803. + ------------------------------------------------------------------- Mon Feb 1 20:58:07 UTC 2021 - Dirk Müller diff --git a/python-coverage.spec b/python-coverage.spec index 99ce180..db7c17e 100644 --- a/python-coverage.spec +++ b/python-coverage.spec @@ -18,12 +18,21 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-coverage -Version: 5.4 +Version: 5.5 Release: 0 Summary: Code coverage measurement for Python License: Apache-2.0 URL: https://github.com/nedbat/coveragepy Source: https://files.pythonhosted.org/packages/source/c/coverage/coverage-%{version}.tar.gz +# PATCH-FIX-UPSTREAM traced_file_absolute.patch gh#nedbat/coveragepy#1161 mcepl@suse.com +# traced file names seem to be absolute now? +Patch0: traced_file_absolute.patch +# PATCH-FIX-UPSTREAM 0001-make-data-collection-operations-thread-safe.patch gh#nedbat/coveragepy#commit-e36b42e2db46 alarrosa@suse.com +# Make data collection operations thread safe +Patch1: 0001-make-data-collection-operations-thread-safe.patch +# PATCH-FIX-UPSTREAM change__file__report-dir.patch gh#nedbat/coveragepy#1161 mcepl@suse.com +# Fix yet another regression in Python 3.8.10, this time about __file__ value for directories. +Patch2: change__file__report-dir.patch BuildRequires: %{python_module devel} BuildRequires: %{python_module flaky} BuildRequires: %{python_module hypothesis >= 4.57} @@ -41,7 +50,7 @@ Requires: python Requires: python-setuptools Requires: python-toml Requires(post): update-alternatives -Requires(postun): update-alternatives +Requires(postun):update-alternatives %python_subpackages %description @@ -50,7 +59,8 @@ the code analysis tools and tracing hooks provided in the Python standard library to determine which lines are executable, and which have been executed. %prep -%setup -q -n coverage-%{version} +%autosetup -p1 -n coverage-%{version} + # do not require xdist sed -i -e '/addopts/d' setup.cfg # writes in /usr/ @@ -92,6 +102,7 @@ for filepath in %{buildroot}%{_bindir}/coverage*-%{$python_bin_suffix}; do done } export PATH="$(pwd)/build/bin:$PATH" +%python_exec -mcoverage debug sys # the tests need the empty leading part for importing local test projects, the x is a dummy" export PYTHONPATH=":x" %pytest_arch -k 'not (test_get_encoded_zip_files or test_egg or test_doctest or test_unicode or test_version or test_multiprocessing_with_branching or test_farm or test_dothtml_not_python or test_one_of or test_bytes or test_encoding or test_multi or test_xdist_sys_path_nuttiness_is_fixed or test_debug_sys_ctracer)' diff --git a/traced_file_absolute.patch b/traced_file_absolute.patch new file mode 100644 index 0000000..5ab2cd0 --- /dev/null +++ b/traced_file_absolute.patch @@ -0,0 +1,66 @@ +From 06cb51b39620e2140f915393f0f41b281594e05b Mon Sep 17 00:00:00 2001 +From: Ned Batchelder +Date: Sat, 8 May 2021 21:27:45 -0400 +Subject: [PATCH] test: traced file names seem to be absolute now? #1161 + +This was changed in 3.10.0b1 and 3.9.5. Seems like a strange change to +throw into 3.9.5, but there it is. Fixes #1161. +--- + tests/test_debug.py | 6 ++++-- + tests/test_oddball.py | 16 +++++++++------- + 2 files changed, 13 insertions(+), 9 deletions(-) + +--- a/tests/test_debug.py ++++ b/tests/test_debug.py +@@ -124,8 +124,10 @@ class DebugTraceTest(CoverageTest): + def test_debug_trace(self): + out_lines = self.f1_debug_output(["trace"]) + +- # We should have a line like "Tracing 'f1.py'" +- assert "Tracing 'f1.py'" in out_lines ++ # We should have a line like "Tracing 'f1.py'", perhaps with an ++ # absolute path. ++ f1 = re_lines(out_lines, r"Tracing '.*f1.py'") ++ assert f1 + + # We should have lines like "Not tracing 'collector.py'..." + coverage_lines = re_lines( +--- a/tests/test_oddball.py ++++ b/tests/test_oddball.py +@@ -451,10 +451,12 @@ class GettraceTest(CoverageTest): + def test_setting_new_trace_function(self): + # https://github.com/nedbat/coveragepy/issues/436 + self.check_coverage('''\ ++ import os.path + import sys + + def tracer(frame, event, arg): +- print("%s: %s @ %d" % (event, frame.f_code.co_filename, frame.f_lineno)) ++ filename = os.path.basename(frame.f_code.co_filename) ++ print("%s: %s @ %d" % (event, filename, frame.f_lineno)) + return tracer + + def begin(): +@@ -474,16 +476,16 @@ class GettraceTest(CoverageTest): + a = 21 + b = 22 + ''', +- lines=[1, 3, 4, 5, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 20, 21, 22], +- missing="4-5, 11-12", ++ lines=[1, 2, 4, 5, 6, 7, 9, 10, 12, 13, 14, 16, 17, 18, 20, 21, 22, 23, 24], ++ missing="5-7, 13-14", + ) + + out = self.stdout().replace(self.last_module_name, "coverage_test") + expected = ( +- "call: coverage_test.py @ 10\n" +- "line: coverage_test.py @ 11\n" +- "line: coverage_test.py @ 12\n" +- "return: coverage_test.py @ 12\n" ++ "call: coverage_test.py @ 12\n" ++ "line: coverage_test.py @ 13\n" ++ "line: coverage_test.py @ 14\n" ++ "return: coverage_test.py @ 14\n" + ) + assert expected == out +