From b06e8cefde3018276670697f173a50d714d5ce31 Mon Sep 17 00:00:00 2001 From: InspectorCaracal Date: Fri, 14 Oct 2022 11:59:42 -0600 Subject: [PATCH] fix edge cases, add tests --- evennia/utils/tests/test_utils.py | 6 ++++++ evennia/utils/utils.py | 20 +++++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/evennia/utils/tests/test_utils.py b/evennia/utils/tests/test_utils.py index b8d23d4829..40007547b7 100644 --- a/evennia/utils/tests/test_utils.py +++ b/evennia/utils/tests/test_utils.py @@ -66,8 +66,12 @@ class TestListToString(TestCase): [1,2,3] -> '1, 2, 3' with sep==';' and endsep==';': [1,2,3] -> '1; 2; 3' + with sep=='or': + [1,2,3] -> '1 or 2, and 3' with endsep=='and': [1,2,3] -> '1, 2 and 3' + with endsep=='; and': + [1,2,3] -> '1, 2; and 3' with endsep=='': [1,2,3] -> '1, 2 3' with addquote and endsep="and" @@ -80,6 +84,8 @@ class TestListToString(TestCase): self.assertEqual("1, 2 and 3", utils.list_to_string([1, 2, 3], endsep="and")) self.assertEqual("1, 2 3", utils.list_to_string([1, 2, 3], endsep="")) self.assertEqual("1; 2; 3", utils.list_to_string([1, 2, 3], sep=";", endsep=";")) + self.assertEqual("1 or 2, and 3", utils.list_to_string([1, 2, 3], sep="or")) + self.assertEqual("1, 2; and 3", utils.list_to_string([1, 2, 3], endsep="; and")) self.assertEqual( '"1", "2", "3"', utils.list_to_string([1, 2, 3], endsep=",", addquote=True) ) diff --git a/evennia/utils/utils.py b/evennia/utils/utils.py index b2a9748299..94d033142b 100644 --- a/evennia/utils/utils.py +++ b/evennia/utils/utils.py @@ -25,6 +25,7 @@ from collections import OrderedDict, defaultdict from inspect import getmembers, getmodule, getmro, ismodule, trace from os.path import join as osjoin from unicodedata import east_asian_width +from string import punctuation from django.apps import apps from django.conf import settings @@ -403,18 +404,23 @@ def iter_to_str(iterable, sep=",", endsep=", and", addquote=False): if not iterable: return "" len_iter = len(iterable) - + if addquote: iterable = tuple(f'"{val}"' for val in iterable) else: iterable = tuple(str(val) for val in iterable) - if endsep.startswith(sep): - # oxford comma alternative - endsep = endsep[1:] if len_iter < 3 else endsep - elif endsep: - # normal space-separated end separator - endsep = " " + str(endsep).strip() + if endsep: + if endsep.startswith(sep): + # oxford comma alternative + endsep = endsep[1:] if len_iter < 3 else endsep + elif endsep[0] not in punctuation: + # add a leading space if endsep is a word + endsep = " " + str(endsep).strip() + + # also add a leading space if separator is a word + if sep not in punctuation: + sep = " "+sep if len_iter == 1: return str(iterable[0])