[Python-Dev] Re: Alternative Implementation forPEP292:SimpleString Substitutions

Raymond Hettinger raymond.hettinger at verizon.net
Fri Sep 10 07:50:40 CEST 2004


[Barry]
> And to make effbot and Raymond happy, it won't auto-promote to unicode
> if everything's an 8bit string.

Glad to see that my happiness now ranks as a development objective ;-)



> There will be updated unit tests, and I will update the documentation
> and the PEP as appropriate -- if we've reached agreement on it.

+1 
Beautiful job.



Barry asked me to bring up one remaining implementation issue for
discussion on python-dev.  

The docs clearly state that only python identifiers are allowed as
placeholders:
 
    [_A-Za-z][_A-Za-z0-9]*

The challenge is that templates can be exposed to non-programmer
end-users with no reason to suspect that one letter of their alphabet is
different from another.  So, as it stands right now, there is a
usability issue with placeholder errors passing silently:

    >>> fechas = {u'hoy':u'lunes', u'mañana':u'martes'}
    >>> t = Template(u'¿Puede volver $hoy o $mañana?')
    >>> t.safe_substitute(fechas)
    u'¿Puede volver lunes o $mañana?'

The substitution failed silently (no ValueError as would have occurred
with $@ or a dangling $).  It may be especially baffling for the user
because one placeholder succeeded and the other failed without a hint of
why (he can see the key in the mapping, it just won't substitute).  No
clue is offered that the Template was looking for $ma, a partial token,
and didn't find it (the situation is even worse if it does find $ma and
substitutes an unintended value).

I suggest that the above should raise an error:

    ValueError:  Invalid token $mañana on line 1, column 24

It is easily possible to detect and report such errors (see an example
in nondist/sandbox/string/curry292.py).

The arguments against such reporting are:
* Raymond is smoking crack.  End users will never make this mistake.
* The docs say python identifiers only.  You blew it.  Tough.  Not a
bug.
* For someone who understands exactly what they are doing, perhaps $ma
is the intended placeholder -- why force them to uses braces:
${ma}ñana.


In addition to the above usability issue, there is one other nit.  The
new invocation syntax offers us the opportunity for to also accept
keyword arguments as mapping alternatives:

    def substitute(self, mapping=None, **kwds):
        if mapping is None:
           mapping == kwds
     . . .

When applicable, this makes for beautiful, readable calls:

    t.substitute(who="Barry", what="mailmeister", when=now())

This would be a simple and nice enchancement to Barry's excellent
implementation.  I recommend that keyword arguments be adopted.



Raymond 



More information about the Python-Dev mailing list