• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

.github/H03-Mar-2021-7467

docs/H03-Mar-2021-6343

inflect.egg-info/H03-May-2022-587410

tests/H03-May-2022-2,3331,958

.coveragercH A D03-Mar-202150 64

.editorconfigH A D03-Mar-2021195 1612

.flake8H A D03-Mar-2021136 107

.gitignoreH A D03-Mar-202168 98

.pre-commit-config.yamlH A D03-Mar-2021175 119

.readthedocs.ymlH A D03-Mar-202179 76

CHANGES.rstH A D03-Mar-20214.6 KiB225146

LICENSEH A D03-Mar-20211 KiB2016

PKG-INFOH A D03-Mar-202124.4 KiB587410

README.rstH A D03-Mar-202119.2 KiB563387

inflect.pyH A D03-Mar-202198.6 KiB3,8523,074

mypy.iniH A D03-Mar-202137 32

pyproject.tomlH A D03-Mar-2021367 2114

pytest.iniH A D03-Mar-2021198 87

setup.cfgH A D03-Mar-20211.3 KiB6153

setup.pyH A D03-Mar-202192 73

skeleton.mdH A D03-Mar-20219.9 KiB167105

tox.iniH A D03-Mar-2021801 4439

README.rst

1.. image:: https://img.shields.io/pypi/v/inflect.svg
2   :target: `PyPI link`_
3
4.. image:: https://img.shields.io/pypi/pyversions/inflect.svg
5   :target: `PyPI link`_
6
7.. _PyPI link: https://pypi.org/project/inflect
8
9.. image:: https://github.com/jaraco/inflect/workflows/tests/badge.svg
10   :target: https://github.com/jaraco/inflect/actions?query=workflow%3A%22tests%22
11   :alt: tests
12
13.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
14   :target: https://github.com/psf/black
15   :alt: Code style: Black
16
17.. .. image:: https://readthedocs.org/projects/skeleton/badge/?version=latest
18..    :target: https://skeleton.readthedocs.io/en/latest/?badge=latest
19
20.. image:: https://coveralls.io/repos/github/jaraco/inflect/badge.svg?branch=master
21    :target: https://coveralls.io/github/jaraco/inflect?branch=master
22
23.. image:: https://tidelift.com/badges/package/pypi/inflect
24   :target: https://tidelift.com/subscription/pkg/pypi-inflect?utm_source=pypi-inflect&utm_medium=readme
25
26NAME
27====
28
29inflect.py - Correctly generate plurals, singular nouns, ordinals, indefinite articles; convert numbers to words.
30
31SYNOPSIS
32========
33
34.. code-block:: python
35
36    import inflect
37
38    p = inflect.engine()
39
40    # METHODS:
41
42    # plural plural_noun plural_verb plural_adj singular_noun no num
43    # compare compare_nouns compare_nouns compare_adjs
44    # a an
45    # present_participle
46    # ordinal number_to_words
47    # join
48    # inflect classical gender
49    # defnoun defverb defadj defa defan
50
51
52    # UNCONDITIONALLY FORM THE PLURAL
53
54    print("The plural of ", word, " is ", p.plural(word))
55
56
57    # CONDITIONALLY FORM THE PLURAL
58
59    print("I saw", cat_count, p.plural("cat", cat_count))
60
61
62    # FORM PLURALS FOR SPECIFIC PARTS OF SPEECH
63
64    print(
65        p.plural_noun("I", N1),
66        p.plural_verb("saw", N1),
67        p.plural_adj("my", N2),
68        p.plural_noun("saw", N2),
69    )
70
71
72    # FORM THE SINGULAR OF PLURAL NOUNS
73
74    print("The singular of ", word, " is ", p.singular_noun(word))
75
76    # SELECT THE GENDER OF SINGULAR PRONOUNS
77
78    print(p.singular_noun("they"))  # 'it'
79    p.gender("f")
80    print(p.singular_noun("they"))  # 'she'
81
82
83    # DEAL WITH "0/1/N" -> "no/1/N" TRANSLATION:
84
85    print("There ", p.plural_verb("was", errors), p.no(" error", errors))
86
87
88    # USE DEFAULT COUNTS:
89
90    print(
91        p.num(N1, ""),
92        p.plural("I"),
93        p.plural_verb(" saw"),
94        p.num(N2),
95        p.plural_noun(" saw"),
96    )
97    print("There ", p.num(errors, ""), p.plural_verb("was"), p.no(" error"))
98
99
100    # COMPARE TWO WORDS "NUMBER-INSENSITIVELY":
101
102    if p.compare(word1, word2):
103        print("same")
104    if p.compare_nouns(word1, word2):
105        print("same noun")
106    if p.compare_verbs(word1, word2):
107        print("same verb")
108    if p.compare_adjs(word1, word2):
109        print("same adj.")
110
111
112    # ADD CORRECT "a" OR "an" FOR A GIVEN WORD:
113
114    print("Did you want ", p.a(thing), " or ", p.an(idea))
115
116
117    # CONVERT NUMERALS INTO ORDINALS (i.e. 1->1st, 2->2nd, 3->3rd, etc.)
118
119    print("It was", p.ordinal(position), " from the left\n")
120
121    # CONVERT NUMERALS TO WORDS (i.e. 1->"one", 101->"one hundred and one", etc.)
122    # RETURNS A SINGLE STRING...
123
124    words = p.number_to_words(1234)
125    # "one thousand, two hundred and thirty-four"
126    words = p.number_to_words(p.ordinal(1234))
127    # "one thousand, two hundred and thirty-fourth"
128
129
130    # GET BACK A LIST OF STRINGS, ONE FOR EACH "CHUNK"...
131
132    words = p.number_to_words(1234, wantlist=True)
133    # ("one thousand","two hundred and thirty-four")
134
135
136    # OPTIONAL PARAMETERS CHANGE TRANSLATION:
137
138    words = p.number_to_words(12345, group=1)
139    # "one, two, three, four, five"
140
141    words = p.number_to_words(12345, group=2)
142    # "twelve, thirty-four, five"
143
144    words = p.number_to_words(12345, group=3)
145    # "one twenty-three, forty-five"
146
147    words = p.number_to_words(1234, andword="")
148    # "one thousand, two hundred thirty-four"
149
150    words = p.number_to_words(1234, andword=", plus")
151    # "one thousand, two hundred, plus thirty-four"
152    # TODO: I get no comma before plus: check perl
153
154    words = p.number_to_words(555_1202, group=1, zero="oh")
155    # "five, five, five, one, two, oh, two"
156
157    words = p.number_to_words(555_1202, group=1, one="unity")
158    # "five, five, five, unity, two, oh, two"
159
160    words = p.number_to_words(123.456, group=1, decimal="mark")
161    # "one two three mark four five six"
162    # TODO: DOCBUG: perl gives commas here as do I
163
164    # LITERAL STYLE ONLY NAMES NUMBERS LESS THAN A CERTAIN THRESHOLD...
165
166    words = p.number_to_words(9, threshold=10)  # "nine"
167    words = p.number_to_words(10, threshold=10)  # "ten"
168    words = p.number_to_words(11, threshold=10)  # "11"
169    words = p.number_to_words(1000, threshold=10)  # "1,000"
170
171    # JOIN WORDS INTO A LIST:
172
173    mylist = join(("apple", "banana", "carrot"))
174    # "apple, banana, and carrot"
175
176    mylist = join(("apple", "banana"))
177    # "apple and banana"
178
179    mylist = join(("apple", "banana", "carrot"), final_sep="")
180    # "apple, banana and carrot"
181
182
183    # REQUIRE "CLASSICAL" PLURALS (EG: "focus"->"foci", "cherub"->"cherubim")
184
185    p.classical()  # USE ALL CLASSICAL PLURALS
186
187    p.classical(all=True)  # USE ALL CLASSICAL PLURALS
188    p.classical(all=False)  # SWITCH OFF CLASSICAL MODE
189
190    p.classical(zero=True)  #  "no error" INSTEAD OF "no errors"
191    p.classical(zero=False)  #  "no errors" INSTEAD OF "no error"
192
193    p.classical(herd=True)  #  "2 buffalo" INSTEAD OF "2 buffalos"
194    p.classical(herd=False)  #  "2 buffalos" INSTEAD OF "2 buffalo"
195
196    p.classical(persons=True)  # "2 chairpersons" INSTEAD OF "2 chairpeople"
197    p.classical(persons=False)  # "2 chairpeople" INSTEAD OF "2 chairpersons"
198
199    p.classical(ancient=True)  # "2 formulae" INSTEAD OF "2 formulas"
200    p.classical(ancient=False)  # "2 formulas" INSTEAD OF "2 formulae"
201
202
203    # INTERPOLATE "plural()", "plural_noun()", "plural_verb()", "plural_adj()", "singular_noun()",
204    # a()", "an()", "num()" AND "ordinal()" WITHIN STRINGS:
205
206    print(p.inflect("The plural of {0} is plural('{0}')".format(word)))
207    print(p.inflect("The singular of {0} is singular_noun('{0}')".format(word)))
208    print(p.inflect("I saw {0} plural('cat',{0})".format(cat_count)))
209    print(
210        p.inflect(
211            "plural('I',{0}) "
212            "plural_verb('saw',{0}) "
213            "plural('a',{1}) "
214            "plural_noun('saw',{1})".format(N1, N2)
215        )
216    )
217    print(
218        p.inflect(
219            "num({0}, False)plural('I') "
220            "plural_verb('saw') "
221            "num({1}, False)plural('a') "
222            "plural_noun('saw')".format(N1, N2)
223        )
224    )
225    print(p.inflect("I saw num({0}) plural('cat')\nnum()".format(cat_count)))
226    print(p.inflect("There plural_verb('was',{0}) no('error',{0})".format(errors)))
227    print(p.inflect("There num({0}, False)plural_verb('was') no('error')".format(errors)))
228    print(p.inflect("Did you want a('{0}') or an('{1}')".format(thing, idea)))
229    print(p.inflect("It was ordinal('{0}') from the left".format(position)))
230
231
232    # ADD USER-DEFINED INFLECTIONS (OVERRIDING INBUILT RULES):
233
234    p.defnoun("VAX", "VAXen")  # SINGULAR => PLURAL
235
236    p.defverb(
237        "will",  # 1ST PERSON SINGULAR
238        "shall",  # 1ST PERSON PLURAL
239        "will",  # 2ND PERSON SINGULAR
240        "will",  # 2ND PERSON PLURAL
241        "will",  # 3RD PERSON SINGULAR
242        "will",  # 3RD PERSON PLURAL
243    )
244
245    p.defadj("hir", "their")  # SINGULAR => PLURAL
246
247    p.defa("h")  # "AY HALWAYS SEZ 'HAITCH'!"
248
249    p.defan("horrendous.*")  # "AN HORRENDOUS AFFECTATION"
250
251
252DESCRIPTION
253===========
254
255The methods of the class ``engine`` in module ``inflect.py`` provide plural
256inflections, singular noun inflections, "a"/"an" selection for English words,
257and manipulation of numbers as words.
258
259Plural forms of all nouns, most verbs, and some adjectives are
260provided. Where appropriate, "classical" variants (for example: "brother" ->
261"brethren", "dogma" -> "dogmata", etc.) are also provided.
262
263Single forms of nouns are also provided. The gender of singular pronouns
264can be chosen (for example "they" -> "it" or "she" or "he" or "they").
265
266Pronunciation-based "a"/"an" selection is provided for all English
267words, and most initialisms.
268
269It is also possible to inflect numerals (1,2,3) to ordinals (1st, 2nd, 3rd)
270and to English words ("one", "two", "three").
271
272In generating these inflections, ``inflect.py`` follows the Oxford
273English Dictionary and the guidelines in Fowler's Modern English
274Usage, preferring the former where the two disagree.
275
276The module is built around standard British spelling, but is designed
277to cope with common American variants as well. Slang, jargon, and
278other English dialects are *not* explicitly catered for.
279
280Where two or more inflected forms exist for a single word (typically a
281"classical" form and a "modern" form), ``inflect.py`` prefers the
282more common form (typically the "modern" one), unless "classical"
283processing has been specified
284(see `MODERN VS CLASSICAL INFLECTIONS`).
285
286FORMING PLURALS AND SINGULARS
287=============================
288
289Inflecting Plurals and Singulars
290--------------------------------
291
292All of the ``plural...`` plural inflection methods take the word to be
293inflected as their first argument and return the corresponding inflection.
294Note that all such methods expect the *singular* form of the word. The
295results of passing a plural form are undefined (and unlikely to be correct).
296Similarly, the ``si...`` singular inflection method expects the *plural*
297form of the word.
298
299The ``plural...`` methods also take an optional second argument,
300which indicates the grammatical "number" of the word (or of another word
301with which the word being inflected must agree). If the "number" argument is
302supplied and is not ``1`` (or ``"one"`` or ``"a"``, or some other adjective that
303implies the singular), the plural form of the word is returned. If the
304"number" argument *does* indicate singularity, the (uninflected) word
305itself is returned. If the number argument is omitted, the plural form
306is returned unconditionally.
307
308The ``si...`` method takes a second argument in a similar fashion. If it is
309some form of the number ``1``, or is omitted, the singular form is returned.
310Otherwise the plural is returned unaltered.
311
312
313The various methods of ``inflect.engine`` are:
314
315
316
317``plural_noun(word, count=None)``
318
319 The method ``plural_noun()`` takes a *singular* English noun or
320 pronoun and returns its plural. Pronouns in the nominative ("I" ->
321 "we") and accusative ("me" -> "us") cases are handled, as are
322 possessive pronouns ("mine" -> "ours").
323
324
325``plural_verb(word, count=None)``
326
327 The method ``plural_verb()`` takes the *singular* form of a
328 conjugated verb (that is, one which is already in the correct "person"
329 and "mood") and returns the corresponding plural conjugation.
330
331
332``plural_adj(word, count=None)``
333
334 The method ``plural_adj()`` takes the *singular* form of
335 certain types of adjectives and returns the corresponding plural form.
336 Adjectives that are correctly handled include: "numerical" adjectives
337 ("a" -> "some"), demonstrative adjectives ("this" -> "these", "that" ->
338 "those"), and possessives ("my" -> "our", "cat's" -> "cats'", "child's"
339 -> "childrens'", etc.)
340
341
342``plural(word, count=None)``
343
344 The method ``plural()`` takes a *singular* English noun,
345 pronoun, verb, or adjective and returns its plural form. Where a word
346 has more than one inflection depending on its part of speech (for
347 example, the noun "thought" inflects to "thoughts", the verb "thought"
348 to "thought"), the (singular) noun sense is preferred to the (singular)
349 verb sense.
350
351 Hence ``plural("knife")`` will return "knives" ("knife" having been treated
352 as a singular noun), whereas ``plural("knifes")`` will return "knife"
353 ("knifes" having been treated as a 3rd person singular verb).
354
355 The inherent ambiguity of such cases suggests that,
356 where the part of speech is known, ``plural_noun``, ``plural_verb``, and
357 ``plural_adj`` should be used in preference to ``plural``.
358
359
360``singular_noun(word, count=None)``
361
362 The method ``singular_noun()`` takes a *plural* English noun or
363 pronoun and returns its singular. Pronouns in the nominative ("we" ->
364 "I") and accusative ("us" -> "me") cases are handled, as are
365 possessive pronouns ("ours" -> "mine"). When third person
366 singular pronouns are returned they take the neuter gender by default
367 ("they" -> "it"), not ("they"-> "she") nor ("they" -> "he"). This can be
368 changed with ``gender()``.
369
370Note that all these methods ignore any whitespace surrounding the
371word being inflected, but preserve that whitespace when the result is
372returned. For example, ``plural(" cat  ")`` returns " cats  ".
373
374
375``gender(genderletter)``
376
377 The third person plural pronoun takes the same form for the female, male and
378 neuter (e.g. "they"). The singular however, depends upon gender (e.g. "she",
379 "he", "it" and "they" -- "they" being the gender neutral form.) By default
380 ``singular_noun`` returns the neuter form, however, the gender can be selected with
381 the ``gender`` method. Pass the first letter of the gender to
382 ``gender`` to return the f(eminine), m(asculine), n(euter) or t(hey)
383 form of the singular. e.g.
384 gender('f') followed by singular_noun('themselves') returns 'herself'.
385
386Numbered plurals
387----------------
388
389The ``plural...`` methods return only the inflected word, not the count that
390was used to inflect it. Thus, in order to produce "I saw 3 ducks", it
391is necessary to use:
392
393.. code-block:: python
394
395    print("I saw", N, p.plural_noun(animal, N))
396
397Since the usual purpose of producing a plural is to make it agree with
398a preceding count, inflect.py provides a method
399(``no(word, count)``) which, given a word and a(n optional) count, returns the
400count followed by the correctly inflected word. Hence the previous
401example can be rewritten:
402
403.. code-block:: python
404
405    print("I saw ", p.no(animal, N))
406
407In addition, if the count is zero (or some other term which implies
408zero, such as ``"zero"``, ``"nil"``, etc.) the count is replaced by the
409word "no". Hence, if ``N`` had the value zero, the previous example
410would print (the somewhat more elegant)::
411
412    I saw no animals
413
414rather than::
415
416    I saw 0 animals
417
418Note that the name of the method is a pun: the method
419returns either a number (a *No.*) or a ``"no"``, in front of the
420inflected word.
421
422
423Reducing the number of counts required
424--------------------------------------
425
426In some contexts, the need to supply an explicit count to the various
427``plural...`` methods makes for tiresome repetition. For example:
428
429.. code-block:: python
430
431    print(
432        plural_adj("This", errors),
433        plural_noun(" error", errors),
434        plural_verb(" was", errors),
435        " fatal.",
436    )
437
438inflect.py therefore provides a method
439(``num(count=None, show=None)``) which may be used to set a persistent "default number"
440value. If such a value is set, it is subsequently used whenever an
441optional second "number" argument is omitted. The default value thus set
442can subsequently be removed by calling ``num()`` with no arguments.
443Hence we could rewrite the previous example:
444
445.. code-block:: python
446
447    p.num(errors)
448    print(p.plural_adj("This"), p.plural_noun(" error"), p.plural_verb(" was"), "fatal.")
449    p.num()
450
451Normally, ``num()`` returns its first argument, so that it may also
452be "inlined" in contexts like:
453
454.. code-block:: python
455
456    print(p.num(errors), p.plural_noun(" error"), p.plural_verb(" was"), " detected.")
457    if severity > 1:
458        print(
459            p.plural_adj("This"), p.plural_noun(" error"), p.plural_verb(" was"), "fatal."
460        )
461
462However, in certain contexts (see `INTERPOLATING INFLECTIONS IN STRINGS`)
463it is preferable that ``num()`` return an empty string. Hence ``num()``
464provides an optional second argument. If that argument is supplied (that is, if
465it is defined) and evaluates to false, ``num`` returns an empty string
466instead of its first argument. For example:
467
468.. code-block:: python
469
470    print(p.num(errors, 0), p.no("error"), p.plural_verb(" was"), " detected.")
471    if severity > 1:
472        print(
473            p.plural_adj("This"), p.plural_noun(" error"), p.plural_verb(" was"), "fatal."
474        )
475
476
477
478Number-insensitive equality
479---------------------------
480
481inflect.py also provides a solution to the problem
482of comparing words of differing plurality through the methods
483``compare(word1, word2)``, ``compare_nouns(word1, word2)``,
484``compare_verbs(word1, word2)``, and ``compare_adjs(word1, word2)``.
485Each  of these methods takes two strings, and  compares them
486using the corresponding plural-inflection method (``plural()``, ``plural_noun()``,
487``plural_verb()``, and ``plural_adj()`` respectively).
488
489The comparison returns true if:
490
491- the strings are equal, or
492- one string is equal to a plural form of the other, or
493- the strings are two different plural forms of the one word.
494
495
496Hence all of the following return true:
497
498.. code-block:: python
499
500    p.compare("index", "index")  # RETURNS "eq"
501    p.compare("index", "indexes")  # RETURNS "s:p"
502    p.compare("index", "indices")  # RETURNS "s:p"
503    p.compare("indexes", "index")  # RETURNS "p:s"
504    p.compare("indices", "index")  # RETURNS "p:s"
505    p.compare("indices", "indexes")  # RETURNS "p:p"
506    p.compare("indexes", "indices")  # RETURNS "p:p"
507    p.compare("indices", "indices")  # RETURNS "eq"
508
509As indicated by the comments in the previous example, the actual value
510returned by the various ``compare`` methods encodes which of the
511three equality rules succeeded: "eq" is returned if the strings were
512identical, "s:p" if the strings were singular and plural respectively,
513"p:s" for plural and singular, and "p:p" for two distinct plurals.
514Inequality is indicated by returning an empty string.
515
516It should be noted that two distinct singular words which happen to take
517the same plural form are *not* considered equal, nor are cases where
518one (singular) word's plural is the other (plural) word's singular.
519Hence all of the following return false:
520
521.. code-block:: python
522
523    p.compare("base", "basis")  # ALTHOUGH BOTH -> "bases"
524    p.compare("syrinx", "syringe")  # ALTHOUGH BOTH -> "syringes"
525    p.compare("she", "he")  # ALTHOUGH BOTH -> "they"
526
527    p.compare("opus", "operas")  # ALTHOUGH "opus" -> "opera" -> "operas"
528    p.compare("taxi", "taxes")  # ALTHOUGH "taxi" -> "taxis" -> "taxes"
529
530Note too that, although the comparison is "number-insensitive" it is *not*
531case-insensitive (that is, ``plural("time","Times")`` returns false. To obtain
532both number and case insensitivity, use the ``lower()`` method on both strings
533(that is, ``plural("time".lower(), "Times".lower())`` returns true).
534
535Related Functionality
536=====================
537
538Shout out to these libraries that provide related functionality:
539
540* `WordSet <https://jaracotext.readthedocs.io/en/latest/#jaraco.text.WordSet>`_
541  parses identifiers like variable names into sets of words suitable for re-assembling
542  in another form.
543
544* `word2number <https://pypi.org/project/word2number/>`_ converts words to
545  a number.
546
547
548For Enterprise
549==============
550
551Available as part of the Tidelift Subscription.
552
553This project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.
554
555`Learn more <https://tidelift.com/subscription/pkg/pypi-PROJECT?utm_source=pypi-PROJECT&utm_medium=referral&utm_campaign=github>`_.
556
557Security Contact
558================
559
560To report a security vulnerability, please use the
561`Tidelift security contact <https://tidelift.com/security>`_.
562Tidelift will coordinate the fix and disclosure.
563