ClassBase::ClassBase(const char* name,bool visible,PyTypeObject* type,ptrdiff_t offset) :type(type) { // Verify that GEODE_DECLARE_TYPE(GEODE_CORE_EXPORT) has been used, and initialize name if (!type->tp_name || strncmp(type->tp_name,"geode_default_name",18)) { PyErr_Format(PyExc_AssertionError,"%s->type->tp_name is %s: did you forget GEODE_DECLARE_TYPE(GEODE_CORE_EXPORT)?",name,type->tp_name?type->tp_name:"0"); throw_python_error(); } type->tp_name = name; // Make sure base starts at the beginning if (offset) { PyErr_Format(PyExc_AssertionError,"%s is offset %d bytes before its base",name,(int)offset); throw_python_error(); } // Verify that base class has been initialized if (type->tp_base && !strncmp(type->tp_base->tp_name,"geode_default_name",18)) { PyErr_Format(PyExc_AssertionError,"%s's base class hasn't been initialized for python: make sure wrap_<base> is called before wrap_<self>",name); throw_python_error(); } // Fill in some additional fields automatically if (PyType_Ready(type)<0) throw_python_error(); // Prevent tp_new from inheriting, since the base tp_new constructs an instance of the base class type->tp_new = 0; // Add the type to current module if (visible) { Py_INCREF(type); python::add_object(type->tp_name,(PyObject*)type); } }
PyObject* wrap_property_helper(PyTypeObject* type,const char* name,getter get_wrapper,setter set_wrapper,void* getset) { // Make a PyGetSetDef PyGetSetDef* def = (PyGetSetDef*)malloc(sizeof(PyGetSetDef)); memset(def,0,sizeof(PyGetSetDef)); def->name = const_cast_(name); def->get = get_wrapper; def->set = set_wrapper; def->closure = getset; // Allocate descriptor PyObject* descr = PyDescr_NewGetSet(type,def); if (!descr) throw_python_error(); return descr; }
Ref<> numpy_from_any(PyObject* op, PyArray_Descr* dtype, int min_rank, int max_rank, int requirements) { if (op==Py_None) // PyArray_FromAny silently converts None to a singleton nan, which is not cool throw TypeError("Expected array, got None"); // Perform the conversion PyObject* const array = PyArray_FromAny(op,dtype,0,0,requirements,0); if (!array) throw_python_error(); // Numpy produces uninformative error messages on rank mismatch, so we roll our own. const int rank = PyArray_NDIM((PyArrayObject*)array); if ( (min_rank && rank<min_rank) || (max_rank && rank>max_rank)) throw ValueError(min_rank==max_rank ? format("Expected array with rank %d, got rank %d",min_rank,rank) : !min_rank ? format("Expected array with rank <= %d, got rank %d",max_rank,rank) : !max_rank ? format("Expected array with rank >= %d, got rank %d",min_rank,rank) : format("Expected array with %d <= rank <= %d, got rank %d",min_rank,max_rank,rank)); // Success! return steal_ref(*array); }
void throw_tuple_mismatch_error(int expected, int got) { PyErr_Format(PyExc_TypeError,"expected tuple of length %d, got %d",expected,got); throw_python_error(); }