diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..06e4886 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,4 @@ +[report] +exclude_lines = + pragma: no cover + if TYPE_CHECKING: diff --git a/src/human_readable/lists.py b/src/human_readable/lists.py index fd6e378..d31f80b 100644 --- a/src/human_readable/lists.py +++ b/src/human_readable/lists.py @@ -2,11 +2,15 @@ from __future__ import annotations +from collections.abc import Sequence +from typing import Any __all__ = ["listing"] -def listing(items: list[str], separator: str, conjunction: str = "") -> str: +def listing( + items: Sequence[Any], separator: Any, conjunction: Any = None, oxford: bool = False +) -> str: """Return human readable list separated by separator. Optional argument is conjuntion that substitutes the last separator. @@ -15,6 +19,7 @@ def listing(items: list[str], separator: str, conjunction: str = "") -> str: items: list of items. separator: separator of items. conjunction: word/string as last separator. Defaults to None. + oxford: apply separators in the same manner as an oxford comma Returns: str: list in natural language. @@ -24,11 +29,13 @@ def listing(items: list[str], separator: str, conjunction: str = "") -> str: if len_items == 0: return "" if len_items == 1: - return items[0] - phrase = items[0] - if conjunction: + return str(items[0]) + phrase = str(items[0]) + if conjunction is not None: for i in range(1, len_items - 1): phrase += f"{separator} {items[i]}" + if oxford and len_items > 2: + phrase += str(separator) phrase += f" {conjunction} {items[len_items - 1]}" else: for i in range(1, len_items): diff --git a/tests/unit/test_lists.py b/tests/unit/test_lists.py index 874cb46..3dee915 100644 --- a/tests/unit/test_lists.py +++ b/tests/unit/test_lists.py @@ -38,3 +38,22 @@ def test_listing_with_conjunction( ) -> None: """Listing with separator and conjunction.""" assert lists.listing(*params) == expected + + +@pytest.mark.parametrize( + "params, expected", + [ + (([], ";", "or"), ""), # empty list + ((["jorbas"], ";", "or"), "jorbas"), # one element + ((["jorbas", "maria"], ";", "or"), "jorbas or maria"), # two elements + ( + (["jorbas", "maria", "gustavo"], ";", "or"), + "jorbas; maria; or gustavo", + ), # three elements + ], +) +def test_listing_with_conjunction_oxford( + params: tuple[list[str], str, str], expected: str +) -> None: + """Listing with separator and conjunction.""" + assert lists.listing(*params, oxford=True) == expected