[Python-ideas] Fix the DRY problem (was Re: PEP 501 - i18n with marked strings)

Barry Warsaw barry at python.org
Wed Aug 12 18:06:27 CEST 2015


On Aug 12, 2015, at 08:50 AM, Guido van Rossum wrote:

>> I think he was proposing an immutable mapping

FTR, yes.  Immutable reads are all that's required for i18n.

>It also has the same problems as locals(), sys._getframe(), etc., which is
>that their presence makes certain optimizations harder (in IronPython IIRC
>the creation of frame objects is normally skipped to speed up function
>calls, but the optimizer must detect the presence of those functions in
>order to disable that optimization). That doesn't mean I'm opposed to it (I
>don't have a problem with locals()), but it does mean that I think their
>use should probably not be encouraged.

I'm much less concerned about the performance impact loss of optimization
provides because I think i18n is already generally slower... and that's okay!
I mean _() has to at least do a dictionary look (assuming the catalog is
warmed in memory) and then a piece-wise interpolation into the resulting
translated string.  So you're already paying runtime penalty to do i18n.

>TBH I'm sorry Barry, but whenever someone use DRY as a rallying cry I get a
>bad taste in my mouth. The solutions that are then proposed are too often
>uglier than the problem. (So I'm glad PEP 498 doesn't mention DRY. :-)

I can appreciate that.  It reminds me of the days of Python before keyword
arguments.  Remember the fun we had with tkinter back then? :)

i18n is one of those places where DRY really is a limiting factor.  You just
can't force coders to pass in all the arguments to their translated strings,
say into the _() function.  The code looked horrible, it's way too much
typing, and people (well, *I* ;) just won't do it.  After implementing the
sys._getframe() hack, it made i18n just so much more pleasant and easy to
write, you almost couldn't not do it.

One of the things that intrigues me about this whole idea of syntactic and
compiler support is the ability to narrow down the set of substitution values
available for interpolation, by parsing the source string and passing them
into the interpolation call.

Currently, _() is forced to expose all of locals and global to interpolation,
although I guess it could also parse out the $-placeholders in the source
string too[1].  Not doing this does open an information leak vector via
maliciously translated strings.  If the source string were parsed and *only*
those names were available for interpolation, a maliciously translated string
couldn't be used to expose additional information because the keys in the
interpolation dictionary would be limited.

This mythical scope() could take arguments which would name the variables in
the enclosing scopes it should export.  It would still be a PITA if used
explicitly, but could work nicely if i-strings essentially boiled down to:

    placeholders = source_string.extract_placeholders()
    substitutions = scope(*placeholders)
    translated_string = i18n.lookup(source_string)
    return translated_string.safe_substitute(substitutions)

That would actually be quite useful.

Cheers,
-Barry

[1] https://gitlab.com/warsaw/flufl.i18n/issues/1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20150812/e34b657c/attachment.sig>


More information about the Python-ideas mailing list