Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #2519 > unrolled thread
| Started by | Alia Khouri <alia_khouri@yahoo.com> |
|---|---|
| First post | 2011-04-03 03:07 -0700 |
| Last post | 2011-04-04 14:32 -0700 |
| Articles | 9 — 5 participants |
Back to article view | Back to comp.lang.python
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
| From | Alia Khouri <alia_khouri@yahoo.com> |
|---|---|
| Date | 2011-04-03 03:07 -0700 |
| Subject | proposal to allow to set the delimiter in str.format to something other than curly bracket |
| Message-ID | <a227e6f7-45ae-4404-973f-b69adf156440@d19g2000yql.googlegroups.com> |
Hi folks,
I've been using ironpython2.7 in a project, and I was generating some
csharp code when i discovered that I couldn't use use str.format
because the interference with the brackets-aplenty situation in
csharp.
In [1]: code = "class {0}Model { public bool IsModel(){ return
true; } }"
In [2]: code.format('My')
---------------------------------------------------------------------------
KeyError Traceback (most recent call
last)
KeyError: ' public bool IsModel(){ return true; } '
Please note I had no trouble with the trusty old % interpolation
method.
Now given that using str.format in this use case (code generation) is
equally difficult for other bracketed languages, and that str.format
is supposed to eventually become 'best-practice' for python string
formatting, can I get some feedback on a proposal that for the odd
case when brackets don't cut it, there is a way to redefine the
delimiter for str.format so that one could do something like this:
str.format_delimiter = ("[[", "]]")
and we could write something like this:
In [1]: code = "class [[0]]Model { public bool IsModel(){ return
true; } }"
In [2]: code.format('My')
Out[3]: 'class MyModel { public bool IsModel(){ return true; } }'
Please give your +N or -N and reasons below.
AK
[toc] | [next] | [standalone]
| From | Corey Richardson <kb1pkl@aim.com> |
|---|---|
| Date | 2011-04-03 06:53 -0400 |
| Message-ID | <mailman.166.1301828304.2990.python-list@python.org> |
| In reply to | #2519 |
On 04/03/2011 06:07 AM, Alia Khouri wrote: > Hi folks, > > I've been using ironpython2.7 in a project, and I was generating some > csharp code when i discovered that I couldn't use use str.format > because the interference with the brackets-aplenty situation in > csharp. > Roll your own http://docs.python.org/library/string.html#string.Formatter -- Corey Richardson
[toc] | [prev] | [next] | [standalone]
| From | Alia Khouri <alia_khouri@yahoo.com> |
|---|---|
| Date | 2011-04-03 05:17 -0700 |
| Message-ID | <0c67412d-32fa-498e-bc2a-23a48e1deef3@e21g2000yqe.googlegroups.com> |
| In reply to | #2524 |
On Apr 3, 1:53 pm, Corey Richardson <kb1...@aim.com> wrote: > On 04/03/2011 06:07 AM, Alia Khouri wrote: > > > Hi folks, > > > I've been using ironpython2.7 in a project, and I was generating some > > csharp code when i discovered that I couldn't use use str.format > > because the interference with the brackets-aplenty situation in > > csharp. > > Roll your ownhttp://docs.python.org/library/string.html#string.Formatter > (-: Thanks for the tip, looks I can subclass string.Template to get what I need. Kicking myself for posting too early... AK
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2011-04-04 01:17 -0400 |
| Message-ID | <mailman.180.1301894287.2990.python-list@python.org> |
| In reply to | #2519 |
On 4/3/2011 6:07 AM, Alia Khouri wrote:
> Hi folks,
>
> I've been using ironpython2.7 in a project, and I was generating some
> csharp code when i discovered that I couldn't use use str.format
> because the interference with the brackets-aplenty situation in
> csharp.
>
> In [1]: code = "class {0}Model { public bool IsModel(){ return
> true; } }"
>
> In [2]: code.format('My')
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; } }'
--
Terry Jan Reedy
[toc] | [prev] | [next] | [standalone]
| From | Alia Khouri <alia_khouri@yahoo.com> |
|---|---|
| Date | 2011-04-04 08:42 -0700 |
| Message-ID | <902f640f-7540-4309-bb54-a1e71d86bb87@d28g2000yqc.googlegroups.com> |
| In reply to | #2547 |
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>
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2011-04-04 18:18 +0200 |
| Message-ID | <mailman.7.1301933897.9059.python-list@python.org> |
| In reply to | #2571 |
Alia Khouri wrote:
> 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.
You could automatically convert from a custom format like that in your
original post:
import re
_lookup = {
"[[": "{",
"]]": "}",
"{": "{{",
"}": "}}",
}
def _substitute(m):
return _lookup[m.group()]
def custom_format(template, *args, **kw):
return (re.compile(r"\[\[|]]|\{|\}")
.sub(_substitute, template)
.format(*args, **kw))
code = "class [[0]]Model { public bool IsModel(){ return a[42] || true; } }"
print custom_format(code, "My")
[toc] | [prev] | [next] | [standalone]
| From | Alia Khouri <alia_khouri@yahoo.com> |
|---|---|
| Date | 2011-04-04 13:45 -0700 |
| Message-ID | <de6117d4-867a-450d-bf8a-4a9482204cd4@18g2000prd.googlegroups.com> |
| In reply to | #2573 |
Peter Otten wrote:
> You could automatically convert from a custom format like that in your
> original post:
>
> import re
>
> _lookup = {
> "[[": "{",
> "]]": "}",
> "{": "{{",
> "}": "}}",
>
> }
>
> def _substitute(m):
> return _lookup[m.group()]
>
> def custom_format(template, *args, **kw):
> return (re.compile(r"\[\[|]]|\{|\}")
> .sub(_substitute, template)
> .format(*args, **kw))
>
> code = "class [[0]]Model { public bool IsModel(){ return a[42] || true; } }"
> print custom_format(code, "My")
Nice! I didn't think of that. I guess I could get some additional
performance by taking the re.compile step out of the function. Thanks
for the tip!
AK
AK
[toc] | [prev] | [next] | [standalone]
| From | Neil Cerutti <neilc@norwich.edu> |
|---|---|
| Date | 2011-04-05 13:45 +0000 |
| Message-ID | <900kohFh35U8@mid.individual.net> |
| In reply to | #2596 |
On 2011-04-04, Alia Khouri <alia_khouri@yahoo.com> wrote: > Nice! I didn't think of that. I guess I could get some > additional performance by taking the re.compile step out of the > function. Thanks for the tip! I recommend "The Pragmatic Programmer," (Hunt, Thomas) ISBN 978-0201616224 and "The Practice of Programming," (Kernighan, Pike) ISBN 978-0201615869 for more practical tips like this one. As a mostly self-taught programmer, both books helped me immensely. If you're a seasoned pro with a CS degree, you might not find them quite as interesting, though. The second book, especially, does not cover issues relating to large scale software development. As for factoring out re.compile, I believe they are cached by the re module, so you would save the cost of retrieving the cached regex, but not the cost of building it. -- Neil Cerutti
[toc] | [prev] | [next] | [standalone]
| From | Alia Khouri <alia_khouri@yahoo.com> |
|---|---|
| Date | 2011-04-04 14:32 -0700 |
| Message-ID | <e86c298c-069d-447a-bb8a-ea2f9fffb552@34g2000pru.googlegroups.com> |
| In reply to | #2573 |
Peter Otten wrote:
> You could automatically convert from a custom format like that in your
> original post...
<snip>
Here's a class wrapping your functionality:
import re
class Template(object):
'''uses double brackets e.g [[ob.attr]] as delims to get
around curly bracket ({}) collisions when generating code
'''
_pattern = re.compile(r"\[\[|]]|\{|\}")
_lookup = {
"[[": "{",
"]]": "}",
"{": "{{",
"}": "}}",
}
def __init__(self, txt):
self.txt = txt
self.type = type
def _substitute(self, m):
return self._lookup[m.group()]
def render(self, *args, **kwds):
return self._pattern.sub(
self._substitute, self.txt).format(*args, **kwds)
def test_Template():
class P: pass
p = P()
p.name = 'peter'
txt = 'hello there [[o.name]]'
t = Template(txt)
assert t.render(o=p) == 'hello there peter'
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web