Skip to content

Commit b9f13b2

Browse files
Abel Milashclaude
andcommitted
Revert pluralization to simple + "s" default
Removes _pluralize helper and TestPluralize; DisplayCollectionName falls back to display_name + "s" when not provided explicitly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 882c217 commit b9f13b2

4 files changed

Lines changed: 8 additions & 86 deletions

File tree

src/PowerPlatform/Dataverse/data/_odata.py

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -978,28 +978,6 @@ def _label(self, text: str) -> Dict[str, Any]:
978978
],
979979
}
980980

981-
@staticmethod
982-
def _pluralize(word: str) -> str:
983-
"""Return a simple English plural for *word*.
984-
985-
Covers the most common patterns without an external dependency:
986-
- consonant + y → -ies (Company → Companies, Category → Categories)
987-
- s / x / z → -es (Class → Classes, Box → Boxes)
988-
- ch / sh → -es (Match → Matches, Dish → Dishes)
989-
- everything else → -s (Product → Products, Account → Accounts)
990-
991-
For irregular plurals (e.g. Person → People) callers should supply
992-
``display_collection_name`` explicitly.
993-
"""
994-
if not word:
995-
return word
996-
suffix = word.lower()
997-
if suffix.endswith("y") and len(suffix) > 1 and suffix[-2] not in "aeiou":
998-
return word[:-1] + "ies"
999-
if suffix.endswith(("ch", "sh", "s", "x", "z")):
1000-
return word + "es"
1001-
return word + "s"
1002-
1003981
def _to_pascal(self, name: str) -> str:
1004982
parts = re.split(r"[^A-Za-z0-9]+", name)
1005983
return "".join(p[:1].upper() + p[1:] for p in parts if p)
@@ -1042,7 +1020,7 @@ def _create_entity(
10421020
"SchemaName": table_schema_name,
10431021
"DisplayName": self._label(display_name),
10441022
"DisplayCollectionName": self._label(
1045-
display_collection_name if display_collection_name is not None else self._pluralize(display_name)
1023+
display_collection_name if display_collection_name is not None else display_name + "s"
10461024
),
10471025
"Description": self._label(description if description is not None else f"Custom entity for {display_name}"),
10481026
"OwnershipType": "UserOwned",
@@ -1678,7 +1656,7 @@ def _create_table(
16781656
:type primary_column_schema_name: ``str`` | ``None``
16791657
:param display_name: Human-readable display name for the table. Defaults to ``table_schema_name``.
16801658
:type display_name: ``str`` | ``None``
1681-
:param display_collection_name: Plural display name shown in navigation. Defaults to a simple English plural of ``display_name``.
1659+
:param display_collection_name: Plural display name shown in navigation. Defaults to ``display_name + "s"``.
16821660
:type display_collection_name: ``str`` | ``None``
16831661
:param description: Description for the table. Defaults to a generated string.
16841662
:type description: ``str`` | ``None``
@@ -2179,7 +2157,7 @@ def _build_create_entity(
21792157
"SchemaName": table,
21802158
"DisplayName": self._label(label),
21812159
"DisplayCollectionName": self._label(
2182-
display_collection_name if display_collection_name is not None else self._pluralize(label)
2160+
display_collection_name if display_collection_name is not None else label + "s"
21832161
),
21842162
"Description": self._label(description if description is not None else f"Custom entity for {label}"),
21852163
"OwnershipType": "UserOwned",

src/PowerPlatform/Dataverse/operations/batch.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ def create(
382382
When omitted, defaults to the table schema name.
383383
:type display_name: str or None
384384
:param display_collection_name: Plural display name shown in navigation (e.g. ``"Products"``).
385-
When omitted, a simple English plural of ``display_name`` is used.
385+
When omitted, defaults to ``display_name + "s"``.
386386
:type display_collection_name: str or None
387387
:param description: Description for the table. When omitted, a default description is generated.
388388
:type description: str or None

src/PowerPlatform/Dataverse/operations/tables.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,7 @@ def create(
103103
(e.g. ``"Product"``). When omitted, defaults to the table schema name.
104104
:type display_name: :class:`str` or None
105105
:param display_collection_name: Plural display name shown in navigation
106-
(e.g. ``"Products"``). When omitted, a simple English plural of
107-
``display_name`` is used (e.g. ``"Company"`` → ``"Companies"``).
106+
(e.g. ``"Products"``). When omitted, defaults to ``display_name + "s"``.
108107
:type display_collection_name: :class:`str` or None
109108
:param description: Description for the table. When omitted, a default
110109
description is generated.

tests/unit/data/test_odata_internal.py

Lines changed: 3 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -596,61 +596,6 @@ def test_to_pascal_basic(self):
596596
self.assertEqual(client._to_pascal("single"), "Single")
597597

598598

599-
class TestPluralize(unittest.TestCase):
600-
"""Unit tests for _ODataClient._pluralize."""
601-
602-
def _p(self, word: str) -> str:
603-
return _ODataClient._pluralize(word)
604-
605-
# --- regular -s words ---
606-
def test_regular_word(self):
607-
self.assertEqual(self._p("Product"), "Products")
608-
609-
def test_regular_word_account(self):
610-
self.assertEqual(self._p("Account"), "Accounts")
611-
612-
# --- consonant + y → -ies ---
613-
def test_consonant_y_company(self):
614-
self.assertEqual(self._p("Company"), "Companies")
615-
616-
def test_consonant_y_category(self):
617-
self.assertEqual(self._p("Category"), "Categories")
618-
619-
def test_consonant_y_policy(self):
620-
self.assertEqual(self._p("Policy"), "Policies")
621-
622-
# --- vowel + y → -ys (not -ies) ---
623-
def test_vowel_y_key(self):
624-
self.assertEqual(self._p("Key"), "Keys")
625-
626-
def test_vowel_y_day(self):
627-
self.assertEqual(self._p("Day"), "Days")
628-
629-
# --- -s / -x / -z / -ch / -sh → -es ---
630-
def test_s_ending(self):
631-
self.assertEqual(self._p("Class"), "Classes")
632-
633-
def test_x_ending(self):
634-
self.assertEqual(self._p("Box"), "Boxes")
635-
636-
def test_ch_ending(self):
637-
self.assertEqual(self._p("Match"), "Matches")
638-
639-
def test_sh_ending(self):
640-
self.assertEqual(self._p("Dish"), "Dishes")
641-
642-
# --- multi-word display names ---
643-
def test_multi_word(self):
644-
self.assertEqual(self._p("Health Inspection"), "Health Inspections")
645-
646-
def test_multi_word_y(self):
647-
self.assertEqual(self._p("Budget Category"), "Budget Categories")
648-
649-
# --- edge cases ---
650-
def test_empty_string(self):
651-
self.assertEqual(self._p(""), "")
652-
653-
654599
class TestRequestErrorParsing(unittest.TestCase):
655600
"""Unit tests for _ODataClient._request error response handling."""
656601

@@ -2963,7 +2908,7 @@ def test_display_name_defaults_to_schema_name(self):
29632908
self.assertEqual(body["DisplayName"]["LocalizedLabels"][0]["Label"], "new_TestTable")
29642909

29652910
def test_display_collection_name_derived_from_display_name(self):
2966-
"""_build_create_entity uses _pluralize(display_name) for DisplayCollectionName."""
2911+
"""_build_create_entity appends 's' to display_name for DisplayCollectionName."""
29672912
body = self._body(display_name="Test Table")
29682913
self.assertEqual(body["DisplayCollectionName"]["LocalizedLabels"][0]["Label"], "Test Tables")
29692914

@@ -3075,8 +3020,8 @@ def test_display_collection_name_explicit(self):
30753020
body = json.loads(self.od._build_create_entity("new_TestTable", {}, display_collection_name="Test Tables").body)
30763021
self.assertEqual(body["DisplayCollectionName"]["LocalizedLabels"][0]["Label"], "Test Tables")
30773022

3078-
def test_display_collection_name_defaults_to_pluralized_label(self):
3079-
"""_build_create_entity uses _pluralize(label) when display_collection_name is omitted."""
3023+
def test_display_collection_name_defaults_to_display_name_plus_s(self):
3024+
"""_build_create_entity appends 's' to the label when display_collection_name is omitted."""
30803025
body = self._body(display_name="Widget")
30813026
self.assertEqual(body["DisplayCollectionName"]["LocalizedLabels"][0]["Label"], "Widgets")
30823027

0 commit comments

Comments
 (0)