None is a valid assignment to any python object, including one  
declared to be a Cython type. One can declare

def __init__(self, ntl_ZZ_pX f not None):
     ...

if one wants a type error on None. See the section "Extension types  
and None" at http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/ 
version/Doc/Manual/extension_types.html

This is probably a common problem and we should probably be using  
this more often in our code.

- Robert


On Oct 12, 2007, at 3:10 PM, David Roe wrote:

> Hey Robert,
> David Harvey and I were tracing down a bug in the ntl code I'm  
> writing and came across what we think is a bug in Cython.
>
> The issue arises when a def'd function in a cython file asserts  
> that one of its arguments is a certain type.  In my case, this  
> happened in ntl_ZZ_pEContext.pyx (which I'm writing), where I have  
> the code:
>     def __init__(self, ntl_ZZ_pX f):
>          pass
>
>     def __new__(self, ntl_ZZ_pX f):
>         self.pc = f.c
>         self.pc.restore_c()
>         ZZ_pEContext_construct_ZZ_pX(&self.x, &f.x)
>         ZZ_pEContextDict[(repr(f),repr(f.c.p))] = self
>         self.f = f
>
> There was a bug in other code that created one of these that called  
> the constructor with f = None (which caused Sage to crash).  Now,  
> David and my thought was that if f was the wrong type, the  
> generated code would either raise a TypeError, or try to cast it to  
> a ntl_ZZ_pX, and upon failure raise a TypeError.  However, upon  
> examination of the generated C code, we found the following.  In  
> the generated code for __init__ and __new__, the following calls to  
> __Pyx_ArgTypeTest happened:
>   if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f),  
> __pyx_ptype_4sage_4libs_3ntl_9ntl_ZZ_pX_ntl_ZZ_pX, 1, "f")))  
> {__pyx_filename = __pyx_f[1]; __pyx_lineno = 28;\
>  goto __pyx_L1;}
>   if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f),  
> __pyx_ptype_4sage_4libs_3ntl_9ntl_ZZ_pX_ntl_ZZ_pX, 1, "f")))  
> {__pyx_filename = __pyx_f[1]; __pyx_lineno = 49;\
>  goto __pyx_L1;}
>
> We looked at the code for __Pyx_ArgTypeTest,
>
> static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int  
> none_allowed, char *name) {
>     if (!type) {
>         PyErr_Format(PyExc_SystemError, "Missing type object");
>         return 0;
>     }
>     if ((none_allowed && obj == Py_None) || PyObject_TypeCheck(obj,  
> type))
>         return 1;
>     PyErr_Format(PyExc_TypeError,
>         "Argument '%s' has incorrect type (expected %s, got %s)",
>         name, type->tp_name, obj->ob_type->tp_name);
>     return 0;
> }
>
> and saw the variable none_allowed (which is 1 in these calls).  Is  
> it the case that a TypeError is not getting raised in these cases  
> because we're passing in f=None?
> David


--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to sage-devel@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sage-devel
URLs: http://sage.scipy.org/sage/ and http://modular.math.washington.edu/sage/
-~----------~----~----~----~------~----~------~--~---

Reply via email to