New Upstream Release - python-inflect
Ready changes
Summary
Merged new upstream version: 7.0.0 (was: 6.0.4).
Resulting package
Built on 2023-08-14T17:21 (took 5m31s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases python3-inflect
Lintian Result
Diff
diff --git a/.flake8 b/.flake8
deleted file mode 100644
index 48b2e24..0000000
--- a/.flake8
+++ /dev/null
@@ -1,9 +0,0 @@
-[flake8]
-max-line-length = 88
-
-# jaraco/skeleton#34
-max-complexity = 10
-
-extend-ignore =
- # Black creates whitespace before colon
- E203
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 9629a26..2c1d27e 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -2,6 +2,9 @@ name: tests
on: [push, pull_request]
+permissions:
+ contents: read
+
env:
# Environment variables to support color support (jaraco/skeleton#66):
# Request colored output from CLI tools supporting it. Different tools
@@ -39,25 +42,24 @@ jobs:
strategy:
matrix:
python:
- - "3.7"
+ - "3.8"
- "3.11"
- "3.12"
- # Workaround for actions/setup-python#508
- dev:
- - -dev
platform:
- ubuntu-latest
- macos-latest
- windows-latest
include:
- - python: "3.8"
- platform: ubuntu-latest
- python: "3.9"
platform: ubuntu-latest
- python: "3.10"
platform: ubuntu-latest
- python: pypy3.9
platform: ubuntu-latest
+ - python: "3.x"
+ platform: ubuntu-latest
+ env:
+ TOX_ENV: pydantic1
runs-on: ${{ matrix.platform }}
continue-on-error: ${{ matrix.python == '3.12' }}
steps:
@@ -65,7 +67,8 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v4
with:
- python-version: ${{ matrix.python }}${{ matrix.dev }}
+ python-version: ${{ matrix.python }}
+ allow-prereleases: true
- name: Install tox
run: |
python -m pip install tox
@@ -80,8 +83,6 @@ jobs:
- uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v4
- with:
- python-version: ${{ matrix.python }}${{ matrix.dev }}
- name: Install tox
run: |
python -m pip install tox
@@ -104,6 +105,8 @@ jobs:
jobs: ${{ toJSON(needs) }}
release:
+ permissions:
+ contents: write
needs:
- check
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index 6bef349..053c728 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -5,9 +5,8 @@ python:
extra_requirements:
- docs
-# workaround for readthedocs/readthedocs.org#9623
+# required boilerplate readthedocs/readthedocs.org#10401
build:
- # workaround for readthedocs/readthedocs.org#9635
os: ubuntu-22.04
tools:
python: "3"
diff --git a/LICENSE b/LICENSE
index 353924b..1bb5a44 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,5 +1,3 @@
-Copyright Jason R. Coombs
-
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
diff --git a/CHANGES.rst b/NEWS.rst
similarity index 89%
rename from CHANGES.rst
rename to NEWS.rst
index 2178306..a57b538 100644
--- a/CHANGES.rst
+++ b/NEWS.rst
@@ -1,3 +1,56 @@
+v7.0.0
+======
+
+Features
+--------
+
+- Refine type hint for ``singular_noun`` to indicate a literal return type for ``False``. (#186)
+
+
+Deprecations and Removals
+-------------------------
+
+- Removed methods renamed in 0.2.0.
+
+
+v6.2.0
+======
+
+Features
+--------
+
+- Project now supports Pydantic 2 while retaining support for Pydantic 1. (#187)
+
+
+Bugfixes
+--------
+
+- Added validation of user-defined words and amended the type declarations to match, allowing for null values but not empty strings. (#187)
+
+
+v6.1.1
+======
+
+Bugfixes
+--------
+
+- ``ordinal`` now handles float types correctly without first coercing them to strings. (#178)
+
+
+v6.1.0
+======
+
+Features
+--------
+
+- Require Python 3.8 or later.
+
+
+v6.0.5
+======
+
+* #187: Pin to Pydantic 1 to avoid breaking in Pydantic 2.
+
v6.0.4
======
diff --git a/PKG-INFO b/PKG-INFO
index 5295526..60c0732 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: inflect
-Version: 6.0.4
+Version: 7.0.0
Summary: Correctly generate plurals, singular nouns, ordinals, indefinite articles; convert numbers to words
Home-page: https://github.com/jaraco/inflect
Author: Paul Dyson
@@ -16,7 +16,7 @@ Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Linguistic
-Requires-Python: >=3.7
+Requires-Python: >=3.8
Provides-Extra: testing
Provides-Extra: docs
License-File: LICENSE
@@ -30,6 +30,10 @@ License-File: LICENSE
:target: https://github.com/jaraco/inflect/actions?query=workflow%3A%22tests%22
:alt: tests
+.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
+ :target: https://github.com/astral-sh/ruff
+ :alt: Ruff
+
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black
:alt: Code style: Black
diff --git a/README.rst b/README.rst
index d61f59b..42a0fb3 100644
--- a/README.rst
+++ b/README.rst
@@ -7,6 +7,10 @@
:target: https://github.com/jaraco/inflect/actions?query=workflow%3A%22tests%22
:alt: tests
+.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
+ :target: https://github.com/astral-sh/ruff
+ :alt: Ruff
+
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black
:alt: Code style: Black
diff --git a/debian/changelog b/debian/changelog
index d74b94f..3b30fd1 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+python-inflect (7.0.0-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk> Mon, 14 Aug 2023 17:16:47 -0000
+
python-inflect (6.0.4-1) unstable; urgency=medium
[ Debian Janitor ]
diff --git a/docs/conf.py b/docs/conf.py
index 4e5eae3..c973dd9 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -9,7 +9,7 @@ html_theme = "furo"
# Link dates and other references in the changelog
extensions += ['rst.linker']
link_files = {
- '../CHANGES.rst': dict(
+ '../NEWS.rst': dict(
using=dict(GH='https://github.com'),
replace=[
dict(
diff --git a/docs/history.rst b/docs/history.rst
index 8e21750..5bdc232 100644
--- a/docs/history.rst
+++ b/docs/history.rst
@@ -5,4 +5,4 @@
History
*******
-.. include:: ../CHANGES (links).rst
+.. include:: ../NEWS (links).rst
diff --git a/inflect.egg-info/PKG-INFO b/inflect.egg-info/PKG-INFO
index 5295526..60c0732 100644
--- a/inflect.egg-info/PKG-INFO
+++ b/inflect.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: inflect
-Version: 6.0.4
+Version: 7.0.0
Summary: Correctly generate plurals, singular nouns, ordinals, indefinite articles; convert numbers to words
Home-page: https://github.com/jaraco/inflect
Author: Paul Dyson
@@ -16,7 +16,7 @@ Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Linguistic
-Requires-Python: >=3.7
+Requires-Python: >=3.8
Provides-Extra: testing
Provides-Extra: docs
License-File: LICENSE
@@ -30,6 +30,10 @@ License-File: LICENSE
:target: https://github.com/jaraco/inflect/actions?query=workflow%3A%22tests%22
:alt: tests
+.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
+ :target: https://github.com/astral-sh/ruff
+ :alt: Ruff
+
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black
:alt: Code style: Black
diff --git a/inflect.egg-info/SOURCES.txt b/inflect.egg-info/SOURCES.txt
index 0202261..8e1bb49 100644
--- a/inflect.egg-info/SOURCES.txt
+++ b/inflect.egg-info/SOURCES.txt
@@ -1,16 +1,16 @@
.coveragerc
.editorconfig
-.flake8
.gitignore
.pre-commit-config.yaml
.readthedocs.yaml
-CHANGES.rst
LICENSE
+NEWS.rst
README.rst
mypy.ini
pyproject.toml
pytest.ini
setup.cfg
+towncrier.toml
tox.ini
.github/FUNDING.yml
.github/dependabot.yml
@@ -25,6 +25,9 @@ inflect.egg-info/SOURCES.txt
inflect.egg-info/dependency_links.txt
inflect.egg-info/requires.txt
inflect.egg-info/top_level.txt
+inflect/compat/__init__.py
+inflect/compat/pydantic.py
+inflect/compat/pydantic1.py
tests/inflections.txt
tests/test_an.py
tests/test_classical_all.py
diff --git a/inflect.egg-info/requires.txt b/inflect.egg-info/requires.txt
index 9308940..b4c715f 100644
--- a/inflect.egg-info/requires.txt
+++ b/inflect.egg-info/requires.txt
@@ -1,4 +1,5 @@
pydantic>=1.9.1
+typing_extensions
[docs]
sphinx>=3.5
@@ -11,14 +12,11 @@ jaraco.tidelift>=1.4
[testing]
pytest>=6
pytest-checkdocs>=2.4
-flake8<5
pytest-cov
-pytest-enabler>=1.3
+pytest-enabler>=2.2
+pytest-ruff
pygments
[testing:platform_python_implementation != "PyPy"]
pytest-black>=0.3.7
pytest-mypy>=0.9.1
-
-[testing:python_version < "3.12"]
-pytest-flake8
diff --git a/inflect/__init__.py b/inflect/__init__.py
index 1c8bd34..b638c6b 100644
--- a/inflect/__init__.py
+++ b/inflect/__init__.py
@@ -3,8 +3,6 @@ inflect: english language inflection
- correctly generate plurals, ordinals, indefinite articles
- convert numbers to words
-Copyright (C) 2010 Paul Dyson
-
Based upon the Perl module
`Lingua::EN::Inflect <https://metacpan.org/pod/Lingua::EN::Inflect>`_.
@@ -70,11 +68,16 @@ from typing import (
cast,
Any,
)
+from typing_extensions import Literal
from numbers import Number
-from pydantic import Field, validate_arguments
-from pydantic.typing import Annotated
+from pydantic import Field
+from typing_extensions import Annotated
+
+
+from .compat.pydantic1 import validate_call
+from .compat.pydantic import same_method
class UnknownClassicalModeError(Exception):
@@ -105,14 +108,6 @@ class BadGenderError(Exception):
pass
-STDOUT_ON = False
-
-
-def print3(txt: str) -> None:
- if STDOUT_ON:
- print(txt)
-
-
def enclose(s: str) -> str:
return f"(?:{s})"
@@ -1727,66 +1722,44 @@ plverb_irregular_pres = {
"is": "are",
"was": "were",
"were": "were",
- "was": "were",
- "have": "have",
"have": "have",
"has": "have",
"do": "do",
- "do": "do",
"does": "do",
}
plverb_ambiguous_pres = {
- "act": "act",
"act": "act",
"acts": "act",
"blame": "blame",
- "blame": "blame",
"blames": "blame",
"can": "can",
- "can": "can",
- "can": "can",
- "must": "must",
"must": "must",
- "must": "must",
- "fly": "fly",
"fly": "fly",
"flies": "fly",
"copy": "copy",
- "copy": "copy",
"copies": "copy",
"drink": "drink",
- "drink": "drink",
"drinks": "drink",
"fight": "fight",
- "fight": "fight",
"fights": "fight",
"fire": "fire",
- "fire": "fire",
"fires": "fire",
"like": "like",
- "like": "like",
"likes": "like",
"look": "look",
- "look": "look",
"looks": "look",
"make": "make",
- "make": "make",
"makes": "make",
"reach": "reach",
- "reach": "reach",
"reaches": "reach",
"run": "run",
- "run": "run",
"runs": "run",
"sink": "sink",
- "sink": "sink",
"sinks": "sink",
"sleep": "sleep",
- "sleep": "sleep",
"sleeps": "sleep",
"view": "view",
- "view": "view",
"views": "view",
}
@@ -2056,11 +2029,11 @@ class engine:
self.classical_dict = def_classical.copy()
self.persistent_count: Optional[int] = None
self.mill_count = 0
- self.pl_sb_user_defined: List[str] = []
- self.pl_v_user_defined: List[str] = []
- self.pl_adj_user_defined: List[str] = []
- self.si_sb_user_defined: List[str] = []
- self.A_a_user_defined: List[str] = []
+ self.pl_sb_user_defined: List[Optional[Word]] = []
+ self.pl_v_user_defined: List[Optional[Word]] = []
+ self.pl_adj_user_defined: List[Optional[Word]] = []
+ self.si_sb_user_defined: List[Optional[Word]] = []
+ self.A_a_user_defined: List[Optional[Word]] = []
self.thegender = "neuter"
self.__number_args: Optional[Dict[str, str]] = None
@@ -2072,28 +2045,8 @@ class engine:
def _number_args(self, val):
self.__number_args = val
- deprecated_methods = dict(
- pl="plural",
- plnoun="plural_noun",
- plverb="plural_verb",
- pladj="plural_adj",
- sinoun="single_noun",
- prespart="present_participle",
- numwords="number_to_words",
- plequal="compare",
- plnounequal="compare_nouns",
- plverbequal="compare_verbs",
- pladjequal="compare_adjs",
- wordlist="join",
- )
-
- def __getattr__(self, meth):
- if meth in self.deprecated_methods:
- print3(f"{meth}() deprecated, use {self.deprecated_methods[meth]}()")
- raise DeprecationWarning
- raise AttributeError
-
- def defnoun(self, singular: str, plural: str) -> int:
+ @validate_call
+ def defnoun(self, singular: Optional[Word], plural: Optional[Word]) -> int:
"""
Set the noun plural of singular to plural.
@@ -2104,7 +2057,16 @@ class engine:
self.si_sb_user_defined.extend((plural, singular))
return 1
- def defverb(self, s1: str, p1: str, s2: str, p2: str, s3: str, p3: str) -> int:
+ @validate_call
+ def defverb(
+ self,
+ s1: Optional[Word],
+ p1: Optional[Word],
+ s2: Optional[Word],
+ p2: Optional[Word],
+ s3: Optional[Word],
+ p3: Optional[Word],
+ ) -> int:
"""
Set the verb plurals for s1, s2 and s3 to p1, p2 and p3 respectively.
@@ -2120,7 +2082,8 @@ class engine:
self.pl_v_user_defined.extend((s1, p1, s2, p2, s3, p3))
return 1
- def defadj(self, singular: str, plural: str) -> int:
+ @validate_call
+ def defadj(self, singular: Optional[Word], plural: Optional[Word]) -> int:
"""
Set the adjective plural of singular to plural.
@@ -2130,7 +2093,8 @@ class engine:
self.pl_adj_user_defined.extend((singular, plural))
return 1
- def defa(self, pattern: str) -> int:
+ @validate_call
+ def defa(self, pattern: Optional[Word]) -> int:
"""
Define the indefinite article as 'a' for words matching pattern.
@@ -2139,7 +2103,8 @@ class engine:
self.A_a_user_defined.extend((pattern, "a"))
return 1
- def defan(self, pattern: str) -> int:
+ @validate_call
+ def defan(self, pattern: Optional[Word]) -> int:
"""
Define the indefinite article as 'an' for words matching pattern.
@@ -2148,7 +2113,7 @@ class engine:
self.A_a_user_defined.extend((pattern, "an"))
return 1
- def checkpat(self, pattern: Optional[str]) -> None:
+ def checkpat(self, pattern: Optional[Word]) -> None:
"""
check for errors in a regex pattern
"""
@@ -2157,16 +2122,15 @@ class engine:
try:
re.match(pattern, "")
except re.error:
- print3(f"\nBad user-defined singular pattern:\n\t{pattern}\n")
- raise BadUserDefinedPatternError
+ raise BadUserDefinedPatternError(pattern)
- def checkpatplural(self, pattern: str) -> None:
+ def checkpatplural(self, pattern: Optional[Word]) -> None:
"""
check for errors in a regex replace pattern
"""
return
- @validate_arguments
+ @validate_call
def ud_match(self, word: Word, wordlist: Sequence[Optional[Word]]) -> Optional[str]:
for i in range(len(wordlist) - 2, -2, -2): # backwards through even elements
mo = re.search(fr"^{wordlist[i]}$", word, re.IGNORECASE)
@@ -2306,7 +2270,7 @@ class engine:
# 0. PERFORM GENERAL INFLECTIONS IN A STRING
- @validate_arguments
+ @validate_call
def inflect(self, text: Word) -> str:
"""
Perform inflections in a string.
@@ -2383,7 +2347,7 @@ class engine:
else:
return "", "", ""
- @validate_arguments
+ @validate_call
def plural(self, text: Word, count: Optional[Union[str, int, Any]] = None) -> str:
"""
Return the plural of text.
@@ -2407,7 +2371,7 @@ class engine:
)
return f"{pre}{plural}{post}"
- @validate_arguments
+ @validate_call
def plural_noun(
self, text: Word, count: Optional[Union[str, int, Any]] = None
) -> str:
@@ -2428,7 +2392,7 @@ class engine:
plural = self.postprocess(word, self._plnoun(word, count))
return f"{pre}{plural}{post}"
- @validate_arguments
+ @validate_call
def plural_verb(
self, text: Word, count: Optional[Union[str, int, Any]] = None
) -> str:
@@ -2452,7 +2416,7 @@ class engine:
)
return f"{pre}{plural}{post}"
- @validate_arguments
+ @validate_call
def plural_adj(
self, text: Word, count: Optional[Union[str, int, Any]] = None
) -> str:
@@ -2473,7 +2437,7 @@ class engine:
plural = self.postprocess(word, self._pl_special_adjective(word, count) or word)
return f"{pre}{plural}{post}"
- @validate_arguments
+ @validate_call
def compare(self, word1: Word, word2: Word) -> Union[str, bool]:
"""
compare word1 and word2 for equality regardless of plurality
@@ -2496,15 +2460,15 @@ class engine:
>>> compare('egg', '')
Traceback (most recent call last):
...
- pydantic.error_wrappers.ValidationError: 1 validation error for Compare
- word2
- ensure this value has at least 1 characters...
+ pydantic...ValidationError: ...
+ ...
+ ...at least 1 characters...
"""
norms = self.plural_noun, self.plural_verb, self.plural_adj
results = (self._plequal(word1, word2, norm) for norm in norms)
return next(filter(None, results), False)
- @validate_arguments
+ @validate_call
def compare_nouns(self, word1: Word, word2: Word) -> Union[str, bool]:
"""
compare word1 and word2 for equality regardless of plurality
@@ -2520,7 +2484,7 @@ class engine:
"""
return self._plequal(word1, word2, self.plural_noun)
- @validate_arguments
+ @validate_call
def compare_verbs(self, word1: Word, word2: Word) -> Union[str, bool]:
"""
compare word1 and word2 for equality regardless of plurality
@@ -2536,7 +2500,7 @@ class engine:
"""
return self._plequal(word1, word2, self.plural_verb)
- @validate_arguments
+ @validate_call
def compare_adjs(self, word1: Word, word2: Word) -> Union[str, bool]:
"""
compare word1 and word2 for equality regardless of plurality
@@ -2552,13 +2516,13 @@ class engine:
"""
return self._plequal(word1, word2, self.plural_adj)
- @validate_arguments
+ @validate_call
def singular_noun(
self,
text: Word,
count: Optional[Union[int, str, Any]] = None,
gender: Optional[str] = None,
- ) -> Union[str, bool]:
+ ) -> Union[str, Literal[False]]:
"""
Return the singular of text, where text is a plural noun.
@@ -2610,12 +2574,12 @@ class engine:
return "s:p"
self.classical_dict = classval.copy()
- if pl == self.plural or pl == self.plural_noun:
+ if same_method(pl, self.plural) or same_method(pl, self.plural_noun):
if self._pl_check_plurals_N(word1, word2):
return "p:p"
if self._pl_check_plurals_N(word2, word1):
return "p:p"
- if pl == self.plural or pl == self.plural_adj:
+ if same_method(pl, self.plural) or same_method(pl, self.plural_adj):
if self._pl_check_plurals_adj(word1, word2):
return "p:p"
return False
@@ -3265,11 +3229,11 @@ class engine:
if words.last in si_sb_irregular_caps:
llen = len(words.last)
- return "{}{}".format(word[:-llen], si_sb_irregular_caps[words.last])
+ return f"{word[:-llen]}{si_sb_irregular_caps[words.last]}"
if words.last.lower() in si_sb_irregular:
llen = len(words.last.lower())
- return "{}{}".format(word[:-llen], si_sb_irregular[words.last.lower()])
+ return f"{word[:-llen]}{si_sb_irregular[words.last.lower()]}"
dash_split = words.lowered.split("-")
if (" ".join(dash_split[-2:])).lower() in si_sb_irregular_compound:
@@ -3486,7 +3450,7 @@ class engine:
# ADJECTIVES
- @validate_arguments
+ @validate_call
def a(self, text: Word, count: Optional[Union[int, str, Any]] = 1) -> str:
"""
Return the appropriate indefinite article followed by text.
@@ -3567,7 +3531,7 @@ class engine:
# 2. TRANSLATE ZERO-QUANTIFIED $word TO "no plural($word)"
- @validate_arguments
+ @validate_call
def no(self, text: Word, count: Optional[Union[int, str]] = None) -> str:
"""
If count is 0, no, zero or nil, return 'no' followed by the plural
@@ -3605,7 +3569,7 @@ class engine:
# PARTICIPLES
- @validate_arguments
+ @validate_call
def present_participle(self, word: Word) -> str:
"""
Return the present participle for word.
@@ -3624,31 +3588,31 @@ class engine:
# NUMERICAL INFLECTIONS
- @validate_arguments
- def ordinal(self, num: Word) -> str:
+ @validate_call(config=dict(arbitrary_types_allowed=True))
+ def ordinal(self, num: Union[Number, Word]) -> str:
"""
Return the ordinal of num.
- num can be an integer or text
-
- e.g. ordinal(1) returns '1st'
- ordinal('one') returns 'first'
-
+ >>> ordinal = engine().ordinal
+ >>> ordinal(1)
+ '1st'
+ >>> ordinal('one')
+ 'first'
"""
if DIGIT.match(str(num)):
- if isinstance(num, (int, float)):
+ if isinstance(num, (float, int)) and int(num) == num:
n = int(num)
else:
if "." in str(num):
try:
# numbers after decimal,
# so only need last one for ordinal
- n = int(num[-1])
+ n = int(str(num)[-1])
except ValueError: # ends with '.', so need to use whole string
- n = int(num[:-1])
+ n = int(str(num)[:-1])
else:
- n = int(num)
+ n = int(num) # type: ignore
try:
post = nth[n % 100]
except KeyError:
@@ -3657,7 +3621,7 @@ class engine:
else:
# Mad props to Damian Conway (?) whose ordinal()
# algorithm is type-bendy enough to foil MyPy
- str_num: str = num # type: ignore[assignment]
+ str_num: str = num # type: ignore[assignment]
mo = ordinal_suff.search(str_num)
if mo:
post = ordinal[mo.group(1)]
@@ -3668,7 +3632,6 @@ class engine:
def millfn(self, ind: int = 0) -> str:
if ind > len(mill) - 1:
- print3("number out of range")
raise NumOutOfRangeError
return mill[ind]
@@ -3784,7 +3747,7 @@ class engine:
num = ONE_DIGIT_WORD.sub(self.unitsub, num, 1)
return num
- @validate_arguments(config=dict(arbitrary_types_allowed=True)) # noqa: C901
+ @validate_call(config=dict(arbitrary_types_allowed=True)) # noqa: C901
def number_to_words( # noqa: C901
self,
num: Union[Number, Word],
@@ -3936,7 +3899,7 @@ class engine:
# Join words with commas and a trailing 'and' (when appropriate)...
- @validate_arguments
+ @validate_call
def join(
self,
words: Optional[Sequence[Word]],
diff --git a/inflect/compat/__init__.py b/inflect/compat/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/inflect/compat/pydantic.py b/inflect/compat/pydantic.py
new file mode 100644
index 0000000..d777564
--- /dev/null
+++ b/inflect/compat/pydantic.py
@@ -0,0 +1,19 @@
+class ValidateCallWrapperWrapper:
+ def __init__(self, wrapped):
+ self.orig = wrapped
+
+ def __eq__(self, other):
+ return self.raw_function == other.raw_function
+
+ @property
+ def raw_function(self):
+ return getattr(self.orig, 'raw_function') or self.orig
+
+
+def same_method(m1, m2) -> bool:
+ """
+ Return whether m1 and m2 are the same method.
+
+ Workaround for pydantic/pydantic#6390.
+ """
+ return ValidateCallWrapperWrapper(m1) == ValidateCallWrapperWrapper(m2)
diff --git a/inflect/compat/pydantic1.py b/inflect/compat/pydantic1.py
new file mode 100644
index 0000000..8262fdc
--- /dev/null
+++ b/inflect/compat/pydantic1.py
@@ -0,0 +1,8 @@
+try:
+ from pydantic import validate_call # type: ignore
+except ImportError:
+ # Pydantic 1
+ from pydantic import validate_arguments as validate_call # type: ignore
+
+
+__all__ = ['validate_call']
diff --git a/pyproject.toml b/pyproject.toml
index 60de242..dce944d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,15 +6,3 @@ build-backend = "setuptools.build_meta"
skip-string-normalization = true
[tool.setuptools_scm]
-
-[tool.pytest-enabler.black]
-addopts = "--black"
-
-[tool.pytest-enabler.mypy]
-addopts = "--mypy"
-
-[tool.pytest-enabler.flake8]
-addopts = "--flake8"
-
-[tool.pytest-enabler.cov]
-addopts = "--cov"
diff --git a/pytest.ini b/pytest.ini
index 99a2519..d9a15ed 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -7,19 +7,11 @@ filterwarnings=
# Ensure ResourceWarnings are emitted
default::ResourceWarning
- # Suppress deprecation warning in flake8
- ignore:SelectableGroups dict interface is deprecated::flake8
-
# shopkeep/pytest-black#55
ignore:<class 'pytest_black.BlackItem'> is not using a cooperative constructor:pytest.PytestDeprecationWarning
ignore:The \(fspath. py.path.local\) argument to BlackItem is deprecated.:pytest.PytestDeprecationWarning
ignore:BlackItem is an Item subclass and should not be a collector:pytest.PytestWarning
- # tholo/pytest-flake8#83
- ignore:<class 'pytest_flake8.Flake8Item'> is not using a cooperative constructor:pytest.PytestDeprecationWarning
- ignore:The \(fspath. py.path.local\) argument to Flake8Item is deprecated.:pytest.PytestDeprecationWarning
- ignore:Flake8Item is an Item subclass and should not be a collector:pytest.PytestWarning
-
# shopkeep/pytest-black#67
ignore:'encoding' argument not specified::pytest_black
@@ -29,4 +21,7 @@ filterwarnings=
# python/cpython#100750
ignore:'encoding' argument not specified::platform
+ # pypa/build#615
+ ignore:'encoding' argument not specified::build.env
+
## end upstream
diff --git a/setup.cfg b/setup.cfg
index 2720d6f..0b94e3a 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -21,9 +21,10 @@ classifiers =
[options]
packages = find_namespace:
include_package_data = true
-python_requires = >=3.7
+python_requires = >=3.8
install_requires =
pydantic >= 1.9.1
+ typing_extensions
keywords = plural inflect participle
[options.packages.find]
@@ -37,15 +38,13 @@ exclude =
testing =
pytest >= 6
pytest-checkdocs >= 2.4
- pytest-flake8; \
- python_version < "3.12"
- flake8 < 5
pytest-black >= 0.3.7; \
python_implementation != "PyPy"
pytest-cov
pytest-mypy >= 0.9.1; \
python_implementation != "PyPy"
- pytest-enabler >= 1.3
+ pytest-enabler >= 2.2
+ pytest-ruff
pygments
docs =
diff --git a/tests/test_classical_all.py b/tests/test_classical_all.py
index d30afd1..348e0ff 100644
--- a/tests/test_classical_all.py
+++ b/tests/test_classical_all.py
@@ -1,106 +1,49 @@
-import unittest
-
import inflect
-class test(unittest.TestCase):
+class Test:
def test_classical(self):
p = inflect.engine()
# DEFAULT...
- self.assertEqual(
- p.plural_noun("error", 0), "errors", msg="classical 'zero' not active"
- )
- self.assertEqual(
- p.plural_noun("wildebeest"),
- "wildebeests",
- msg="classical 'herd' not active",
- )
- self.assertEqual(
- p.plural_noun("Sally"), "Sallys", msg="classical 'names' active"
- )
- self.assertEqual(
- p.plural_noun("brother"), "brothers", msg="classical others not active"
- )
- self.assertEqual(
- p.plural_noun("person"), "people", msg="classical 'persons' not active"
- )
- self.assertEqual(
- p.plural_noun("formula"), "formulas", msg="classical 'ancient' not active"
- )
+ assert p.plural_noun("error", 0) == "errors", "classical 'zero' not active"
+ assert (
+ p.plural_noun("wildebeest") == "wildebeests"
+ ), "classical 'herd' not active"
+ assert p.plural_noun("Sally") == "Sallys", "classical 'names' active"
+ assert p.plural_noun("brother") == "brothers", "classical others not active"
+ assert p.plural_noun("person") == "people", "classical 'persons' not active"
+ assert p.plural_noun("formula") == "formulas", "classical 'ancient' not active"
# CLASSICAL PLURALS ACTIVATED...
p.classical(all=True)
- self.assertEqual(
- p.plural_noun("error", 0), "error", msg="classical 'zero' active"
- )
- self.assertEqual(
- p.plural_noun("wildebeest"), "wildebeest", msg="classical 'herd' active"
- )
- self.assertEqual(
- p.plural_noun("Sally"), "Sallys", msg="classical 'names' active"
- )
- self.assertEqual(
- p.plural_noun("brother"), "brethren", msg="classical others active"
- )
- self.assertEqual(
- p.plural_noun("person"), "persons", msg="classical 'persons' active"
- )
- self.assertEqual(
- p.plural_noun("formula"), "formulae", msg="classical 'ancient' active"
- )
+ assert p.plural_noun("error", 0) == "error", "classical 'zero' active"
+ assert p.plural_noun("wildebeest") == "wildebeest", "classical 'herd' active"
+ assert p.plural_noun("Sally") == "Sallys", "classical 'names' active"
+ assert p.plural_noun("brother") == "brethren", "classical others active"
+ assert p.plural_noun("person") == "persons", "classical 'persons' active"
+ assert p.plural_noun("formula") == "formulae", "classical 'ancient' active"
# CLASSICAL PLURALS DEACTIVATED...
p.classical(all=False)
- self.assertEqual(
- p.plural_noun("error", 0), "errors", msg="classical 'zero' not active"
- )
- self.assertEqual(
- p.plural_noun("wildebeest"),
- "wildebeests",
- msg="classical 'herd' not active",
- )
- self.assertEqual(
- p.plural_noun("Sally"), "Sallies", msg="classical 'names' not active"
- )
- self.assertEqual(
- p.plural_noun("brother"), "brothers", msg="classical others not active"
- )
- self.assertEqual(
- p.plural_noun("person"), "people", msg="classical 'persons' not active"
- )
- self.assertEqual(
- p.plural_noun("formula"), "formulas", msg="classical 'ancient' not active"
- )
+ assert p.plural_noun("error", 0) == "errors", "classical 'zero' not active"
+ assert (
+ p.plural_noun("wildebeest") == "wildebeests"
+ ), "classical 'herd' not active"
+ assert p.plural_noun("Sally") == "Sallies", "classical 'names' not active"
+ assert p.plural_noun("brother") == "brothers", "classical others not active"
+ assert p.plural_noun("person") == "people", "classical 'persons' not active"
+ assert p.plural_noun("formula") == "formulas", "classical 'ancient' not active"
# CLASSICAL PLURALS REREREACTIVATED...
p.classical()
- self.assertEqual(
- p.plural_noun("error", 0), "error", msg="classical 'zero' active"
- )
- self.assertEqual(
- p.plural_noun("wildebeest"), "wildebeest", msg="classical 'herd' active"
- )
- self.assertEqual(
- p.plural_noun("Sally"), "Sallys", msg="classical 'names' active"
- )
- self.assertEqual(
- p.plural_noun("brother"), "brethren", msg="classical others active"
- )
- self.assertEqual(
- p.plural_noun("person"), "persons", msg="classical 'persons' active"
- )
- self.assertEqual(
- p.plural_noun("formula"), "formulae", msg="classical 'ancient' active"
- )
-
-
-if __name__ == "__main__":
- try:
- unittest.main()
- except SystemExit:
- pass
+ assert p.plural_noun("error", 0) == "error", "classical 'zero' active"
+ assert p.plural_noun("wildebeest") == "wildebeest", "classical 'herd' active"
+ assert p.plural_noun("Sally") == "Sallys", "classical 'names' active"
+ assert p.plural_noun("brother") == "brethren", "classical others active"
+ assert p.plural_noun("person") == "persons", "classical 'persons' active"
+ assert p.plural_noun("formula") == "formulae", "classical 'ancient' active"
diff --git a/tests/test_inflections.py b/tests/test_inflections.py
index bfbded8..7a49416 100644
--- a/tests/test_inflections.py
+++ b/tests/test_inflections.py
@@ -1,5 +1,4 @@
import os
-import io
import pytest
@@ -82,7 +81,7 @@ def check_all(p, is_nv, singular, mod_PL_val, class_PL_val, mod_plural, class_pl
assert is_eq(p, singular, class_plural) in ("s:p", "p:s", "eq")
assert is_eq(p, class_plural, singular) in ("p:s", "s:p", "eq")
assert singular != ""
- expected = mod_PL_val if class_PL_val else "%s|%s" % (mod_PL_val, class_PL_val)
+ expected = mod_PL_val if class_PL_val else "{}|{}".format(mod_PL_val, class_PL_val)
assert mod_PL_val == expected
if is_nv != "_V":
@@ -122,7 +121,7 @@ def test_def():
def test_ordinal():
p = inflect.engine()
assert p.ordinal(0) == "0th"
- assert p.ordinal(1) == "1st"
+ assert p.ordinal(1) == p.ordinal("1") == "1st"
assert p.ordinal(2) == "2nd"
assert p.ordinal(3) == "3rd"
assert p.ordinal(4) == "4th"
@@ -152,7 +151,7 @@ def test_ordinal():
assert p.ordinal(103) == "103rd"
assert p.ordinal(104) == "104th"
- assert p.ordinal(1.1) == "1.1st"
+ assert p.ordinal(1.1) == p.ordinal("1.1") == "1.1st"
assert p.ordinal(1.2) == "1.2nd"
assert p.ordinal(5.502) == "5.502nd"
@@ -265,5 +264,5 @@ def test_NameError_in_strings():
def get_data():
filename = os.path.join(os.path.dirname(__file__), "inflections.txt")
- with io.open(filename, encoding='utf-8') as strm:
+ with open(filename, encoding='utf-8') as strm:
return list(map(str.strip, strm))
diff --git a/tests/test_pwd.py b/tests/test_pwd.py
index a8b841e..acacf00 100644
--- a/tests/test_pwd.py
+++ b/tests/test_pwd.py
@@ -1,7 +1,3 @@
-#!/usr/bin/python
-
-import unittest
-
import pytest
from inflect import (
@@ -12,114 +8,102 @@ from inflect import (
UnknownClassicalModeError,
)
import inflect
+from inflect.compat.pydantic import same_method
-class test(unittest.TestCase):
- def TODO(
- self,
- ans,
- answer_wanted,
- answer_gives_now="default_that_will_never_occur__can't_use_None"
- "_as_that_is_a_possible_valid_value",
- ):
- """
- make this test for future testing
-
- so can easily rename these to assertEqual when code ready
- """
- if ans == answer_wanted:
- print("test unexpectedly passed!: {} == {}".format(ans, answer_wanted))
- if answer_gives_now != (
- "default_that_will_never_occur__can't_use_None"
- "_as_that_is_a_possible_valid_value"
- ):
- self.assertEqual(ans, answer_gives_now)
+missing = object()
+
+class Test:
def test_enclose(self):
# def enclose
- self.assertEqual(inflect.enclose("test"), "(?:test)")
+ assert inflect.enclose("test") == "(?:test)"
def test_joinstem(self):
# def joinstem
- self.assertEqual(
- inflect.joinstem(-2, ["ephemeris", "iris", ".*itis"]), "(?:ephemer|ir|.*it)"
+ assert (
+ inflect.joinstem(-2, ["ephemeris", "iris", ".*itis"])
+ == "(?:ephemer|ir|.*it)"
)
def test_classical(self):
# classical dicts
- self.assertEqual(
- set(inflect.def_classical.keys()), set(inflect.all_classical.keys())
- )
- self.assertEqual(
- set(inflect.def_classical.keys()), set(inflect.no_classical.keys())
- )
+ assert set(inflect.def_classical.keys()) == set(inflect.all_classical.keys())
+ assert set(inflect.def_classical.keys()) == set(inflect.no_classical.keys())
# def classical
p = inflect.engine()
- self.assertEqual(p.classical_dict, inflect.def_classical)
+ assert p.classical_dict == inflect.def_classical
p.classical()
- self.assertEqual(p.classical_dict, inflect.all_classical)
-
- self.assertRaises(TypeError, p.classical, 0)
- self.assertRaises(TypeError, p.classical, 1)
- self.assertRaises(TypeError, p.classical, "names")
- self.assertRaises(TypeError, p.classical, "names", "zero")
- self.assertRaises(TypeError, p.classical, "all")
+ assert p.classical_dict == inflect.all_classical
+
+ with pytest.raises(TypeError):
+ p.classical(0)
+ with pytest.raises(TypeError):
+ p.classical(1)
+ with pytest.raises(TypeError):
+ p.classical("names")
+ with pytest.raises(TypeError):
+ p.classical("names", "zero")
+ with pytest.raises(TypeError):
+ p.classical("all")
p.classical(all=False)
- self.assertEqual(p.classical_dict, inflect.no_classical)
+ assert p.classical_dict == inflect.no_classical
p.classical(names=True, zero=True)
mydict = inflect.def_classical.copy()
mydict.update(dict(names=1, zero=1))
- self.assertEqual(p.classical_dict, mydict)
+ assert p.classical_dict == mydict
p.classical(all=True)
- self.assertEqual(p.classical_dict, inflect.all_classical)
+ assert p.classical_dict == inflect.all_classical
p.classical(all=False)
p.classical(names=True, zero=True)
mydict = inflect.def_classical.copy()
mydict.update(dict(names=True, zero=True))
- self.assertEqual(p.classical_dict, mydict)
+ assert p.classical_dict == mydict
p.classical(all=False)
p.classical(names=True, zero=False)
mydict = inflect.def_classical.copy()
mydict.update(dict(names=True, zero=False))
- self.assertEqual(p.classical_dict, mydict)
+ assert p.classical_dict == mydict
- self.assertRaises(UnknownClassicalModeError, p.classical, bogus=True)
+ with pytest.raises(UnknownClassicalModeError):
+ p.classical(bogus=True)
def test_num(self):
# def num
p = inflect.engine()
- self.assertTrue(p.persistent_count is None)
+ assert p.persistent_count is None
p.num()
- self.assertTrue(p.persistent_count is None)
+ assert p.persistent_count is None
ret = p.num(3)
- self.assertEqual(p.persistent_count, 3)
- self.assertEqual(ret, "3")
+ assert p.persistent_count == 3
+ assert ret == "3"
p.num()
ret = p.num("3")
- self.assertEqual(p.persistent_count, 3)
- self.assertEqual(ret, "3")
+ assert p.persistent_count == 3
+ assert ret == "3"
p.num()
ret = p.num(count=3, show=1)
- self.assertEqual(p.persistent_count, 3)
- self.assertEqual(ret, "3")
+ assert p.persistent_count == 3
+ assert ret == "3"
p.num()
ret = p.num(count=3, show=0)
- self.assertEqual(p.persistent_count, 3)
- self.assertEqual(ret, "")
+ assert p.persistent_count == 3
+ assert ret == ""
- self.assertRaises(BadNumValueError, p.num, "text")
+ with pytest.raises(BadNumValueError):
+ p.num("text")
def test_inflect(self):
p = inflect.engine()
@@ -131,9 +115,7 @@ class test(unittest.TestCase):
(" num(1) ", " 1 "),
("num(3) num(1)", "3 1"),
):
- self.assertEqual(
- p.inflect(txt), ans, msg='p.inflect("{}") != "{}"'.format(txt, ans)
- )
+ assert p.inflect(txt) == ans, f'p.inflect("{txt}") != "{ans}"'
for txt, ans in (
("plural('rock')", "rocks"),
@@ -151,73 +133,75 @@ class test(unittest.TestCase):
),
("a('cat',0) a('cat',1) a('cat',2) a('cat', 2)", "0 cat a cat 2 cat 2 cat"),
):
- self.assertEqual(
- p.inflect(txt), ans, msg='p.inflect("{}") != "{}"'.format(txt, ans)
- )
+ assert p.inflect(txt) == ans, f'p.inflect("{txt}") != "{ans}"'
def test_user_input_fns(self):
p = inflect.engine()
- self.assertEqual(p.pl_sb_user_defined, [])
+ assert p.pl_sb_user_defined == []
p.defnoun("VAX", "VAXen")
- self.assertEqual(p.plural("VAX"), "VAXEN")
- self.assertEqual(p.pl_sb_user_defined, ["VAX", "VAXen"])
+ assert p.plural("VAX") == "VAXEN"
+ assert p.pl_sb_user_defined == ["VAX", "VAXen"]
- self.assertTrue(p.ud_match("word", p.pl_sb_user_defined) is None)
- self.assertEqual(p.ud_match("VAX", p.pl_sb_user_defined), "VAXen")
- self.assertTrue(p.ud_match("VVAX", p.pl_sb_user_defined) is None)
+ assert p.ud_match("word", p.pl_sb_user_defined) is None
+ assert p.ud_match("VAX", p.pl_sb_user_defined) == "VAXen"
+ assert p.ud_match("VVAX", p.pl_sb_user_defined) is None
p.defnoun("cow", "cows|kine")
- self.assertEqual(p.plural("cow"), "cows")
+ assert p.plural("cow") == "cows"
p.classical()
- self.assertEqual(p.plural("cow"), "kine")
+ assert p.plural("cow") == "kine"
- self.assertEqual(p.ud_match("cow", p.pl_sb_user_defined), "cows|kine")
+ assert p.ud_match("cow", p.pl_sb_user_defined) == "cows|kine"
p.defnoun("(.+i)o", r"$1i")
- self.assertEqual(p.plural("studio"), "studii")
- self.assertEqual(p.ud_match("studio", p.pl_sb_user_defined), "studii")
+ assert p.plural("studio") == "studii"
+ assert p.ud_match("studio", p.pl_sb_user_defined) == "studii"
p.defnoun("aviatrix", "aviatrices")
- self.assertEqual(p.plural("aviatrix"), "aviatrices")
- self.assertEqual(p.ud_match("aviatrix", p.pl_sb_user_defined), "aviatrices")
+ assert p.plural("aviatrix") == "aviatrices"
+ assert p.ud_match("aviatrix", p.pl_sb_user_defined) == "aviatrices"
p.defnoun("aviatrix", "aviatrixes")
- self.assertEqual(p.plural("aviatrix"), "aviatrixes")
- self.assertEqual(p.ud_match("aviatrix", p.pl_sb_user_defined), "aviatrixes")
+ assert p.plural("aviatrix") == "aviatrixes"
+ assert p.ud_match("aviatrix", p.pl_sb_user_defined) == "aviatrixes"
p.defnoun("aviatrix", None)
- self.assertEqual(p.plural("aviatrix"), "aviatrices")
- self.assertEqual(p.ud_match("aviatrix", p.pl_sb_user_defined), None)
+ assert p.plural("aviatrix") == "aviatrices"
+ assert p.ud_match("aviatrix", p.pl_sb_user_defined) is None
p.defnoun("(cat)", r"$1s")
- self.assertEqual(p.plural("cat"), "cats")
+ assert p.plural("cat") == "cats"
- inflect.STDOUT_ON = False
- self.assertRaises(inflect.BadUserDefinedPatternError, p.defnoun, "(??", None)
- inflect.STDOUT_ON = True
+ with pytest.raises(inflect.BadUserDefinedPatternError):
+ p.defnoun("(??", None)
- p.defnoun(None, "") # check None doesn't crash it
-
- # defverb
- p.defverb("will", "shall", "will", "will", "will", "will")
- self.assertEqual(p.ud_match("will", p.pl_v_user_defined), "will")
- self.assertEqual(p.plural("will"), "will")
- # TODO: will -> shall. Tests below fail
- self.TODO(p.compare("will", "shall"), "s:p")
- self.TODO(p.compare_verbs("will", "shall"), "s:p")
+ p.defnoun(None, "any") # check None doesn't crash it
# defadj
p.defadj("hir", "their")
- self.assertEqual(p.plural("hir"), "their")
- self.assertEqual(p.ud_match("hir", p.pl_adj_user_defined), "their")
+ assert p.plural("hir") == "their"
+ assert p.ud_match("hir", p.pl_adj_user_defined) == "their"
# defa defan
p.defa("h")
- self.assertEqual(p.a("h"), "a h")
- self.assertEqual(p.ud_match("h", p.A_a_user_defined), "a")
+ assert p.a("h") == "a h"
+ assert p.ud_match("h", p.A_a_user_defined) == "a"
p.defan("horrendous.*")
- self.assertEqual(p.a("horrendously"), "an horrendously")
- self.assertEqual(p.ud_match("horrendously", p.A_a_user_defined), "an")
+ assert p.a("horrendously") == "an horrendously"
+ assert p.ud_match("horrendously", p.A_a_user_defined) == "an"
+
+ def test_user_input_defverb(self):
+ p = inflect.engine()
+ p.defverb("will", "shall", "will", "will", "will", "will")
+ assert p.ud_match("will", p.pl_v_user_defined) == "will"
+ assert p.plural("will") == "will"
+
+ @pytest.mark.xfail(reason="todo")
+ def test_user_input_defverb_compare(self):
+ p = inflect.engine()
+ p.defverb("will", "shall", "will", "will", "will", "will")
+ assert p.compare("will", "shall") == "s:p"
+ assert p.compare_verbs("will", "shall") == "s:p"
def test_postprocess(self):
p = inflect.engine()
@@ -230,10 +214,10 @@ class test(unittest.TestCase):
("Entry", "entries", "Entries"),
("can of Coke", "cans of coke", "cans of Coke"),
):
- self.assertEqual(p.postprocess(orig, infl), txt)
+ assert p.postprocess(orig, infl) == txt
p.classical()
- self.assertEqual(p.postprocess("cow", "cows|kine"), "kine")
+ assert p.postprocess("cow", "cows|kine") == "kine"
def test_partition_word(self):
p = inflect.engine()
@@ -250,7 +234,7 @@ class test(unittest.TestCase):
# (' '),(' ', ' ', '')),
# (' '),(' ', ' ', '')),
):
- self.assertEqual(p.partition_word(txt), part)
+ assert p.partition_word(txt) == part
def test_pl(self):
p = inflect.engine()
@@ -279,12 +263,8 @@ class test(unittest.TestCase):
(p.plural_adj, "cat's", "cats'"),
(p.plural_adj, "child's", "children's"),
):
- self.assertEqual(
- fn(sing),
- plur,
- msg='{}("{}") == "{}" != "{}"'.format(
- fn.__name__, sing, fn(sing), plur
- ),
+ assert fn(sing) == plur, '{}("{}") == "{}" != "{}"'.format(
+ fn.__name__, sing, fn(sing), plur
)
for sing, num, plur in (
@@ -299,17 +279,17 @@ class test(unittest.TestCase):
("runs", 1, "runs"),
("am", 0, "are"),
):
- self.assertEqual(p.plural(sing, num), plur)
+ assert p.plural(sing, num) == plur
p.classical(zero=True)
- self.assertEqual(p.plural("cow", 0), "cow")
- self.assertEqual(p.plural("cow", "zero"), "cow")
- self.assertEqual(p.plural("runs", 0), "runs")
- self.assertEqual(p.plural("am", 0), "am")
- self.assertEqual(p.plural_verb("runs", 1), "runs")
+ assert p.plural("cow", 0) == "cow"
+ assert p.plural("cow", "zero") == "cow"
+ assert p.plural("runs", 0) == "runs"
+ assert p.plural("am", 0) == "am"
+ assert p.plural_verb("runs", 1) == "runs"
- self.assertEqual(p.plural("die"), "dice")
- self.assertEqual(p.plural_noun("die"), "dice")
+ assert p.plural("die") == "dice"
+ assert p.plural_noun("die") == "dice"
with pytest.raises(Exception):
p.plural("")
@@ -324,30 +304,30 @@ class test(unittest.TestCase):
("die", "dice"),
("goose", "geese"),
):
- self.assertEqual(p.singular_noun(plur), sing)
- self.assertEqual(p.inflect("singular_noun('%s')" % plur), sing)
+ assert p.singular_noun(plur) == sing
+ assert p.inflect("singular_noun('%s')" % plur) == sing
- self.assertEqual(p.singular_noun("cats", count=2), "cats")
- self.assertEqual(p.singular_noun("open valves", count=2), "open valves")
+ assert p.singular_noun("cats", count=2) == "cats"
+ assert p.singular_noun("open valves", count=2) == "open valves"
- self.assertEqual(p.singular_noun("zombies"), "zombie")
+ assert p.singular_noun("zombies") == "zombie"
- self.assertEqual(p.singular_noun("shoes"), "shoe")
- self.assertEqual(p.singular_noun("dancing shoes"), "dancing shoe")
+ assert p.singular_noun("shoes") == "shoe"
+ assert p.singular_noun("dancing shoes") == "dancing shoe"
- self.assertEqual(p.singular_noun("Matisses"), "Matisse")
- self.assertEqual(p.singular_noun("bouillabaisses"), "bouillabaisse")
+ assert p.singular_noun("Matisses") == "Matisse"
+ assert p.singular_noun("bouillabaisses") == "bouillabaisse"
- self.assertEqual(p.singular_noun("quartzes"), "quartz")
+ assert p.singular_noun("quartzes") == "quartz"
- self.assertEqual(p.singular_noun("Nietzsches"), "Nietzsche")
- self.assertEqual(p.singular_noun("aches"), "ache")
+ assert p.singular_noun("Nietzsches") == "Nietzsche"
+ assert p.singular_noun("aches") == "ache"
- self.assertEqual(p.singular_noun("Clives"), "Clive")
- self.assertEqual(p.singular_noun("weaves"), "weave")
+ assert p.singular_noun("Clives") == "Clive"
+ assert p.singular_noun("weaves") == "weave"
- self.assertEqual(p.singular_noun("status"), False)
- self.assertEqual(p.singular_noun("hiatus"), False)
+ assert p.singular_noun("status") is False
+ assert p.singular_noun("hiatus") is False
def test_gender(self):
p = inflect.engine()
@@ -359,14 +339,10 @@ class test(unittest.TestCase):
("to her", "to them"),
("to herself", "to themselves"),
):
- self.assertEqual(
- p.singular_noun(plur),
- sing,
- "singular_noun({}) == {} != {}".format(
- plur, p.singular_noun(plur), sing
- ),
- )
- self.assertEqual(p.inflect("singular_noun('%s')" % plur), sing)
+ assert (
+ p.singular_noun(plur) == sing
+ ), f"singular_noun({plur}) == {p.singular_noun(plur)} != {sing}"
+ assert p.inflect("singular_noun('%s')" % plur) == sing
p.gender("masculine")
for sing, plur in (
@@ -376,14 +352,10 @@ class test(unittest.TestCase):
("to him", "to them"),
("to himself", "to themselves"),
):
- self.assertEqual(
- p.singular_noun(plur),
- sing,
- "singular_noun({}) == {} != {}".format(
- plur, p.singular_noun(plur), sing
- ),
- )
- self.assertEqual(p.inflect("singular_noun('%s')" % plur), sing)
+ assert (
+ p.singular_noun(plur) == sing
+ ), f"singular_noun({plur}) == {p.singular_noun(plur)} != {sing}"
+ assert p.inflect("singular_noun('%s')" % plur) == sing
p.gender("gender-neutral")
for sing, plur in (
@@ -393,14 +365,10 @@ class test(unittest.TestCase):
("to them", "to them"),
("to themself", "to themselves"),
):
- self.assertEqual(
- p.singular_noun(plur),
- sing,
- "singular_noun({}) == {} != {}".format(
- plur, p.singular_noun(plur), sing
- ),
- )
- self.assertEqual(p.inflect("singular_noun('%s')" % plur), sing)
+ assert (
+ p.singular_noun(plur) == sing
+ ), f"singular_noun({plur}) == {p.singular_noun(plur)} != {sing}"
+ assert p.inflect("singular_noun('%s')" % plur) == sing
p.gender("neuter")
for sing, plur in (
@@ -410,16 +378,13 @@ class test(unittest.TestCase):
("to it", "to them"),
("to itself", "to themselves"),
):
- self.assertEqual(
- p.singular_noun(plur),
- sing,
- "singular_noun({}) == {} != {}".format(
- plur, p.singular_noun(plur), sing
- ),
- )
- self.assertEqual(p.inflect("singular_noun('%s')" % plur), sing)
+ assert (
+ p.singular_noun(plur) == sing
+ ), f"singular_noun({plur}) == {p.singular_noun(plur)} != {sing}"
+ assert p.inflect("singular_noun('%s')" % plur) == sing
- self.assertRaises(BadGenderError, p.gender, "male")
+ with pytest.raises(BadGenderError):
+ p.gender("male")
for sing, plur, gen in (
("it", "they", "neuter"),
@@ -429,87 +394,111 @@ class test(unittest.TestCase):
("she or he", "they", "feminine or masculine"),
("he or she", "they", "masculine or feminine"),
):
- self.assertEqual(p.singular_noun(plur, gender=gen), sing)
+ assert p.singular_noun(plur, gender=gen) == sing
- with self.assertRaises(BadGenderError):
+ with pytest.raises(BadGenderError):
p.singular_noun("cats", gender="unknown gender")
- def test_plequal(self):
+ @pytest.mark.parametrize(
+ 'sing,plur,res',
+ (
+ ("index", "index", "eq"),
+ ("index", "indexes", "s:p"),
+ ("index", "indices", "s:p"),
+ ("indexes", "index", "p:s"),
+ ("indices", "index", "p:s"),
+ ("indices", "indexes", "p:p"),
+ ("indexes", "indices", "p:p"),
+ ("indices", "indices", "eq"),
+ ("inverted index", "inverted indices", "s:p"),
+ ("inverted indices", "inverted index", "p:s"),
+ ("inverted indexes", "inverted indices", "p:p"),
+ ("opuses", "opera", "p:p"),
+ ("opera", "opuses", "p:p"),
+ ("brothers", "brethren", "p:p"),
+ ("cats", "cats", "eq"),
+ ("base", "basis", False),
+ ("syrinx", "syringe", False),
+ ("she", "he", False),
+ ("opus", "operas", False),
+ ("taxi", "taxes", False),
+ ("time", "Times", False),
+ ("time".lower(), "Times".lower(), "s:p"),
+ ("courts martial", "court martial", "p:s"),
+ ("my", "my", "eq"),
+ ("my", "our", "s:p"),
+ ("our", "our", "eq"),
+ pytest.param(
+ "dresses's", "dresses'", "p:p", marks=pytest.mark.xfail(reason="todo")
+ ),
+ pytest.param(
+ "dress's", "dress'", "s:s", marks=pytest.mark.xfail(reason='todo')
+ ),
+ pytest.param(
+ "Jess's", "Jess'", "s:s", marks=pytest.mark.xfail(reason='todo')
+ ),
+ ),
+ )
+ def test_compare_simple(self, sing, plur, res):
+ assert inflect.engine().compare(sing, plur) == res
+
+ @pytest.mark.parametrize(
+ 'sing,plur,res',
+ (
+ ("index", "index", "eq"),
+ ("index", "indexes", "s:p"),
+ ("index", "indices", "s:p"),
+ ("indexes", "index", "p:s"),
+ ("indices", "index", "p:s"),
+ ("indices", "indexes", "p:p"),
+ ("indexes", "indices", "p:p"),
+ ("indices", "indices", "eq"),
+ ("inverted index", "inverted indices", "s:p"),
+ ("inverted indices", "inverted index", "p:s"),
+ ("inverted indexes", "inverted indices", "p:p"),
+ ),
+ )
+ def test_compare_nouns(self, sing, plur, res):
+ assert inflect.engine().compare_nouns(sing, plur) == res
+
+ @pytest.mark.parametrize(
+ 'sing,plur,res',
+ (
+ ("runs", "runs", "eq"),
+ ("runs", "run", "s:p"),
+ ("run", "run", "eq"),
+ ),
+ )
+ def test_compare_verbs(self, sing, plur, res):
+ assert inflect.engine().compare_verbs(sing, plur) == res
+
+ @pytest.mark.parametrize(
+ 'sing,plur,res',
+ (
+ ("my", "my", "eq"),
+ ("my", "our", "s:p"),
+ ("our", "our", "eq"),
+ pytest.param(
+ "dresses's", "dresses'", "p:p", marks=pytest.mark.xfail(reason="todo")
+ ),
+ pytest.param(
+ "dress's", "dress'", "s:s", marks=pytest.mark.xfail(reason='todo')
+ ),
+ pytest.param(
+ "Jess's", "Jess'", "s:s", marks=pytest.mark.xfail(reason='todo')
+ ),
+ ),
+ )
+ def test_compare_adjectives(self, sing, plur, res):
+ assert inflect.engine().compare_adjs(sing, plur) == res
+
+ @pytest.mark.xfail()
+ def test_compare_your_our(self):
+ # multiple adjective plurals not (yet) supported
p = inflect.engine()
- for fn, sing, plur, res in (
- (p.compare, "index", "index", "eq"),
- (p.compare, "index", "indexes", "s:p"),
- (p.compare, "index", "indices", "s:p"),
- (p.compare, "indexes", "index", "p:s"),
- (p.compare, "indices", "index", "p:s"),
- (p.compare, "indices", "indexes", "p:p"),
- (p.compare, "indexes", "indices", "p:p"),
- (p.compare, "indices", "indices", "eq"),
- (p.compare, "inverted index", "inverted indices", "s:p"),
- (p.compare, "inverted indices", "inverted index", "p:s"),
- (p.compare, "inverted indexes", "inverted indices", "p:p"),
- (p.compare, "opuses", "opera", "p:p"),
- (p.compare, "opera", "opuses", "p:p"),
- (p.compare, "brothers", "brethren", "p:p"),
- (p.compare, "cats", "cats", "eq"),
- (p.compare, "base", "basis", False),
- (p.compare, "syrinx", "syringe", False),
- (p.compare, "she", "he", False),
- (p.compare, "opus", "operas", False),
- (p.compare, "taxi", "taxes", False),
- (p.compare, "time", "Times", False),
- (p.compare, "time".lower(), "Times".lower(), "s:p"),
- (p.compare, "courts martial", "court martial", "p:s"),
- (p.compare, "my", "my", "eq"),
- (p.compare, "my", "our", "s:p"),
- (p.compare, "our", "our", "eq"),
- (p.compare_nouns, "index", "index", "eq"),
- (p.compare_nouns, "index", "indexes", "s:p"),
- (p.compare_nouns, "index", "indices", "s:p"),
- (p.compare_nouns, "indexes", "index", "p:s"),
- (p.compare_nouns, "indices", "index", "p:s"),
- (p.compare_nouns, "indices", "indexes", "p:p"),
- (p.compare_nouns, "indexes", "indices", "p:p"),
- (p.compare_nouns, "indices", "indices", "eq"),
- (p.compare_nouns, "inverted index", "inverted indices", "s:p"),
- (p.compare_nouns, "inverted indices", "inverted index", "p:s"),
- (p.compare_nouns, "inverted indexes", "inverted indices", "p:p"),
- (p.compare_verbs, "runs", "runs", "eq"),
- (p.compare_verbs, "runs", "run", "s:p"),
- (p.compare_verbs, "run", "run", "eq"),
- (p.compare_adjs, "my", "my", "eq"),
- (p.compare_adjs, "my", "our", "s:p"),
- (p.compare_adjs, "our", "our", "eq"),
- ):
- self.assertEqual(fn(sing, plur), res)
-
- for fn, sing, plur, res, badres in (
- (
- p.compare,
- "dresses's",
- "dresses'",
- "p:p",
- "p:s",
- ), # TODO: should return p:p
- (
- p.compare_adjs,
- "dresses's",
- "dresses'",
- "p:p",
- False,
- ), # TODO: should return p:p
- # TODO: future: support different singulars one day.
- (p.compare, "dress's", "dress'", "s:s", "p:s"),
- (p.compare_adjs, "dress's", "dress'", "s:s", False),
- (p.compare, "Jess's", "Jess'", "s:s", "p:s"),
- (p.compare_adjs, "Jess's", "Jess'", "s:s", False),
- ):
- self.TODO(fn(sing, plur), res, badres)
-
- # TODO: pass upstream. multiple adjective plurals not supported
- self.assertEqual(p.compare("your", "our"), False)
+ assert p.compare("your", "our") is False
p.defadj("my", "our|your") # what's ours is yours
- self.TODO(p.compare("your", "our"), "p:p")
+ assert p.compare("your", "our") == "p:p"
def test__pl_reg_plurals(self):
p = inflect.engine()
@@ -518,26 +507,26 @@ class test(unittest.TestCase):
("indexes|robots", "dummy|ind", "exes", "ices", False),
("beaus|beaux", ".*eau", "s", "x", True),
):
- self.assertEqual(p._pl_reg_plurals(pair, stems, end1, end2), ans)
+ assert p._pl_reg_plurals(pair, stems, end1, end2) == ans
def test__pl_check_plurals_N(self):
p = inflect.engine()
- self.assertEqual(p._pl_check_plurals_N("index", "indices"), False)
- self.assertEqual(p._pl_check_plurals_N("indexes", "indices"), True)
- self.assertEqual(p._pl_check_plurals_N("indices", "indexes"), True)
- self.assertEqual(p._pl_check_plurals_N("stigmata", "stigmas"), True)
- self.assertEqual(p._pl_check_plurals_N("phalanxes", "phalanges"), True)
+ assert p._pl_check_plurals_N("index", "indices") is False
+ assert p._pl_check_plurals_N("indexes", "indices") is True
+ assert p._pl_check_plurals_N("indices", "indexes") is True
+ assert p._pl_check_plurals_N("stigmata", "stigmas") is True
+ assert p._pl_check_plurals_N("phalanxes", "phalanges") is True
def test__pl_check_plurals_adj(self):
p = inflect.engine()
- self.assertEqual(p._pl_check_plurals_adj("indexes's", "indices's"), True)
- self.assertEqual(p._pl_check_plurals_adj("indices's", "indexes's"), True)
- self.assertEqual(p._pl_check_plurals_adj("indexes'", "indices's"), True)
- self.assertEqual(p._pl_check_plurals_adj("indexes's", "indices'"), True)
- self.assertEqual(p._pl_check_plurals_adj("indexes's", "indexes's"), False)
- self.assertEqual(p._pl_check_plurals_adj("dogmas's", "dogmata's"), True)
- self.assertEqual(p._pl_check_plurals_adj("dogmas'", "dogmata'"), True)
- self.assertEqual(p._pl_check_plurals_adj("indexes'", "indices'"), True)
+ assert p._pl_check_plurals_adj("indexes's", "indices's") is True
+ assert p._pl_check_plurals_adj("indices's", "indexes's") is True
+ assert p._pl_check_plurals_adj("indexes'", "indices's") is True
+ assert p._pl_check_plurals_adj("indexes's", "indices'") is True
+ assert p._pl_check_plurals_adj("indexes's", "indexes's") is False
+ assert p._pl_check_plurals_adj("dogmas's", "dogmata's") is True
+ assert p._pl_check_plurals_adj("dogmas'", "dogmata'") is True
+ assert p._pl_check_plurals_adj("indexes'", "indices'") is True
def test_count(self):
p = inflect.engine()
@@ -562,11 +551,11 @@ class test(unittest.TestCase):
("that", 1),
("dummy", 2),
):
- self.assertEqual(p.get_count(txt), num)
+ assert p.get_count(txt) == num
- self.assertEqual(p.get_count(), "")
+ assert p.get_count() == ""
p.num(3)
- self.assertEqual(p.get_count(), 2)
+ assert p.get_count() == 2
def test__plnoun(self):
p = inflect.engine()
@@ -621,15 +610,11 @@ class test(unittest.TestCase):
("zoo", "zoos"),
("tomato", "tomatoes"),
):
- self.assertEqual(
- p._plnoun(sing),
- plur,
- msg='p._plnoun("{}") == {} != "{}"'.format(sing, p._plnoun(sing), plur),
+ assert p._plnoun(sing) == plur, 'p._plnoun("{}") == {} != "{}"'.format(
+ sing, p._plnoun(sing), plur
)
- self.assertEqual(
- p._sinoun(plur), sing, msg='p._sinoun("{}") != "{}"'.format(plur, sing)
- )
+ assert p._sinoun(plur) == sing, f'p._sinoun("{plur}") != "{sing}"'
# words where forming singular is ambiguous or not attempted
for sing, plur in (
@@ -638,34 +623,24 @@ class test(unittest.TestCase):
("basis", "bases"),
("Jess", "Jesses"),
):
- self.assertEqual(
- p._plnoun(sing), plur, msg='p._plnoun("{}") != "{}"'.format(sing, plur)
- )
-
- for sing, plur in (
- # TODO: does not keep case
- ("about ME", "about US"),
- # TODO: does not keep case
- ("YOU", "YOU"),
- ):
- self.TODO(p._plnoun(sing), plur)
+ assert p._plnoun(sing) == plur, f'p._plnoun("{sing}") != "{plur}"'
p.num(1)
- self.assertEqual(p._plnoun("cat"), "cat")
+ assert p._plnoun("cat") == "cat"
p.num(3)
p.classical(herd=True)
- self.assertEqual(p._plnoun("swine"), "swine")
+ assert p._plnoun("swine") == "swine"
p.classical(herd=False)
- self.assertEqual(p._plnoun("swine"), "swines")
+ assert p._plnoun("swine") == "swines"
p.classical(persons=True)
- self.assertEqual(p._plnoun("chairperson"), "chairpersons")
+ assert p._plnoun("chairperson") == "chairpersons"
p.classical(persons=False)
- self.assertEqual(p._plnoun("chairperson"), "chairpeople")
+ assert p._plnoun("chairperson") == "chairpeople"
p.classical(ancient=True)
- self.assertEqual(p._plnoun("formula"), "formulae")
+ assert p._plnoun("formula") == "formulae"
p.classical(ancient=False)
- self.assertEqual(p._plnoun("formula"), "formulas")
+ assert p._plnoun("formula") == "formulas"
p.classical()
for sing, plur in (
@@ -687,75 +662,109 @@ class test(unittest.TestCase):
("goy", "goyim"),
("afrit", "afriti"),
):
- self.assertEqual(p._plnoun(sing), plur)
+ assert p._plnoun(sing) == plur
# p.classical(0)
# p.classical('names')
# classical now back to the default mode
+ @pytest.mark.parametrize(
+ 'sing, plur',
+ (
+ pytest.param(
+ 'about ME',
+ 'about US',
+ marks=pytest.mark.xfail(reason='does not keep case'),
+ ),
+ pytest.param(
+ 'YOU',
+ 'YOU',
+ marks=pytest.mark.xfail(reason='does not keep case'),
+ ),
+ ),
+ )
+ def test_plnoun_retains_case(self, sing, plur):
+ assert inflect.engine()._plnoun(sing) == plur
+
def test_classical_pl(self):
p = inflect.engine()
p.classical()
for sing, plur in (("brother", "brethren"), ("dogma", "dogmata")):
- self.assertEqual(p.plural(sing), plur)
+ assert p.plural(sing) == plur
def test__pl_special_verb(self):
p = inflect.engine()
with pytest.raises(Exception):
- self.assertEqual(p._pl_special_verb(""), False)
- self.assertEqual(p._pl_special_verb("am"), "are")
- self.assertEqual(p._pl_special_verb("am", 0), "are")
- self.assertEqual(p._pl_special_verb("runs", 0), "run")
+ assert p._pl_special_verb("") is False
+ assert p._pl_special_verb("am") == "are"
+ assert p._pl_special_verb("am", 0) == "are"
+ assert p._pl_special_verb("runs", 0) == "run"
p.classical(zero=True)
- self.assertEqual(p._pl_special_verb("am", 0), False)
- self.assertEqual(p._pl_special_verb("am", 1), "am")
- self.assertEqual(p._pl_special_verb("am", 2), "are")
- self.assertEqual(p._pl_special_verb("runs", 0), False)
- self.assertEqual(p._pl_special_verb("am going to"), "are going to")
- self.assertEqual(p._pl_special_verb("did"), "did")
- self.assertEqual(p._pl_special_verb("wasn't"), "weren't")
- self.assertEqual(p._pl_special_verb("shouldn't"), "shouldn't")
- self.assertEqual(p._pl_special_verb("bias"), False)
- self.assertEqual(p._pl_special_verb("news"), False)
- self.assertEqual(p._pl_special_verb("Jess"), False)
- self.assertEqual(p._pl_special_verb(" "), False)
- self.assertEqual(p._pl_special_verb("brushes"), "brush")
- self.assertEqual(p._pl_special_verb("fixes"), "fix")
- self.assertEqual(p._pl_special_verb("quizzes"), "quiz")
- self.assertEqual(p._pl_special_verb("fizzes"), "fizz")
- self.assertEqual(p._pl_special_verb("dresses"), "dress")
- self.assertEqual(p._pl_special_verb("flies"), "fly")
- self.assertEqual(p._pl_special_verb("canoes"), "canoe")
- self.assertEqual(p._pl_special_verb("horseshoes"), "horseshoe")
- self.assertEqual(p._pl_special_verb("does"), "do")
+ assert p._pl_special_verb("am", 0) is False
+ assert p._pl_special_verb("am", 1) == "am"
+ assert p._pl_special_verb("am", 2) == "are"
+ assert p._pl_special_verb("runs", 0) is False
+ assert p._pl_special_verb("am going to") == "are going to"
+ assert p._pl_special_verb("did") == "did"
+ assert p._pl_special_verb("wasn't") == "weren't"
+ assert p._pl_special_verb("shouldn't") == "shouldn't"
+ assert p._pl_special_verb("bias") is False
+ assert p._pl_special_verb("news") is False
+ assert p._pl_special_verb("Jess") is False
+ assert p._pl_special_verb(" ") is False
+ assert p._pl_special_verb("brushes") == "brush"
+ assert p._pl_special_verb("fixes") == "fix"
+ assert p._pl_special_verb("quizzes") == "quiz"
+ assert p._pl_special_verb("fizzes") == "fizz"
+ assert p._pl_special_verb("dresses") == "dress"
+ assert p._pl_special_verb("flies") == "fly"
+ assert p._pl_special_verb("canoes") == "canoe"
+ assert p._pl_special_verb("horseshoes") == "horseshoe"
+ assert p._pl_special_verb("does") == "do"
# TODO: what's a real word to test this case?
- self.assertEqual(p._pl_special_verb("zzzoes"), "zzzo")
- self.assertEqual(p._pl_special_verb("runs"), "run")
+ assert p._pl_special_verb("zzzoes") == "zzzo"
+ assert p._pl_special_verb("runs") == "run"
def test__pl_general_verb(self):
p = inflect.engine()
- self.assertEqual(p._pl_general_verb("acts"), "act")
- self.assertEqual(p._pl_general_verb("act"), "act")
- self.assertEqual(p._pl_general_verb("saw"), "saw")
- self.assertEqual(p._pl_general_verb("runs", 1), "runs")
-
- def test__pl_special_adjective(self):
- p = inflect.engine()
- self.assertEqual(p._pl_special_adjective("a"), "some")
- self.assertEqual(p._pl_special_adjective("my"), "our")
- self.assertEqual(p._pl_special_adjective("John's"), "Johns'")
- # TODO: original can't handle this. should we handle it?
- self.TODO(p._pl_special_adjective("JOHN's"), "JOHNS'")
- # TODO: can't handle capitals
- self.TODO(p._pl_special_adjective("JOHN'S"), "JOHNS'")
- self.TODO(p._pl_special_adjective("TUNA'S"), "TUNA'S")
- self.assertEqual(p._pl_special_adjective("tuna's"), "tuna's")
- self.assertEqual(p._pl_special_adjective("TUNA's"), "TUNA's")
- self.assertEqual(p._pl_special_adjective("bad"), False)
-
- def test_a(self):
+ assert p._pl_general_verb("acts") == "act"
+ assert p._pl_general_verb("act") == "act"
+ assert p._pl_general_verb("saw") == "saw"
+ assert p._pl_general_verb("runs", 1) == "runs"
+
+ @pytest.mark.parametrize(
+ 'adj,plur',
+ (
+ ("a", "some"),
+ ("my", "our"),
+ ("John's", "Johns'"),
+ ("tuna's", "tuna's"),
+ ("TUNA's", "TUNA's"),
+ ("bad", False),
+ pytest.param(
+ "JOHN's",
+ "JOHNS'",
+ marks=pytest.mark.xfail(reason='should this be handled?'),
+ ),
+ pytest.param(
+ "JOHN'S",
+ "JOHNS'",
+ marks=pytest.mark.xfail(reason="can't handle capitals"),
+ ),
+ pytest.param(
+ "TUNA'S",
+ "TUNA'S",
+ marks=pytest.mark.xfail(reason="can't handle capitals"),
+ ),
+ ),
+ )
+ def test__pl_special_adjective(self, adj, plur):
p = inflect.engine()
- for sing, plur in (
+ assert p._pl_special_adjective(adj) == plur
+
+ @pytest.mark.parametrize(
+ 'sing, plur',
+ (
("cat", "a cat"),
("euphemism", "a euphemism"),
("Euler number", "an Euler number"),
@@ -797,30 +806,39 @@ class test(unittest.TestCase):
("a cat", "a cat"),
("an cat", "a cat"),
("a ant", "an ant"),
- ):
- self.assertEqual(p.a(sing), plur)
+ ),
+ )
+ def test_a(self, sing, plur):
+ p = inflect.engine()
+ assert p.a(sing) == plur
- self.assertEqual(p.a("cat", 1), "a cat")
- self.assertEqual(p.a("cat", 2), "2 cat")
+ def test_a_alt(self):
+ p = inflect.engine()
+ assert p.a("cat", 1) == "a cat"
+ assert p.a("cat", 2) == "2 cat"
- self.assertEqual(p.a, p.an)
with pytest.raises(Exception):
p.a("")
+ def test_a_and_an_same_method(self):
+ assert same_method(inflect.engine.a, inflect.engine.an)
+ p = inflect.engine()
+ assert same_method(p.a, p.an)
+
def test_no(self):
p = inflect.engine()
- self.assertEqual(p.no("cat"), "no cats")
- self.assertEqual(p.no("cat", count=3), "3 cats")
- self.assertEqual(p.no("cat", count="three"), "three cats")
- self.assertEqual(p.no("cat", count=1), "1 cat")
- self.assertEqual(p.no("cat", count="one"), "one cat")
- self.assertEqual(p.no("mouse"), "no mice")
+ assert p.no("cat") == "no cats"
+ assert p.no("cat", count=3) == "3 cats"
+ assert p.no("cat", count="three") == "three cats"
+ assert p.no("cat", count=1) == "1 cat"
+ assert p.no("cat", count="one") == "one cat"
+ assert p.no("mouse") == "no mice"
p.num(3)
- self.assertEqual(p.no("cat"), "3 cats")
+ assert p.no("cat") == "3 cats"
- def test_prespart(self):
- p = inflect.engine()
- for sing, plur in (
+ @pytest.mark.parametrize(
+ 'sing, plur',
+ (
("runs", "running"),
("dies", "dying"),
("glues", "gluing"),
@@ -833,19 +851,21 @@ class test(unittest.TestCase):
("eats", "eating"),
("loves", "loving"),
("spies", "spying"),
- ):
- self.assertEqual(p.present_participle(sing), plur)
-
- self.assertEqual(p.present_participle("hoes"), "hoeing")
- self.assertEqual(p.present_participle("alibis"), "alibiing")
- self.assertEqual(p.present_participle("is"), "being")
- self.assertEqual(p.present_participle("are"), "being")
- self.assertEqual(p.present_participle("had"), "having")
- self.assertEqual(p.present_participle("has"), "having")
-
- def test_ordinal(self):
+ ("hoes", "hoeing"),
+ ("alibis", "alibiing"),
+ ("is", "being"),
+ ("are", "being"),
+ ("had", "having"),
+ ("has", "having"),
+ ),
+ )
+ def test_prespart(self, sing, plur):
p = inflect.engine()
- for num, numord in (
+ assert p.present_participle(sing) == plur
+
+ @pytest.mark.parametrize(
+ 'num, ord',
+ (
("1", "1st"),
("2", "2nd"),
("3", "3rd"),
@@ -865,95 +885,95 @@ class test(unittest.TestCase):
("one hundered and one", "one hundered and first"),
("zero", "zeroth"),
("n", "nth"), # bonus!
- ):
- self.assertEqual(p.ordinal(num), numord)
+ ),
+ )
+ def test_ordinal(self, num, ord):
+ p = inflect.engine()
+ assert p.ordinal(num) == ord
def test_millfn(self):
p = inflect.engine()
millfn = p.millfn
- self.assertEqual(millfn(1), " thousand")
- self.assertEqual(millfn(2), " million")
- self.assertEqual(millfn(3), " billion")
- self.assertEqual(millfn(0), " ")
- self.assertEqual(millfn(11), " decillion")
- inflect.STDOUT_ON = False
- self.assertRaises(NumOutOfRangeError, millfn, 12)
- inflect.STDOUT_ON = True
+ assert millfn(1) == " thousand"
+ assert millfn(2) == " million"
+ assert millfn(3) == " billion"
+ assert millfn(0) == " "
+ assert millfn(11) == " decillion"
+ with pytest.raises(NumOutOfRangeError):
+ millfn(12)
def test_unitfn(self):
p = inflect.engine()
unitfn = p.unitfn
- self.assertEqual(unitfn(1, 2), "one million")
- self.assertEqual(unitfn(1, 3), "one billion")
- self.assertEqual(unitfn(5, 3), "five billion")
- self.assertEqual(unitfn(5, 0), "five ")
- self.assertEqual(unitfn(0, 0), " ")
+ assert unitfn(1, 2) == "one million"
+ assert unitfn(1, 3) == "one billion"
+ assert unitfn(5, 3) == "five billion"
+ assert unitfn(5, 0) == "five "
+ assert unitfn(0, 0) == " "
def test_tenfn(self):
p = inflect.engine()
tenfn = p.tenfn
- self.assertEqual(tenfn(3, 1, 2), "thirty-one million")
- self.assertEqual(tenfn(3, 0, 2), "thirty million")
- self.assertEqual(tenfn(0, 1, 2), "one million")
- self.assertEqual(tenfn(1, 1, 2), "eleven million")
- self.assertEqual(tenfn(1, 0, 2), "ten million")
- self.assertEqual(tenfn(1, 0, 0), "ten ")
- self.assertEqual(tenfn(0, 0, 0), " ")
+ assert tenfn(3, 1, 2) == "thirty-one million"
+ assert tenfn(3, 0, 2) == "thirty million"
+ assert tenfn(0, 1, 2) == "one million"
+ assert tenfn(1, 1, 2) == "eleven million"
+ assert tenfn(1, 0, 2) == "ten million"
+ assert tenfn(1, 0, 0) == "ten "
+ assert tenfn(0, 0, 0) == " "
def test_hundfn(self):
p = inflect.engine()
hundfn = p.hundfn
p._number_args = dict(andword="and")
- self.assertEqual(hundfn(4, 3, 1, 2), "four hundred and thirty-one million, ")
- self.assertEqual(hundfn(4, 0, 0, 2), "four hundred million, ")
- self.assertEqual(hundfn(4, 0, 5, 2), "four hundred and five million, ")
- self.assertEqual(hundfn(0, 3, 1, 2), "thirty-one million, ")
- self.assertEqual(hundfn(0, 0, 7, 2), "seven million, ")
+ assert hundfn(4, 3, 1, 2) == "four hundred and thirty-one million, "
+ assert hundfn(4, 0, 0, 2) == "four hundred million, "
+ assert hundfn(4, 0, 5, 2) == "four hundred and five million, "
+ assert hundfn(0, 3, 1, 2) == "thirty-one million, "
+ assert hundfn(0, 0, 7, 2) == "seven million, "
def test_enword(self):
p = inflect.engine()
enword = p.enword
- self.assertEqual(enword("5", 1), "five, ")
+ assert enword("5", 1) == "five, "
p._number_args = dict(zero="zero", one="one", andword="and")
- self.assertEqual(enword("0", 1), " zero, ")
- self.assertEqual(enword("1", 1), " one, ")
- self.assertEqual(enword("347", 1), "three, four, seven, ")
-
- self.assertEqual(enword("34", 2), "thirty-four , ")
- self.assertEqual(enword("347", 2), "thirty-four , seven, ")
- self.assertEqual(enword("34768", 2), "thirty-four , seventy-six , eight, ")
- self.assertEqual(enword("1", 2), "one, ")
- p._number_args["one"] = "single"
- self.TODO(
- enword("1", 2), "single, ", "one, "
- ) # TODO: doesn't use default word for 'one' here
-
- p._number_args["one"] = "one"
-
- self.assertEqual(enword("134", 3), " one thirty-four , ")
-
- self.assertEqual(enword("0", -1), "zero")
- self.assertEqual(enword("1", -1), "one")
-
- self.assertEqual(enword("3", -1), "three , ")
- self.assertEqual(enword("12", -1), "twelve , ")
- self.assertEqual(enword("123", -1), "one hundred and twenty-three , ")
- self.assertEqual(
- enword("1234", -1), "one thousand, two hundred and thirty-four , "
+ assert enword("0", 1) == " zero, "
+ assert enword("1", 1) == " one, "
+ assert enword("347", 1) == "three, four, seven, "
+
+ assert enword("34", 2) == "thirty-four , "
+ assert enword("347", 2) == "thirty-four , seven, "
+ assert enword("34768", 2) == "thirty-four , seventy-six , eight, "
+ assert enword("1", 2) == "one, "
+
+ assert enword("134", 3) == " one thirty-four , "
+
+ assert enword("0", -1) == "zero"
+ assert enword("1", -1) == "one"
+
+ assert enword("3", -1) == "three , "
+ assert enword("12", -1) == "twelve , "
+ assert enword("123", -1) == "one hundred and twenty-three , "
+ assert enword("1234", -1) == "one thousand, two hundred and thirty-four , "
+ assert (
+ enword("12345", -1) == "twelve thousand, three hundred and forty-five , "
)
- self.assertEqual(
- enword("12345", -1), "twelve thousand, three hundred and forty-five , "
+ assert (
+ enword("123456", -1)
+ == "one hundred and twenty-three thousand, four hundred and fifty-six , "
)
- self.assertEqual(
- enword("123456", -1),
- "one hundred and twenty-three thousand, four hundred and fifty-six , ",
- )
- self.assertEqual(
- enword("1234567", -1),
- "one million, two hundred and thirty-four thousand, "
- "five hundred and sixty-seven , ",
+ assert (
+ enword("1234567", -1)
+ == "one million, two hundred and thirty-four thousand, "
+ "five hundred and sixty-seven , "
)
+ @pytest.mark.xfail(reason="doesn't use indicated word for 'one'")
+ def test_enword_number_args_override(self):
+ p = inflect.engine()
+ p._number_args["one"] = "single"
+ p.enword("1", 2) == "single, "
+
def test_numwords(self):
p = inflect.engine()
numwords = p.number_to_words
@@ -972,13 +992,13 @@ class test(unittest.TestCase):
("10.", "ten point"),
(".10", "point one zero"),
):
- self.assertEqual(numwords(n), word)
+ assert numwords(n) == word
for n, word, wrongword in (
# TODO: should be one point two three
("1.23", "one point two three", "one point twenty-three"),
):
- self.assertEqual(numwords(n), word)
+ assert numwords(n) == word
for n, txt in (
(3, "three bottles of beer on the wall"),
@@ -986,214 +1006,211 @@ class test(unittest.TestCase):
(1, "a solitary bottle of beer on the wall"),
(0, "no more bottles of beer on the wall"),
):
- self.assertEqual(
+ assert (
"{}{}".format(
numwords(n, one="a solitary", zero="no more"),
p.plural(" bottle of beer on the wall", n),
- ),
- txt,
+ )
+ == txt
)
- self.assertEqual(numwords(0, one="one", zero="zero"), "zero")
-
- self.assertEqual(numwords("1234"), "one thousand, two hundred and thirty-four")
- self.assertEqual(
- numwords("1234", wantlist=True),
- ["one thousand", "two hundred and thirty-four"],
- )
- self.assertEqual(
- numwords("1234567", wantlist=True),
- [
- "one million",
- "two hundred and thirty-four thousand",
- "five hundred and sixty-seven",
- ],
- )
- self.assertEqual(numwords("+10", wantlist=True), ["plus", "ten"])
- self.assertEqual(
- numwords("1234", andword=""), "one thousand, two hundred thirty-four"
+ assert numwords(0, one="one", zero="zero") == "zero"
+
+ assert numwords("1234") == "one thousand, two hundred and thirty-four"
+ assert numwords("1234", wantlist=True) == [
+ "one thousand",
+ "two hundred and thirty-four",
+ ]
+ assert numwords("1234567", wantlist=True) == [
+ "one million",
+ "two hundred and thirty-four thousand",
+ "five hundred and sixty-seven",
+ ]
+ assert numwords("+10", wantlist=True) == ["plus", "ten"]
+ assert numwords("1234", andword="") == "one thousand, two hundred thirty-four"
+ assert (
+ numwords("1234", andword="plus")
+ == "one thousand, two hundred plus thirty-four"
)
- self.assertEqual(
- numwords("1234", andword="plus"),
- "one thousand, two hundred plus thirty-four",
- )
- self.assertEqual(numwords(p.ordinal("21")), "twenty-first")
- self.assertEqual(numwords("9", threshold=10), "nine")
- self.assertEqual(numwords("10", threshold=10), "ten")
- self.assertEqual(numwords("11", threshold=10), "11")
- self.assertEqual(numwords("1000", threshold=10), "1,000")
- self.assertEqual(numwords("123", threshold=10), "123")
- self.assertEqual(numwords("1234", threshold=10), "1,234")
- self.assertEqual(numwords("1234.5678", threshold=10), "1,234.5678")
- self.assertEqual(numwords("1", decimal=None), "one")
- self.assertEqual(
- numwords("1234.5678", decimal=None),
- "twelve million, three hundred and forty-five "
- "thousand, six hundred and seventy-eight",
+ assert numwords(p.ordinal("21")) == "twenty-first"
+ assert numwords("9", threshold=10) == "nine"
+ assert numwords("10", threshold=10) == "ten"
+ assert numwords("11", threshold=10) == "11"
+ assert numwords("1000", threshold=10) == "1,000"
+ assert numwords("123", threshold=10) == "123"
+ assert numwords("1234", threshold=10) == "1,234"
+ assert numwords("1234.5678", threshold=10) == "1,234.5678"
+ assert numwords("1", decimal=None) == "one"
+ assert (
+ numwords("1234.5678", decimal=None)
+ == "twelve million, three hundred and forty-five "
+ "thousand, six hundred and seventy-eight"
)
- def test_numwords_group(self):
+ def test_numwords_group_chunking_error(self):
p = inflect.engine()
- numwords = p.number_to_words
- self.assertEqual(numwords("12345", group=2), "twelve, thirty-four, five")
- # TODO: 'hundred and' missing
- self.TODO(
- numwords("12345", group=3),
- "one hundred and twenty-three",
- "one twenty-three, forty-five",
- )
- self.assertEqual(
- numwords("123456", group=3), "one twenty-three, four fifty-six"
- )
- self.assertEqual(numwords("12345", group=1), "one, two, three, four, five")
- self.assertEqual(
- numwords("1234th", group=0, andword="and"),
- "one thousand, two hundred and thirty-fourth",
- )
- self.assertEqual(
- numwords(p.ordinal("1234"), group=0),
- "one thousand, two hundred and thirty-fourth",
- )
- self.assertEqual(numwords("120", group=2), "twelve, zero")
- self.assertEqual(numwords("120", group=2, zero="oh", one="unity"), "twelve, oh")
- # TODO: ignoring 'one' param with group=2
- self.TODO(
- numwords("101", group=2, zero="oh", one="unity"), "ten, unity", "ten, one"
- )
- self.assertEqual(
- numwords("555_1202", group=1, zero="oh"),
- "five, five, five, one, two, oh, two",
- )
- self.assertEqual(
- numwords("555_1202", group=1, one="unity"),
- "five, five, five, unity, two, zero, two",
- )
- self.assertEqual(
- numwords("123.456", group=1, decimal="mark", one="one"),
- "one, two, three, mark, four, five, six",
- )
-
- inflect.STDOUT_ON = False
- self.assertRaises(BadChunkingOptionError, numwords, "1234", group=4)
- inflect.STDOUT_ON = True
+ with pytest.raises(BadChunkingOptionError):
+ p.number_to_words("1234", group=4)
+
+ @pytest.mark.parametrize(
+ 'input,kwargs,expect',
+ (
+ ("12345", dict(group=2), "twelve, thirty-four, five"),
+ ("123456", dict(group=3), "one twenty-three, four fifty-six"),
+ ("12345", dict(group=1), "one, two, three, four, five"),
+ (
+ "1234th",
+ dict(group=0, andword="and"),
+ "one thousand, two hundred and thirty-fourth",
+ ),
+ (
+ "1234th",
+ dict(group=0),
+ "one thousand, two hundred and thirty-fourth",
+ ),
+ ("120", dict(group=2), "twelve, zero"),
+ ("120", dict(group=2, zero="oh", one="unity"), "twelve, oh"),
+ (
+ "555_1202",
+ dict(group=1, zero="oh"),
+ "five, five, five, one, two, oh, two",
+ ),
+ (
+ "555_1202",
+ dict(group=1, one="unity"),
+ "five, five, five, unity, two, zero, two",
+ ),
+ (
+ "123.456",
+ dict(group=1, decimal="mark", one="one"),
+ "one, two, three, mark, four, five, six",
+ ),
+ pytest.param(
+ '12345',
+ dict(group=3),
+ 'one hundred and twenty-three',
+ marks=pytest.mark.xfail(reason="'hundred and' missing"),
+ ),
+ pytest.param(
+ '101',
+ dict(group=2, zero="oh", one="unity"),
+ "ten, unity",
+ marks=pytest.mark.xfail(reason="ignoring 'one' param with group=2"),
+ ),
+ ),
+ )
+ def test_numwords_group(self, input, kwargs, expect):
+ p = inflect.engine()
+ assert p.number_to_words(input, **kwargs) == expect
def test_wordlist(self):
p = inflect.engine()
wordlist = p.join
- self.assertEqual(wordlist([]), "")
- self.assertEqual(wordlist(("apple",)), "apple")
- self.assertEqual(wordlist(("apple", "banana")), "apple and banana")
- self.assertEqual(
- wordlist(("apple", "banana", "carrot")), "apple, banana, and carrot"
+ assert wordlist([]) == ""
+ assert wordlist(("apple",)) == "apple"
+ assert wordlist(("apple", "banana")) == "apple and banana"
+ assert wordlist(("apple", "banana", "carrot")) == "apple, banana, and carrot"
+ assert wordlist(("apple", "1,000", "carrot")) == "apple; 1,000; and carrot"
+ assert (
+ wordlist(("apple", "1,000", "carrot"), sep=",")
+ == "apple, 1,000, and carrot"
)
- self.assertEqual(
- wordlist(("apple", "1,000", "carrot")), "apple; 1,000; and carrot"
+ assert (
+ wordlist(("apple", "banana", "carrot"), final_sep="")
+ == "apple, banana and carrot"
)
- self.assertEqual(
- wordlist(("apple", "1,000", "carrot"), sep=","), "apple, 1,000, and carrot"
+ assert (
+ wordlist(("apple", "banana", "carrot"), final_sep=";")
+ == "apple, banana; and carrot"
)
- self.assertEqual(
- wordlist(("apple", "banana", "carrot"), final_sep=""),
- "apple, banana and carrot",
+ assert (
+ wordlist(("apple", "banana", "carrot"), conj="or")
+ == "apple, banana, or carrot"
)
- self.assertEqual(
- wordlist(("apple", "banana", "carrot"), final_sep=";"),
- "apple, banana; and carrot",
+
+ assert wordlist(("apple", "banana"), conj=" or ") == "apple or banana"
+ assert wordlist(("apple", "banana"), conj="&") == "apple & banana"
+ assert (
+ wordlist(("apple", "banana"), conj="&", conj_spaced=False) == "apple&banana"
)
- self.assertEqual(
- wordlist(("apple", "banana", "carrot"), conj="or"),
- "apple, banana, or carrot",
+ assert (
+ wordlist(("apple", "banana"), conj="& ", conj_spaced=False)
+ == "apple& banana"
)
- self.assertEqual(
- wordlist(("apple", "banana"), conj=" or "), "apple or banana"
+ assert (
+ wordlist(("apple", "banana", "carrot"), conj=" or ")
+ == "apple, banana, or carrot"
)
- self.assertEqual(
- wordlist(("apple", "banana"), conj="&"), "apple & banana"
- ) # TODO: want spaces here. Done, report upstream
- self.assertEqual(
- wordlist(("apple", "banana"), conj="&", conj_spaced=False), "apple&banana"
+ assert (
+ wordlist(("apple", "banana", "carrot"), conj="+")
+ == "apple, banana, + carrot"
)
- self.assertEqual(
- wordlist(("apple", "banana"), conj="& ", conj_spaced=False), "apple& banana"
+ assert (
+ wordlist(("apple", "banana", "carrot"), conj="&")
+ == "apple, banana, & carrot"
)
-
- self.assertEqual(
- wordlist(("apple", "banana", "carrot"), conj=" or "),
- "apple, banana, or carrot",
+ assert (
+ wordlist(("apple", "banana", "carrot"), conj="&", conj_spaced=False)
+ == "apple, banana,&carrot"
)
- self.assertEqual(
- wordlist(("apple", "banana", "carrot"), conj="+"), "apple, banana, + carrot"
+ assert (
+ wordlist(("apple", "banana", "carrot"), conj=" &", conj_spaced=False)
+ == "apple, banana, &carrot"
)
- self.assertEqual(
- wordlist(("apple", "banana", "carrot"), conj="&"), "apple, banana, & carrot"
- ) # 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 upstream
- self.assertEqual(
- wordlist(("apple", "banana", "carrot"), conj=" &", conj_spaced=False),
- "apple, banana, &carrot",
- ) # TODO: want space here. Done, report upstream
-
- def test_print(self):
- inflect.STDOUT_ON = True
- inflect.print3("") # make sure it doesn't crash
- inflect.STDOUT_ON = False
def test_doc_examples(self):
p = inflect.engine()
- self.assertEqual(p.plural_noun("I"), "we")
- self.assertEqual(p.plural_verb("saw"), "saw")
- self.assertEqual(p.plural_adj("my"), "our")
- self.assertEqual(p.plural_noun("saw"), "saws")
- self.assertEqual(p.plural("was"), "were")
- self.assertEqual(p.plural("was", 1), "was")
- self.assertEqual(p.plural_verb("was", 2), "were")
- self.assertEqual(p.plural_verb("was"), "were")
- self.assertEqual(p.plural_verb("was", 1), "was")
+ assert p.plural_noun("I") == "we"
+ assert p.plural_verb("saw") == "saw"
+ assert p.plural_adj("my") == "our"
+ assert p.plural_noun("saw") == "saws"
+ assert p.plural("was") == "were"
+ assert p.plural("was", 1) == "was"
+ assert p.plural_verb("was", 2) == "were"
+ assert p.plural_verb("was") == "were"
+ assert p.plural_verb("was", 1) == "was"
for errors, txt in (
(0, "There were no errors"),
(1, "There was 1 error"),
(2, "There were 2 errors"),
):
- self.assertEqual(
+ assert (
"There {}{}".format(
p.plural_verb("was", errors), p.no(" error", errors)
- ),
- txt,
+ )
+ == txt
)
- self.assertEqual(
+ assert (
p.inflect(
"There plural_verb('was',%d) no('error',%d)" % (errors, errors)
- ),
- txt,
+ )
+ == txt
)
for num1, num2, txt in ((1, 2, "I saw 2 saws"), (2, 1, "we saw 1 saw")):
- self.assertEqual(
+ assert (
"{}{}{} {}{}".format(
p.num(num1, ""),
p.plural("I"),
p.plural_verb(" saw"),
p.num(num2),
p.plural_noun(" saw"),
- ),
- txt,
+ )
+ == txt
)
- self.assertEqual(
+ assert (
p.inflect(
"num(%d, False)plural('I') plural_verb('saw') "
"num(%d) plural_noun('saw')" % (num1, num2)
- ),
- txt,
+ )
+ == txt
)
- self.assertEqual(p.a("a cat"), "a cat")
+ assert p.a("a cat") == "a cat"
for word, txt in (
("cat", "a cat"),
@@ -1201,38 +1218,11 @@ class test(unittest.TestCase):
("ewe", "a ewe"),
("hour", "an hour"),
):
- self.assertEqual(
- p.a("{} {}".format(p.number_to_words(1, one="a"), word)), txt
- )
+ assert p.a("{} {}".format(p.number_to_words(1, one="a"), word)) == txt
p.num(2)
- def test_deprecation(self):
- p = inflect.engine()
- for meth in (
- "pl",
- "plnoun",
- "plverb",
- "pladj",
- "sinoun",
- "prespart",
- "numwords",
- "plequal",
- "plnounequal",
- "plverbequal",
- "pladjequal",
- "wordlist",
- ):
- self.assertRaises(DeprecationWarning, getattr, p, meth)
-
def test_unknown_method(self):
p = inflect.engine()
- with self.assertRaises(AttributeError):
+ with pytest.raises(AttributeError):
p.unknown_method
-
-
-if __name__ == "__main__":
- try:
- unittest.main()
- except SystemExit:
- pass
diff --git a/tests/test_unicode.py b/tests/test_unicode.py
index d864515..a46c710 100644
--- a/tests/test_unicode.py
+++ b/tests/test_unicode.py
@@ -1,8 +1,7 @@
-import unittest
import inflect
-class TestUnicode(unittest.TestCase):
+class TestUnicode:
"""Unicode compatibility test cases"""
def test_unicode_plural(self):
@@ -10,4 +9,4 @@ class TestUnicode(unittest.TestCase):
engine = inflect.engine()
unicode_test_cases = {"cliché": "clichés", "ångström": "ångströms"}
for singular, plural in unicode_test_cases.items():
- self.assertEqual(plural, engine.plural(singular))
+ assert plural == engine.plural(singular)
diff --git a/towncrier.toml b/towncrier.toml
new file mode 100644
index 0000000..6fa480e
--- /dev/null
+++ b/towncrier.toml
@@ -0,0 +1,2 @@
+[tool.towncrier]
+title_format = "{version}"
diff --git a/tox.ini b/tox.ini
index 5a67821..4b6eaa4 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,8 +1,4 @@
[tox]
-envlist = python
-minversion = 3.2
-# https://github.com/jaraco/skeleton/issues/6
-tox_pip_extensions_ext_venv_update = true
toxworkdir={env:TOX_WORK_DIR:.tox}
@@ -16,6 +12,10 @@ usedevelop = True
extras =
testing
+[testenv:pydantic1]
+deps =
+ pydantic < 2
+
[testenv:docs]
extras =
docs
@@ -25,6 +25,16 @@ commands =
python -m sphinx -W --keep-going . {toxinidir}/build/html
python -m sphinxlint
+[testenv:finalize]
+skip_install = True
+deps =
+ towncrier
+ jaraco.develop >= 7.23
+passenv = *
+commands =
+ python -m jaraco.develop.finalize
+
+
[testenv:release]
skip_install = True
deps =
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in second set of .debs but not in first
-rw-r--r-- root/root /usr/lib/python3/dist-packages/inflect-7.0.0.dist-info/INSTALLER -rw-r--r-- root/root /usr/lib/python3/dist-packages/inflect-7.0.0.dist-info/METADATA -rw-r--r-- root/root /usr/lib/python3/dist-packages/inflect-7.0.0.dist-info/WHEEL -rw-r--r-- root/root /usr/lib/python3/dist-packages/inflect-7.0.0.dist-info/top_level.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/inflect/compat/__init__.py -rw-r--r-- root/root /usr/lib/python3/dist-packages/inflect/compat/pydantic.py -rw-r--r-- root/root /usr/lib/python3/dist-packages/inflect/compat/pydantic1.py
Files in first set of .debs but not in second
-rw-r--r-- root/root /usr/lib/python3/dist-packages/inflect-6.0.4.dist-info/METADATA -rw-r--r-- root/root /usr/lib/python3/dist-packages/inflect-6.0.4.dist-info/RECORD -rw-r--r-- root/root /usr/lib/python3/dist-packages/inflect-6.0.4.dist-info/WHEEL -rw-r--r-- root/root /usr/lib/python3/dist-packages/inflect-6.0.4.dist-info/top_level.txt
Control files: lines which differ (wdiff format)
Depends: python3-pydantic, python3-typing-extensions, python3:any