This commit is contained in:
parent
aace705f2e
commit
b491ce97f0
3 changed files with 109 additions and 2 deletions
|
@ -6,8 +6,10 @@ steps:
|
||||||
- name: validate
|
- name: validate
|
||||||
image: python:3
|
image: python:3
|
||||||
commands:
|
commands:
|
||||||
- pip install mypy
|
- pip install mypy pytest
|
||||||
- mypy bytetrie/bytetrie.py
|
- mypy bytetrie/bytetrie.py
|
||||||
|
- mypy bytetrie/util.py
|
||||||
|
- python -m pytest
|
||||||
|
|
||||||
- name: publish
|
- name: publish
|
||||||
image: python:3
|
image: python:3
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
|
from typing import Sequence, MutableSequence, ByteString, Any, Optional
|
||||||
|
|
||||||
def has_common_prefix(label: ByteString, other_label: ByteString) -> bool:
|
def has_common_prefix(label: ByteString, other_label: ByteString) -> bool:
|
||||||
""" Whether label and other_label have a prefix in common. """
|
""" Whether label and other_label have a prefix in common. """
|
||||||
assert label and other_label
|
if not label or not other_label: return False
|
||||||
return True if label[0] == other_label[0] else False
|
return True if label[0] == other_label[0] else False
|
||||||
|
|
||||||
def common_prefix(label: ByteString, other_label: ByteString) -> ByteString:
|
def common_prefix(label: ByteString, other_label: ByteString) -> ByteString:
|
||||||
""" Get the common prefix of label and other_label. """
|
""" Get the common prefix of label and other_label. """
|
||||||
buffer = bytearray()
|
buffer = bytearray()
|
||||||
|
if not label or not other_label: return buffer
|
||||||
for (a,b) in zip(label, other_label):
|
for (a,b) in zip(label, other_label):
|
||||||
if a == b: buffer.append(a)
|
if a == b: buffer.append(a)
|
||||||
else: break
|
else: break
|
||||||
|
@ -13,6 +16,8 @@ def common_prefix(label: ByteString, other_label: ByteString) -> ByteString:
|
||||||
|
|
||||||
def is_prefix_of(prefix: ByteString, label: ByteString) -> bool:
|
def is_prefix_of(prefix: ByteString, label: ByteString) -> bool:
|
||||||
""" Whether label starts with prefix """
|
""" Whether label starts with prefix """
|
||||||
|
if not prefix or not label: return False
|
||||||
|
|
||||||
if len(prefix) > len(label):
|
if len(prefix) > len(label):
|
||||||
return False
|
return False
|
||||||
for (a,b) in zip(prefix, label):
|
for (a,b) in zip(prefix, label):
|
||||||
|
|
100
tests/test_util.py
Normal file
100
tests/test_util.py
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from bytetrie import util
|
||||||
|
|
||||||
|
class TestHasCommonPrefix:
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("label", "other_label"),
|
||||||
|
((b"", b"val"),
|
||||||
|
("val", b""),
|
||||||
|
(None, b"val"),
|
||||||
|
(b"val", None)))
|
||||||
|
def test_falsy_argument_false(self, label, other_label):
|
||||||
|
assert not util.has_common_prefix(label, other_label)
|
||||||
|
|
||||||
|
def test_first_char_differs_false(self):
|
||||||
|
assert not util.has_common_prefix(b"ab", b"bb")
|
||||||
|
|
||||||
|
def test_first_char_equal_true(self):
|
||||||
|
assert util.has_common_prefix(b"ab", b"aa")
|
||||||
|
|
||||||
|
def test_handles_different_byte_types(self):
|
||||||
|
assert util.has_common_prefix(b"a", bytes([97]))
|
||||||
|
assert util.has_common_prefix(bytes("a", 'utf-8'), bytes([0x61]))
|
||||||
|
assert util.has_common_prefix(bytearray("a", 'utf-8'), bytes([0x61]))
|
||||||
|
assert util.has_common_prefix(b"a", memoryview(bytes("a", 'utf-8')))
|
||||||
|
|
||||||
|
class TestCommonPrefix:
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("label", "other_label"),
|
||||||
|
((b"", b"val"),
|
||||||
|
("val", b""),
|
||||||
|
(None, b"val"),
|
||||||
|
(b"val", None)))
|
||||||
|
def test_falsy_argument_empty(self, label, other_label):
|
||||||
|
assert util.common_prefix(label, other_label) == bytes()
|
||||||
|
|
||||||
|
def test_first_char_differs_empty(self):
|
||||||
|
assert util.common_prefix(b"ab", b"bb") == bytes()
|
||||||
|
|
||||||
|
def test_has_common_prefix_prefix(self):
|
||||||
|
assert util.common_prefix(b"abd", b"abc") == b"ab"
|
||||||
|
|
||||||
|
def test_handles_different_lengths(self):
|
||||||
|
assert util.common_prefix(b"abde", b"abc") == b"ab"
|
||||||
|
assert util.common_prefix(b"ab", b"ab") == b"ab"
|
||||||
|
assert util.common_prefix(b"ab", b"abc") == b"ab"
|
||||||
|
assert util.common_prefix(b"abde", b"abcde") == b"ab"
|
||||||
|
|
||||||
|
def test_other_label_is_prefix(self):
|
||||||
|
assert util.common_prefix(b"abc", b"ab") == b"ab"
|
||||||
|
|
||||||
|
class TestIsPrefixOf:
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("label", "other_label"),
|
||||||
|
((b"", b"val"),
|
||||||
|
("val", b""),
|
||||||
|
(None, b"val"),
|
||||||
|
(b"val", None)))
|
||||||
|
def test_falsy_argument_false(self, label, other_label):
|
||||||
|
assert not util.is_prefix_of(label, other_label)
|
||||||
|
|
||||||
|
def test_prefix_too_long_false(self):
|
||||||
|
assert not util.is_prefix_of(b"ab", b"a")
|
||||||
|
|
||||||
|
def test_no_prefix_false(self):
|
||||||
|
assert not util.is_prefix_of(b"b", b"ab")
|
||||||
|
assert not util.is_prefix_of(b"ab", b"ac")
|
||||||
|
|
||||||
|
def test_prefix_true(self):
|
||||||
|
assert util.is_prefix_of(b"ab", b"abc")
|
||||||
|
|
||||||
|
class TestCutOffPrefix:
|
||||||
|
def test_no_prefix_error(self):
|
||||||
|
with pytest.raises(AssertionError):
|
||||||
|
util.cut_off_prefix(b"ab", "bb")
|
||||||
|
|
||||||
|
def test_prefix_cut_off(self):
|
||||||
|
assert util.cut_off_prefix(b"ab", b"abc") == b"c"
|
||||||
|
|
||||||
|
def test_equals_empyt(self):
|
||||||
|
assert util.cut_off_prefix(b"ab", b"ab") == b""
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("prefix", "label"),
|
||||||
|
((b"", b"val"),
|
||||||
|
("val", b""),
|
||||||
|
(None, b"val"),
|
||||||
|
(b"val", None)))
|
||||||
|
def test_falsy_error(self, prefix, label):
|
||||||
|
with pytest.raises(AssertionError):
|
||||||
|
util.cut_off_prefix(prefix, label)
|
||||||
|
|
||||||
|
def test_does_not_modify(self):
|
||||||
|
p = b"ab"
|
||||||
|
l = b"abc"
|
||||||
|
|
||||||
|
assert util.cut_off_prefix(p, l) == b"c"
|
||||||
|
assert l == b"abc"
|
||||||
|
assert p == b"ab"
|
||||||
|
|
Loading…
Reference in a new issue