diff --git a/.coveragerc b/.coveragerc index e03c14d0..15cd15f3 100644 --- a/.coveragerc +++ b/.coveragerc @@ -4,15 +4,23 @@ [report] -omit = +omit = */python?.?/* */site-packages/* *__init__* exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + @abstractmethod + raise NotImplementedError - def __repr__ # exclude __repr__ methods - def __str__ # exclude __repr__ methods + + def __repr__ + + def __str__ + def __fields + def __invariants diff --git a/ands/ds/LinearProbingHashTable.py b/ands/ds/LinearProbingHashTable.py index da5e870f..33dd1cea 100644 --- a/ands/ds/LinearProbingHashTable.py +++ b/ands/ds/LinearProbingHashTable.py @@ -91,16 +91,21 @@ def __init__(self, capacity: int = 11): self._keys = [None] * self._n self._values = [None] * self._n + def __invariants(self): + """These conditions should always hold at the beginning and end of public methods!""" + assert len(self._keys) == len(self._values) == self._n + assert not has_duplicates_ignore_nones(self._keys) + @property def size(self) -> int: """Returns the number of pairs key-value in this map.""" - self.__invariants__() + self.__invariants() return sum(k is not None for k in self._keys) @property def capacity(self) -> int: """Returns the size of the internal buffers that store the keys and the values.""" - self.__invariants__() + self.__invariants() return len(self._keys) def put(self, key: object, value: object) -> None: @@ -110,9 +115,9 @@ def put(self, key: object, value: object) -> None: if key is None: raise TypeError("key cannot be None.") - self.__invariants__() + self.__invariants() self._put(key, value, self._n) - self.__invariants__() + self.__invariants() def _put(self, key: object, value: object, size: int) -> None: """Helper method of `self.put` and thus it's considered PRIVATE.""" @@ -181,17 +186,17 @@ def get(self, key: object) -> object: """Returns the value associated with `key`. If `key` is `None`, a `TypeError` is raised, because keys cannot be None.""" - self.__invariants__() + self.__invariants() if key is None: raise TypeError("key cannot be None.") value = LinearProbingHashTable._get(key, self._keys, self._values, self._n) - self.__invariants__() + self.__invariants() return value def delete(self, key: object) -> object: """Deletes the mapping between `key` and its corresponding associated value. If there's no mapping, nothing is done.""" - self.__invariants__() + self.__invariants() if key is None: raise TypeError("key cannot be None.") @@ -202,10 +207,10 @@ def delete(self, key: object) -> object: i = self._keys.index(key) v = self._values[i] self._keys[i] = self._values[i] = None - self.__invariants__() + self.__invariants() return v except ValueError: - self.__invariants__() + self.__invariants() pass def show(self) -> None: @@ -230,11 +235,6 @@ def __str__(self): def __repr__(self): return self.__str__() - def __invariants__(self): - """These conditions should always hold at the beginning and end of public methods!""" - assert len(self._keys) == len(self._values) == self._n - assert not has_duplicates_ignore_nones(self._keys) - @staticmethod def _hash_code(key, size: int) -> int: """Returns a hash code (an int) between 0 and `size` (excluded). diff --git a/ands/ds/TST.py b/ands/ds/TST.py index 87e98fa4..89ef85b2 100644 --- a/ands/ds/TST.py +++ b/ands/ds/TST.py @@ -139,7 +139,7 @@ def __init__(self): self._n = 0 self._root = None - def __invariants__(self) -> None: + def __invariants(self) -> None: """These propositions should always be true at the BEGINNING and END of every PUBLIC method of this TST. @@ -210,7 +210,7 @@ def insert(self, key: str, value: object) -> None: which also represents how many times we follow the middle link, and h is the number of left and right turns. So a lower bound of the complexity would be &Omega(m);.""" - self.__invariants__() + self.__invariants() if not isinstance(key, str): raise TypeError("key must be an instance of type str.") if not key: @@ -218,7 +218,7 @@ def insert(self, key: str, value: object) -> None: if value is None: raise ValueError("value cannot be None.") self._root = self._insert(self._root, key, value, 0) - self.__invariants__() + self.__invariants() def _insert(self, node: TSTNode, key: str, value: object, index: int): """Inserts `key` with `value` into self starting from `node`.""" @@ -370,7 +370,7 @@ def delete(self, key: str) -> TSTNode: k is the number of "no more necessary" cleaned up after deletion of the node associated with `key`. Unnecessary nodes are nodes with no children and value equal to None.""" - self.__invariants__() + self.__invariants() if not isinstance(key, str): raise TypeError("key must be an instance of type str.") @@ -390,7 +390,7 @@ def delete(self, key: str) -> TSTNode: else: result = None - self.__invariants__() + self.__invariants() return result def _delete_fix(self, u: TSTNode) -> None: diff --git a/tests/ds/test_LinearProbingHashTable.py b/tests/ds/test_LinearProbingHashTable.py index 143aabfb..a3a16d80 100755 --- a/tests/ds/test_LinearProbingHashTable.py +++ b/tests/ds/test_LinearProbingHashTable.py @@ -235,10 +235,3 @@ def test_show(self): t.put(elem, choice(string.ascii_letters)) print() t.show() - - def test_repr(self): - t = LinearProbingHashTable() - ls = sample(range(5), 5) - for elem in ls: - t.put(elem, choice(string.ascii_letters)) - print(repr(t)) diff --git a/tests/ds/test_MaxHeap.py b/tests/ds/test_MaxHeap.py index 7c683952..d6745361 100755 --- a/tests/ds/test_MaxHeap.py +++ b/tests/ds/test_MaxHeap.py @@ -526,11 +526,3 @@ def test_is_on_odd_level(self): self.assertFalse(h.is_on_odd_level(6)) self.assertTrue(h.is_on_odd_level(7)) self.assertTrue(h.is_on_odd_level(8)) - - def test_str(self): - h = MaxHeap([12, 14, 28, 6, 7, 18, 10, 3, 1]) - print(h) - - def test_repr(self): - h = MaxHeap([1, 2, 3, 4, 5]) - print(repr(h)) diff --git a/tests/ds/test_MinHeap.py b/tests/ds/test_MinHeap.py index 51f4b00f..a17a837e 100755 --- a/tests/ds/test_MinHeap.py +++ b/tests/ds/test_MinHeap.py @@ -584,11 +584,3 @@ def test_is_on_odd_level(self): self.assertFalse(h.is_on_odd_level(6)) self.assertTrue(h.is_on_odd_level(7)) self.assertTrue(h.is_on_odd_level(8)) - - def test_str(self): - h = MinHeap([1, 2, 3, 4, 5]) - print(h) - - def test_repr(self): - h = MinHeap([1, 2, 3, 4, 5]) - print(repr(h)) diff --git a/tests/ds/test_MinMaxHeap.py b/tests/ds/test_MinMaxHeap.py index 554cbaf6..3c1062ec 100755 --- a/tests/ds/test_MinMaxHeap.py +++ b/tests/ds/test_MinMaxHeap.py @@ -248,12 +248,4 @@ def test_index_of_min_and_max(self): self.assertEqual(h.index_of_min(7), -1) self.assertEqual(h.index_of_max(7), -1) self.assertEqual(h.index_of_min(8), -1) - self.assertEqual(h.index_of_max(8), -1) - - def test_str(self): - h = MinMaxHeap([7, 2, 92, 67]) - print(h) - - def test_repr(self): - h = MinMaxHeap([7, 2, 92, 67]) - print(repr(h)) + self.assertEqual(h.index_of_max(8), -1) \ No newline at end of file diff --git a/tests/ds/test_Queue.py b/tests/ds/test_Queue.py index fc0ab211..5c41dd46 100644 --- a/tests/ds/test_Queue.py +++ b/tests/ds/test_Queue.py @@ -86,7 +86,4 @@ def test_dequeue_many(self): elem = q.dequeue() self.assertEqual(elem, ls[i]) - self.assertTrue(q.is_empty()) - - def test_str(self): - self.assertEqual(repr(Queue(["first", "second", "last"])), str(["first", "second", "last"])) + self.assertTrue(q.is_empty()) \ No newline at end of file diff --git a/tests/ds/test_Stack.py b/tests/ds/test_Stack.py index dd72f539..212c777a 100644 --- a/tests/ds/test_Stack.py +++ b/tests/ds/test_Stack.py @@ -82,6 +82,3 @@ def test_pop_until_empty(self): self.assertEqual(s.size(), len(ls) - (i + 1)) self.assertTrue(s.is_empty()) - - def test_print_stack(self): - print("\n", repr(Stack([11, 2, 3])), sep="") diff --git a/tests/ds/test_TST.py b/tests/ds/test_TST.py index 3375d173..475d5ebc 100644 --- a/tests/ds/test_TST.py +++ b/tests/ds/test_TST.py @@ -38,7 +38,7 @@ def test_creation(self): def test_insert_key_not_string(self): t = TST() - self.assertRaises(TypeError, t.insert, 3.14) + self.assertRaises(TypeError, t.insert, 10, 5) def test_insert_key_empty_string(self): t = TST() @@ -117,14 +117,14 @@ def test_search_key_empty_string(self): self.assertRaises(ValueError, t.search, "") self.assertRaises(ValueError, t.search_iteratively, "") - def test_contains_empty_tst(self): - t = TST() - self.assertFalse(t.contains("contains in an empty tst")) - def test_contains_key_not_string(self): t = TST() self.assertRaises(TypeError, t.contains, 3.14) + def test_contains_empty_tst(self): + t = TST() + self.assertFalse(t.contains("contains in an empty tst")) + def test_contains_key_empty_string(self): t = TST() self.assertRaises(ValueError, t.contains, "")