4 # string_template_compat.py: string.Template for Python <= 2.4
5 # =====================================================
7 # This is just an excerpt of the standard string module to provide backwards
13 """Helper class for combining multiple mappings.
15 Used by .{safe_,}substitute() to combine the mapping and keyword
18 def __init__(self
, primary
, secondary
):
19 self
._primary
= primary
20 self
._secondary
= secondary
22 def __getitem__(self
, key
):
24 return self
._primary
[key
]
26 return self
._secondary
[key
]
29 class _TemplateMetaclass(type):
32 (?P<escaped>%(delim)s) | # Escape sequence of two delimiters
33 (?P<named>%(id)s) | # delimiter and a Python identifier
34 {(?P<braced>%(id)s)} | # delimiter and a braced identifier
35 (?P<invalid>) # Other ill-formed delimiter exprs
39 def __init__(cls
, name
, bases
, dct
):
40 super(_TemplateMetaclass
, cls
).__init
__(name
, bases
, dct
)
44 pattern
= _TemplateMetaclass
.pattern
% {
45 'delim' : _re
.escape(cls
.delimiter
),
48 cls
.pattern
= _re
.compile(pattern
, _re
.IGNORECASE | _re
.VERBOSE
)
52 """A string class for supporting $-substitutions."""
53 __metaclass__
= _TemplateMetaclass
56 idpattern
= r
'[_a-z][_a-z0-9]*'
58 def __init__(self
, template
):
59 self
.template
= template
61 # Search for $$, $identifier, ${identifier}, and any bare $'s
63 def _invalid(self
, mo
):
64 i
= mo
.start('invalid')
65 lines
= self
.template
[:i
].splitlines(True)
70 colno
= i
- len(''.join(lines
[:-1]))
72 raise ValueError('Invalid placeholder in string: line %d, col %d' %
75 def substitute(self
, *args
, **kws
):
77 raise TypeError('Too many positional arguments')
81 mapping
= _multimap(kws
, args
[0])
84 # Helper function for .sub()
86 # Check the most common path first.
87 named
= mo
.group('named') or mo
.group('braced')
90 # We use this idiom instead of str() because the latter will
91 # fail if val is a Unicode containing non-ASCII characters.
93 if mo
.group('escaped') is not None:
95 if mo
.group('invalid') is not None:
97 raise ValueError('Unrecognized named group in pattern',
99 return self
.pattern
.sub(convert
, self
.template
)
101 def safe_substitute(self
, *args
, **kws
):
103 raise TypeError('Too many positional arguments')
107 mapping
= _multimap(kws
, args
[0])
110 # Helper function for .sub()
112 named
= mo
.group('named')
113 if named
is not None:
115 # We use this idiom instead of str() because the latter
116 # will fail if val is a Unicode containing non-ASCII
117 return '%s' % (mapping
[named
],)
119 return self
.delimiter
+ named
120 braced
= mo
.group('braced')
121 if braced
is not None:
123 return '%s' % (mapping
[braced
],)
125 return self
.delimiter
+ '{' + braced
+ '}'
126 if mo
.group('escaped') is not None:
127 return self
.delimiter
128 if mo
.group('invalid') is not None:
129 return self
.delimiter
130 raise ValueError('Unrecognized named group in pattern',
132 return self
.pattern
.sub(convert
, self
.template
)