diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2019-07-30 11:06:36 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2019-07-31 10:24:39 -0400 |
commit | e94f523162dd39acddfa17b20f4234f1ee5dec7f (patch) | |
tree | a793a838a78b13b159b5eec8c2184b6cdf85a9df /coverage/numbits.py | |
parent | ad620d081c8508f94846fc01be331f107cb14050 (diff) | |
download | python-coveragepy-git-e94f523162dd39acddfa17b20f4234f1ee5dec7f.tar.gz |
Refactor numbits into their own files
Diffstat (limited to 'coverage/numbits.py')
-rw-r--r-- | coverage/numbits.py | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/coverage/numbits.py b/coverage/numbits.py new file mode 100644 index 00000000..bc29ed94 --- /dev/null +++ b/coverage/numbits.py @@ -0,0 +1,42 @@ +# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 +# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt + +""" +Functions to manipulate packed binary representations of number sets. + +To save space, coverage stores sets of line numbers in SQLite using a packed +binary representation called a numbits. A numbits is stored as a blob in the +database. The exact meaning of the bytes in the blobs should be considered an +implementation detail that might change in the future. Use these functions to +work with those binary blobs of data. + +""" + +from coverage.backward import bytes_to_ints, binary_bytes, zip_longest +from coverage.misc import contract + + +@contract(nums='Iterable', returns='bytes') +def nums_to_numbits(nums): + """Convert `nums` (an iterable of ints) into a numbits.""" + nbytes = max(nums) // 8 + 1 + b = bytearray(nbytes) + for num in nums: + b[num//8] |= 1 << num % 8 + return bytes(b) + +@contract(numbits='bytes', returns='list[int]') +def numbits_to_nums(numbits): + """Convert a numbits into a list of numbers.""" + nums = [] + for byte_i, byte in enumerate(bytes_to_ints(numbits)): + for bit_i in range(8): + if (byte & (1 << bit_i)): + nums.append(byte_i * 8 + bit_i) + return nums + +@contract(numbits1='bytes', numbits2='bytes', returns='bytes') +def merge_numbits(numbits1, numbits2): + """Merge two numbits""" + byte_pairs = zip_longest(bytes_to_ints(numbits1), bytes_to_ints(numbits2), fillvalue=0) + return binary_bytes(b1 | b2 for b1, b2 in byte_pairs) |