And here's an example with regex's, and a format_spec to say whether to escape the text or not: import re def to_re(istring): # escape the value of the embedded expressions result = [] for part in istring.parts(): result.append(part.literal) if part.expr is not None: if part.format_spec == 'raw': result.append(part.value) else: result.append(re.escape(part.value)) return re.compile(''.join(result)) delimiter = '+' trailing_re = r'\S+' regex = i(r'{delimiter}\d+{delimiter}{trailing_re:raw}') print(to_re(regex)) If we did i-strings for real, that line would be: regex = ri'{delimiter}\d+{delimiter}{trailing_re:raw}' I'm not really sold on i-strings yet. But there's enough here for people to play with. Eric. On 08/24/2015 01:10 PM, Eric V. Smith wrote:
And because I can't leave well enough alone, here's an improved version. It includes a little logging example, plus an implementation of f-strings. Again, using f("") instead of f"".
It might only work with the hg tip (what will be 3.6). I don't have a 3.5 around to test it with. It won't work with 3.3 due to changes in _string.formatter_parse. It's possible simpler expressions might work, but I'm not well motivated to try it out.
Eric.
On 08/24/2015 11:55 AM, Eric V. Smith wrote:
I should have added: this is for i-strings that look like PEP 498's f-strings. I'm not trying to jump to conclusions about the syntax: I'm just trying to reuse some code, and making i-strings and f-strings look like str.format strings allows me to reuse lots of infrastructure (as I hope can be seen from this example).
For the final version, we can choose whatever syntax makes sense. I would argue for i"Value={value}" (same for f-strings), but if we decide to make it something else, I'll live with the decision.
Eric.
On 08/24/2015 11:14 AM, Eric V. Smith wrote:
On 08/23/2015 09:13 PM, Guido van Rossum wrote:
But for i-strings, I think it would be good if we could gather more actual experience using them. Every potential use case brought up for these so far (translation, html/shell/sql quoting) feels like there's a lot of work needing to be done to see if the idea is actually viable there. It would be a shame if we added all the (considerable!) machinery for i-strings and all we got was yet another way to do it (https://xkcd.com/927/), without killing at least one competing approach (similar to the way .format() has failed to replace %).
It's tough to envision how we could gather more experience with i-strings *without* building them into the language, but I'm really hesitant to add them without more experience. (This is the "new on the job market" paradox. :-) Maybe they could be emulated using a function call that uses sys._getframe() under the covers? Or maybe it's possible to cook up an experiment using other syntax hooks? E.g. the coding hack used in pyxl (https://github.com/dropbox/pyxl).[1]
I hope you don't mind that I borrowed the keys to the time machine. I'm using the implementation of _string.formatter_parser() that I added for implementing string.Formatter:
---8<--------------------------------------------- import sys import _string
class i: def __init__(self, s): self.s = s locals = sys._getframe(1).f_locals globals = sys._getframe(1).f_globals self.values = {} # evaluate the expressions for literal, expr, format_spec, conversion in \ _string.formatter_parser(self.s): if expr: value = eval(expr, locals, globals) self.values[expr] = value
def __str__(self): result = [] for literal, expr, format_spec, conversion in \ _string.formatter_parser(self.s): result.append(literal) if expr: value = self.values[expr] result.append(value.__format__(format_spec)) return ''.join(result) ---8<---------------------------------------------
So now, instead of i"x={x}", we say i("x={x}").
Let's use it with str:
x = i('Version in caps {sys.version[0:7].upper()}') x <__main__.i object at 0x7f1653311e90> str(x) 'Version in caps 3.6.0A0'
Cool. Now let's whip up a simple i18n example:
def gettext(s): ... # Our complicated string lookup ... if s == 'My name is {name}, my dog is {dog}': ... return 'Mi pero es {dog}, y mi nombre es {name}' ... return s ... def _(istring): ... result = [] ... # do the gettext lookup ... s = gettext(istring.s) ... # use the values from our original istring, ... # but the literals and ordering from our ... # looked-up string ... for literal, expr, format_spec, conversion in \ ... _string.formatter_parser(s): ... result.append(literal) ... if expr is not None: ... result.append(istring.values[expr]) ... return ''.join(result) ... name = 'Eric' dog = 'Misty' x = i('My name is {name}, my dog is {dog}') str(x) 'My name is Eric, my dog is Misty' _(x) 'Mi pero es Misty, y mi nombre es Eric'
That should be enough to play with i-strings in logging, sql, xml, etc.
Several things should be addressed: hiding the call to _string.formatter_parse inside the 'i' class, for example. And of course don't use sys._getframe. But the ideas are all there.
I can't swear that _string.formatter_parser will parse all known expressions, since that's not what it was designed to do. It will likely fail with expressions that contain strings and braces, for example. I haven't really checked. But hey, what do you want for free?
With a slight tweak, this code even works with 2.7: replace "_string.formatter_parser" with "str._formatter_parser". Unfortunately, 2.7 will then only support very simple expressions. Oh, well.
Enjoy!
Eric.
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/