From 6d6e46934a01da7fd82f972d212ddb59d7cfb231 Mon Sep 17 00:00:00 2001 From: zwimer Date: Thu, 26 Sep 2024 20:36:50 -0400 Subject: [PATCH 1/5] Support oxford comma and non-string types in listing --- src/human_readable/lists.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/human_readable/lists.py b/src/human_readable/lists.py index 0757019..cf10df3 100644 --- a/src/human_readable/lists.py +++ b/src/human_readable/lists.py @@ -1,11 +1,17 @@ """Tests for lists humanization.""" from __future__ import annotations +from typing import TYPE_CHECKING + + +if TYPE_CHECKING: + 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. @@ -14,6 +20,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. @@ -22,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): From 82de55868da5c1b7ae88c5a552d99b745f5c0a12 Mon Sep 17 00:00:00 2001 From: zwimer Date: Mon, 30 Dec 2024 09:16:01 -0500 Subject: [PATCH 2/5] Format with pre-commit --- src/human_readable/lists.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/human_readable/lists.py b/src/human_readable/lists.py index e05331b..75a5ac6 100644 --- a/src/human_readable/lists.py +++ b/src/human_readable/lists.py @@ -1,6 +1,7 @@ """Tests for lists humanization.""" from __future__ import annotations + from typing import TYPE_CHECKING @@ -12,7 +13,9 @@ __all__ = ["listing"] -def listing(items: Sequence[Any], separator: Any, conjunction: Any = None, oxford: bool = False) -> 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. From 092415fcb608d73904a721377548e65b22c5be02 Mon Sep 17 00:00:00 2001 From: zwimer Date: Mon, 30 Dec 2024 09:39:06 -0500 Subject: [PATCH 3/5] Add listing oxford test case --- tests/unit/test_lists.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) 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 From fca339d0404a005877473ec3f9b7bd7a39a101c5 Mon Sep 17 00:00:00 2001 From: zwimer Date: Mon, 30 Dec 2024 09:46:22 -0500 Subject: [PATCH 4/5] Add coveragerc file to exclude if TYPE_CHECKING statements --- .coveragerc | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .coveragerc 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: From 49bfd4e5ea8d3d3a37a0115aa07a09d19b3f3e0f Mon Sep 17 00:00:00 2001 From: staticdev Date: Fri, 17 Jan 2025 20:46:31 +0100 Subject: [PATCH 5/5] Simplify imports --- src/human_readable/lists.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/human_readable/lists.py b/src/human_readable/lists.py index f5d209c..d31f80b 100644 --- a/src/human_readable/lists.py +++ b/src/human_readable/lists.py @@ -2,13 +2,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING - - -if TYPE_CHECKING: - from collections.abc import Sequence - from typing import Any - +from collections.abc import Sequence +from typing import Any __all__ = ["listing"]