From 49263d433d2f34fb63b83145ad7ef27c1634dcea Mon Sep 17 00:00:00 2001 From: Copilot Date: Thu, 6 Aug 2026 09:17:23 +0000 Subject: [PATCH 1/2] Add pluralize utility with unit tests Extract duplicated pluralization logic from bowtie/_cli.py into a small, reusable bowtie._utils.pluralize helper, and cover it with unit tests and doctests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- bowtie/_cli.py | 7 +++---- bowtie/_utils.py | 22 ++++++++++++++++++++++ tests/test_utils.py | 25 +++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 bowtie/_utils.py create mode 100644 tests/test_utils.py diff --git a/bowtie/_cli.py b/bowtie/_cli.py index 04c921db8..21476f686 100644 --- a/bowtie/_cli.py +++ b/bowtie/_cli.py @@ -28,6 +28,7 @@ from bowtie import _report from bowtie._commands import Test, TestCase +from bowtie._utils import pluralize from bowtie._core import ( DialectRunner, GotStderr, @@ -207,14 +208,13 @@ def _failure_table( summary: _report._Summary, # type: ignore[reportPrivateUsage] results: list[tuple[tuple[str, str], _report.Count]], ): - test = "tests" if summary.total_tests != 1 else "test" table = Table( "Implementation", "Skips", "Errors", "Failures", title="Bowtie", - caption=f"{summary.total_tests} {test} ran\n", + caption=f"{pluralize(summary.total_tests, 'test')} ran\n", ) for (implementation, language), counts in results: table.add_row( @@ -252,12 +252,11 @@ def _validation_results_table( summary: _report._Summary, # type: ignore[reportPrivateUsage] results: Iterable[tuple[Any, Iterable[tuple[Any, dict[str, str]]]]], ): - test = "tests" if summary.total_tests != 1 else "test" table = Table( Column(header="Schema", vertical="middle"), "", title="Bowtie", - caption=f"{summary.total_tests} {test} ran", + caption=f"{pluralize(summary.total_tests, 'test')} ran", ) for schema, case_results in results: diff --git a/bowtie/_utils.py b/bowtie/_utils.py new file mode 100644 index 000000000..94578175e --- /dev/null +++ b/bowtie/_utils.py @@ -0,0 +1,22 @@ +""" +Small, generic helpers shared across Bowtie's modules. +""" +from __future__ import annotations + + +def pluralize(count: int, noun: str, plural: str | None = None) -> str: + """ + Combine a count with the singular or plural form of a noun. + + >>> pluralize(1, "test") + '1 test' + >>> pluralize(0, "test") + '0 tests' + >>> pluralize(2, "test") + '2 tests' + >>> pluralize(2, "story", plural="stories") + '2 stories' + """ + plural = plural or f"{noun}s" + word = noun if count == 1 else plural + return f"{count} {word}" diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 000000000..a0b57c338 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,25 @@ +from bowtie._utils import pluralize + + +def test_pluralize_singular(): + assert pluralize(1, "test") == "1 test" + + +def test_pluralize_plural(): + assert pluralize(2, "test") == "2 tests" + + +def test_pluralize_zero(): + assert pluralize(0, "test") == "0 tests" + + +def test_pluralize_negative(): + assert pluralize(-1, "test") == "-1 tests" + + +def test_pluralize_custom_plural(): + assert pluralize(2, "story", plural="stories") == "2 stories" + + +def test_pluralize_custom_plural_singular_unaffected(): + assert pluralize(1, "story", plural="stories") == "1 story" From fc72aaa270d8fd970321b35bbdc0de74e82bae05 Mon Sep 17 00:00:00 2001 From: Copilot Date: Thu, 6 Aug 2026 09:18:56 +0000 Subject: [PATCH 2/2] Fix import ordering in _cli.py --- bowtie/_cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bowtie/_cli.py b/bowtie/_cli.py index 21476f686..d7af5f7ee 100644 --- a/bowtie/_cli.py +++ b/bowtie/_cli.py @@ -28,7 +28,6 @@ from bowtie import _report from bowtie._commands import Test, TestCase -from bowtie._utils import pluralize from bowtie._core import ( DialectRunner, GotStderr, @@ -36,6 +35,7 @@ NoSuchImage, StartupFailed, ) +from bowtie._utils import pluralize from bowtie.exceptions import ( _ProtocolError, # type: ignore[reportPrivateUsage] )