From a19a9794994f077090f1564ea71e7e9d9a8bb536 Mon Sep 17 00:00:00 2001 From: Jeremy Fincher Date: Fri, 28 Jan 2005 15:23:18 +0000 Subject: [PATCH] Robustified and improved utils.str.format a bit; added a simple test. --- src/conf.py | 5 ++++ src/utils/str.py | 63 +++++++++++++++++++++++++++++++++++++--------- test/test_utils.py | 8 ++++++ 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/conf.py b/src/conf.py index 0812b825d..2377d0138 100644 --- a/src/conf.py +++ b/src/conf.py @@ -281,6 +281,11 @@ registerChannelValue(supybot.reply.format, 'time', for human reading should be formatted. Refer to the Python documentation for the time module to see valid formatting characters for time formats.""")) +def timestamp(t): + t = time.localtime(t) + format = conf.get(supybot.reply.format.time, dynamic.channel) + return time.strftime(format, t) +utils.str.timestamp = timestamp registerGroup(supybot.reply.format.time, 'elapsed') registerChannelValue(supybot.reply.format.time.elapsed, 'short', diff --git a/src/utils/str.py b/src/utils/str.py index eafcece9b..1ba76db09 100644 --- a/src/utils/str.py +++ b/src/utils/str.py @@ -38,8 +38,9 @@ import textwrap import supybot.structures as structures -curry = new.instancemethod +from iter import all, any +curry = new.instancemethod chars = string.maketrans('', '') def rsplit(s, sep=None, maxsplit=-1): @@ -327,29 +328,67 @@ def toBool(s): else: raise ValueError, 'Invalid string for toBool: %s' % quoted(s) +# Replace me! +def timestamp(t): + return time.ctime(t) + +_formatRe = re.compile('%([bfhiLnpqst%])') def format(s, *args, **kwargs): - kwargs.setdefault('decimalSeparator', decimalSeparator) - kwargs.setdefault('thousandsSeparator', thousandsSeparator) + """w00t. + + %: literal %. + i: integer + s: string + f: float + b: form of the verb 'to be' (takes an int) + h: form of the verb 'to have' (takes an int) + L: commaAndify (takes a list of strings) + p: pluralize (takes a string) + q: quoted (takes a string) + n: nItems (takes a 2-tuple of (n, item) or a 3-tuple of (n, between, item)) + t: time, formated (takes an int) + """ args = list(args) - args.reverse() # For more efficiency popping. + args.reverse() # For more efficient popping. def sub(match): char = match.group(1) - if char == 's': # Plain string. + if char == 's': return str(args.pop()) - elif char == 'i': # Integer + elif char == 'i': # XXX Improve me! return str(args.pop()) - elif char == 'f': # Float + elif char == 'f': # XXX Improve me! return str(args.pop()) - elif char == 'b': # form of the verb 'to be' + elif char == 'b': return be(args.pop()) - elif char == 'h': # form of the verb 'to have' + elif char == 'h': return has(args.pop()) - elif char == 'L': # commaAndify the list. + elif char == 'L': return commaAndify(args.pop()) + elif char == 'p': + return pluralize(args.pop()) + elif char == 'q': + return quoted(args.pop()) + elif char == 'n': + t = args.pop() + if not isinstance(t, (tuple, list)): + raise ValueError, 'Invalid value for %%n in format: %s' % t + if len(t) == 2: + return nItems(*t) + elif len(t) == 3: + return nItems(t[0], t[2], between=t[1]) + else: + raise ValueError, 'Invalid value for %%n in format: %s' % t + elif char == 't': + return timestamp(args.pop()) + elif char == '%': + return '%' else: - assert False, 'Invalid char in sub (in format).' - return _formatRe.sub(sub, s) + raise ValueError, 'Invalid char in sub (in format).' + try: + return _formatRe.sub(sub, s) + except IndexError: + raise ValueError, 'Extra format chars in format spec: %r' % s # vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: diff --git a/test/test_utils.py b/test/test_utils.py index c38fed3d8..42bff17e3 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -417,5 +417,13 @@ class WebTest(SupyTestCase): url = 'http://slashdot.org/' self.failUnless(len(utils.web.getUrl(url, 1024)) == 1024) +class FormatTestCase(SupyTestCase): + def testNormal(self): + format = utils.str.format + self.assertEqual(format('I have %n of fruit: %L.', (3, 'kind'), + ['apples', 'oranges', 'watermelon']), + 'I have 3 kinds of fruit: ' + 'apples, oranges, and watermelon.') + # vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: