From 03c9c051e25da4df21c7f47aaece0734add60658 Mon Sep 17 00:00:00 2001 From: cootshk <83678457+cootshk@users.noreply.github.com> Date: Thu, 2 Nov 2023 13:35:29 -0500 Subject: [PATCH] more tests --- tables.py | 35 ++++++++++++++--------------------- tests/test_foreach.py | 16 ++++++++++++++++ tests/test_inheritance.py | 17 +++++++++++++++++ tests/test_main.py | 23 ++++++----------------- tests/test_operands.py | 22 ++++++++++++++++++++++ 5 files changed, 75 insertions(+), 38 deletions(-) create mode 100644 tests/test_foreach.py create mode 100644 tests/test_inheritance.py create mode 100644 tests/test_operands.py diff --git a/tables.py b/tables.py index 8ff24fb..472caf8 100644 --- a/tables.py +++ b/tables.py @@ -5,7 +5,7 @@ """ # check for python version -from typing import Iterable, override, Any, Optional, overload, Callable +from typing import Iterable, Any, Optional, overload, Callable import sys if sys.version_info < (3, 12): print("This script requires Python 3.12+") @@ -27,7 +27,7 @@ class Table(Iterable): Table(1,2,3) == Table([1,2,3]) # True len(Table("a", "b", "c", four="d", five="e")) # 5 Types: - KeyValue (str | int): Any key value, either a string or an int. A string is used for dictionary keys, + KeyValue (str | int): Any key value, either a string or an int. A string is used for dictionary keys, and an int is used for list indices. """ type KeyValue = str | int @@ -64,6 +64,7 @@ def find_keys(self, value: Any, /) -> KeyValue: ... @overload def find_keys[default]( + # type: ignore self, value: Any, /, *, default: Any = None) -> list[KeyValue] | default: ... @overload @@ -109,13 +110,12 @@ def sort(self, *, key: Callable, reverse: bool) -> "Table": ... # sort ############################################### - @override def __init__(self, *args: Optional[Any], **kwargs: Optional[Any]): - """The init function. + """The init function. Args: *list_values (list[Any] | Any): The list values. If there is only one argument, then that is set to the list. **dict_values (dict[str, Any] | Any): The dict values. If there is only one argument, then that is set to the dict. - + Examples: see the Table() documentation @@ -159,7 +159,7 @@ def __setitem__(self, key: KeyValue | Iterable[KeyValue], value: Any): elif isinstance(key, int): self.list[key] = value elif isinstance(key, Iterable): - for i, j, _ in zip(key, value): + for i, j in zip(key, value): self[i] = j else: raise TypeError(f"Table indices must be integers or strings, not { @@ -187,7 +187,6 @@ def __delitem__(self, key: KeyValue | Iterable[KeyValue]): raise TypeError(f"Table indices must be integers or strings, not { type(key).__name__}") - @override def __iter__(self) -> Any: return iter(self.list) @@ -200,7 +199,6 @@ def _list_len_(self) -> int: def _dict_len_(self) -> int: return len(self.dict) - @override def __repr__(self) -> str: if len(self) == 0: return "Table()" @@ -214,19 +212,19 @@ def _unpack_kwargs_to_str_(self) -> str: ret += f"{k}: {v if not isinstance(v, str) else f"'{v}'"}, " return ret.removesuffix(", ") - @override def __str__(self) -> str: # if len(self) == 0: # return "<>" return f"<{(''.join([ f'{x}, ' for x in self.list ])).removesuffix(', ')}, { - self._unpack_kwargs_to_str_()}>".replace( + self._unpack_kwargs_to_str_()}>".replace( "<, ", "<").replace( ", >", ">") def __contains__(self, key: str) -> bool: return (key in self.dict) or (key in self.list) + def find_keys(self, value: Any, /, *, default: Any=None) -> list[KeyValue] | Any: """Finds all keys and indices that have a value equal to value. @@ -250,7 +248,6 @@ def find_keys(self, value: Any, /, *, default: Any=None) -> list[KeyValue] | Any return ret[0] return ret - @override def append(self, value: Any) -> "Table": """Append a value to the end of the list. @@ -263,7 +260,6 @@ def append(self, value: Any) -> "Table": self.list.append(value) return self - @override def extend(self, value: Iterable[Any]) -> "Table": """Extend the list with another iterable. @@ -276,7 +272,6 @@ def extend(self, value: Iterable[Any]) -> "Table": self.list.extend(value) return self - @override def insert(self, index: int, value: Any) -> "Table": """Insert a value at a specific index. @@ -290,7 +285,6 @@ def insert(self, index: int, value: Any) -> "Table": self.list.insert(index, value) return self - @override def pop(self, index: int = -1) -> Any: """Returns a specific value in a list and removes it. @@ -351,7 +345,7 @@ def count(self, value: Any, count_list: bool = True, count_dict_keys: bool = Fa ret += list(self.dict.keys()).count(value) if count_dict_keys else 0 return ret - def foreach(self, func: Callable, /, list_eval: bool =True, dict_eval: bool=True) -> list[Any] | Any: + def foreach(self, func: Callable, /, list_eval: bool = True, dict_eval: bool=True) -> list[Any] | Any: """Call a function on each item in the table. Args: @@ -371,13 +365,13 @@ def foreach(self, func: Callable, /, list_eval: bool =True, dict_eval: bool=True ret = [] if bool(list_eval): for i, j in enumerate(self.list): - ret += func(i, j) # type: ignore + print(i, j,func) + ret.append(func(i, j)) if bool(dict_eval): for k, v in zip(self.dict.keys(), self.dict.values()): - ret += func(k, v) # type: ignore + ret.append(func(k, v)) # type: ignore return ret if len(ret) > 1 else ret[0] if len(ret) == 1 else None - @override def __eq__(self, other): if isinstance(other, Table): return self.list == other.list and self.dict == other.dict @@ -394,8 +388,8 @@ def __add__(self, other: Any) -> "Table": raise TypeError( f"unsupported operand type(s) for +: 'Table' and '{type(other).__name__}'") - @override - def sort(self, *, key: Optional[Callable] = None, reverse: bool=False) -> "Table": + # type: ignore + def sort(self, *, key: Any = None, reverse: bool =False) -> "Table": """Sorts the list in place. Args: @@ -408,7 +402,6 @@ def sort(self, *, key: Optional[Callable] = None, reverse: bool=False) -> "Table self.list.sort(key=key, reverse=reverse) return self - @override def __bool__(self) -> bool: return bool(self.list) or bool(self.dict) diff --git a/tests/test_foreach.py b/tests/test_foreach.py new file mode 100644 index 0000000..1175ec3 --- /dev/null +++ b/tests/test_foreach.py @@ -0,0 +1,16 @@ +"""Testing table.foreach() method. + This is a **very dangerous** method, so it is tested separately. +""" +from ..tables import Table + + +def test_tables() -> None: + """The actual tests.""" + tbl = Table(1, 2, 3) + assert isinstance(tbl.foreach(lambda x, y: y), + list), "Foreach test 1 failed!" + assert tbl.foreach(lambda x, y: [x, y, True]) == [ + [0, 1, True], + [1, 2, True], + [2, 3, True] + ], "Foreach test 2 failed!" diff --git a/tests/test_inheritance.py b/tests/test_inheritance.py new file mode 100644 index 0000000..11d7f0d --- /dev/null +++ b/tests/test_inheritance.py @@ -0,0 +1,17 @@ +"""Testing list and dict methods of tables""" +from ..tables import Table + +def test_inheritance() -> None: + """The actual tests. + + Returns: + Optional[bool]: True or None if the test passes, False or errors if it fails. + """ + assert Table(1,3,2).sort() == Table(1,2,3), "Inheritance test 1 failed!" + assert bool(Table(1,2,3)), "Inheritance test 2 failed!" + assert not bool(Table()), "Inheritance test 3 failed!" + assert Table(1,2,3).list == [1,2,3], "Inheritance test 4 failed!" + assert Table(1,2,3).dict == {}, "Inheritance test 5 failed!" + x = Table(1,2,3) + assert x.pop(1) == 2, "Inheritance test 6 failed!" + assert x == Table(1,3), "Inheritance test 7 failed!" diff --git a/tests/test_main.py b/tests/test_main.py index 4f6a6ee..a8381e7 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1,13 +1,7 @@ """Unit tests for main.py """ -try: - from ..tables import Table -except: - try: - from tables import Table - except: - from .tables import Table +from ..tables import Table def test_tables(): """Unit tests for Table() class @@ -22,13 +16,8 @@ def test_tables(): assert repr(x) == "Table([1, 2, 3]; {'foo': 'bar', 'spam': 'eggs'})", "Test 4 failed!" assert x.list == [1,2,3], "Test 5 failed!" assert x.dict == {"foo":"bar", "spam":"eggs"}, "Test 6 failed!" - assert x == Table(1,2,3, foo="bar", spam="eggs"), "Test 7 failed!" - assert x + Table(4,5,6) == Table(1,2,3,4,5,6, foo="bar", spam="eggs"), "Test 8 failed!" - assert x.foreach( - lambda k, v: [k, v]) == [0, 1, 1, 2, 2, 3, "foo", "bar", "spam", "eggs" - ], "Test 9 failed!" - assert Table(1,3,2).sort() == Table(1,2,3), "Test 10 failed!" - assert bool(Table(1,2,3)), "Test 11 failed!" - assert not bool(Table()), "Test 12 failed!" - #congrats, the code works! - print("All tests passed!") + assert x[0] == 1, "Test 7 failed!" + assert x[1] == 2, "Test 8 failed!" + assert x[2] == 3, "Test 9 failed!" + assert x["foo"] == "bar", "Test 10 failed!" + assert x["spam"] == "eggs", "Test 11 failed!" diff --git a/tests/test_operands.py b/tests/test_operands.py new file mode 100644 index 0000000..ec4f574 --- /dev/null +++ b/tests/test_operands.py @@ -0,0 +1,22 @@ +"""Testing table operands, like +, ==, etc.""" +from ..tables import Table + + +def test_operands() -> None: + """The actual tests.""" + assert Table() + Table() == Table(), "Operands test 1 failed!" + assert Table(1, 2, 3) + Table(4, 5, 6) == Table(1, 2, + 3, 4, 5, 6), "Operands test 2 failed!" + assert Table(1, 2, 3) != Table( + 1, 2, 3, foo="bar"), "Operands test 3 failed!" + assert Table(1, 2, 3) == Table(1, 2, 3), "Operands test 4 failed!" + assert Table(1, 2, 3) != Table(1, 2, 4), "Operands test 5 failed!" + assert Table(foo="bar") == Table(foo="bar"), "Operands test 6 failed!" + assert Table(foo="bar") != Table(foo="baz"), "Operands test 7 failed!" + assert Table(1, 2, 3) + Table(foo="bar") == Table(1, 2, + 3, foo="bar"), "Operands test 8 failed!" + x = Table() + x.append(2) + x["foo"] = "bar" + assert x == Table(2, foo="bar"), "Operands test 9 failed!" + assert id(x) != id(Table(2, foo="bar")), "Operands test 10 failed!"