diff --git a/cloudbot/util/formatting.py b/cloudbot/util/formatting.py index 1357455de..32d67bbfa 100644 --- a/cloudbot/util/formatting.py +++ b/cloudbot/util/formatting.py @@ -47,6 +47,7 @@ import copy import html.entities import re +import warnings from html.parser import HTMLParser from cloudbot.util.colors import strip_irc @@ -247,11 +248,65 @@ def pluralize(num=0, text=''): Takes a number and a string, and pluralizes that string using the number and combines the results. :rtype: str """ - return "{:,} {}{}".format(num, text, "s"[num == 1:]) + warnings.warn( + "formatting.pluralize() is deprecated, please use one of the other formatting.pluralize_*() functions", + DeprecationWarning + ) + return pluralize_suffix(num, text) -# alternate form -pluralise = pluralize +def pluralise(num=0, text=''): + """ + Takes a number and a string, and pluralizes that string using the number and combines the results. + :rtype: str + """ + warnings.warn( + "formatting.pluralise() is deprecated, please use one of the other formatting.pluralise_*() functions", + DeprecationWarning + ) + return pluralise_suffix(num, text) + + +def pluralize_suffix(num=0, text='', suffix='s'): + """ + Takes a number and a string, and pluralizes that string using the number and combines the results. + :rtype: str + """ + return pluralize_select(num, text, text + suffix) + + +pluralise_suffix = pluralize_suffix + + +def pluralize_select(count, single, plural): + return "{:,} {}".format(count, single if count == 1 else plural) + + +pluralise_select = pluralize_select + + +def pluralize_auto(count, thing): + if thing.endswith(('s', 'ss', 'sh', 'ch', 'x', 'z')): + return pluralize_suffix(count, thing, 'es') + elif thing.endswith(('f', 'fe')): + return pluralize_select(count, thing, thing.rsplit('f', 1)[0] + 'ves') + elif thing.endswith('y') and thing[-2:-1].lower() not in "aeiou": + return pluralize_select(count, thing, thing[:-1] + 'ies') + elif thing.endswith('y') and thing[-2:-1].lower() in "aeiou": + return pluralize_suffix(count, thing) + elif thing.endswith('o'): + return pluralize_suffix(count, thing, 'es') + elif thing.endswith('us'): + return pluralize_select(count, thing, thing[:-2] + 'i') + elif thing.endswith('is'): + return pluralize_select(count, thing, thing[:-2] + 'es') + elif thing.endswith('on'): + return pluralize_select(count, thing, thing[:-2] + 'a') + else: + return pluralize_suffix(count, thing) + + +pluralise_auto = pluralize_auto def dict_format(args, formats): diff --git a/cloudbot/util/test/test_formatting.py b/cloudbot/util/test/test_formatting.py index c8faa90fa..daca8ab7e 100644 --- a/cloudbot/util/test/test_formatting.py +++ b/cloudbot/util/test/test_formatting.py @@ -1,5 +1,6 @@ -from cloudbot.util.formatting import munge, dict_format, pluralize, strip_colors, truncate, truncate_str, \ - strip_html, multi_replace, multiword_replace, truncate_words, smart_split, get_text_list, ireplace, chunk_str +from cloudbot.util.formatting import munge, dict_format, strip_colors, truncate, truncate_str, \ + strip_html, multi_replace, multiword_replace, truncate_words, smart_split, get_text_list, ireplace, chunk_str, \ + pluralize_suffix test_munge_input = "The quick brown fox jumps over the lazy dog" test_munge_count = 3 @@ -55,8 +56,8 @@ def test_dict_format(): def test_pluralize(): - assert pluralize(test_pluralize_num_a, test_pluralize_text) == test_pluralize_result_a - assert pluralize(test_pluralize_num_b, test_pluralize_text) == test_pluralize_result_b + assert pluralize_suffix(test_pluralize_num_a, test_pluralize_text) == test_pluralize_result_a + assert pluralize_suffix(test_pluralize_num_b, test_pluralize_text) == test_pluralize_result_b def test_strip_colors(): diff --git a/plugins/chain.py b/plugins/chain.py index 4167b68a9..0842d02af 100644 --- a/plugins/chain.py +++ b/plugins/chain.py @@ -7,7 +7,7 @@ from cloudbot import hook from cloudbot.event import CommandEvent from cloudbot.util import database -from cloudbot.util.formatting import chunk_str, pluralize +from cloudbot.util.formatting import chunk_str, pluralize_auto commands = Table( 'chain_commands', @@ -103,7 +103,7 @@ def chainallow(text, db, notice_doc, bot): res = db.execute(commands.delete().where(commands.c.hook == hook_name)) db.commit() load_cache(db) - return "Deleted {}.".format(pluralize(res.rowcount, "row")) + return "Deleted {}.".format(pluralize_auto(res.rowcount, "row")) else: return notice_doc() diff --git a/plugins/duckhunt.py b/plugins/duckhunt.py index 66a4fde37..62793dcf4 100644 --- a/plugins/duckhunt.py +++ b/plugins/duckhunt.py @@ -10,7 +10,7 @@ from cloudbot import hook from cloudbot.event import EventType from cloudbot.util import database -from cloudbot.util.formatting import pluralize +from cloudbot.util.formatting import pluralize_auto duck_tail = "・゜゜・。。・゜゜" duck = ["\_o< ", "\_O< ", "\_0< ", "\_\u00f6< ", "\_\u00f8< ", "\_\u00f3< "] @@ -392,7 +392,7 @@ def attack(event, nick, chan, message, db, conn, notice, attack): event.reply("An unknown error has occurred.") raise - message(msg.format(nick, shoot - deploy, pluralize(score, "duck"), chan)) + message(msg.format(nick, shoot - deploy, pluralize_auto(score, "duck"), chan)) set_ducktime(chan, conn.name) diff --git a/plugins/reddit.py b/plugins/reddit.py index c745c43d4..093679bed 100644 --- a/plugins/reddit.py +++ b/plugins/reddit.py @@ -49,8 +49,8 @@ def format_output(item, show_url=False): raw_time = datetime.fromtimestamp(int(item["created_utc"])) item["timesince"] = timeformat.time_since(raw_time, count=1, simple=True) - item["comments"] = formatting.pluralize(item["num_comments"], 'comment') - item["points"] = formatting.pluralize(item["score"], 'point') + item["comments"] = formatting.pluralize_auto(item["num_comments"], 'comment') + item["points"] = formatting.pluralize_auto(item["score"], 'point') if item["over_18"]: item["warning"] = " \x02NSFW\x02" diff --git a/plugins/reddit_info.py b/plugins/reddit_info.py index 40555921f..65062572f 100644 --- a/plugins/reddit_info.py +++ b/plugins/reddit_info.py @@ -6,7 +6,7 @@ from cloudbot import hook from cloudbot.util import colors -from cloudbot.util.formatting import pluralize +from cloudbot.util.formatting import pluralize_auto from cloudbot.util.pager import paginated_list search_pages = defaultdict(dict) @@ -115,7 +115,7 @@ def karma(text, reply): if age > 365: age //= 365 age_unit = "year" - out += "redditor for {}.".format(pluralize(age, age_unit)) + out += "redditor for {}.".format(pluralize_auto(age, age_unit)) return colors.parse(out) @@ -143,7 +143,7 @@ def cake_day(text, reply): if age > 365: age //= 365 age_unit = "year" - out += "they have been a redditor for {}.".format(pluralize(age, age_unit)) + out += "they have been a redditor for {}.".format(pluralize_auto(age, age_unit)) return out diff --git a/plugins/voat.py b/plugins/voat.py index 6d6b93b05..286ac7973 100644 --- a/plugins/voat.py +++ b/plugins/voat.py @@ -39,8 +39,8 @@ def format_output(item, show_url=False): raw_time = isodate.parse_date(item['Date']) item["timesince"] = timeformat.time_since(raw_time, count=1, simple=True) - item["comments"] = formatting.pluralize(item["CommentCount"], 'comment') - item["points"] = formatting.pluralize(item["Likes"], 'point') + item["comments"] = formatting.pluralize_auto(item["CommentCount"], 'comment') + item["points"] = formatting.pluralize_auto(item["Likes"], 'point') if item["Type"] == 2: item["warning"] = " \x02Link\x02" diff --git a/plugins/youtube.py b/plugins/youtube.py index a3815c1db..0c11ddb93 100644 --- a/plugins/youtube.py +++ b/plugins/youtube.py @@ -6,7 +6,7 @@ from cloudbot import hook from cloudbot.util import timeformat -from cloudbot.util.formatting import pluralize +from cloudbot.util.formatting import pluralize_auto youtube_re = re.compile(r'(?:youtube.*?(?:v=|/v/)|youtu\.be/|yooouuutuuube.*?id=)([-_a-zA-Z0-9]+)', re.I) @@ -47,8 +47,8 @@ def get_video_description(video_id): if total_votes != 0: # format - likes = pluralize(int(statistics['likeCount']), "like") - dislikes = pluralize(int(statistics['dislikeCount']), "dislike") + likes = pluralize_auto(int(statistics['likeCount']), "like") + dislikes = pluralize_auto(int(statistics['dislikeCount']), "dislike") percent = 100 * float(statistics['likeCount']) / total_votes out += ' - {}, {} (\x02{:.1f}\x02%)'.format(likes,