blob: 51b2067ab9430436b145cf62cbcd9cd89c15f056 [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
5whitespace -- a string containing all characters considered whitespace
6lowercase -- a string containing all characters considered lowercase letters
7uppercase -- a string containing all characters considered uppercase letters
8letters -- a string containing all characters considered letters
9digits -- a string containing all characters considered decimal digits
10hexdigits -- a string containing all characters considered hexadecimal digits
11octdigits -- a string containing all characters considered octal digits
Fred Drakefd64c592000-09-18 19:38:11 +000012punctuation -- a string containing all characters considered punctuation
13printable -- a string containing all characters considered printable
Guido van Rossum20032041997-12-29 19:26:28 +000014
15"""
16
Guido van Rossumc6360141990-10-13 19:23:40 +000017# Some strings for ctype-style character classification
Guido van Rossum8e2ec561993-07-29 09:37:38 +000018whitespace = ' \t\n\r\v\f'
Guido van Rossumc6360141990-10-13 19:23:40 +000019lowercase = 'abcdefghijklmnopqrstuvwxyz'
20uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
21letters = lowercase + uppercase
Fred Drake960fdf92001-07-20 18:38:26 +000022ascii_lowercase = lowercase
23ascii_uppercase = uppercase
24ascii_letters = ascii_lowercase + ascii_uppercase
Guido van Rossumc6360141990-10-13 19:23:40 +000025digits = '0123456789'
26hexdigits = digits + 'abcdef' + 'ABCDEF'
27octdigits = '01234567'
Tim Peters495ad3c2001-01-15 01:36:40 +000028punctuation = """!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
Fred Drake6b2320f2000-09-18 16:46:17 +000029printable = digits + letters + punctuation + whitespace
Guido van Rossumc6360141990-10-13 19:23:40 +000030
31# Case conversion helpers
Martin v. Löwis5357c652002-10-14 20:03:40 +000032# Use str to convert Unicode literal in case of -U
Guido van Rossumc1f779c2007-07-03 08:25:58 +000033_idmap = str('').join(chr(c) for c in range(256))
Guido van Rossumc6360141990-10-13 19:23:40 +000034
Barry Warsaw8bee7612004-08-25 02:22:30 +000035# Functions which aren't available as string methods.
36
37# Capitalize the words in a string, e.g. " aBc dEf " -> "Abc Def".
Barry Warsaw8bee7612004-08-25 02:22:30 +000038def capwords(s, sep=None):
39 """capwords(s, [sep]) -> string
40
41 Split the argument into words using split, capitalize each
42 word using capitalize, and join the capitalized words using
43 join. Note that this replaces runs of whitespace characters by
44 a single space.
45
46 """
47 return (sep or ' ').join([x.capitalize() for x in s.split(sep)])
48
49
50# Construct a translation string
51_idmapL = None
52def maketrans(fromstr, tostr):
53 """maketrans(frm, to) -> string
54
55 Return a translation table (a string of 256 bytes long)
56 suitable for use in string.translate. The strings frm and to
57 must be of the same length.
58
59 """
60 if len(fromstr) != len(tostr):
61 raise ValueError, "maketrans arguments must have same length"
62 global _idmapL
63 if not _idmapL:
Guido van Rossumc1f779c2007-07-03 08:25:58 +000064 _idmapL = list(_idmap)
Barry Warsaw8bee7612004-08-25 02:22:30 +000065 L = _idmapL[:]
Guido van Rossumc1f779c2007-07-03 08:25:58 +000066 for i, c in enumerate(fromstr):
67 L[ord(c)] = tostr[i]
Barry Warsaw8bee7612004-08-25 02:22:30 +000068 return ''.join(L)
69
70
Raymond Hettinger57aef9c2004-12-07 07:55:07 +000071
Raymond Hettinger0d58e2b2004-08-26 00:21:13 +000072####################################################################
Barry Warsaw8bee7612004-08-25 02:22:30 +000073import re as _re
74
Barry Warsaw46b629c2004-09-13 14:35:04 +000075class _multimap:
76 """Helper class for combining multiple mappings.
77
78 Used by .{safe_,}substitute() to combine the mapping and keyword
79 arguments.
80 """
81 def __init__(self, primary, secondary):
82 self._primary = primary
83 self._secondary = secondary
84
85 def __getitem__(self, key):
86 try:
87 return self._primary[key]
88 except KeyError:
89 return self._secondary[key]
90
91
Barry Warsaw12827c12004-09-10 03:08:08 +000092class _TemplateMetaclass(type):
93 pattern = r"""
Raymond Hettinger55593c32004-09-26 18:56:44 +000094 %(delim)s(?:
95 (?P<escaped>%(delim)s) | # Escape sequence of two delimiters
96 (?P<named>%(id)s) | # delimiter and a Python identifier
97 {(?P<braced>%(id)s)} | # delimiter and a braced identifier
98 (?P<invalid>) # Other ill-formed delimiter exprs
99 )
Barry Warsaw12827c12004-09-10 03:08:08 +0000100 """
101
102 def __init__(cls, name, bases, dct):
103 super(_TemplateMetaclass, cls).__init__(name, bases, dct)
104 if 'pattern' in dct:
105 pattern = cls.pattern
106 else:
107 pattern = _TemplateMetaclass.pattern % {
Barry Warsaw17cb6002004-09-18 00:06:34 +0000108 'delim' : _re.escape(cls.delimiter),
Barry Warsaw12827c12004-09-10 03:08:08 +0000109 'id' : cls.idpattern,
110 }
111 cls.pattern = _re.compile(pattern, _re.IGNORECASE | _re.VERBOSE)
112
113
Guido van Rossum52cc1d82007-03-18 15:41:51 +0000114class Template(metaclass=_TemplateMetaclass):
Barry Warsaw8bee7612004-08-25 02:22:30 +0000115 """A string class for supporting $-substitutions."""
Barry Warsaw12827c12004-09-10 03:08:08 +0000116
Barry Warsaw17cb6002004-09-18 00:06:34 +0000117 delimiter = '$'
Barry Warsaw12827c12004-09-10 03:08:08 +0000118 idpattern = r'[_a-z][_a-z0-9]*'
119
120 def __init__(self, template):
121 self.template = template
Barry Warsaw8bee7612004-08-25 02:22:30 +0000122
123 # Search for $$, $identifier, ${identifier}, and any bare $'s
Barry Warsaw8bee7612004-08-25 02:22:30 +0000124
Barry Warsawb5c6b5b2004-09-13 20:52:50 +0000125 def _invalid(self, mo):
126 i = mo.start('invalid')
Barry Warsaw12827c12004-09-10 03:08:08 +0000127 lines = self.template[:i].splitlines(True)
128 if not lines:
129 colno = 1
130 lineno = 1
131 else:
132 colno = i - len(''.join(lines[:-1]))
133 lineno = len(lines)
134 raise ValueError('Invalid placeholder in string: line %d, col %d' %
135 (lineno, colno))
136
Barry Warsawb6234a92004-09-13 15:25:15 +0000137 def substitute(self, *args, **kws):
138 if len(args) > 1:
139 raise TypeError('Too many positional arguments')
140 if not args:
141 mapping = kws
Barry Warsaw46b629c2004-09-13 14:35:04 +0000142 elif kws:
Barry Warsawb6234a92004-09-13 15:25:15 +0000143 mapping = _multimap(kws, args[0])
144 else:
145 mapping = args[0]
Barry Warsaw46b629c2004-09-13 14:35:04 +0000146 # Helper function for .sub()
Barry Warsaw8bee7612004-08-25 02:22:30 +0000147 def convert(mo):
Barry Warsawb5c6b5b2004-09-13 20:52:50 +0000148 # Check the most common path first.
149 named = mo.group('named') or mo.group('braced')
150 if named is not None:
151 val = mapping[named]
152 # We use this idiom instead of str() because the latter will
153 # fail if val is a Unicode containing non-ASCII characters.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000154 return '%s' % (val,)
Raymond Hettinger0d58e2b2004-08-26 00:21:13 +0000155 if mo.group('escaped') is not None:
Barry Warsaw17cb6002004-09-18 00:06:34 +0000156 return self.delimiter
Barry Warsawb5c6b5b2004-09-13 20:52:50 +0000157 if mo.group('invalid') is not None:
158 self._invalid(mo)
Neal Norwitz6627a962004-10-17 16:27:18 +0000159 raise ValueError('Unrecognized named group in pattern',
160 self.pattern)
Barry Warsaw12827c12004-09-10 03:08:08 +0000161 return self.pattern.sub(convert, self.template)
Barry Warsaw8bee7612004-08-25 02:22:30 +0000162
Barry Warsawb6234a92004-09-13 15:25:15 +0000163 def safe_substitute(self, *args, **kws):
164 if len(args) > 1:
165 raise TypeError('Too many positional arguments')
166 if not args:
167 mapping = kws
Barry Warsaw46b629c2004-09-13 14:35:04 +0000168 elif kws:
Barry Warsawb6234a92004-09-13 15:25:15 +0000169 mapping = _multimap(kws, args[0])
170 else:
171 mapping = args[0]
Barry Warsaw46b629c2004-09-13 14:35:04 +0000172 # Helper function for .sub()
Barry Warsaw8bee7612004-08-25 02:22:30 +0000173 def convert(mo):
Raymond Hettinger0d58e2b2004-08-26 00:21:13 +0000174 named = mo.group('named')
Barry Warsaw8bee7612004-08-25 02:22:30 +0000175 if named is not None:
176 try:
Barry Warsaw12827c12004-09-10 03:08:08 +0000177 # We use this idiom instead of str() because the latter
178 # will fail if val is a Unicode containing non-ASCII
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000179 return '%s' % (mapping[named],)
Barry Warsaw8bee7612004-08-25 02:22:30 +0000180 except KeyError:
Barry Warsaw17cb6002004-09-18 00:06:34 +0000181 return self.delimiter + named
Raymond Hettinger0d58e2b2004-08-26 00:21:13 +0000182 braced = mo.group('braced')
Raymond Hettinger6d191112004-09-14 02:34:08 +0000183 if braced is not None:
184 try:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000185 return '%s' % (mapping[braced],)
Raymond Hettinger6d191112004-09-14 02:34:08 +0000186 except KeyError:
Barry Warsaw17cb6002004-09-18 00:06:34 +0000187 return self.delimiter + '{' + braced + '}'
Barry Warsawb5c6b5b2004-09-13 20:52:50 +0000188 if mo.group('escaped') is not None:
Barry Warsaw17cb6002004-09-18 00:06:34 +0000189 return self.delimiter
Barry Warsawb5c6b5b2004-09-13 20:52:50 +0000190 if mo.group('invalid') is not None:
Barry Warsaw8c72eae2004-11-01 03:52:43 +0000191 return self.delimiter
Neal Norwitz6627a962004-10-17 16:27:18 +0000192 raise ValueError('Unrecognized named group in pattern',
193 self.pattern)
Barry Warsaw12827c12004-09-10 03:08:08 +0000194 return self.pattern.sub(convert, self.template)