Bug? cgi.escape(int)

Alex Martelli aleax at aleax.it
Thu Jul 25 09:54:45 EDT 2002


Thomas Guettler wrote:
        ...
>> Many Python functions expect to get arguments of specific types
>> (or polymorphic to such types, i.e., supplying all necessary
>> methods and operations with equal signatures).
>> 
>> Having them accept arguments of wrong types, with silent coercion,
>> would hurt all careful developers, by hiding bugs.
> 
> I agree, but than the exception should have a better message:

Should it?  Maybe I should have written than types supplying all
necessary methods and operations with equal signatures are OK
too.  Oh, I _DID_?  Hmmm... 

 
> $ python escape.py
> Traceback (most recent call last):
>    File "escape.py", line 3, in ?
>      cgi.escape(2)
>    File "/usr/lib/python2.2/cgi.py", line 1024, in escape
>      s = s.replace("&", "&") # Must be done first!
> AttributeError: 'int' object has no attribute 'replace'
> 
> 
> A exception with a message like:
> "Argument must be a string"
> 
> would be better

No, it would be an outright LIE.

Why do you think a lie would be better than the truth?


import cgi

class goodenuf:
    def __init__(self, *args): pass
    def replace(self, *args): return self
    def __str__(self): return 'gotcha!'

print cgi.escape(goodenuf())


An instance of class goodenuf is of course not a string.

cgi.escape is perfectly happy to accept such an instance.

Therefore, if cgi.escape said that its argument must be
a string, then cgi.escape would be lying through its teeth.

Lying is not nice.

What cgi.escape SHOULD say, if an argument is passed to it
that is unacceptable, is that the argument lacks a 'replace'
[callable] attribute.  THAT is the actual requirement.

Wait a sec -- that *IS* exactly what the exception's value
is saying!  Strange, isn't it?

It's giving you even more information, specifically WHAT
is the type of the object that is lacking a [callable, but
that's not yet diagnosed at that point] 'replace' attribute.
Seems a nice information to give, and costs nothing.


Note that other functions in Python's standard library DO
lie.  And some apply the deplorable practice called type
checking, so that the smooth, perfect, seamless polymorphism
of writing a "good enough" implementation of the actually
needed methods/signatures isn't good enough any more.

But you're criticizing one of the library functions that
is impeccable in these respects.  It requires just the
minimal amount of functionality it in fact needs from the
object you pass as an argument, and lets you know that
said minimal amount is missing if it is.  Perfect.


Therefore, I find your criticism totally unfounded.


Alex




More information about the Python-list mailing list