Robert Bradshaw wrote:
>> +---
>> | Dr. Simon Anders, Dipl.-Phys.
>> | European Molecular Biology Laboratory (EMBL), Heidelberg
>> | office phone +49-6221-387-8632
>> | preferred (permanent) e-mail: [email protected]
>>
>>
>> From: Simon Anders <[email protected]>
>> Date: August 25, 2009 3:46:52 AM PDT
>> To: [email protected]
>> Subject: Type checking bug when passing None instead of a Cython  
>> object
>>
>>
>> Hi,
>>
>> I'm a rather new user of Cython but if I am not completely  
>> mistaken, I've found a bug in the type checking of function arguments.
>>
>> Consider the following simple Cython module:
>>
>> ---8<--- test1.pyx ---------
>>
>> cdef class foo:
>>    cdef public int value
>>    def __init__( self, value ):
>>       self.value = value
>>
>> def getValue( foo obj ):
>>    return obj.value
>>
>> ---8<-----------------------
>>
>> Now observe how the function 'getValue' correctly accepts an  
>> argument of class 'foo', refuses an argument of type 'str', but  
>> fails to reject a 'None':
>>
>> ---8<-----------------------
>>
>> Python 2.5.2 (r252:60911, Oct  5 2008, 19:29:17)
>> [GCC 4.3.2] on linux2
>> Type "help", "copyright", "credits" or "license" for more information.
>>
>>>>> import test1
>>>>> f = test1.foo( 3 )
>>>>> test1.getValue( f )
>> 3
>>
>>>>> test1.getValue( "A" )
>> Traceback (most recent call last):
>>   File "<stdin>", line 1, in <module>
>>   File "test1.pyx", line 8, in test1.getValue (test1.c:412)
>>     def getValue( foo obj ):
>> TypeError: Argument 'obj' has incorrect type (expected test1.foo,  
>> got str)
>>
>>>>> test1.getValue( None )
>> 3
>>
>> ---8<-----------------------
>>
>>
>> As you can see, 'None' was treated as an object of type 'foo', was  
>> dereferenced and the slot 'value' accessed. By chance, we found a  
>> 3, but we might as well have gotten a segfault (which is how I  
>> stumbled over this in the first instance.)

Actually, this is documented and relied-upon behaviour (None is used as 
a "blank", "no object", in much control flow). See e.g.

http://thread.gmane.org/gmane.comp.python.cython.devel/7041

The short story is, you can put

#cython: nonecheck=True

at the top of your file and all access will be checked for None, but it 
will slow things down. Alternatively,

def foo(MyClass a not None): <...>

is a short-hand for

def foo(MyClass a):
     if a is None: raise <...>
     <...>

(It would be great if this was added to the FAQ, it tends to come up a 
lot. Perhaps we should switch to making nonecheck the default?)

-- 
Dag Sverre
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to