[Python-Dev] PEP 399: Pure Python/C Accelerator Module Compatibiilty Requirements

Brett Cannon brett at python.org
Tue Apr 5 20:24:49 CEST 2011


On Tue, Apr 5, 2011 at 05:01, Nick Coghlan <ncoghlan at gmail.com> wrote:

> On Tue, Apr 5, 2011 at 9:46 AM, Brett Cannon <brett at python.org> wrote:
> >     try:
> >         c_heapq.heappop(Spam())
> >     except TypeError:
> >         # "heap argument must be a list"
> >         pass
> >
> >     try:
> >         py_heapq.heappop(Spam())
> >     except AttributeError:
> >         # "'Foo' object has no attribute 'pop'"
> >         pass
> >
> > This kind of divergence is a problem for users as they unwittingly
> > write code that is CPython-specific. This is also an issue for other
> > VM teams as they have to deal with bug reports from users thinking
> > that they incorrectly implemented the module when in fact it was
> > caused by an untested case.
>
> While I agree with the PEP in principle, I disagree with the way this
> example is written. Guido has stated in the past that code simply
> *cannot* rely on TypeError being consistently thrown instead of
> AttributeError (or vice-versa) when it comes to duck-typing. Code that
> cares which of the two is thrown is wrong.
>

Which is unfortunate since least common base class is Exception. But I can
add a note to the PEP saying that this is the case and change the example.


>
> However, there actually *is* a significant semantic discrepancy in the
> heapq case, which is that py_heapq is duck-typed, while c_heapq is
> not:
>
> >>> from test.support import import_fresh_module
> >>> c_heapq = import_fresh_module('heapq', fresh=['_heapq'])
> >>> py_heapq = import_fresh_module('heapq', blocked=['_heapq'])
> >>> from collections import UserList
> >>> class Seq(UserList): pass
> ...
> >>> c_heapq.heappop(UserList())
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
> TypeError: heap argument must be a list
> >>> py_heapq.heappop(UserList())
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
>  File "/home/ncoghlan/devel/py3k/Lib/heapq.py", line 140, in heappop
>    lastelt = heap.pop()    # raises appropriate IndexError if heap is empty
>  File "/home/ncoghlan/devel/py3k/Lib/collections/__init__.py", line 848, in
> pop
>    def pop(self, i=-1): return self.data.pop(i)
> IndexError: pop from empty list
>
> Cheers,
> Nick.
>
> P.S. The reason I was bugging Guido to answer the TypeError vs
> AttributeError question in the first place was to find out whether or
> not I needed to get rid of the following gross inconsistency in the
> behaviour of the with statement relative to other language constructs:
>
> >>> 1()
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
> TypeError: 'int' object is not callable
> >>> with 1: pass
> ...
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
> AttributeError: 'int' object has no attribute '__exit__'
>
>
>
> Cheers,
> Nick.
>
> --
> Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20110405/16557b44/attachment-0001.html>


More information about the Python-Dev mailing list