My first thought was that this is a job for string.Template, which has always struck me as subclassing-friendly. Took about a half hour of wrangling the regex to get here:
from string import Template, _sentinel_dict class TemplateWithDefaults(Template): braceidpattern = r'([_a-z][_a-z0-9]*))((:(?P<default>([^}]*)))?' def substitute(self, mapping=_sentinel_dict, /, **kws): if mapping is _sentinel_dict: mapping = kws elif kws: mapping = _ChainMap(kws, mapping) def convert(mo): named = mo.group('named') or mo.group('braced') if named is not None: try: return str(mapping[named]) except KeyError: default = mo.group('default') if not default: raise return default if mo.group('escaped') is not None: return self.delimiter if mo.group('invalid') is not None: self._invalid(mo) raise ValueError('Unrecognized named group in pattern', self.pattern) return self.pattern.sub(convert, self.template) template = TemplateWithDefaults('Where ${prep:was} my default? ${here}.') options = {'prep':'is', 'here':'Nowhere'} print(template.substitute(options)) print(template.substitute(here='Here')) print(template.substitute()) # Should fail with key error on 'here' On Fri, Apr 1, 2022 at 8:13 AM Brian McCall <brian.patrick.mcc...@gmail.com> wrote: > Oh, I didn't even know about `format_map`! Or `__format__` for that > matter. This makes everything much easier. For my purposes, I don't even > need to use `__format__` since I am not using format strings. > > In a show of appreciation, here is a URL to a GIF of James Corden bowing: > https://media.giphy.com/media/l2R0eYcNq9rJUsVAA/giphy.gif > > ``` > class Options(UserDict): > def __getitem__(self, key): > if key in self: > return super().__getitem__(key) > key, *default = key.split('?') > if key in self: > return super().__getitem__(key) > return ''.join(default) > > options = {'baud': 19200} > result = 'BAUD: {baud?9600}'.format_map(Options(options)) > print(result) > > options = {} > result = 'BAUD: {baud?9600}'.format_map(Options(options)) > print(result) > > ``` > _______________________________________________ > Python-ideas mailing list -- python-ideas@python.org > To unsubscribe send an email to python-ideas-le...@python.org > https://mail.python.org/mailman3/lists/python-ideas.python.org/ > Message archived at > https://mail.python.org/archives/list/python-ideas@python.org/message/HPV3AJ4PUYDGVWAKLQQQL7EEHSRBP7N7/ > Code of Conduct: http://python.org/psf/codeofconduct/ >
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/UM7BUM3N3UYC3KTMO7QIHACIMR2P5GCP/ Code of Conduct: http://python.org/psf/codeofconduct/