blob: f3365c67fb4fb5f36aee60a9cf85494f31a0d2eb [file] [log] [blame]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001"""A collection of string constants.
Guido van Rossum20032041997-12-29 19:26:28 +00002
3Public module variables:
4
Georg Brandl50767402008-11-22 08:31:09 +00005whitespace -- a string containing all ASCII whitespace
6ascii_lowercase -- a string containing all ASCII lowercase letters
7ascii_uppercase -- a string containing all ASCII uppercase letters
8ascii_letters -- a string containing all ASCII letters
9digits -- a string containing all ASCII decimal digits
10hexdigits -- a string containing all ASCII hexadecimal digits
11octdigits -- a string containing all ASCII octal digits
12punctuation -- a string containing all ASCII punctuation characters
13printable -- a string containing all ASCII characters considered printable
Guido van Rossum20032041997-12-29 19:26:28 +000014
15"""
16
Georg Brandl66c221e2010-10-14 07:04:07 +000017import _string
18
Guido van Rossumc6360141990-10-13 19:23:40 +000019# Some strings for ctype-style character classification
Guido van Rossum8e2ec561993-07-29 09:37:38 +000020whitespace = ' \t\n\r\v\f'
Martin v. Löwis967f1e32007-08-14 09:23:10 +000021ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz'
22ascii_uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
Fred Drake960fdf92001-07-20 18:38:26 +000023ascii_letters = ascii_lowercase + ascii_uppercase
Guido van Rossumc6360141990-10-13 19:23:40 +000024digits = '0123456789'
25hexdigits = digits + 'abcdef' + 'ABCDEF'
26octdigits = '01234567'
Tim Peters495ad3c2001-01-15 01:36:40 +000027punctuation = """!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
Martin v. Löwis967f1e32007-08-14 09:23:10 +000028printable = digits + ascii_letters + punctuation + whitespace
Guido van Rossumc6360141990-10-13 19:23:40 +000029
Barry Warsaw8bee7612004-08-25 02:22:30 +000030# Functions which aren't available as string methods.
31
32# Capitalize the words in a string, e.g. " aBc dEf " -> "Abc Def".
Barry Warsaw8bee7612004-08-25 02:22:30 +000033def capwords(s, sep=None):
Ezio Melottia40bdda2009-09-26 12:33:22 +000034 """capwords(s [,sep]) -> string
Barry Warsaw8bee7612004-08-25 02:22:30 +000035
36 Split the argument into words using split, capitalize each
37 word using capitalize, and join the capitalized words using
Ezio Melottia40bdda2009-09-26 12:33:22 +000038 join. If the optional second argument sep is absent or None,
39 runs of whitespace characters are replaced by a single space
40 and leading and trailing whitespace are removed, otherwise
41 sep is used to split and join the words.
Barry Warsaw8bee7612004-08-25 02:22:30 +000042
43 """
Ezio Melottia40bdda2009-09-26 12:33:22 +000044 return (sep or ' ').join(x.capitalize() for x in s.split(sep))
Barry Warsaw8bee7612004-08-25 02:22:30 +000045
46
Raymond Hettinger0d58e2b2004-08-26 00:21:13 +000047####################################################################
Barry Warsaw8bee7612004-08-25 02:22:30 +000048import re as _re
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000049from collections import ChainMap
Barry Warsaw46b629c2004-09-13 14:35:04 +000050
Barry Warsaw12827c12004-09-10 03:08:08 +000051class _TemplateMetaclass(type):
52 pattern = r"""
Raymond Hettinger55593c32004-09-26 18:56:44 +000053 %(delim)s(?:
54 (?P<escaped>%(delim)s) | # Escape sequence of two delimiters
55 (?P<named>%(id)s) | # delimiter and a Python identifier
56 {(?P<braced>%(id)s)} | # delimiter and a braced identifier
57 (?P<invalid>) # Other ill-formed delimiter exprs
58 )
Barry Warsaw12827c12004-09-10 03:08:08 +000059 """
60
61 def __init__(cls, name, bases, dct):
62 super(_TemplateMetaclass, cls).__init__(name, bases, dct)
63 if 'pattern' in dct:
64 pattern = cls.pattern
65 else:
66 pattern = _TemplateMetaclass.pattern % {
Barry Warsaw17cb6002004-09-18 00:06:34 +000067 'delim' : _re.escape(cls.delimiter),
Barry Warsaw12827c12004-09-10 03:08:08 +000068 'id' : cls.idpattern,
69 }
Georg Brandl056cb932010-07-29 17:16:10 +000070 cls.pattern = _re.compile(pattern, cls.flags | _re.VERBOSE)
Barry Warsaw12827c12004-09-10 03:08:08 +000071
72
Guido van Rossum52cc1d82007-03-18 15:41:51 +000073class Template(metaclass=_TemplateMetaclass):
Barry Warsaw8bee7612004-08-25 02:22:30 +000074 """A string class for supporting $-substitutions."""
Barry Warsaw12827c12004-09-10 03:08:08 +000075
Barry Warsaw17cb6002004-09-18 00:06:34 +000076 delimiter = '$'
Barry Warsaw12827c12004-09-10 03:08:08 +000077 idpattern = r'[_a-z][_a-z0-9]*'
Georg Brandl056cb932010-07-29 17:16:10 +000078 flags = _re.IGNORECASE
Barry Warsaw12827c12004-09-10 03:08:08 +000079
80 def __init__(self, template):
81 self.template = template
Barry Warsaw8bee7612004-08-25 02:22:30 +000082
83 # Search for $$, $identifier, ${identifier}, and any bare $'s
Barry Warsaw8bee7612004-08-25 02:22:30 +000084
Barry Warsawb5c6b5b2004-09-13 20:52:50 +000085 def _invalid(self, mo):
86 i = mo.start('invalid')
Ezio Melottid8b509b2011-09-28 17:37:55 +030087 lines = self.template[:i].splitlines(keepends=True)
Barry Warsaw12827c12004-09-10 03:08:08 +000088 if not lines:
89 colno = 1
90 lineno = 1
91 else:
92 colno = i - len(''.join(lines[:-1]))
93 lineno = len(lines)
94 raise ValueError('Invalid placeholder in string: line %d, col %d' %
95 (lineno, colno))
96
Serhiy Storchaka8ffe9172015-03-24 22:28:43 +020097 def substitute(*args, **kws):
98 if not args:
99 raise TypeError("descriptor 'substitute' of 'Template' object "
100 "needs an argument")
101 self, *args = args # allow the "self" keyword be passed
Barry Warsawb6234a92004-09-13 15:25:15 +0000102 if len(args) > 1:
103 raise TypeError('Too many positional arguments')
104 if not args:
105 mapping = kws
Barry Warsaw46b629c2004-09-13 14:35:04 +0000106 elif kws:
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +0000107 mapping = ChainMap(kws, args[0])
Barry Warsawb6234a92004-09-13 15:25:15 +0000108 else:
109 mapping = args[0]
Barry Warsaw46b629c2004-09-13 14:35:04 +0000110 # Helper function for .sub()
Barry Warsaw8bee7612004-08-25 02:22:30 +0000111 def convert(mo):
Barry Warsawb5c6b5b2004-09-13 20:52:50 +0000112 # Check the most common path first.
113 named = mo.group('named') or mo.group('braced')
114 if named is not None:
115 val = mapping[named]
116 # We use this idiom instead of str() because the latter will
117 # fail if val is a Unicode containing non-ASCII characters.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000118 return '%s' % (val,)
Raymond Hettinger0d58e2b2004-08-26 00:21:13 +0000119 if mo.group('escaped') is not None:
Barry Warsaw17cb6002004-09-18 00:06:34 +0000120 return self.delimiter
Barry Warsawb5c6b5b2004-09-13 20:52:50 +0000121 if mo.group('invalid') is not None:
122 self._invalid(mo)
Neal Norwitz6627a962004-10-17 16:27:18 +0000123 raise ValueError('Unrecognized named group in pattern',
124 self.pattern)
Barry Warsaw12827c12004-09-10 03:08:08 +0000125 return self.pattern.sub(convert, self.template)
Barry Warsaw8bee7612004-08-25 02:22:30 +0000126
Serhiy Storchaka8ffe9172015-03-24 22:28:43 +0200127 def safe_substitute(*args, **kws):
128 if not args:
129 raise TypeError("descriptor 'safe_substitute' of 'Template' object "
130 "needs an argument")
131 self, *args = args # allow the "self" keyword be passed
Barry Warsawb6234a92004-09-13 15:25:15 +0000132 if len(args) > 1:
133 raise TypeError('Too many positional arguments')
134 if not args:
135 mapping = kws
Barry Warsaw46b629c2004-09-13 14:35:04 +0000136 elif kws:
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +0000137 mapping = ChainMap(kws, args[0])
Barry Warsawb6234a92004-09-13 15:25:15 +0000138 else:
139 mapping = args[0]
Barry Warsaw46b629c2004-09-13 14:35:04 +0000140 # Helper function for .sub()
Barry Warsaw8bee7612004-08-25 02:22:30 +0000141 def convert(mo):
Florent Xiclunaeb19dce2010-09-18 23:34:07 +0000142 named = mo.group('named') or mo.group('braced')
Barry Warsaw8bee7612004-08-25 02:22:30 +0000143 if named is not None:
144 try:
Barry Warsaw12827c12004-09-10 03:08:08 +0000145 # We use this idiom instead of str() because the latter
146 # will fail if val is a Unicode containing non-ASCII
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000147 return '%s' % (mapping[named],)
Barry Warsaw8bee7612004-08-25 02:22:30 +0000148 except KeyError:
Florent Xiclunaeb19dce2010-09-18 23:34:07 +0000149 return mo.group()
Barry Warsawb5c6b5b2004-09-13 20:52:50 +0000150 if mo.group('escaped') is not None:
Barry Warsaw17cb6002004-09-18 00:06:34 +0000151 return self.delimiter
Barry Warsawb5c6b5b2004-09-13 20:52:50 +0000152 if mo.group('invalid') is not None:
Florent Xiclunaeb19dce2010-09-18 23:34:07 +0000153 return mo.group()
Neal Norwitz6627a962004-10-17 16:27:18 +0000154 raise ValueError('Unrecognized named group in pattern',
155 self.pattern)
Barry Warsaw12827c12004-09-10 03:08:08 +0000156 return self.pattern.sub(convert, self.template)
Eric Smith8c663262007-08-25 02:26:07 +0000157
158
159
160########################################################################
161# the Formatter class
162# see PEP 3101 for details and purpose of this class
163
Benjamin Petersonf608c612008-11-16 18:33:53 +0000164# The hard parts are reused from the C implementation. They're exposed as "_"
Florent Xicluna7b2a7712010-09-06 20:27:55 +0000165# prefixed methods of str.
Eric Smith8c663262007-08-25 02:26:07 +0000166
Georg Brandl66c221e2010-10-14 07:04:07 +0000167# The overall parser is implemented in _string.formatter_parser.
168# The field name parser is implemented in _string.formatter_field_name_split
Eric Smith8c663262007-08-25 02:26:07 +0000169
170class Formatter:
Serhiy Storchaka8ffe9172015-03-24 22:28:43 +0200171 def format(*args, **kwargs):
172 if not args:
173 raise TypeError("descriptor 'format' of 'Formatter' object "
174 "needs an argument")
175 self, *args = args # allow the "self" keyword be passed
176 try:
177 format_string, *args = args # allow the "format_string" keyword be passed
178 except ValueError:
179 if 'format_string' in kwargs:
180 format_string = kwargs.pop('format_string')
Serhiy Storchakab876df42015-03-24 22:30:46 +0200181 import warnings
182 warnings.warn("Passing 'format_string' as keyword argument is "
183 "deprecated", DeprecationWarning, stacklevel=2)
Serhiy Storchaka8ffe9172015-03-24 22:28:43 +0200184 else:
185 raise TypeError("format() missing 1 required positional "
186 "argument: 'format_string'") from None
Eric Smith8c663262007-08-25 02:26:07 +0000187 return self.vformat(format_string, args, kwargs)
188
189 def vformat(self, format_string, args, kwargs):
Eric Smith3bcc42a2007-08-31 02:26:31 +0000190 used_args = set()
Eric Smith11529192007-09-04 23:04:22 +0000191 result = self._vformat(format_string, args, kwargs, used_args, 2)
192 self.check_unused_args(used_args, args, kwargs)
193 return result
194
Eric V. Smith7ce90742014-04-14 16:43:50 -0400195 def _vformat(self, format_string, args, kwargs, used_args, recursion_depth,
196 auto_arg_index=0):
Eric Smith11529192007-09-04 23:04:22 +0000197 if recursion_depth < 0:
198 raise ValueError('Max string recursion exceeded')
Eric Smith8c663262007-08-25 02:26:07 +0000199 result = []
Eric Smith9e7c8da2007-08-28 11:15:20 +0000200 for literal_text, field_name, format_spec, conversion in \
201 self.parse(format_string):
Eric Smith625cbf22007-08-29 03:22:59 +0000202
203 # output the literal text
204 if literal_text:
205 result.append(literal_text)
206
207 # if there's a field, output it
208 if field_name is not None:
Eric Smith9e7c8da2007-08-28 11:15:20 +0000209 # this is some markup, find the object and do
210 # the formatting
211
Eric V. Smith7ce90742014-04-14 16:43:50 -0400212 # handle arg indexing when empty field_names are given.
213 if field_name == '':
214 if auto_arg_index is False:
215 raise ValueError('cannot switch from manual field '
216 'specification to automatic field '
217 'numbering')
218 field_name = str(auto_arg_index)
219 auto_arg_index += 1
220 elif field_name.isdigit():
221 if auto_arg_index:
222 raise ValueError('cannot switch from manual field '
223 'specification to automatic field '
224 'numbering')
225 # disable auto arg incrementing, if it gets
226 # used later on, then an exception will be raised
227 auto_arg_index = False
228
Eric Smith7ade6482007-08-26 22:27:13 +0000229 # given the field_name, find the object it references
Eric Smith3bcc42a2007-08-31 02:26:31 +0000230 # and the argument it came from
Eric Smith9d4ba392007-09-02 15:33:26 +0000231 obj, arg_used = self.get_field(field_name, args, kwargs)
Eric Smith3bcc42a2007-08-31 02:26:31 +0000232 used_args.add(arg_used)
Eric Smith7ade6482007-08-26 22:27:13 +0000233
234 # do any conversion on the resulting object
Eric Smith9e7c8da2007-08-28 11:15:20 +0000235 obj = self.convert_field(obj, conversion)
Eric Smith7ade6482007-08-26 22:27:13 +0000236
Eric Smith11529192007-09-04 23:04:22 +0000237 # expand the format spec, if needed
238 format_spec = self._vformat(format_spec, args, kwargs,
Eric V. Smith7ce90742014-04-14 16:43:50 -0400239 used_args, recursion_depth-1,
240 auto_arg_index=auto_arg_index)
Eric Smith11529192007-09-04 23:04:22 +0000241
Eric Smith7ade6482007-08-26 22:27:13 +0000242 # format the object and append to the result
243 result.append(self.format_field(obj, format_spec))
Eric Smith625cbf22007-08-29 03:22:59 +0000244
Eric Smith8c663262007-08-25 02:26:07 +0000245 return ''.join(result)
246
Eric Smith9e7c8da2007-08-28 11:15:20 +0000247
Eric Smith8c663262007-08-25 02:26:07 +0000248 def get_value(self, key, args, kwargs):
Eric Smith7ade6482007-08-26 22:27:13 +0000249 if isinstance(key, int):
250 return args[key]
251 else:
252 return kwargs[key]
Eric Smith8c663262007-08-25 02:26:07 +0000253
Eric Smith9e7c8da2007-08-28 11:15:20 +0000254
Eric Smith8c663262007-08-25 02:26:07 +0000255 def check_unused_args(self, used_args, args, kwargs):
256 pass
257
Eric Smith9e7c8da2007-08-28 11:15:20 +0000258
Eric Smith8c663262007-08-25 02:26:07 +0000259 def format_field(self, value, format_spec):
Eric Smith7ade6482007-08-26 22:27:13 +0000260 return format(value, format_spec)
Eric Smith9e7c8da2007-08-28 11:15:20 +0000261
262
263 def convert_field(self, value, conversion):
264 # do any conversion on the resulting object
R David Murraye56bf972012-08-19 17:26:34 -0400265 if conversion is None:
266 return value
Eric Smith9e7c8da2007-08-28 11:15:20 +0000267 elif conversion == 's':
268 return str(value)
R David Murraye56bf972012-08-19 17:26:34 -0400269 elif conversion == 'r':
270 return repr(value)
271 elif conversion == 'a':
272 return ascii(value)
Florent Xicluna7b2a7712010-09-06 20:27:55 +0000273 raise ValueError("Unknown conversion specifier {0!s}".format(conversion))
Eric Smith9e7c8da2007-08-28 11:15:20 +0000274
275
276 # returns an iterable that contains tuples of the form:
277 # (literal_text, field_name, format_spec, conversion)
Eric Smith625cbf22007-08-29 03:22:59 +0000278 # literal_text can be zero length
279 # field_name can be None, in which case there's no
280 # object to format and output
281 # if field_name is not None, it is looked up, formatted
282 # with format_spec and conversion and then used
Eric Smith9e7c8da2007-08-28 11:15:20 +0000283 def parse(self, format_string):
Georg Brandl66c221e2010-10-14 07:04:07 +0000284 return _string.formatter_parser(format_string)
Eric Smith9e7c8da2007-08-28 11:15:20 +0000285
286
287 # given a field_name, find the object it references.
288 # field_name: the field being looked up, e.g. "0.name"
289 # or "lookup[3]"
290 # used_args: a set of which args have been used
291 # args, kwargs: as passed in to vformat
Eric Smith9d4ba392007-09-02 15:33:26 +0000292 def get_field(self, field_name, args, kwargs):
Georg Brandl66c221e2010-10-14 07:04:07 +0000293 first, rest = _string.formatter_field_name_split(field_name)
Eric Smith9e7c8da2007-08-28 11:15:20 +0000294
Eric Smith9e7c8da2007-08-28 11:15:20 +0000295 obj = self.get_value(first, args, kwargs)
296
297 # loop through the rest of the field_name, doing
298 # getattr or getitem as needed
299 for is_attr, i in rest:
300 if is_attr:
301 obj = getattr(obj, i)
302 else:
303 obj = obj[i]
304
Eric Smith3bcc42a2007-08-31 02:26:31 +0000305 return obj, first