Skip to content

Commit 8c98268

Browse files
committed
Added new Plural class.
1 parent fc2b153 commit 8c98268

File tree

3 files changed

+86
-1
lines changed

3 files changed

+86
-1
lines changed

doc-source/api/words.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,5 @@
6565
.. autofunction:: domdf_python_tools.words.as_text
6666

6767
.. autofunction:: domdf_python_tools.words.word_join
68+
69+
.. autoclass:: domdf_python_tools.words.Plural

domdf_python_tools/words.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,11 @@
3535

3636
# stdlib
3737
import functools
38+
import platform
3839
import random
3940
import re
41+
from gettext import ngettext
42+
from reprlib import recursive_repr
4043
from string import ascii_lowercase, ascii_uppercase
4144
from typing import Any, Dict, Iterable, List, Optional
4245

@@ -68,8 +71,12 @@
6871
"TAB",
6972
"CR",
7073
"LF",
74+
"Plural",
7175
]
7276

77+
# this package
78+
from domdf_python_tools.doctools import prettify_docstrings
79+
7380
ascii_digits = "0123456789"
7481
"""
7582
ASCII numbers.
@@ -560,3 +567,59 @@ def word_join(
560567
561568
.. versionadded:: 1.3.0
562569
"""
570+
571+
_docs = domdf_python_tools.__docs
572+
573+
574+
@prettify_docstrings
575+
class Plural(functools.partial):
576+
"""
577+
Represents a word as its singular and plural.
578+
579+
.. versionadded:: 2.0.0
580+
581+
:param singular: The singular form of the word.
582+
:param plural: The plural form of the word.
583+
584+
.. code-block:: python
585+
586+
>>> cow = Plural("cow", "cows")
587+
>>> n = 1
588+
>>> print(f"The farmer has {n} {cow(n)}.")
589+
The farmer has 1 cow.
590+
>>> n = 2
591+
>>> print(f"The farmer has {n} {cow(n)}.")
592+
The farmer has 2 cows.
593+
>>> n = 3
594+
>>> print(f"The farmer has {n} {cow(n)}.")
595+
The farmer has 3 cows.
596+
"""
597+
598+
if _docs: # pragma: no cover
599+
600+
def __init__(self, singular: str, plural: str):
601+
pass
602+
603+
def __call__(self, n: int) -> str:
604+
"""
605+
Returns either the singular or plural form of the word depending on the value of ``n``.
606+
607+
:param n:
608+
"""
609+
610+
if platform.python_implementation() == "PyPy":
611+
612+
def __init__(self, singular: str, plural: str):
613+
super().__init__(ngettext, singular, plural)
614+
else:
615+
616+
def __new__(cls, singular: str, plural: str):
617+
return super().__new__(cls, ngettext, singular, plural)
618+
619+
@recursive_repr()
620+
def __repr__(self):
621+
qualname = type(self).__qualname__
622+
args = []
623+
args.extend(repr(x) for x in self.args)
624+
args.extend(f"{k}={v!r}" for (k, v) in self.keywords.items())
625+
return f"{qualname}({', '.join(args)})"

tests/test_words.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from domdf_python_tools import words
1212
from domdf_python_tools.paths import PathPlus
1313
from domdf_python_tools.stringlist import StringList
14-
from domdf_python_tools.words import DOUBLESTRUCK_LETTERS, alpha_sort, get_random_word, get_words_list
14+
from domdf_python_tools.words import DOUBLESTRUCK_LETTERS, Plural, alpha_sort, get_random_word, get_words_list
1515

1616

1717
@pytest.mark.parametrize(
@@ -145,3 +145,23 @@ def test_as_text(value, expects):
145145
)
146146
def test_word_join(args, kwargs, expects):
147147
assert words.word_join(*args, **kwargs) == expects
148+
149+
150+
def test_plural():
151+
cow = Plural("cow", "cows")
152+
glass = Plural("glass", "glasses")
153+
154+
n = 1
155+
assert f"The farmer has {n} {cow(n)}." == "The farmer has 1 cow."
156+
assert f"The bar has {n} {glass(n)}." == "The bar has 1 glass."
157+
158+
n = 2
159+
assert f"The farmer has {n} {cow(n)}." == "The farmer has 2 cows."
160+
assert f"The bar has {n} {glass(n)}." == "The bar has 2 glasses."
161+
162+
n = 3
163+
assert f"The farmer has {n} {cow(n)}." == "The farmer has 3 cows."
164+
assert f"The bar has {n} {glass(n)}." == "The bar has 3 glasses."
165+
166+
assert repr(cow) == "Plural('cow', 'cows')"
167+
assert repr(glass) == "Plural('glass', 'glasses')"

0 commit comments

Comments
 (0)