coverage 7.6.10__cp312-cp312-musllinux_1_2_aarch64.whl → 7.12.0__cp312-cp312-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coverage/__init__.py +3 -1
- coverage/__main__.py +3 -1
- coverage/annotate.py +2 -3
- coverage/bytecode.py +178 -4
- coverage/cmdline.py +330 -155
- coverage/collector.py +32 -43
- coverage/config.py +167 -63
- coverage/context.py +5 -6
- coverage/control.py +165 -86
- coverage/core.py +71 -34
- coverage/data.py +4 -5
- coverage/debug.py +113 -57
- coverage/disposition.py +2 -1
- coverage/env.py +29 -78
- coverage/exceptions.py +29 -7
- coverage/execfile.py +19 -14
- coverage/files.py +24 -19
- coverage/html.py +118 -75
- coverage/htmlfiles/coverage_html.js +12 -10
- coverage/htmlfiles/index.html +45 -10
- coverage/htmlfiles/pyfile.html +2 -2
- coverage/htmlfiles/style.css +54 -6
- coverage/htmlfiles/style.scss +85 -3
- coverage/inorout.py +62 -45
- coverage/jsonreport.py +22 -9
- coverage/lcovreport.py +16 -18
- coverage/misc.py +51 -47
- coverage/multiproc.py +12 -7
- coverage/numbits.py +4 -5
- coverage/parser.py +150 -251
- coverage/patch.py +166 -0
- coverage/phystokens.py +25 -26
- coverage/plugin.py +14 -14
- coverage/plugin_support.py +37 -36
- coverage/python.py +13 -14
- coverage/pytracer.py +31 -33
- coverage/regions.py +3 -2
- coverage/report.py +60 -44
- coverage/report_core.py +7 -10
- coverage/results.py +152 -68
- coverage/sqldata.py +261 -211
- coverage/sqlitedb.py +37 -29
- coverage/sysmon.py +237 -162
- coverage/templite.py +19 -7
- coverage/tomlconfig.py +13 -13
- coverage/tracer.cpython-312-aarch64-linux-musl.so +0 -0
- coverage/tracer.pyi +3 -1
- coverage/types.py +26 -23
- coverage/version.py +4 -19
- coverage/xmlreport.py +17 -14
- {coverage-7.6.10.dist-info → coverage-7.12.0.dist-info}/METADATA +50 -28
- coverage-7.12.0.dist-info/RECORD +59 -0
- {coverage-7.6.10.dist-info → coverage-7.12.0.dist-info}/WHEEL +1 -1
- coverage-7.6.10.dist-info/RECORD +0 -58
- {coverage-7.6.10.dist-info → coverage-7.12.0.dist-info}/entry_points.txt +0 -0
- {coverage-7.6.10.dist-info → coverage-7.12.0.dist-info/licenses}/LICENSE.txt +0 -0
- {coverage-7.6.10.dist-info → coverage-7.12.0.dist-info}/top_level.txt +0 -0
coverage/misc.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
|
|
2
|
-
# For details: https://github.com/
|
|
2
|
+
# For details: https://github.com/coveragepy/coveragepy/blob/main/NOTICE.txt
|
|
3
3
|
|
|
4
4
|
"""Miscellaneous stuff for coverage.py."""
|
|
5
5
|
|
|
@@ -18,20 +18,16 @@ import os.path
|
|
|
18
18
|
import re
|
|
19
19
|
import sys
|
|
20
20
|
import types
|
|
21
|
-
|
|
22
|
-
from types import ModuleType
|
|
23
|
-
from typing import (
|
|
24
|
-
Any, NoReturn, TypeVar,
|
|
25
|
-
)
|
|
26
21
|
from collections.abc import Iterable, Iterator, Mapping, Sequence
|
|
27
|
-
|
|
28
|
-
from
|
|
29
|
-
from coverage.types import TArc
|
|
22
|
+
from types import ModuleType
|
|
23
|
+
from typing import Any, NoReturn, TypeVar
|
|
30
24
|
|
|
31
25
|
# In 6.0, the exceptions moved from misc.py to exceptions.py. But a number of
|
|
32
26
|
# other packages were importing the exceptions from misc, so import them here.
|
|
33
27
|
# pylint: disable=unused-wildcard-import
|
|
34
|
-
from coverage.exceptions import *
|
|
28
|
+
from coverage.exceptions import * # pylint: disable=wildcard-import
|
|
29
|
+
from coverage.exceptions import CoverageException
|
|
30
|
+
from coverage.types import TArc
|
|
35
31
|
|
|
36
32
|
ISOLATED_MODULES: dict[ModuleType, ModuleType] = {}
|
|
37
33
|
|
|
@@ -54,11 +50,13 @@ def isolate_module(mod: ModuleType) -> ModuleType:
|
|
|
54
50
|
setattr(new_mod, name, value)
|
|
55
51
|
return ISOLATED_MODULES[mod]
|
|
56
52
|
|
|
53
|
+
|
|
57
54
|
os = isolate_module(os)
|
|
58
55
|
|
|
59
56
|
|
|
60
57
|
class SysModuleSaver:
|
|
61
58
|
"""Saves the contents of sys.modules, and removes new modules later."""
|
|
59
|
+
|
|
62
60
|
def __init__(self) -> None:
|
|
63
61
|
self.old_modules = set(sys.modules)
|
|
64
62
|
|
|
@@ -111,9 +109,9 @@ def nice_pair(pair: TArc) -> str:
|
|
|
111
109
|
"""
|
|
112
110
|
start, end = pair
|
|
113
111
|
if start == end:
|
|
114
|
-
return "
|
|
112
|
+
return f"{start}"
|
|
115
113
|
else:
|
|
116
|
-
return "
|
|
114
|
+
return f"{start}-{end}"
|
|
117
115
|
|
|
118
116
|
|
|
119
117
|
def bool_or_none(b: Any) -> bool | None:
|
|
@@ -158,37 +156,39 @@ def ensure_dir_for_file(path: str) -> None:
|
|
|
158
156
|
|
|
159
157
|
class Hasher:
|
|
160
158
|
"""Hashes Python data for fingerprinting."""
|
|
159
|
+
|
|
161
160
|
def __init__(self) -> None:
|
|
162
161
|
self.hash = hashlib.new("sha3_256", usedforsecurity=False)
|
|
163
162
|
|
|
164
163
|
def update(self, v: Any) -> None:
|
|
165
164
|
"""Add `v` to the hash, recursively if needed."""
|
|
166
165
|
self.hash.update(str(type(v)).encode("utf-8"))
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
166
|
+
match v:
|
|
167
|
+
case None:
|
|
168
|
+
pass
|
|
169
|
+
case str():
|
|
170
|
+
self.hash.update(v.encode("utf-8"))
|
|
171
|
+
case bytes():
|
|
172
|
+
self.hash.update(v)
|
|
173
|
+
case int() | float():
|
|
174
|
+
self.hash.update(str(v).encode("utf-8"))
|
|
175
|
+
case tuple() | list():
|
|
176
|
+
for e in v:
|
|
177
|
+
self.update(e)
|
|
178
|
+
case dict():
|
|
179
|
+
keys = v.keys()
|
|
180
|
+
for k in sorted(keys):
|
|
181
|
+
self.update(k)
|
|
182
|
+
self.update(v[k])
|
|
183
|
+
case _:
|
|
184
|
+
for k in dir(v):
|
|
185
|
+
if k.startswith("__"):
|
|
186
|
+
continue
|
|
187
|
+
a = getattr(v, k)
|
|
188
|
+
if inspect.isroutine(a):
|
|
189
|
+
continue
|
|
190
|
+
self.update(k)
|
|
191
|
+
self.update(a)
|
|
192
192
|
self.hash.update(b".")
|
|
193
193
|
|
|
194
194
|
def hexdigest(self) -> str:
|
|
@@ -218,6 +218,7 @@ class DefaultValue:
|
|
|
218
218
|
and Sphinx output.
|
|
219
219
|
|
|
220
220
|
"""
|
|
221
|
+
|
|
221
222
|
def __init__(self, display_as: str) -> None:
|
|
222
223
|
self.display_as = display_as
|
|
223
224
|
|
|
@@ -244,13 +245,13 @@ def substitute_variables(text: str, variables: Mapping[str, str]) -> str:
|
|
|
244
245
|
dollar_pattern = r"""(?x) # Use extended regex syntax
|
|
245
246
|
\$ # A dollar sign,
|
|
246
247
|
(?: # then
|
|
247
|
-
(?P<dollar
|
|
248
|
-
(?P<word1
|
|
249
|
-
{
|
|
250
|
-
(?P<word2
|
|
251
|
-
(?:
|
|
252
|
-
(?P<strict
|
|
253
|
-
-(?P<defval>[^}]*)
|
|
248
|
+
(?P<dollar> \$ ) | # a dollar sign, or
|
|
249
|
+
(?P<word1> \w+ ) | # a plain word, or
|
|
250
|
+
\{ # a {-wrapped
|
|
251
|
+
(?P<word2> \w+ ) # word,
|
|
252
|
+
(?: # either
|
|
253
|
+
(?P<strict> \? ) | # with a strict marker
|
|
254
|
+
-(?P<defval> [^}]* ) # or a default value
|
|
254
255
|
)? # maybe.
|
|
255
256
|
}
|
|
256
257
|
)
|
|
@@ -261,7 +262,7 @@ def substitute_variables(text: str, variables: Mapping[str, str]) -> str:
|
|
|
261
262
|
def dollar_replace(match: re.Match[str]) -> str:
|
|
262
263
|
"""Called for each $replacement."""
|
|
263
264
|
# Only one of the dollar_groups will have matched, just get its text.
|
|
264
|
-
word = next(g for g in match.group(*dollar_groups) if g)
|
|
265
|
+
word = next(g for g in match.group(*dollar_groups) if g) # pragma: always breaks
|
|
265
266
|
if word == "$":
|
|
266
267
|
return "$"
|
|
267
268
|
elif word in variables:
|
|
@@ -277,8 +278,7 @@ def substitute_variables(text: str, variables: Mapping[str, str]) -> str:
|
|
|
277
278
|
|
|
278
279
|
|
|
279
280
|
def format_local_datetime(dt: datetime.datetime) -> str:
|
|
280
|
-
"""Return a string with local timezone representing the date.
|
|
281
|
-
"""
|
|
281
|
+
"""Return a string with local timezone representing the date."""
|
|
282
282
|
return dt.astimezone().strftime("%Y-%m-%d %H:%M %z")
|
|
283
283
|
|
|
284
284
|
|
|
@@ -311,6 +311,7 @@ def _human_key(s: str) -> tuple[list[str | int], str]:
|
|
|
311
311
|
The original string is appended as a last value to ensure the
|
|
312
312
|
key is unique enough so that "x1y" and "x001y" can be distinguished.
|
|
313
313
|
"""
|
|
314
|
+
|
|
314
315
|
def tryint(s: str) -> str | int:
|
|
315
316
|
"""If `s` is a number, return an int, else `s` unchanged."""
|
|
316
317
|
try:
|
|
@@ -320,6 +321,7 @@ def _human_key(s: str) -> tuple[list[str | int], str]:
|
|
|
320
321
|
|
|
321
322
|
return ([tryint(c) for c in re.split(r"(\d+)", s)], s)
|
|
322
323
|
|
|
324
|
+
|
|
323
325
|
def human_sorted(strings: Iterable[str]) -> list[str]:
|
|
324
326
|
"""Sort the given iterable of strings the way that humans expect.
|
|
325
327
|
|
|
@@ -330,8 +332,10 @@ def human_sorted(strings: Iterable[str]) -> list[str]:
|
|
|
330
332
|
"""
|
|
331
333
|
return sorted(strings, key=_human_key)
|
|
332
334
|
|
|
335
|
+
|
|
333
336
|
SortableItem = TypeVar("SortableItem", bound=Sequence[Any])
|
|
334
337
|
|
|
338
|
+
|
|
335
339
|
def human_sorted_items(
|
|
336
340
|
items: Iterable[SortableItem],
|
|
337
341
|
reverse: bool = False,
|
coverage/multiproc.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
|
|
2
|
-
# For details: https://github.com/
|
|
2
|
+
# For details: https://github.com/coveragepy/coveragepy/blob/main/NOTICE.txt
|
|
3
3
|
|
|
4
4
|
"""Monkey-patching to add multiprocessing support for coverage.py"""
|
|
5
5
|
|
|
@@ -11,7 +11,6 @@ import os
|
|
|
11
11
|
import os.path
|
|
12
12
|
import sys
|
|
13
13
|
import traceback
|
|
14
|
-
|
|
15
14
|
from typing import Any
|
|
16
15
|
|
|
17
16
|
from coverage.debug import DebugControl
|
|
@@ -22,16 +21,18 @@ PATCHED_MARKER = "_coverage$patched"
|
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
OriginalProcess = multiprocessing.process.BaseProcess
|
|
25
|
-
original_bootstrap = OriginalProcess._bootstrap
|
|
24
|
+
original_bootstrap = OriginalProcess._bootstrap # type: ignore[attr-defined]
|
|
25
|
+
|
|
26
26
|
|
|
27
|
-
class ProcessWithCoverage(OriginalProcess):
|
|
27
|
+
class ProcessWithCoverage(OriginalProcess): # pylint: disable=abstract-method
|
|
28
28
|
"""A replacement for multiprocess.Process that starts coverage."""
|
|
29
29
|
|
|
30
|
-
def _bootstrap(self, *args, **kwargs):
|
|
30
|
+
def _bootstrap(self, *args, **kwargs): # type: ignore[no-untyped-def]
|
|
31
31
|
"""Wrapper around _bootstrap to start coverage."""
|
|
32
32
|
debug: DebugControl | None = None
|
|
33
33
|
try:
|
|
34
|
-
from coverage import Coverage
|
|
34
|
+
from coverage import Coverage # avoid circular import
|
|
35
|
+
|
|
35
36
|
cov = Coverage(data_suffix=True, auto_data=True)
|
|
36
37
|
cov._warn_preimported_source = False
|
|
37
38
|
cov.start()
|
|
@@ -61,8 +62,10 @@ class ProcessWithCoverage(OriginalProcess): # pylint: disable=abstract-m
|
|
|
61
62
|
if debug:
|
|
62
63
|
debug.write("Saved multiprocessing data")
|
|
63
64
|
|
|
65
|
+
|
|
64
66
|
class Stowaway:
|
|
65
67
|
"""An object to pickle, so when it is unpickled, it can apply the monkey-patch."""
|
|
68
|
+
|
|
66
69
|
def __init__(self, rcfile: str) -> None:
|
|
67
70
|
self.rcfile = rcfile
|
|
68
71
|
|
|
@@ -86,7 +89,7 @@ def patch_multiprocessing(rcfile: str) -> None:
|
|
|
86
89
|
if hasattr(multiprocessing, PATCHED_MARKER):
|
|
87
90
|
return
|
|
88
91
|
|
|
89
|
-
OriginalProcess._bootstrap = ProcessWithCoverage._bootstrap
|
|
92
|
+
OriginalProcess._bootstrap = ProcessWithCoverage._bootstrap # type: ignore[attr-defined]
|
|
90
93
|
|
|
91
94
|
# Set the value in ProcessWithCoverage that will be pickled into the child
|
|
92
95
|
# process.
|
|
@@ -100,10 +103,12 @@ def patch_multiprocessing(rcfile: str) -> None:
|
|
|
100
103
|
# Windows only spawns, so this is needed to keep Windows working.
|
|
101
104
|
try:
|
|
102
105
|
from multiprocessing import spawn
|
|
106
|
+
|
|
103
107
|
original_get_preparation_data = spawn.get_preparation_data
|
|
104
108
|
except (ImportError, AttributeError):
|
|
105
109
|
pass
|
|
106
110
|
else:
|
|
111
|
+
|
|
107
112
|
def get_preparation_data_with_stowaway(name: str) -> dict[str, Any]:
|
|
108
113
|
"""Get the original preparation data, and also insert our stowaway."""
|
|
109
114
|
d = original_get_preparation_data(name)
|
coverage/numbits.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
|
|
2
|
-
# For details: https://github.com/
|
|
2
|
+
# For details: https://github.com/coveragepy/coveragepy/blob/main/NOTICE.txt
|
|
3
3
|
|
|
4
4
|
"""
|
|
5
5
|
Functions to manipulate packed binary representations of number sets.
|
|
@@ -18,9 +18,8 @@ from __future__ import annotations
|
|
|
18
18
|
|
|
19
19
|
import json
|
|
20
20
|
import sqlite3
|
|
21
|
-
|
|
22
|
-
from itertools import zip_longest
|
|
23
21
|
from collections.abc import Iterable
|
|
22
|
+
from itertools import zip_longest
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
def nums_to_numbits(nums: Iterable[int]) -> bytes:
|
|
@@ -39,7 +38,7 @@ def nums_to_numbits(nums: Iterable[int]) -> bytes:
|
|
|
39
38
|
return b""
|
|
40
39
|
b = bytearray(nbytes)
|
|
41
40
|
for num in nums:
|
|
42
|
-
b[num//8] |= 1 << num % 8
|
|
41
|
+
b[num // 8] |= 1 << num % 8
|
|
43
42
|
return bytes(b)
|
|
44
43
|
|
|
45
44
|
|
|
@@ -59,7 +58,7 @@ def numbits_to_nums(numbits: bytes) -> list[int]:
|
|
|
59
58
|
nums = []
|
|
60
59
|
for byte_i, byte in enumerate(numbits):
|
|
61
60
|
for bit_i in range(8):
|
|
62
|
-
if
|
|
61
|
+
if byte & (1 << bit_i):
|
|
63
62
|
nums.append(byte_i * 8 + bit_i)
|
|
64
63
|
return nums
|
|
65
64
|
|