Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #2571

Re: proposal to allow to set the delimiter in str.format to something other than curly bracket

From Alia Khouri <alia_khouri@yahoo.com>
Newsgroups comp.lang.python
Subject Re: proposal to allow to set the delimiter in str.format to something other than curly bracket
Date 2011-04-04 08:42 -0700
Organization http://groups.google.com
Message-ID <902f640f-7540-4309-bb54-a1e71d86bb87@d28g2000yqc.googlegroups.com> (permalink)
References <a227e6f7-45ae-4404-973f-b69adf156440@d19g2000yql.googlegroups.com> <mailman.180.1301894287.2990.python-list@python.org>

Show all headers | View raw


Terry Reedy wrote:

> Just double the brackets, just as one doubles '\\' to get '\' in a string.
>
>  >>> "class {0}Model {{ public bool IsModel(){{ returntrue; }}}}".format('My')
>
> 'class MyModel { public bool IsModel(){ returntrue; } }'
>

Indeed, I tried that, but it means I have to double bracket all the
csharp code which just creates more work for me.

Here is my solution (aka Cheetah ultra-light) ripped from
stdlib.string: it involves hacking the string.Template class so that
you get attribute lookups. I know it uses eval, and it's probably
highly insecure, but it's for one off batch jobs, and I hope it
doesn't hurt anyone:

<code>
import re

class _multimap:
    """Helper class for combining multiple mappings.

    Used by .substitute() to combine the mapping and keyword
    arguments.
    """
    def __init__(self, primary, secondary):
        self._primary = primary
        self._secondary = secondary

    def __getitem__(self, key):
        try:
            return self._primary[key]
        except KeyError:
            return self._secondary[key]


class _TemplateMetaclass(type):
    pattern = r"""
    %(delim)s(?:
      (?P<escaped>%(delim)s) |   # Escape sequence of two delimiters
      (?P<named>%(id)s)      |   # delimiter and a Python identifier
      {(?P<braced>%(id)s)}   |   # delimiter and a braced identifier
      (?P<invalid>)              # Other ill-formed delimiter exprs
    )
    """

    def __init__(cls, name, bases, dct):
        super(_TemplateMetaclass, cls).__init__(name, bases, dct)
        if 'pattern' in dct:
            pattern = cls.pattern
        else:
            pattern = _TemplateMetaclass.pattern % {
                'delim' : re.escape(cls.delimiter),
                'id'    : cls.idpattern,
                }
        cls.pattern = re.compile(pattern, re.IGNORECASE | re.VERBOSE)


class Template:
    """A string class for supporting $-substitutions."""
    __metaclass__ = _TemplateMetaclass

    delimiter = '$'
    idpattern = r'[_a-z][_a-z0-9\.]*'

    def __init__(self, template):
        self.template = template

    # Search for $$, $identifier, ${identifier}, and any bare $'s

    def _invalid(self, mo):
        i = mo.start('invalid')
        lines = self.template[:i].splitlines(True)
        if not lines:
            colno = 1
            lineno = 1
        else:
            colno = i - len(''.join(lines[:-1]))
            lineno = len(lines)
        raise ValueError('Invalid placeholder in string: line %d, col
%d' %
                         (lineno, colno))

    def substitute(self, *args, **kws):
        if len(args) > 1:
            raise TypeError('Too many positional arguments')
        if not args:
            mapping = kws
        elif kws:
            mapping = _multimap(kws, args[0])
        else:
            mapping = args[0]
        # Helper function for .sub()
        def convert(mo):
            # Check the most common path first.
            named = mo.group('named') or mo.group('braced')
            if named is not None:
                # We use this idiom instead of str() because the
latter will
                # fail if val is a Unicode containing non-ASCII
characters.
                # XXXX here is the probably dangerous eval hack XXXXXX
                if '.' in named:
                    return eval(named, kws)
                else:
                    val = mapping[named]
                    return '%s' % (val,)

            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)


def test_templates():
    class P: pass
    p = P()
    p.name = 'ak'
    txt = 'hello there ${o.name}'
    t = Template(txt)
    assert t.substitute(o=p) == 'hello there ak'

if __name__ == '__main__': test_templates()

</code>

Back to comp.lang.python | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

proposal to allow to set the delimiter in str.format to something other than curly bracket Alia Khouri <alia_khouri@yahoo.com> - 2011-04-03 03:07 -0700
  Re: proposal to allow to set the delimiter in str.format to something other than curly bracket Corey Richardson <kb1pkl@aim.com> - 2011-04-03 06:53 -0400
    Re: proposal to allow to set the delimiter in str.format to something other than curly bracket Alia Khouri <alia_khouri@yahoo.com> - 2011-04-03 05:17 -0700
  Re: proposal to allow to set the delimiter in str.format to something other than curly bracket Terry Reedy <tjreedy@udel.edu> - 2011-04-04 01:17 -0400
    Re: proposal to allow to set the delimiter in str.format to something other than curly bracket Alia Khouri <alia_khouri@yahoo.com> - 2011-04-04 08:42 -0700
      Re: proposal to allow to set the delimiter in str.format to something other than curly bracket Peter Otten <__peter__@web.de> - 2011-04-04 18:18 +0200
        Re: proposal to allow to set the delimiter in str.format to something other than curly bracket Alia Khouri <alia_khouri@yahoo.com> - 2011-04-04 13:45 -0700
          Re: proposal to allow to set the delimiter in str.format to something other than curly bracket Neil Cerutti <neilc@norwich.edu> - 2011-04-05 13:45 +0000
        Re: proposal to allow to set the delimiter in str.format to something other than curly bracket Alia Khouri <alia_khouri@yahoo.com> - 2011-04-04 14:32 -0700

csiph-web