[Python-Dev] About raising NotPortableWarning for CPython specific code

Terry Reedy tjreedy at udel.edu
Sat Mar 12 20:52:41 CET 2011


On 3/12/2011 8:59 AM, Nick Coghlan wrote:
> On Sat, Mar 12, 2011 at 8:33 AM, Laura Creighton<lac at openend.se>  wrote:
>> For those of you not at the Language Summit at PyCON the day before yesterday,
>> there was talk of identifying non-portable behaviour, such as relying on
>> CPython's reference counting garbage collector to close files for you as
>> soon as they become unreachable.  And then warning about them.
>>
>> We have a real live user who has a large code base that relies on
>> the CPython behaviour that an object's __radd__ method will take precedence
>> over a list's inplace add behaviour.
>>
>> The thread with the whole gory details begins here:
>> http://codespeak.net/pipermail/pypy-dev/2011q1/006958.html
>>
>> My inclination is to declare code that relies on this as broken, rather
>> than patch every wretched container type in PyPy.  Can this become
>> blessed as a 'you shouldn't have done this'?
>
> Given that the meat of the difference in semantics lies in the
> CPython-specific distinction between nb_add and sq_concat, I'm
> inclined to agree with you.

Me too. Consider filing a tracker issue with the += and * examples from 
the link above as new unit tests.

> I'm actually tempted to call the current CPython semantics flatout
> *wrong*. When a given operation has multiple C level slots, shouldn't
> we be checking all the LHS slots before checking any of the RHS slots?

Yes.

> There's nothing in the language spec that I'm aware of that justifies
> us doing otherwise.

The current CPython behavior strikes me as a buggy optimization. If 
class 'list' were written in Python, it would have an '__iadd__' method 
that would implement +=. No question. I gather that this is what PyPy 
(correctly) does. The CPython implementation makes a (false) distinction 
between numeric + and * and sequence + and * that does not exist in 
Python the language. The reference manual only lists __add__, and not 
__nadd__ and __sadd__ as separate special methods. The fact that CPython 
has both (with different names) should *not* leak into Python semantics 
and behavior.

> (obviously, history now means that changing our behaviour would
> require a deprecation period)

I disagree. Behavior that contradicts intent and doc is a bug and should 
be fixed. Otherwise, the doc should be changed to say that for 
C-implmented objects, the precedence between forward and reverse methods 
depends on the category of object. This would mean that subclasses of 
builtins *should* act differently from their parent, as they can now. 
Example derived from the link:

# 3.2
class C(object):
     def __iter__(self):
         yield 'yes!'
     def __radd__(self, other):
         other.append('bug!')
         return other

class L(list):
     def __iadd__(self, other):
         list.__iadd__(self,other)
         return self

z1,z2 = [], L()
z1 += C()
z2 += C()
print(z1, z2)

 >>>
['bug!'] ['yes!']

Such a change would make the definition of the language more 
C-dependent, which is what Laura is rightly complaining about, rather 
than less. It would also work against efforts to make Python and C 
versions of stdlib modules work the same and pass the same tests.

-- 
Terry Jan Reedy



More information about the Python-Dev mailing list