Skip to content

Support 'oxford comma' format and non-string types in listing#690

Merged
staticdev merged 8 commits into
staticdev:mainfrom
zwimer:support_oxford_comma
Jan 17, 2025
Merged

Support 'oxford comma' format and non-string types in listing#690
staticdev merged 8 commits into
staticdev:mainfrom
zwimer:support_oxford_comma

Conversation

@zwimer

@zwimer zwimer commented Sep 27, 2024

Copy link
Copy Markdown
Contributor

Fixes: #693

This PR:

  1. Adds support for the 'oxford comma' format list format in listing. Depending on location etc., some people list items using an oxford comma. For example:
x = []
for i in range(3):
    x.append(i)
    print(listing(z, ",", "and"))
    print(listing(z, ",", "and", oxford=True))

Prints out

0
0
0 and 1
0 and 1
0, 1 and 2
0, 1, and 2

The default is oxford=False to avoid changing the default behavior.

  1. Allows the use of types other than str in listing. The code for this function almost entirely already allowed this, this PR mostly changes type annotations and adds a couple of str() calls to fully support it. This allows for things like:
class Translate:
    def __init__(self, msg, language):
        self.msg = msg
        self.language = language
    def __str__(self) -> str:
        return translate(self.language, self.msg)   #  External API call 

print(listing([1, 2], ","))  # Non-string items
print(listing([1, 2], ",", Translator("and", "Spanish"))  # Non-string separators and conjunctions

Which may print:

1, 2
1 y 2
  1. Fixes type annotation on items. Python defines list type as invariant; we should use Sequence instead as that is covariant. That is:
class Special(str):
    pass

s = [Special("")]

x: list[str] = s       # type error: since list is invariant, list[Special] is not a list[str]
y: Sequence[str]  = s  # ok: since Sequence is covariant, list[DerivedClass] is a list[BaseClass]

@zwimer

zwimer commented Dec 30, 2024

Copy link
Copy Markdown
Contributor Author

@staticdev The test case for coverage for listing fail before because if TYPE_CHECKING: clauses never get executed during runtime; they are only executed by type checkers like mypy. To deal with this, I added a .coveragerc and instructed it to ignore lines guarded by this if statement.

Comment thread src/human_readable/lists.py Outdated
from typing import TYPE_CHECKING


if TYPE_CHECKING:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it is much simpler to just remove this if statement and always import this. It is the standard approach.

Comment thread tests/unit/test_lists.py
assert lists.listing(*params) == expected


@pytest.mark.parametrize(

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would also be great to explain this in our examples documentation.

@staticdev

staticdev commented Jan 4, 2025

Copy link
Copy Markdown
Owner

@staticdev The test case for coverage for listing fail before because if TYPE_CHECKING: clauses never get executed during runtime; they are only executed by type checkers like mypy. To deal with this, I added a .coveragerc and instructed it to ignore lines guarded by this if statement.

@zwimer I did a review, and I have a suggestion to deal with this in a simpler way.

Comment thread src/human_readable/lists.py Outdated
@staticdev staticdev merged commit 47ef9ab into staticdev:main Jan 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Oxford comma support in listings

2 participants