Skip to content

Commit 0252c34

Browse files
committed
refactor: move numbits aggregate to numbits
1 parent 1c4184c commit 0252c34

3 files changed

Lines changed: 27 additions & 32 deletions

File tree

‎coverage/numbits.py‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,25 @@ def num_in_numbits(num: int, numbits: bytes) -> bool:
109109
return bool(numbits[nbyte] & (1 << nbit))
110110

111111

112+
class NumbitsUnionAgg:
113+
"""SQLite aggregate function for computing union of numbits."""
114+
115+
def __init__(self) -> None:
116+
self.result = 0
117+
self.result_nbytes = 0
118+
119+
def step(self, value: bytes) -> None:
120+
"""Process one value in the aggregation."""
121+
self.result |= int.from_bytes(value, "little")
122+
self.result_nbytes = max(self.result_nbytes, len(value))
123+
124+
def finalize(self) -> bytes:
125+
"""Return the final aggregated result."""
126+
if not self.result_nbytes:
127+
return b""
128+
return self.result.to_bytes(self.result_nbytes, "little")
129+
130+
112131
def register_sqlite_functions(connection: sqlite3.Connection) -> None:
113132
"""
114133
Define numbits functions in a SQLite connection.
@@ -144,3 +163,4 @@ def register_sqlite_functions(connection: sqlite3.Connection) -> None:
144163
connection.create_function("numbits_any_intersection", 2, numbits_any_intersection)
145164
connection.create_function("num_in_numbits", 2, num_in_numbits)
146165
connection.create_function("numbits_to_nums", 1, lambda b: json.dumps(numbits_to_nums(b)))
166+
connection.create_aggregate("numbits_union_agg", 1, NumbitsUnionAgg) # type: ignore[arg-type]

‎coverage/sqldata.py‎

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@
2828
from coverage.debug import NoDebugging, auto_repr, file_summary
2929
from coverage.exceptions import CoverageException, DataError
3030
from coverage.misc import Hasher, file_be_gone, isolate_module
31-
from coverage.numbits import numbits_to_nums, numbits_union, nums_to_numbits
31+
from coverage.numbits import (
32+
numbits_to_nums,
33+
numbits_union,
34+
nums_to_numbits,
35+
register_sqlite_functions,
36+
)
3237
from coverage.sqlitedb import SqliteDb
3338
from coverage.types import AnyCallable, FilePath, TArc, TDebugCtl, TLineNo, TWarnFn
3439
from coverage.version import __version__
@@ -128,25 +133,6 @@ def _wrapped(self: CoverageData, *args: Any, **kwargs: Any) -> Any:
128133
return _wrapped
129134

130135

131-
class NumbitsUnionAgg:
132-
"""SQLite aggregate function for computing union of numbits."""
133-
134-
def __init__(self) -> None:
135-
self.result = 0
136-
self.result_nbytes = 0
137-
138-
def step(self, value: bytes) -> None:
139-
"""Process one value in the aggregation."""
140-
self.result |= int.from_bytes(value, "little")
141-
self.result_nbytes = max(self.result_nbytes, len(value))
142-
143-
def finalize(self) -> bytes:
144-
"""Return the final aggregated result."""
145-
if not self.result_nbytes:
146-
return b""
147-
return self.result.to_bytes(self.result_nbytes, "little")
148-
149-
150136
class CoverageData:
151137
"""Manages collected coverage data, including file storage.
152138
@@ -750,13 +736,8 @@ def update(
750736
con.con.isolation_level = "IMMEDIATE"
751737

752738
# Register functions for SQLite
753-
con.con.create_function("numbits_union", 2, numbits_union)
739+
register_sqlite_functions(con.con)
754740
con.con.create_function("map_path", 1, map_path)
755-
con.con.create_aggregate(
756-
"numbits_union_agg",
757-
1,
758-
NumbitsUnionAgg, # type: ignore[arg-type]
759-
)
760741

761742
# Attach the other database
762743
con.execute_void("ATTACH DATABASE ? AS other_db", (other_data.data_filename(),))

‎tests/test_numbits.py‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
num_in_numbits,
2121
register_sqlite_functions,
2222
)
23-
from coverage.sqldata import NumbitsUnionAgg
2423

2524
from tests.coveragetest import CoverageTest
2625
from tests.hypo import example, given, settings
@@ -113,11 +112,6 @@ def setUp(self) -> None:
113112
conn = sqlite3.connect(":memory:")
114113
register_sqlite_functions(conn)
115114
self.cursor = conn.cursor()
116-
conn.create_aggregate(
117-
"numbits_union_agg",
118-
1,
119-
NumbitsUnionAgg, # type: ignore[arg-type]
120-
)
121115
self.cursor.execute("create table data (id int, numbits blob)")
122116
self.cursor.executemany(
123117
"insert into data (id, numbits) values (?, ?)",

0 commit comments

Comments
 (0)