Correctly generate plurals, ordinals, indefinite articles; convert numbers to words

Overview
Automated Tests Code style: Black https://coveralls.io/repos/github/jaraco/inflect/badge.svg?branch=master https://tidelift.com/badges/package/pypi/inflect

NAME

inflect.py - Correctly generate plurals, singular nouns, ordinals, indefinite articles; convert numbers to words.

SYNOPSIS

import inflect

p = inflect.engine()

# METHODS:

# plural plural_noun plural_verb plural_adj singular_noun no num
# compare compare_nouns compare_nouns compare_adjs
# a an
# present_participle
# ordinal number_to_words
# join
# inflect classical gender
# defnoun defverb defadj defa defan


# UNCONDITIONALLY FORM THE PLURAL

print("The plural of ", word, " is ", p.plural(word))


# CONDITIONALLY FORM THE PLURAL

print("I saw", cat_count, p.plural("cat", cat_count))


# FORM PLURALS FOR SPECIFIC PARTS OF SPEECH

print(
    p.plural_noun("I", N1),
    p.plural_verb("saw", N1),
    p.plural_adj("my", N2),
    p.plural_noun("saw", N2),
)


# FORM THE SINGULAR OF PLURAL NOUNS

print("The singular of ", word, " is ", p.singular_noun(word))

# SELECT THE GENDER OF SINGULAR PRONOUNS

print(p.singular_noun("they"))  # 'it'
p.gender("f")
print(p.singular_noun("they"))  # 'she'


# DEAL WITH "0/1/N" -> "no/1/N" TRANSLATION:

print("There ", p.plural_verb("was", errors), p.no(" error", errors))


# USE DEFAULT COUNTS:

print(
    p.num(N1, ""),
    p.plural("I"),
    p.plural_verb(" saw"),
    p.num(N2),
    p.plural_noun(" saw"),
)
print("There ", p.num(errors, ""), p.plural_verb("was"), p.no(" error"))


# COMPARE TWO WORDS "NUMBER-INSENSITIVELY":

if p.compare(word1, word2):
    print("same")
if p.compare_nouns(word1, word2):
    print("same noun")
if p.compare_verbs(word1, word2):
    print("same verb")
if p.compare_adjs(word1, word2):
    print("same adj.")


# ADD CORRECT "a" OR "an" FOR A GIVEN WORD:

print("Did you want ", p.a(thing), " or ", p.an(idea))


# CONVERT NUMERALS INTO ORDINALS (i.e. 1->1st, 2->2nd, 3->3rd, etc.)

print("It was", p.ordinal(position), " from the left\n")

# CONVERT NUMERALS TO WORDS (i.e. 1->"one", 101->"one hundred and one", etc.)
# RETURNS A SINGLE STRING...

words = p.number_to_words(1234)
# "one thousand, two hundred and thirty-four"
words = p.number_to_words(p.ordinal(1234))
# "one thousand, two hundred and thirty-fourth"


# GET BACK A LIST OF STRINGS, ONE FOR EACH "CHUNK"...

words = p.number_to_words(1234, wantlist=True)
# ("one thousand","two hundred and thirty-four")


# OPTIONAL PARAMETERS CHANGE TRANSLATION:

words = p.number_to_words(12345, group=1)
# "one, two, three, four, five"

words = p.number_to_words(12345, group=2)
# "twelve, thirty-four, five"

words = p.number_to_words(12345, group=3)
# "one twenty-three, forty-five"

words = p.number_to_words(1234, andword="")
# "one thousand, two hundred thirty-four"

words = p.number_to_words(1234, andword=", plus")
# "one thousand, two hundred, plus thirty-four"
# TODO: I get no comma before plus: check perl

words = p.number_to_words(555_1202, group=1, zero="oh")
# "five, five, five, one, two, oh, two"

words = p.number_to_words(555_1202, group=1, one="unity")
# "five, five, five, unity, two, oh, two"

words = p.number_to_words(123.456, group=1, decimal="mark")
# "one two three mark four five six"
# TODO: DOCBUG: perl gives commas here as do I

# LITERAL STYLE ONLY NAMES NUMBERS LESS THAN A CERTAIN THRESHOLD...

words = p.number_to_words(9, threshold=10)  # "nine"
words = p.number_to_words(10, threshold=10)  # "ten"
words = p.number_to_words(11, threshold=10)  # "11"
words = p.number_to_words(1000, threshold=10)  # "1,000"

# JOIN WORDS INTO A LIST:

mylist = join(("apple", "banana", "carrot"))
# "apple, banana, and carrot"

mylist = join(("apple", "banana"))
# "apple and banana"

mylist = join(("apple", "banana", "carrot"), final_sep="")
# "apple, banana and carrot"


# REQUIRE "CLASSICAL" PLURALS (EG: "focus"->"foci", "cherub"->"cherubim")

p.classical()  # USE ALL CLASSICAL PLURALS

p.classical(all=True)  # USE ALL CLASSICAL PLURALS
p.classical(all=False)  # SWITCH OFF CLASSICAL MODE

p.classical(zero=True)  #  "no error" INSTEAD OF "no errors"
p.classical(zero=False)  #  "no errors" INSTEAD OF "no error"

p.classical(herd=True)  #  "2 buffalo" INSTEAD OF "2 buffalos"
p.classical(herd=False)  #  "2 buffalos" INSTEAD OF "2 buffalo"

p.classical(persons=True)  # "2 chairpersons" INSTEAD OF "2 chairpeople"
p.classical(persons=False)  # "2 chairpeople" INSTEAD OF "2 chairpersons"

p.classical(ancient=True)  # "2 formulae" INSTEAD OF "2 formulas"
p.classical(ancient=False)  # "2 formulas" INSTEAD OF "2 formulae"


# INTERPOLATE "plural()", "plural_noun()", "plural_verb()", "plural_adj()", "singular_noun()",
# a()", "an()", "num()" AND "ordinal()" WITHIN STRINGS:

print(p.inflect("The plural of {0} is plural('{0}')".format(word)))
print(p.inflect("The singular of {0} is singular_noun('{0}')".format(word)))
print(p.inflect("I saw {0} plural('cat',{0})".format(cat_count)))
print(
    p.inflect(
        "plural('I',{0}) "
        "plural_verb('saw',{0}) "
        "plural('a',{1}) "
        "plural_noun('saw',{1})".format(N1, N2)
    )
)
print(
    p.inflect(
        "num({0}, False)plural('I') "
        "plural_verb('saw') "
        "num({1}, False)plural('a') "
        "plural_noun('saw')".format(N1, N2)
    )
)
print(p.inflect("I saw num({0}) plural('cat')\nnum()".format(cat_count)))
print(p.inflect("There plural_verb('was',{0}) no('error',{0})".format(errors)))
print(p.inflect("There num({0}, False)plural_verb('was') no('error')".format(errors)))
print(p.inflect("Did you want a('{0}') or an('{1}')".format(thing, idea)))
print(p.inflect("It was ordinal('{0}') from the left".format(position)))


# ADD USER-DEFINED INFLECTIONS (OVERRIDING INBUILT RULES):

p.defnoun("VAX", "VAXen")  # SINGULAR => PLURAL

p.defverb(
    "will",  # 1ST PERSON SINGULAR
    "shall",  # 1ST PERSON PLURAL
    "will",  # 2ND PERSON SINGULAR
    "will",  # 2ND PERSON PLURAL
    "will",  # 3RD PERSON SINGULAR
    "will",  # 3RD PERSON PLURAL
)

p.defadj("hir", "their")  # SINGULAR => PLURAL

p.defa("h")  # "AY HALWAYS SEZ 'HAITCH'!"

p.defan("horrendous.*")  # "AN HORRENDOUS AFFECTATION"

DESCRIPTION

The methods of the class engine in module inflect.py provide plural inflections, singular noun inflections, "a"/"an" selection for English words, and manipulation of numbers as words.

Plural forms of all nouns, most verbs, and some adjectives are provided. Where appropriate, "classical" variants (for example: "brother" -> "brethren", "dogma" -> "dogmata", etc.) are also provided.

Single forms of nouns are also provided. The gender of singular pronouns can be chosen (for example "they" -> "it" or "she" or "he" or "they").

Pronunciation-based "a"/"an" selection is provided for all English words, and most initialisms.

It is also possible to inflect numerals (1,2,3) to ordinals (1st, 2nd, 3rd) and to English words ("one", "two", "three").

In generating these inflections, inflect.py follows the Oxford English Dictionary and the guidelines in Fowler's Modern English Usage, preferring the former where the two disagree.

The module is built around standard British spelling, but is designed to cope with common American variants as well. Slang, jargon, and other English dialects are not explicitly catered for.

Where two or more inflected forms exist for a single word (typically a "classical" form and a "modern" form), inflect.py prefers the more common form (typically the "modern" one), unless "classical" processing has been specified (see MODERN VS CLASSICAL INFLECTIONS).

FORMING PLURALS AND SINGULARS

Inflecting Plurals and Singulars

All of the plural... plural inflection methods take the word to be inflected as their first argument and return the corresponding inflection. Note that all such methods expect the singular form of the word. The results of passing a plural form are undefined (and unlikely to be correct). Similarly, the si... singular inflection method expects the plural form of the word.

The plural... methods also take an optional second argument, which indicates the grammatical "number" of the word (or of another word with which the word being inflected must agree). If the "number" argument is supplied and is not 1 (or "one" or "a", or some other adjective that implies the singular), the plural form of the word is returned. If the "number" argument does indicate singularity, the (uninflected) word itself is returned. If the number argument is omitted, the plural form is returned unconditionally.

The si... method takes a second argument in a similar fashion. If it is some form of the number 1, or is omitted, the singular form is returned. Otherwise the plural is returned unaltered.

The various methods of inflect.engine are:

plural_noun(word, count=None)

The method plural_noun() takes a singular English noun or pronoun and returns its plural. Pronouns in the nominative ("I" -> "we") and accusative ("me" -> "us") cases are handled, as are possessive pronouns ("mine" -> "ours").

plural_verb(word, count=None)

The method plural_verb() takes the singular form of a conjugated verb (that is, one which is already in the correct "person" and "mood") and returns the corresponding plural conjugation.

plural_adj(word, count=None)

The method plural_adj() takes the singular form of certain types of adjectives and returns the corresponding plural form. Adjectives that are correctly handled include: "numerical" adjectives ("a" -> "some"), demonstrative adjectives ("this" -> "these", "that" -> "those"), and possessives ("my" -> "our", "cat's" -> "cats'", "child's" -> "childrens'", etc.)

plural(word, count=None)

The method plural() takes a singular English noun, pronoun, verb, or adjective and returns its plural form. Where a word has more than one inflection depending on its part of speech (for example, the noun "thought" inflects to "thoughts", the verb "thought" to "thought"), the (singular) noun sense is preferred to the (singular) verb sense.

Hence plural("knife") will return "knives" ("knife" having been treated as a singular noun), whereas plural("knifes") will return "knife" ("knifes" having been treated as a 3rd person singular verb).

The inherent ambiguity of such cases suggests that, where the part of speech is known, plural_noun, plural_verb, and plural_adj should be used in preference to plural.

singular_noun(word, count=None)

The method singular_noun() takes a plural English noun or pronoun and returns its singular. Pronouns in the nominative ("we" -> "I") and accusative ("us" -> "me") cases are handled, as are possessive pronouns ("ours" -> "mine"). When third person singular pronouns are returned they take the neuter gender by default ("they" -> "it"), not ("they"-> "she") nor ("they" -> "he"). This can be changed with gender().

Note that all these methods ignore any whitespace surrounding the word being inflected, but preserve that whitespace when the result is returned. For example, plural(" cat ") returns " cats ".

gender(genderletter)

The third person plural pronoun takes the same form for the female, male and neuter (e.g. "they"). The singular however, depends upon gender (e.g. "she", "he", "it" and "they" -- "they" being the gender neutral form.) By default singular_noun returns the neuter form, however, the gender can be selected with the gender method. Pass the first letter of the gender to gender to return the f(eminine), m(asculine), n(euter) or t(hey) form of the singular. e.g. gender('f') followed by singular_noun('themselves') returns 'herself'.

Numbered plurals

The plural... methods return only the inflected word, not the count that was used to inflect it. Thus, in order to produce "I saw 3 ducks", it is necessary to use:

print("I saw", N, p.plural_noun(animal, N))

Since the usual purpose of producing a plural is to make it agree with a preceding count, inflect.py provides a method (no(word, count)) which, given a word and a(n optional) count, returns the count followed by the correctly inflected word. Hence the previous example can be rewritten:

print("I saw ", p.no(animal, N))

In addition, if the count is zero (or some other term which implies zero, such as "zero", "nil", etc.) the count is replaced by the word "no". Hence, if N had the value zero, the previous example would print (the somewhat more elegant):

I saw no animals

rather than:

I saw 0 animals

Note that the name of the method is a pun: the method returns either a number (a No.) or a "no", in front of the inflected word.

Reducing the number of counts required

In some contexts, the need to supply an explicit count to the various plural... methods makes for tiresome repetition. For example:

print(
    plural_adj("This", errors),
    plural_noun(" error", errors),
    plural_verb(" was", errors),
    " fatal.",
)

inflect.py therefore provides a method (num(count=None, show=None)) which may be used to set a persistent "default number" value. If such a value is set, it is subsequently used whenever an optional second "number" argument is omitted. The default value thus set can subsequently be removed by calling num() with no arguments. Hence we could rewrite the previous example:

p.num(errors)
print(p.plural_adj("This"), p.plural_noun(" error"), p.plural_verb(" was"), "fatal.")
p.num()

Normally, num() returns its first argument, so that it may also be "inlined" in contexts like:

print(p.num(errors), p.plural_noun(" error"), p.plural_verb(" was"), " detected.")
if severity > 1:
    print(
        p.plural_adj("This"), p.plural_noun(" error"), p.plural_verb(" was"), "fatal."
    )

However, in certain contexts (see INTERPOLATING INFLECTIONS IN STRINGS) it is preferable that num() return an empty string. Hence num() provides an optional second argument. If that argument is supplied (that is, if it is defined) and evaluates to false, num returns an empty string instead of its first argument. For example:

print(p.num(errors, 0), p.no("error"), p.plural_verb(" was"), " detected.")
if severity > 1:
    print(
        p.plural_adj("This"), p.plural_noun(" error"), p.plural_verb(" was"), "fatal."
    )

Number-insensitive equality

inflect.py also provides a solution to the problem of comparing words of differing plurality through the methods compare(word1, word2), compare_nouns(word1, word2), compare_verbs(word1, word2), and compare_adjs(word1, word2). Each of these methods takes two strings, and compares them using the corresponding plural-inflection method (plural(), plural_noun(), plural_verb(), and plural_adj() respectively).

The comparison returns true if:

  • the strings are equal, or
  • one string is equal to a plural form of the other, or
  • the strings are two different plural forms of the one word.

Hence all of the following return true:

p.compare("index", "index")  # RETURNS "eq"
p.compare("index", "indexes")  # RETURNS "s:p"
p.compare("index", "indices")  # RETURNS "s:p"
p.compare("indexes", "index")  # RETURNS "p:s"
p.compare("indices", "index")  # RETURNS "p:s"
p.compare("indices", "indexes")  # RETURNS "p:p"
p.compare("indexes", "indices")  # RETURNS "p:p"
p.compare("indices", "indices")  # RETURNS "eq"

As indicated by the comments in the previous example, the actual value returned by the various compare methods encodes which of the three equality rules succeeded: "eq" is returned if the strings were identical, "s:p" if the strings were singular and plural respectively, "p:s" for plural and singular, and "p:p" for two distinct plurals. Inequality is indicated by returning an empty string.

It should be noted that two distinct singular words which happen to take the same plural form are not considered equal, nor are cases where one (singular) word's plural is the other (plural) word's singular. Hence all of the following return false:

p.compare("base", "basis")  # ALTHOUGH BOTH -> "bases"
p.compare("syrinx", "syringe")  # ALTHOUGH BOTH -> "syringes"
p.compare("she", "he")  # ALTHOUGH BOTH -> "they"

p.compare("opus", "operas")  # ALTHOUGH "opus" -> "opera" -> "operas"
p.compare("taxi", "taxes")  # ALTHOUGH "taxi" -> "taxis" -> "taxes"

Note too that, although the comparison is "number-insensitive" it is not case-insensitive (that is, plural("time","Times") returns false. To obtain both number and case insensitivity, use the lower() method on both strings (that is, plural("time".lower(), "Times".lower()) returns true).

Related Functionality

Shout out to these libraries that provide related functionality:

  • WordSet parses identifiers like variable names into sets of words suitable for re-assembling in another form.
  • word2number converts words to a number.

For Enterprise

Available as part of the Tidelift Subscription.

This 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.

Learn more.

Security Contact

To report a security vulnerability, please use the Tidelift security contact. Tidelift will coordinate the fix and disclosure.

Comments
  • Add Travis CI and Coveralls

    Add Travis CI and Coveralls

    I've added a configuration file so Travis CI will build each commit and pull request. It runs against each Python version supported by Travis CI: 2.6, 2.7, 3.2, 3.3, 3.4, PyPy and PyPy3, and all of them pass with no changes needed. This will help maintain the codebase by automatically running the tests against all Python versions for each PR -- it's very handy for picking up those Py2/Py3 inconsistencies..

    It also runs the tests with coverage enabled, and sends the coverage reports to Coveralls, so you can see how coverage changes, or if a PR doesn't include tests to cover its new code. Right now, inflect.py has an amazing 98% coverage!

    You get reports like this:

    • https://travis-ci.org/hugovk/inflect.py
    • https://coveralls.io/r/hugovk/inflect.py

    I've added badges to the README to show off how good stats this project has. Both Travis CI and Coveralls are free for open source project, you just need to enable them for the repo. Please can you do so at:

    • https://travis-ci.org/profile
    • https://coveralls.io/repos/new

    Thanks!

    opened by hugovk 18
  • Allow special case dictionaries to match on lowercase final word

    Allow special case dictionaries to match on lowercase final word

    While inflecting some ingredient-related content, I'd noticed that although the word olives is currently handled correctly by singular_noun, black olives is not:

    >>> import inflect
    >>> inflect.__version__
    '4.0.0'
    >>> e = inflect.engine()
    >>> e.singular_noun('olives')
    'olive'
    >>> e.singular_noun('black olives')
    'black olife'
    

    In the inflect code, the handling of single-word olives is performed by a special case which overrides the default logic for items ending ...ves.

    This is one of a number of special cases gated by boolean conditions of the form if lowerword in <map>:, which fail if lowerword doesn't exactly match with a key in the <map>.

    Switching these conditions to use lowerwordlast instead of lowerword results in additional matches for multi-word phrases without negatively impacting any existing test cases.

    It's arguably not 'perfect' since multi-word phrases may have challenging plurality rules (like the situations handled by the compound logic, but hopefully it's a reasonably safe improvement.

    This also resolves https://github.com/jazzband/inflect/issues/30 which falls into a similar special case relating to ...ies tokens.

    opened by jayaddison 14
  • Implement Jazzband guidelines for project inflect.py

    Implement Jazzband guidelines for project inflect.py

    This issue tracks the implementation of the Jazzband guidelines for the project inflect.py

    It was initiated by @jaraco who was automatically assigned in addition to the Jazzband roadies.

    See the TODO list below for the generally required tasks, but feel free to update it in case the project requires it.

    Feel free to ping a Jazzband roadie if you have any question.

    TODOs

    • [x] Fix all links in the docs (and README file etc) from old to new repo
    • [x] Add the Jazzband badge to the README file
    • [x] Add the Jazzband contributing guideline to the CONTRIBUTING.md file
    • [x] Check if continuous testing works (e.g. Travis-CI, CircleCI, AppVeyor, etc)
    • [x] Check if test coverage services work (e.g. Coveralls, Codecov, etc)
    • [x] Add jazzband account to PyPI project as maintainer role (URL: https://pypi.python.org/pypi?:action=role_form&package_name=<PROJECTNAME>)
    • [x] Add jazzband-bot as maintainer to the Read the Docs project (URL: https://readthedocs.org/dashboard/<PROJECTNAME>/users/)
    • [x] Fix project URL in GitHub project description
    • [x] Review project if other services are used and port them to Jazzband

    Project details

    Description Correctly generate plurals, ordinals, indefinite articles; convert numbers to words
    Homepage http://pypi.python.org/pypi/inflect
    Stargazers 0
    Open issues 0
    Forks 0
    Default branch master
    Is a fork True
    Has Wiki True
    Has Pages False
    opened by jazzband-bot 13
  • Transfer project to jaraco

    Transfer project to jaraco

    Given the ~~lack of support for Azure pipelines (#101)~~, the ~~less streamlined process for releases (#80)~~, and the exclusion of sponsorship for these projects (#102), the inclusion of this project in Jazzband is now more of a hindrance than a benefit.

    @jezdez Would you please transfer the project back to /jaraco?

    opened by jaraco 11
  • Plural issues?

    Plural issues?

    Some are wrong, I think:

    >>> p.plural('corpus')  # corpora
    'corpuses'
    >>> p.plural('means')  # means
    'mean'
    >>> p.plural('vita')   # vitae
    'vitas'
    >>> p.plural('backhoe')
    'backhoes'
    >>> p.plural('hoe')  # hoes
    'ho'
    >>> p.plural('ho')   # hos
    'h'
    

    These are technically correct, but unusual (and not a mistake like the octupus-plural):

    >>> p.plural('radius')  # radii, radiuses
    'radiuses'
    >>> p.plural('curriculum')  # curricula, curriculums
    'curriculums'
    >>> p.plural('medium')  # mediums, media
    'mediums'
    >>> p.plural('appendix')  # appendixes, appendices
    'appendixes'
    # also index
    

    Not sure how it should work for uncountables:

    >>> p.plural('cattle')  # cattle        
    'cattles'
    
    help wanted 
    opened by mbr 11
  • query of death

    query of death

    On version 2.1.0 This string: "lens with a lens ()." yields an exception.

    > /lib/python3.6/site-packages/inflect.py in plural(self, text, count)
    >    2239             self._pl_special_adjective(word, count)
    >    2240             or self._pl_special_verb(word, count)
    > -> 2241             or self._plnoun(word, count),
    >    2242         )
    >    2243         return "{}{}{}".format(pre, plural, post)
    > 
    > /lib/python3.6/site-packages/inflect.py in postprocess(self, orig, inflected)
    >    2209                 continue
    >    2210             if word.capitalize() == word:
    > -> 2211                 result[index] = result[index].capitalize()
    >    2212             if word == word.upper():
    >    2213                 result[index] = result[index].upper()
    

    IndexError: list index out of range

    stale invalid 
    opened by uriva 9
  • Cannot install with old setuptools

    Cannot install with old setuptools

    Windows 7 Python 2.7.8

    C:\stufftodelete>pip install -e git+https://github.com/pwdyson/inflect.py#egg=inflect
    Obtaining inflect from git+https://github.com/pwdyson/inflect.py#egg=inflect
      Cloning https://github.com/pwdyson/inflect.py to c:\stufftodelete\src\inflect
      Running setup.py (path:C:\stufftodelete\src\inflect\setup.py) egg_info for package inflect
        usage: -c [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
           or: -c --help [cmd1 cmd2 ...]
           or: -c --help-commands
           or: -c cmd --help
    
        error: invalid command 'egg_info'
        Complete output from command python setup.py egg_info:
        usage: -c [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
    
       or: -c --help [cmd1 cmd2 ...]
    
       or: -c --help-commands
    
       or: -c cmd --help
    
    
    
    error: invalid command 'egg_info'
    
    ----------------------------------------
    Cleaning up...
    Command python setup.py egg_info failed with error code 1 in C:\stufftodelete\src\inflect
    

    But then:

    C:\stufftodelete>pip install --upgrade setuptools
    Downloading/unpacking setuptools from https://pypi.python.org/packages/3.4/s/setuptools/setuptools-7.0-py2.py3-none-any.
    whl#md5=918e7e5ea108507e1ffbbdfccc3496b1
    Installing collected packages: setuptools
      Found existing installation: setuptools 0.6c11
        Uninstalling setuptools:
          Successfully uninstalled setuptools
    Successfully installed setuptools
    Cleaning up...
    

    And so:

    C:\stufftodelete>pip install -e git+https://github.com/pwdyson/inflect.py#egg=inflect
    Obtaining inflect from git+https://github.com/pwdyson/inflect.py#egg=inflect
      Updating c:\stufftodelete\src\inflect clone
      Running setup.py (path:C:\stufftodelete\src\inflect\setup.py) egg_info for package inflect
    
      Installing extra requirements: 'egg'
    Installing collected packages: inflect
      Running setup.py develop for inflect
    
        Creating c:\python27\lib\site-packages\inflect.egg-link (link to .)
        Adding inflect 0.2.5pre1 to easy-install.pth file
    
        Installed c:\stufftodelete\src\inflect
    Successfully installed inflect
    Cleaning up...
    

    Can the dependency to certain setuptools version be included in the setup, or must it already be in place? If not, can it be mentioned in the README installation instructions?

    opened by hugovk 9
  • Failed to import: `Field` default cannot be set in `Annotated` for 'num_Annotated[str, FieldInfo(min_length=1, extra={})]'

    Failed to import: `Field` default cannot be set in `Annotated` for 'num_Annotated[str, FieldInfo(min_length=1, extra={})]'

    Error message:

    Traceback (most recent call last):
      File "/data/cuih7/[REDACTED]", line 7, in <module>
        import inflect
      File "/data/cuih7/miniconda3/envs/nlp20220817/lib/python3.10/site-packages/inflect/__init__.py", line 2046, in <module>
        class engine:
      File "/data/cuih7/miniconda3/envs/nlp20220817/lib/python3.10/site-packages/inflect/__init__.py", line 3781, in engine
        def number_to_words(  # noqa: C901
      File "pydantic/decorator.py", line 36, in pydantic.decorator.validate_arguments.validate
        import sys
      File "pydantic/decorator.py", line 126, in pydantic.decorator.ValidatedFunction.__init__
        try:
      File "pydantic/decorator.py", line 259, in pydantic.decorator.ValidatedFunction.create_model
        return fun
      File "pydantic/main.py", line 972, in pydantic.main.create_model
      File "pydantic/main.py", line 204, in pydantic.main.ModelMetaclass.__new__
      File "pydantic/fields.py", line 488, in pydantic.fields.ModelField.infer
      File "pydantic/fields.py", line 419, in pydantic.fields.ModelField.__init__
      File "pydantic/fields.py", line 534, in pydantic.fields.ModelField.prepare
      File "pydantic/fields.py", line 633, in pydantic.fields.ModelField._type_analysis
      File "pydantic/fields.py", line 776, in pydantic.fields.ModelField._create_sub_type
      File "pydantic/fields.py", line 451, in pydantic.fields.ModelField._get_field_info
    ValueError: `Field` default cannot be set in `Annotated` for 'num_Annotated[str, FieldInfo(min_length=1, extra={})]'
    

    I'm using the library from conda-forge. Downgrading from 6.0.0-pyhd8ed1ab_0 to 5.6.2-pyhd8ed1ab_0 fixes the issue.

    bug 
    opened by cuihaoleo 7
  • dash and lowered_split fix for inflect.py _plnoun()

    dash and lowered_split fix for inflect.py _plnoun()

    In function _plnoun(), the variable lowered_split is split on dashes, but when reusing this variable, code required whitespace split lowerd words, not dash split.

    opened by picobyte 7
  • Import unicode_literals from __futures__ for unicode handling in 2.7

    Import unicode_literals from __futures__ for unicode handling in 2.7

    Unicode strings would cause errors in python 2.7 when using inflect. With this one additional line, no error is thrown.

    Fixes #52

    Includes test file, testing for words containing unicode characters.

    opened by nielstron 7
  • Drop unsupported Python 3.3

    Drop unsupported Python 3.3

    EOL since 2017-09-29: https://en.wikipedia.org/wiki/CPython#Version_history

    See also https://github.com/pwdyson/inflect.py/pull/44 which fixes the flake8 error for Python 3.5 on the CI.

    opened by hugovk 7
  • "Entity" gets pluralized to "Entitys"

    docker run -it python:3.11 bash
    [email protected]:/# pip install inflect==6.0.2
    Collecting inflect==6.0.2
      Downloading inflect-6.0.2-py3-none-any.whl (34 kB)
    Collecting pydantic>=1.9.1
      Downloading pydantic-1.10.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (14.1 MB)
         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 14.1/14.1 MB 9.7 MB/s eta 0:00:00
    Collecting typing-extensions>=4.1.0
      Downloading typing_extensions-4.4.0-py3-none-any.whl (26 kB)
    Installing collected packages: typing-extensions, pydantic, inflect
    Successfully installed inflect-6.0.2 pydantic-1.10.2 typing-extensions-4.4.0
    WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
    [email protected]:/# python
    Python 3.11.1 (main, Dec 21 2022, 18:32:57) [GCC 10.2.1 20210110] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import inflect
    >>> word="Entity"
    >>> print(f'The plural of "{word}" is "{inflect.engine().plural(word)}".')
    The plural of "Entity" is "Entitys".
    >>> print(f'The plural of "{word}" is "{inflect.engine().plural_noun(word)}".')
    The plural of "Entity" is "Entitys".
    
    opened by fezzik1620 2
  • 'defnoun' doesn't seem to work when the word is a part of a string passed

    'defnoun' doesn't seem to work when the word is a part of a string passed

    Originally reported by @aMiss-aWry in #161:

    I can fix the specific words with defnoun('jeans', 'jeans'), which corrects the result for an isolated string 'jeans' -> 'jeans'.

    However, if I try to run plural_noun on 'blue jeans' instead of 'jeans' it then breaks again, returning 'blue jeanss'. I understand this is because 'blue jeans' appears to be a different string from 'jeans', but perhaps it should check the rules for the part of the string it is altering?

    feature help wanted 
    opened by jaraco 1
  • Words ending in 's' should never be pluralized by adding another 's'

    Words ending in 's' should never be pluralized by adding another 's'

    stockings -> stockingss jeans -> jeanss sandals -> sandalss

    How do I avoid this? I can fix the specific words with defnoun('jeans', 'jeans'), which corrects the result for an isolated string 'jeans' -> 'jeans'.

    However, if I try to run plural_noun on 'blue jeans' instead of 'jeans' it then breaks again, returning 'blue jeanss'. I understand this is because 'blue jeans' appears to be a different string from 'jeans', but perhaps it should check the rules for the part of the string it is altering?

    I've gotten around this so far by this incredibly hacky 'solution', so any improvement would obviously be immensely appreciated:

                plural = _INFLECT.plural_noun(key, count)
                if plural.endswith('ss'):
                    plural = plural[0:-1]
    
    feature help wanted 
    opened by aMiss-aWry 4
  • singular_noun on word ending in

    singular_noun on word ending in "s" removes s.

    
    import inflect as Inflect
    inflect = Inflect.engine()
    inflect.singular_noun("car")           # get False, as expected
    inflect.singular_noun("mass")          # get "mas", expected False
    
    

    Is this behavior a bug? singular_noun() is supposed to return False when the word is already singular, and I can find no reference to suggest "mass" is the plural of "mas", which is itself the plural of "ma".

    help wanted 
    opened by eykamp 3
Releases(v6.0.2)
Fastseq 基于ONNXRUNTIME的文本生成加速框架

Fastseq 基于ONNXRUNTIME的文本生成加速框架

Jun Gao 9 Nov 09, 2021
The SVO-Probes Dataset for Verb Understanding

The SVO-Probes Dataset for Verb Understanding This repository contains the SVO-Probes benchmark designed to probe for Subject, Verb, and Object unders

DeepMind 20 Nov 30, 2022
Crie tokens de autenticação íntegros e seguros com UToken.

UToken - Tokens seguros. UToken (ou Unhandleable Token) é uma bilioteca criada para ser utilizada na geração de tokens seguros e íntegros, ou seja, nã

Jaedson Silva 0 Nov 29, 2022
Train BPE with fastBPE, and load to Huggingface Tokenizer.

BPEer Train BPE with fastBPE, and load to Huggingface Tokenizer. Description The BPETrainer of Huggingface consumes a lot of memory when I am training

Lizhuo 1 Dec 23, 2021
Code for our ACL 2021 paper - ConSERT: A Contrastive Framework for Self-Supervised Sentence Representation Transfer

ConSERT Code for our ACL 2021 paper - ConSERT: A Contrastive Framework for Self-Supervised Sentence Representation Transfer Requirements torch==1.6.0

Yan Yuanmeng 478 Dec 25, 2022
The model is designed to train a single and large neural network in order to predict correct translation by reading the given sentence.

Neural Machine Translation communication system The model is basically direct to convert one source language to another targeted language using encode

Nishant Banjade 7 Sep 22, 2022
In this project, we compared Spanish BERT and Multilingual BERT in the Sentiment Analysis task.

Applying BERT Fine Tuning to Sentiment Classification on Amazon Reviews Abstract Sentiment analysis has made great progress in recent years, due to th

Alexander Leonardo Lique Lamas 5 Jan 03, 2022
SentAugment is a data augmentation technique for semi-supervised learning in NLP.

SentAugment SentAugment is a data augmentation technique for semi-supervised learning in NLP. It uses state-of-the-art sentence embeddings to structur

Meta Research 363 Dec 30, 2022
String Gen + Word Checker

Creates random strings and checks if any of them are a real words. Mostly a waste of time ngl but it is cool to see it work and the fact that it can generate a real random word within10sec

1 Jan 06, 2022
Code for paper "Which Training Methods for GANs do actually Converge? (ICML 2018)"

GAN stability This repository contains the experiments in the supplementary material for the paper Which Training Methods for GANs do actually Converg

Lars Mescheder 884 Nov 11, 2022
SASE : Self-Adaptive noise distribution network for Speech Enhancement with heterogeneous data of Cross-Silo Federated learning

SASE : Self-Adaptive noise distribution network for Speech Enhancement with heterogeneous data of Cross-Silo Federated learning We propose a SASE mode

Tower 1 Nov 20, 2021
Simple python code to fix your combo list by removing any text after a separator or removing duplicate combos

Combo List Fixer A simple python code to fix your combo list by removing any text after a separator or removing duplicate combos Removing any text aft

Hamidreza Dehghan 3 Dec 05, 2022
Blazing fast language detection using fastText model

Luga A blazing fast language detection using fastText's language models Luga is a Swahili word for language. fastText provides a blazing fast language

Prayson Wilfred Daniel 18 Dec 20, 2022
無料で使える中品質なテキスト読み上げソフトウェア、VOICEVOXの音声合成エンジン

VOICEVOX ENGINE VOICEVOXの音声合成エンジン。 実態は HTTP サーバーなので、リクエストを送信すればテキスト音声合成できます。 API ドキュメント VOICEVOX ソフトウェアを起動した状態で、ブラウザから

Hiroshiba 3 Jul 05, 2022
Curso práctico: NLP de cero a cien 🤗

Curso Práctico: NLP de cero a cien Comprende todos los conceptos y arquitecturas clave del estado del arte del NLP y aplícalos a casos prácticos utili

Somos NLP 147 Jan 06, 2023
Official Pytorch implementation of Test-Agnostic Long-Tailed Recognition by Test-Time Aggregating Diverse Experts with Self-Supervision.

This repository is the official Pytorch implementation of Test-Agnostic Long-Tailed Recognition by Test-Time Aggregating Diverse Experts with Self-Supervision.

vanint 101 Dec 30, 2022
Korean Simple Contrastive Learning of Sentence Embeddings using SKT KoBERT and kakaobrain KorNLU dataset

KoSimCSE Korean Simple Contrastive Learning of Sentence Embeddings implementation using pytorch SimCSE Installation git clone https://github.com/BM-K/

34 Nov 24, 2022
Two-stage text summarization with BERT and BART

Two-Stage Text Summarization Description We experiment with a 2-stage summarization model on CNN/DailyMail dataset that combines the ability to filter

Yukai Yang (Alexis) 6 Oct 22, 2022
Code for the Python code smells video on the ArjanCodes channel.

7 Python code smells This repository contains the code for the Python code smells video on the ArjanCodes channel (watch the video here). The example

55 Dec 29, 2022
Natural Language Processing Tasks and Examples.

Natural Language Processing Tasks and Examples With the advancement of A.I. technology in recent years, natural language processing technology has bee

Soohwan Kim 53 Dec 20, 2022