1# Copyright 2024 The Pigweed Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14"""Utilities for handling singular/plural forms in logs and tooling.""" 15 16 17def plural( 18 items_or_count, 19 singular: str, 20 count_format='', 21 these: bool = False, 22 number: bool = True, 23 are: bool = False, 24 exist: bool = False, 25) -> str: 26 """Returns the singular or plural form of a word based on a count. 27 28 Args: 29 items_or_count: Number of items or a collection of items 30 singular: Singular form of the name of the item 31 count_format: .format()-style specification for items_or_count 32 these: Prefix the string with "this" or "these", depending on number 33 number: Include the number in the return string (e.g., "3 things" vs. 34 "things") 35 are: Suffix the string with "is" or "are", depending on number 36 exist: Suffix the string with "exists" or "exist", depending on number 37 """ 38 39 try: 40 count = len(items_or_count) 41 except TypeError: 42 count = items_or_count 43 44 prefix = ('this ' if count == 1 else 'these ') if these else '' 45 num = f'{count:{count_format}} ' if number else '' 46 47 suffix = '' 48 if are and exist: 49 raise ValueError(f'cannot combine are ({are}) and exist ({exist})') 50 if are: 51 suffix = ' is' if count == 1 else ' are' 52 if exist: 53 suffix = ' exists' if count == 1 else ' exist' 54 55 if singular.endswith('y'): 56 result = f'{singular[:-1]}{"y" if count == 1 else "ies"}' 57 elif singular.endswith('s'): 58 result = f'{singular}{"" if count == 1 else "es"}' 59 else: 60 result = f'{singular}{"" if count == 1 else "s"}' 61 62 return f'{prefix}{num}{result}{suffix}' 63