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
