Skip to content
This repository was archived by the owner on May 5, 2025. It is now read-only.

Commit 9d1b9b1

Browse files
authored
Remove more unused Report code, change serde code to use str (#575)
1 parent d84177b commit 9d1b9b1

8 files changed

Lines changed: 109 additions & 243 deletions

File tree

shared/reports/readonly.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
END_OF_HEADER,
1313
Report,
1414
ReportTotals,
15-
chunks_from_storage_contains_header,
1615
)
1716
from shared.utils.match import Matcher
1817

@@ -23,8 +22,9 @@ class LazyRustReport(object):
2322
def __init__(self, filename_mapping, chunks, session_mapping):
2423
# Because Rust can't parse the header. It doesn't need it either,
2524
# So it's simpler to just never sent it.
26-
if chunks_from_storage_contains_header(chunks):
27-
_, chunks = chunks.split(END_OF_HEADER, 1)
25+
splits = chunks.split(END_OF_HEADER, maxsplit=1)
26+
if len(splits) > 1:
27+
chunks = splits[1]
2828
self._chunks = chunks
2929
self._filename_mapping = filename_mapping
3030
self._session_mapping = session_mapping

shared/reports/resources.py

Lines changed: 14 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,14 @@
1313
from shared.reports.exceptions import LabelIndexNotFoundError, LabelNotFoundError
1414
from shared.reports.filtered import FilteredReport
1515
from shared.reports.reportfile import ReportFile
16-
from shared.reports.serde import orjson_option, report_default
17-
from shared.reports.types import TOTALS_MAP, ReportHeader, ReportTotals
16+
from shared.reports.types import ReportHeader, ReportTotals
1817
from shared.utils.flare import report_to_flare
1918
from shared.utils.make_network_file import make_network_file
2019
from shared.utils.migrate import migrate_totals
2120
from shared.utils.sessions import Session, SessionType
2221
from shared.utils.totals import agg_totals
2322

24-
from .serde import _encode_chunk, serialize_report
23+
from .serde import END_OF_CHUNK, END_OF_HEADER, serialize_report
2524

2625
log = logging.getLogger(__name__)
2726

@@ -37,21 +36,6 @@ def unique_everseen(iterable):
3736
yield element
3837

3938

40-
END_OF_CHUNK = "\n<<<<< end_of_chunk >>>>>\n"
41-
END_OF_HEADER = "\n<<<<< end_of_header >>>>>\n"
42-
43-
44-
def chunks_from_storage_contains_header(chunks: str) -> bool:
45-
try:
46-
first_line_end = chunks.index("\n")
47-
second_line_end = chunks.index("\n", first_line_end + 1)
48-
except ValueError:
49-
return False
50-
# If the header is present then the END_OF_HEADER marker
51-
# is in the 2nd line of the report
52-
return chunks[first_line_end : second_line_end + 1] == END_OF_HEADER
53-
54-
5539
class Report:
5640
sessions: dict[int, Session]
5741
_header: ReportHeader
@@ -80,14 +64,14 @@ def __init__(
8064
for sid, session in sessions.items()
8165
}
8266

83-
_chunks: list[bytes] = []
67+
_chunks: list[str] = []
8468
if chunks:
85-
if isinstance(chunks, str):
86-
chunks = chunks.encode()
8769
if isinstance(chunks, bytes):
88-
splits = chunks.split(b"\n<<<<< end_of_header >>>>>\n", maxsplit=1)
70+
chunks = chunks.decode()
71+
if isinstance(chunks, str):
72+
splits = chunks.split(END_OF_HEADER, maxsplit=1)
8973
if len(splits) > 1:
90-
_header = orjson.loads(splits[0] or b"{}")
74+
_header = orjson.loads(splits[0] or "{}")
9175
self._header = ReportHeader(
9276
labels_index={
9377
int(k): v
@@ -96,7 +80,7 @@ def __init__(
9680
)
9781
chunks = splits[1]
9882

99-
_chunks = chunks.split(b"\n<<<<< end_of_chunk >>>>>\n")
83+
_chunks = chunks.split(END_OF_CHUNK)
10084
else:
10185
_chunks = chunks
10286

@@ -112,8 +96,7 @@ def __init__(
11296
file_diff_totals = None
11397

11498
try:
115-
_lines = _chunks[chunks_index]
116-
lines = _lines.decode() if isinstance(_lines, bytes) else _lines
99+
lines = _chunks[chunks_index]
117100
except IndexError:
118101
lines = ""
119102

@@ -345,42 +328,12 @@ def is_empty(self):
345328
def __bool__(self):
346329
return self.is_empty() is False
347330

348-
@sentry_sdk.trace
349-
def to_archive(self, with_header=True):
350-
# TODO: confirm removing encoding here is fine
351-
chunks = END_OF_CHUNK.join(
352-
_encode_chunk(chunk).decode() for chunk in self._files.values()
353-
)
354-
if with_header:
355-
# When saving to database we want this
356-
return END_OF_HEADER.join(
357-
[orjson.dumps(self._header, option=orjson_option).decode(), chunks]
358-
)
359-
# This is helpful to build ReadOnlyReport
360-
# Because Rust can't parse the header. It doesn't need it either,
361-
# So it's simpler to just never sent it.
362-
return chunks
363-
364-
@sentry_sdk.trace
365-
def to_database(self):
366-
"""returns (totals, report) to be stored in database"""
367-
totals = dict(zip(TOTALS_MAP, self.totals))
368-
totals["diff"] = self.diff_totals
369-
370-
files = {
371-
file.name: [i, file.totals, None, file.diff_totals]
372-
for i, file in enumerate(self._files.values())
373-
}
374-
return (
375-
totals,
376-
orjson.dumps(
377-
{"files": files, "sessions": self.sessions},
378-
default=report_default,
379-
option=orjson_option,
380-
).decode(),
381-
)
382-
383331
def serialize(self, with_totals=True) -> tuple[bytes, bytes, ReportTotals | None]:
332+
"""
333+
Serializes a report as `(report_json, chunks, totals)`.
334+
335+
The `totals` is either a `ReportTotals`, or `None`, depending on the `with_totals` flag.
336+
"""
384337
return serialize_report(self, with_totals)
385338

386339
@sentry_sdk.trace
@@ -584,10 +537,6 @@ def get_uploaded_flags(self):
584537
flags.update(sess.flags)
585538
return flags
586539

587-
@sentry_sdk.trace
588-
def repack(self):
589-
pass
590-
591540
def delete_labels(
592541
self, sessionids: list[int] | set[int], labels_to_delete: list[int] | set[int]
593542
):

shared/reports/serde.py

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
from .resources import Report
1717

1818

19-
END_OF_CHUNK = b"\n<<<<< end_of_chunk >>>>>\n"
20-
END_OF_HEADER = b"\n<<<<< end_of_header >>>>>\n"
19+
END_OF_CHUNK = "\n<<<<< end_of_chunk >>>>>\n"
20+
END_OF_HEADER = "\n<<<<< end_of_header >>>>>\n"
2121

2222

2323
@sentry_sdk.trace
@@ -33,7 +33,7 @@ def serialize_report(
3333
indexed_files = list(enumerate(report._files.values()))
3434

3535
chunks = (
36-
orjson.dumps(report._header, option=orjson_option)
36+
orjson.dumps(report._header, option=orjson_option).decode()
3737
+ END_OF_HEADER
3838
+ END_OF_CHUNK.join(_encode_chunk(file) for i, file in indexed_files)
3939
)
@@ -57,7 +57,7 @@ def serialize_report(
5757
option=orjson_option,
5858
)
5959

60-
return (report_json, chunks, totals)
60+
return (report_json, chunks.encode(), totals)
6161

6262

6363
def report_default(obj):
@@ -81,18 +81,18 @@ def report_default(obj):
8181
orjson_option = orjson.OPT_PASSTHROUGH_DATACLASS | orjson.OPT_NON_STR_KEYS
8282

8383

84-
def _dumps_not_none(value) -> bytes:
84+
def _dumps_not_none(value) -> str:
8585
if isinstance(value, list):
8686
return orjson.dumps(
8787
_rstrip_none(list(value)), default=report_default, option=orjson_option
88-
)
88+
).decode()
8989
if isinstance(value, ReportLine):
9090
return orjson.dumps(
9191
_rstrip_none(list(value.astuple())),
9292
default=report_default,
9393
option=orjson_option,
94-
)
95-
return value.encode() if value and str(value) != "null" else b""
94+
).decode()
95+
return value if value and value != "null" else ""
9696

9797

9898
def _rstrip_none(lst):
@@ -107,21 +107,19 @@ def chunk_default(obj):
107107
return obj
108108

109109

110-
def _encode_chunk(chunk) -> bytes:
110+
def _encode_chunk(chunk) -> str:
111111
if chunk is None:
112-
return b"null"
112+
return "null"
113113
elif isinstance(chunk, ReportFile):
114114
if isinstance(chunk._raw_lines, str):
115-
return chunk._raw_lines.encode()
115+
return chunk._raw_lines
116116
else:
117117
return (
118-
orjson.dumps(chunk.details, option=orjson_option)
119-
+ b"\n"
120-
+ b"\n".join(_dumps_not_none(line) for line in chunk._lines)
118+
orjson.dumps(chunk.details, option=orjson_option).decode()
119+
+ "\n"
120+
+ "\n".join(_dumps_not_none(line) for line in chunk._lines)
121121
)
122122
elif isinstance(chunk, (list, dict)):
123-
return orjson.dumps(chunk, default=chunk_default, option=orjson_option)
124-
elif isinstance(chunk, str):
125-
return chunk.encode()
123+
return orjson.dumps(chunk, default=chunk_default, option=orjson_option).decode()
126124
else:
127125
return chunk

tests/integration/test_report.py

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -402,42 +402,6 @@ def test_non_zero(r, boolean):
402402
assert bool(r) is boolean
403403

404404

405-
@pytest.mark.integration
406-
def test_to_archive():
407-
chunks = Report(
408-
files={"file.py": [0, ReportTotals()]},
409-
chunks="null\n[1]\n[1]\n[1]\n<<<<< end_of_chunk >>>>>\nnull\n[1]\n[1]\n[1]",
410-
).to_archive()
411-
assert chunks == """{}\n<<<<< end_of_header >>>>>\nnull\n[1]\n[1]\n[1]"""
412-
413-
414-
@pytest.mark.integration
415-
def test_to_database():
416-
totals, report_json = Report(
417-
files={"file.py": [0, ReportTotals()]},
418-
chunks="null\n[1]\n[1]\n[1]\n<<<<< end_of_chunk >>>>>\nnull\n[1]\n[1]\n[1]",
419-
).to_database()
420-
assert totals == {
421-
"M": 0,
422-
"c": None,
423-
"b": 0,
424-
"d": 0,
425-
"f": 1,
426-
"h": 0,
427-
"m": 0,
428-
"C": 0,
429-
"n": 0,
430-
"p": 0,
431-
"s": 0,
432-
"diff": None,
433-
"N": 0,
434-
}
435-
assert (
436-
report_json
437-
== '{"files":{"file.py":[0,[0,0,0,0,0,0,0,0,0,0,0,0,0],null,null]},"sessions":{}}'
438-
)
439-
440-
441405
def test_serialize(mocker):
442406
report = Report(
443407
files={"file.py": [0, ReportTotals()]},

tests/unit/reports/test_carryforward.py

Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import dataclasses
2-
from json import loads
3-
41
import pytest
52

63
from shared.reports.carryforward import (
@@ -9,6 +6,7 @@
96
)
107
from shared.reports.resources import Report, ReportFile, Session
118
from shared.reports.types import LineSession, ReportLine
9+
from tests.unit.reports.utils import convert_report_to_better_readable
1210

1311

1412
@pytest.fixture
@@ -65,50 +63,10 @@ def test_carriedforward_session_name(self):
6563
carriedforward_session_name("CF CF CF CF CF CF CF Dude") == "CF[8] - Dude"
6664
)
6765

68-
def convert_report_to_better_readable(self, report):
69-
totals_dict, report_dict = report.to_database()
70-
report_dict = loads(report_dict)
71-
archive_dict = {}
72-
for filename in report.files:
73-
file_report = report.get(filename)
74-
lines = []
75-
for line_number, line in file_report.lines:
76-
(
77-
coverage,
78-
line_type,
79-
sessions,
80-
messages,
81-
complexity,
82-
datapoints,
83-
) = dataclasses.astuple(line)
84-
sessions = [list(s) for s in sessions]
85-
lines.append(
86-
(
87-
line_number,
88-
coverage,
89-
line_type,
90-
sessions,
91-
messages,
92-
complexity,
93-
datapoints,
94-
)
95-
if datapoints is not None
96-
else (
97-
line_number,
98-
coverage,
99-
line_type,
100-
sessions,
101-
messages,
102-
complexity,
103-
)
104-
)
105-
archive_dict[filename] = lines
106-
return {"totals": totals_dict, "report": report_dict, "archive": archive_dict}
107-
10866
def test_generate_carryforward_report(self, sample_report):
10967
res = generate_carryforward_report(sample_report, flags=["simple"], paths=None)
11068
assert res.files == ["file_1.go", "file_2.py"]
111-
readable_report = self.convert_report_to_better_readable(res)
69+
readable_report = convert_report_to_better_readable(res)
11270
expected_result = {
11371
"archive": {
11472
"file_1.go": [
@@ -199,7 +157,7 @@ def test_generate_carryforward_report_with_paths(self, sample_report):
199157
sample_report, flags=["simple"], paths=["file_1.*"]
200158
)
201159
assert res.files == ["file_1.go"]
202-
readable_report = self.convert_report_to_better_readable(res)
160+
readable_report = convert_report_to_better_readable(res)
203161
expected_result = {
204162
"archive": {
205163
"file_1.go": [
@@ -267,7 +225,7 @@ def test_generate_carryforward_report_with_path_none_matches(self, sample_report
267225
sample_report, flags=["simple"], paths=["file_\\W.*"]
268226
)
269227
assert res.files == []
270-
readable_report = self.convert_report_to_better_readable(res)
228+
readable_report = convert_report_to_better_readable(res)
271229
expected_result = {
272230
"archive": {},
273231
"report": {
@@ -320,7 +278,7 @@ def test_generate_carryforward_report_with_path_two_patterns(self, sample_report
320278
sample_report, flags=["simple"], paths=[".*\\.cpp", ".*_2\\..*"]
321279
)
322280
assert res.files == ["file_2.py"]
323-
readable_report = self.convert_report_to_better_readable(res)
281+
readable_report = convert_report_to_better_readable(res)
324282
assert readable_report == {
325283
"archive": {
326284
"file_2.py": [
@@ -375,7 +333,7 @@ def test_generate_carryforward_report_with_path_two_patterns(self, sample_report
375333
def test_generate_carryforward_report_one_file_not_covered(self, sample_report):
376334
res = generate_carryforward_report(sample_report, flags=["complex"], paths=None)
377335
assert res.files == ["file_1.go"]
378-
readable_report = self.convert_report_to_better_readable(res)
336+
readable_report = convert_report_to_better_readable(res)
379337

380338
expected_result = {
381339
"archive": {
@@ -447,7 +405,7 @@ def test_generate_carryforward_report_session_extras(self, sample_report):
447405
session_extras={"cfed_parent": "0f9ab1fe6c879bc49a9e559b23f49fd033daadb0"},
448406
)
449407
assert res.files == ["file_1.go"]
450-
readable_report = self.convert_report_to_better_readable(res)
408+
readable_report = convert_report_to_better_readable(res)
451409

452410
expected_result = {
453411
"archive": {

0 commit comments

Comments
 (0)