| 139 | return self.pattern.sub(convert, self.template) |
| 140 | |
| 141 | def safe_substitute(self, mapping=_sentinel_dict, /, **kws): |
| 142 | if mapping is _sentinel_dict: |
| 143 | mapping = kws |
| 144 | elif kws: |
| 145 | from collections import ChainMap |
| 146 | mapping = ChainMap(kws, mapping) |
| 147 | # Helper function for .sub() |
| 148 | def convert(mo): |
| 149 | named = mo.group('named') or mo.group('braced') |
| 150 | if named is not None: |
| 151 | try: |
| 152 | return str(mapping[named]) |
| 153 | except KeyError: |
| 154 | return mo.group() |
| 155 | if mo.group('escaped') is not None: |
| 156 | return self.delimiter |
| 157 | if mo.group('invalid') is not None: |
| 158 | return mo.group() |
| 159 | raise ValueError('Unrecognized named group in pattern', |
| 160 | self.pattern) |
| 161 | return self.pattern.sub(convert, self.template) |
| 162 | |
| 163 | def is_valid(self): |
| 164 | for mo in self.pattern.finditer(self.template): |