From 31b9339bd7348a5ad6c61091f08320df888e9345 Mon Sep 17 00:00:00 2001 From: David Gilman Date: Mon, 6 Sep 2021 17:29:50 -0400 Subject: [PATCH 1/8] Don't crash on a suffix-only number_to_words Fixes #131 --- inflect.py | 6 +++++- tests/test_numwords.py | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/inflect.py b/inflect.py index 3bb946b..de2fc5a 100644 --- a/inflect.py +++ b/inflect.py @@ -1848,6 +1848,7 @@ def get_si_pron(thecase, word, gender): 12: "th", 13: "th", } +nth_suff = set(nth.values()) ordinal = dict( ty="tieth", @@ -3706,7 +3707,10 @@ def number_to_words( # noqa: C901 else: sign = "" - myord = num[-2:] in ("st", "nd", "rd", "th") + if num in nth_suff: + num = zero + + myord = num[-2:] in nth_suff if myord: num = num[:-2] finalpoint = False diff --git a/tests/test_numwords.py b/tests/test_numwords.py index 1707400..042b45a 100644 --- a/tests/test_numwords.py +++ b/tests/test_numwords.py @@ -391,3 +391,9 @@ def go(p, i): # eq_ !eval { p.number_to_words(42, and=>); 1; }; # eq_ $@ =~ 'odd number of'; + + +def test_issue_131(): + p = inflect.engine() + for nth_word in inflect.nth_suff: + assert p.number_to_words(nth_word) == "zero" From 6e59dd2b7788af168e6f0f5fe255c8b8a8c99874 Mon Sep 17 00:00:00 2001 From: David Gilman Date: Mon, 6 Sep 2021 17:38:09 -0400 Subject: [PATCH 2/8] Add tranche / tranches Fixes #129 --- inflect.py | 1 + tests/inflections.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/inflect.py b/inflect.py index 3bb946b..b8b7583 100644 --- a/inflect.py +++ b/inflect.py @@ -1413,6 +1413,7 @@ def make_pl_si_lists( "quiches", "stomachaches", "toothaches", + "tranches", ) si_sb_xes_xe = ("annexes", "axes", "deluxes", "pickaxes") diff --git a/tests/inflections.txt b/tests/inflections.txt index b37377c..3d49749 100644 --- a/tests/inflections.txt +++ b/tests/inflections.txt @@ -779,6 +779,7 @@ trapezium -> trapeziums|trapezia trauma -> traumas|traumata travois -> travois + tranche -> tranches trellis -> trellises TODO:siverb tries -> try trilby -> trilbys From 78d00a2c3f492cc3e57183130a77e0f1f357b2ff Mon Sep 17 00:00:00 2001 From: David Gilman Date: Mon, 6 Sep 2021 18:06:55 -0400 Subject: [PATCH 3/8] Fix rST errors in CHANGES.rst Fixes #132 --- CHANGES.rst | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index a1c8450..248df9f 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -93,13 +93,13 @@ v2.0.0 on regular expressions. This also adds support for keyword arguments and built-in constants when calling functions in the string. Unfortunately, this is not backwards compatible in some cases: - * Strings should now be wrapped in single or double quotes - p.inflect("singular_noun(to them)") should now be p.inflect("singular_noun('to them')") - * Empty second argument to a function will now be parsed as None instead of ''. - p.inflect("num(%d,) eggs" % 2) now prints "2 eggs" instead of " eggs" - Since None, True and False are now supported, they can be passed explicitly: - p.inflect("num(%d, False) eggs" % 2) will print " eggs" - p.inflect("num(%d, True) eggs" % 2) will print "2 eggs" +* Strings should now be wrapped in single or double quotes + p.inflect("singular_noun(to them)") should now be p.inflect("singular_noun('to them')") +* Empty second argument to a function will now be parsed as None instead of ''. + p.inflect("num(%d,) eggs" % 2) now prints "2 eggs" instead of " eggs" + Since None, True and False are now supported, they can be passed explicitly: + p.inflect("num(%d, False) eggs" % 2) will print " eggs" + p.inflect("num(%d, True) eggs" % 2) will print "2 eggs" v1.0.2 ====== @@ -127,7 +127,7 @@ v0.3.1 v0.3.0 ====== -* Moved hosting to `jazzband `_. +* Moved hosting to the `jazzband project on GitHub `_. v0.2.5 ====== @@ -172,24 +172,32 @@ v0.2.0 ====== * add gender() to select the gender of singular pronouns - * replace short named methods with longer methods. shorted method now print a message and rasie DecrecationWarning + pl -> plural + plnoun -> plural_noun + plverb -> plural_verb + pladj -> plural_adjective + sinoun -> singular_noun + prespart -> present_participle + numwords -> number_to_words + plequal -> compare + plnounequal -> compare_nouns + plverbequal -> compare_verbs - pladjequal -> compare_adjs - wordlist -> join + pladjequal -> compare_adjs + wordlist -> join * change classical() to only accept keyword args: only one way to do it - * fix bug in numwords where hundreds was giving the wrong number when group=3 @@ -197,8 +205,7 @@ v0.1.8 ====== * add line to setup showing that this provides 'inflect' so that -inflect_dj can require it - + inflect_dj can require it * add the rest of the tests from the Perl version @@ -212,13 +219,9 @@ v0.1.6 ====== * add method sinoun() to generate the singular of a plural noun. Phew! - * add changes from new Perl version: 1.892 - * start adding tests from Perl version - * add test to check sinoun(plnoun(word)) == word Can now use word lists to check these methods without needing to have a list of plurals. ;-) - * fix die -> dice From 312b26dea0f8c1e78c3cc2b0f6ea01f15878285f Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Fri, 17 Sep 2021 19:36:30 +0200 Subject: [PATCH 4/8] Fix typos found by codespell --- CHANGES.rst | 4 ++-- inflect.py | 8 ++++---- tests/test_an.py | 2 +- tests/test_pwd.py | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index a1c8450..79753a7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -146,7 +146,7 @@ v0.2.4 v0.2.3 ====== -* fix a/an for dishonor, Honolulu, mpeg, onetime, Ugandan, Ukranian, +* fix a/an for dishonor, Honolulu, mpeg, onetime, Ugandan, Ukrainian, Unabomber, unanimous, US * merge in 'subspecies' fix by UltraNurd * add arboretum to classical plurals @@ -173,7 +173,7 @@ v0.2.0 * add gender() to select the gender of singular pronouns -* replace short named methods with longer methods. shorted method now print a message and rasie DecrecationWarning +* replace short named methods with longer methods. shorted method now print a message and raise DecrecationWarning pl -> plural plnoun -> plural_noun plverb -> plural_verb diff --git a/inflect.py b/inflect.py index 3bb946b..995c382 100644 --- a/inflect.py +++ b/inflect.py @@ -2071,7 +2071,7 @@ def defadj(self, singular: str, plural: str) -> int: def defa(self, pattern: str) -> int: """ - Define the indefinate article as 'a' for words matching pattern. + Define the indefinite article as 'a' for words matching pattern. """ self.checkpat(pattern) @@ -2080,7 +2080,7 @@ def defa(self, pattern: str) -> int: def defan(self, pattern: str) -> int: """ - Define the indefinate article as 'an' for words matching pattern. + Define the indefinite article as 'an' for words matching pattern. """ self.checkpat(pattern) @@ -2132,7 +2132,7 @@ def classical(self, **kwargs): By default all classical modes are off except names. - unknown value in args or key in kwargs rasies + unknown value in args or key in kwargs raises exception: UnknownClasicalModeError """ @@ -3773,7 +3773,7 @@ def number_to_words( # noqa: C901 if finalpoint: numchunks.append(decimal) - # wantlist: Perl list context. can explictly specify in Python + # wantlist: Perl list context. can explicitly specify in Python if wantlist: if sign: numchunks = [sign] + numchunks diff --git a/tests/test_an.py b/tests/test_an.py index e7ebce4..92182aa 100644 --- a/tests/test_an.py +++ b/tests/test_an.py @@ -14,7 +14,7 @@ def test_an(): assert p.an("mpeg") == "an mpeg" assert p.an("onetime holiday") == "a onetime holiday" assert p.an("Ugandan person") == "a Ugandan person" - assert p.an("Ukranian person") == "a Ukranian person" + assert p.an("Ukrainian person") == "a Ukrainian person" assert p.an("Unabomber") == "a Unabomber" assert p.an("unanimous decision") == "a unanimous decision" assert p.an("US farmer") == "a US farmer" diff --git a/tests/test_pwd.py b/tests/test_pwd.py index 9a99629..60d5a5a 100644 --- a/tests/test_pwd.py +++ b/tests/test_pwd.py @@ -627,7 +627,7 @@ def test__plnoun(self): p._sinoun(plur), sing, msg='p._sinoun("{}") != "{}"'.format(plur, sing) ) - # words where forming singular is ambiguious or not attempted + # words where forming singular is ambiguous or not attempted for sing, plur in ( ("son of a gun", "sons of guns"), ("son-of-a-gun", "sons-of-guns"), @@ -687,7 +687,7 @@ def test__plnoun(self): # p.classical(0) # p.classical('names') - # clasical now back to the default mode + # classical now back to the default mode def test_classical_pl(self): p = inflect.engine() From 3960877775231c5de7461041a1d729683dc755f0 Mon Sep 17 00:00:00 2001 From: MapleCCC Date: Tue, 5 Oct 2021 00:54:34 +0800 Subject: [PATCH 5/8] Relax the type constraint of the `words` parameter of `engine.join()` --- inflect.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inflect.py b/inflect.py index 3bb946b..136b5ef 100644 --- a/inflect.py +++ b/inflect.py @@ -50,7 +50,7 @@ import ast import re -from typing import Dict, Union, Optional, Iterable, List, Match, Tuple, Callable +from typing import Dict, Union, Optional, Iterable, List, Match, Tuple, Callable, Sequence class UnknownClassicalModeError(Exception): @@ -3802,7 +3802,7 @@ def number_to_words( # noqa: C901 def join( self, - words: Optional[List[str]], + words: Optional[Sequence[str]], sep: Optional[str] = None, sep_spaced: bool = True, final_sep: Optional[str] = None, From 4b1329058c5bdd272f50e5536ad6fd13329b7915 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sat, 27 Nov 2021 20:17:35 +1100 Subject: [PATCH 6/8] docs: Fix a few typos There are small typos in: - inflect.py - tests/test_pwd.py Fixes: - Should read `upstream` rather than `updtream`. - Should read `indefinite` rather than `indefinate`. - Should read `accusative` rather than `accusivate`. - Should read `raises` rather than `rasies`. - Should read `explicitly` rather than `explictly`. - Should read `ambiguous` rather than `ambiguious`. --- inflect.py | 12 ++++++------ tests/test_pwd.py | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/inflect.py b/inflect.py index 3bb946b..2219322 100644 --- a/inflect.py +++ b/inflect.py @@ -2071,7 +2071,7 @@ def defadj(self, singular: str, plural: str) -> int: def defa(self, pattern: str) -> int: """ - Define the indefinate article as 'a' for words matching pattern. + Define the indefinite article as 'a' for words matching pattern. """ self.checkpat(pattern) @@ -2080,7 +2080,7 @@ def defa(self, pattern: str) -> int: def defan(self, pattern: str) -> int: """ - Define the indefinate article as 'an' for words matching pattern. + Define the indefinite article as 'an' for words matching pattern. """ self.checkpat(pattern) @@ -2132,7 +2132,7 @@ def classical(self, **kwargs): By default all classical modes are off except names. - unknown value in args or key in kwargs rasies + unknown value in args or key in kwargs raises exception: UnknownClasicalModeError """ @@ -2686,7 +2686,7 @@ def _plnoun( # noqa: C901 # HANDLE PRONOUNS for k, v in pl_pron_acc_keys_bysize.items(): - if word.lower[-k:] in v: # ends with accusivate pronoun + if word.lower[-k:] in v: # ends with accusative pronoun for pk, pv in pl_prep_bysize.items(): if word.lower[:pk] in pv: # starts with a prep if word.lower.split() == [word.lower[:pk], word.lower[-k:]]: @@ -3122,7 +3122,7 @@ def _sinoun( # noqa: C901 # HANDLE PRONOUNS for k, v in si_pron_acc_keys_bysize.items(): - if words.lower[-k:] in v: # ends with accusivate pronoun + if words.lower[-k:] in v: # ends with accusative pronoun for pk, pv in pl_prep_bysize.items(): if words.lower[:pk] in pv: # starts with a prep if words.lower.split() == [words.lower[:pk], words.lower[-k:]]: @@ -3773,7 +3773,7 @@ def number_to_words( # noqa: C901 if finalpoint: numchunks.append(decimal) - # wantlist: Perl list context. can explictly specify in Python + # wantlist: Perl list context. can explicitly specify in Python if wantlist: if sign: numchunks = [sign] + numchunks diff --git a/tests/test_pwd.py b/tests/test_pwd.py index 9a99629..e4b797e 100644 --- a/tests/test_pwd.py +++ b/tests/test_pwd.py @@ -627,7 +627,7 @@ def test__plnoun(self): p._sinoun(plur), sing, msg='p._sinoun("{}") != "{}"'.format(plur, sing) ) - # words where forming singular is ambiguious or not attempted + # words where forming singular is ambiguous or not attempted for sing, plur in ( ("son of a gun", "sons of guns"), ("son-of-a-gun", "sons-of-guns"), @@ -1121,15 +1121,15 @@ def test_wordlist(self): ) self.assertEqual( wordlist(("apple", "banana", "carrot"), conj="&"), "apple, banana, & carrot" - ) # TODO: want space here. Done, report updtream + ) # TODO: want space here. Done, report upstream self.assertEqual( wordlist(("apple", "banana", "carrot"), conj="&", conj_spaced=False), "apple, banana,&carrot", - ) # TODO: want space here. Done, report updtream + ) # TODO: want space here. Done, report upstream self.assertEqual( wordlist(("apple", "banana", "carrot"), conj=" &", conj_spaced=False), "apple, banana, &carrot", - ) # TODO: want space here. Done, report updtream + ) # TODO: want space here. Done, report upstream def test_print(self): inflect.STDOUT_ON = True From 8d610f30f24bcdc524bcb8c734801fbb311eeeec Mon Sep 17 00:00:00 2001 From: Mitch Price Date: Thu, 9 Dec 2021 20:02:18 -0800 Subject: [PATCH 7/8] Update handling of louse/lice plurals to treat it as the exception rather than the norm. --- inflect.py | 23 +++++++++++++++++++++-- tests/inflections.txt | 2 ++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/inflect.py b/inflect.py index 3bb946b..c2ef704 100644 --- a/inflect.py +++ b/inflect.py @@ -846,6 +846,19 @@ def make_pl_si_lists( pl_sb_U_man_mans_caps_bysize, ) = make_pl_si_lists(pl_sb_U_man_mans_caps_list, "s", None, dojoinstem=False) +# UNCONDITIONAL "..louse" -> "..lice" +pl_sb_U_louse_lice_list = ( + "booklouse", + "grapelouse", + "louse", + "woodlouse" +) + +( + si_sb_U_louse_lice_list, + si_sb_U_louse_lice_bysize, + pl_sb_U_louse_lice_bysize, +) = make_pl_si_lists(pl_sb_U_louse_lice_list, "lice", 5, dojoinstem=False) pl_sb_uninflected_s_complete = [ # PAIRS OR GROUPS SUBSUMED TO A SINGULAR... @@ -2745,7 +2758,10 @@ def _plnoun( # noqa: C901 if word.lower[-5:] == "mouse": return f"{word[:-5]}mice" if word.lower[-5:] == "louse": - return f"{word[:-5]}lice" + for k, v in pl_sb_U_louse_lice_bysize.items(): + if word.lower[-k:] in v: + return f"{word[:-5]}lice" + return f"{word}s" if word.lower[-5:] == "goose": return f"{word[:-5]}geese" if word.lower[-5:] == "tooth": @@ -3182,7 +3198,10 @@ def _sinoun( # noqa: C901 if words.lower[-4:] == "mice": return word[:-4] + "mouse" if words.lower[-4:] == "lice": - return word[:-4] + "louse" + print(word.lower) + for k, v in si_sb_U_louse_lice_bysize.items(): + if len(word) == k and words.lower[-k:] in v: + return word[:-4] + "louse" if words.lower[-5:] == "geese": return word[:-5] + "goose" if words.lower[-5:] == "teeth": diff --git a/tests/inflections.txt b/tests/inflections.txt index b37377c..a71f909 100644 --- a/tests/inflections.txt +++ b/tests/inflections.txt @@ -2,6 +2,7 @@ TODO:sing a -> some # INDEFINITE ARTICLE TODO: A.C.R.O.N.Y.M. -> A.C.R.O.N.Y.M.s abscissa -> abscissas|abscissae + accomplice -> accomplices Achinese -> Achinese acropolis -> acropolises adieu -> adieus|adieux @@ -679,6 +680,7 @@ sinus -> sinuses|sinus size -> sizes sizes -> size #VERB FORM + slice -> slices smallpox -> smallpox Smith -> Smiths TODO:siverb snowshoes -> snowshoe From f91b4f0fd485d6c8bc403af43bf5f2966a0fab37 Mon Sep 17 00:00:00 2001 From: Mitch Price Date: Thu, 9 Dec 2021 21:41:05 -0800 Subject: [PATCH 8/8] Minor cleanup --- inflect.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/inflect.py b/inflect.py index c2ef704..b97a46a 100644 --- a/inflect.py +++ b/inflect.py @@ -204,7 +204,6 @@ def make_pl_si_lists( "jerry": "jerries", "mary": "maries", "talouse": "talouses", - "blouse": "blouses", "rom": "roma", "carmen": "carmina", } @@ -2758,9 +2757,9 @@ def _plnoun( # noqa: C901 if word.lower[-5:] == "mouse": return f"{word[:-5]}mice" if word.lower[-5:] == "louse": - for k, v in pl_sb_U_louse_lice_bysize.items(): - if word.lower[-k:] in v: - return f"{word[:-5]}lice" + v = pl_sb_U_louse_lice_bysize.get(len(word)) + if v and word.lower in v: + return f"{word[:-5]}lice" return f"{word}s" if word.lower[-5:] == "goose": return f"{word[:-5]}geese" @@ -3198,10 +3197,9 @@ def _sinoun( # noqa: C901 if words.lower[-4:] == "mice": return word[:-4] + "mouse" if words.lower[-4:] == "lice": - print(word.lower) - for k, v in si_sb_U_louse_lice_bysize.items(): - if len(word) == k and words.lower[-k:] in v: - return word[:-4] + "louse" + v = si_sb_U_louse_lice_bysize.get(len(word)) + if v and words.lower in v: + return word[:-4] + "louse" if words.lower[-5:] == "geese": return word[:-5] + "goose" if words.lower[-5:] == "teeth":