static PyObject * normalizeUserObj(PyObject *obj) { PyCFunctionObject *fn; if (!PyCFunction_Check(obj)) { Py_INCREF(obj); return obj; } /* Replace built-in function objects with a descriptive string because of built-in methods -- keeping a reference to __self__ is probably not a good idea. */ fn = (PyCFunctionObject *)obj; if (fn->m_self == NULL) { /* built-in function: look up the module name */ PyObject *mod = fn->m_module; const char *modname; if (mod && PyUnicode_Check(mod)) { modname = _PyUnicode_AsString(mod); } else if (mod && PyModule_Check(mod)) { modname = PyModule_GetName(mod); if (modname == NULL) { PyErr_Clear(); modname = "builtins"; } } else { modname = "builtins"; } if (strcmp(modname, "builtins") != 0) return PyUnicode_FromFormat("<%s.%s>", modname, fn->m_ml->ml_name); else return PyUnicode_FromFormat("<%s>", fn->m_ml->ml_name); } else { /* built-in method: try to return repr(getattr(type(__self__), __name__)) */ PyObject *self = fn->m_self; PyObject *name = PyUnicode_FromString(fn->m_ml->ml_name); if (name != NULL) { PyObject *mo = _PyType_Lookup(Py_TYPE(self), name); Py_XINCREF(mo); Py_DECREF(name); if (mo != NULL) { PyObject *res = PyObject_Repr(mo); Py_DECREF(mo); if (res != NULL) return res; } } PyErr_Clear(); return PyUnicode_FromFormat("<built-in method %s>", fn->m_ml->ml_name); } }
static PyObject *Nuitka_Method_tp_getattro( struct Nuitka_MethodObject *method, PyObject *name ) { PyObject *descr = _PyType_Lookup( &Nuitka_Method_Type, name ); if ( descr != NULL ) { if ( #if PYTHON_VERSION < 300 PyType_HasFeature( Py_TYPE( descr ), Py_TPFLAGS_HAVE_CLASS ) && #endif ( Py_TYPE( descr )->tp_descr_get != NULL ) ) { return Py_TYPE( descr )->tp_descr_get( descr, (PyObject *)method, (PyObject *)Py_TYPE( method ) ); } else { return INCREASE_REFCOUNT( descr ); } } return PyObject_GetAttr( (PyObject *)method->m_function, name ); }
PyObject *LOOKUP_SPECIAL(PyObject *source, PyObject *attr_name) { #if PYTHON_VERSION < 300 if (PyInstance_Check(source)) { return LOOKUP_INSTANCE(source, attr_name); } #endif // TODO: There is heavy optimization in CPython to avoid it. Potentially // that's worth it to imitate that. PyObject *result = _PyType_Lookup(Py_TYPE(source), attr_name); if (likely(result)) { descrgetfunc func = Py_TYPE(result)->tp_descr_get; if (func == NULL) { Py_INCREF(result); return result; } else { PyObject *func_result = func(result, source, (PyObject *)(Py_TYPE(source))); if (unlikely(func_result == NULL)) { return NULL; } CHECK_OBJECT(func_result); return func_result; } } PyErr_SetObject(PyExc_AttributeError, attr_name); return NULL; }
/* Return true if object has a finalization method. */ static int has_finalizer(PyObject *op) { /* first, dynamic decision per object */ traverseproc traverse; int collectable; traverse = Py_TYPE(op)->tp_traverse; collectable = -1; (void) traverse(op, (visitproc)visit_has_finalizer, (void *)&collectable); if (collectable >= 0) return collectable == 0; if ( PyType_Check(op)) { assert(delstr != NULL); return _PyType_Lookup(Py_TYPE(op), delstr) != NULL; } else if (PyType_HasFeature(op->ob_type, Py_TPFLAGS_HEAPTYPE)) return op->ob_type->tp_del != NULL; else if (PyGen_CheckExact(op)) return PyGen_NeedsFinalizing((PyGenObject *)op); else return op->ob_type->tp_del != NULL; }
static PyObject * math_trunc(PyObject *self, PyObject *number) { static PyObject *trunc_str = NULL; PyObject *trunc; if (Py_TYPE(number)->tp_dict == NULL) { if (PyType_Ready(Py_TYPE(number)) < 0) return NULL; } if (trunc_str == NULL) { trunc_str = PyUnicode_InternFromString("__trunc__"); if (trunc_str == NULL) return NULL; } trunc = _PyType_Lookup(Py_TYPE(number), trunc_str); if (trunc == NULL) { PyErr_Format(PyExc_TypeError, "type %.100s doesn't define __trunc__ method", Py_TYPE(number)->tp_name); return NULL; } return PyObject_CallFunctionObjArgs(trunc, number, NULL); }
static PyObject * method_getattro(PyObject *obj, PyObject *name) { PyMethodObject *im = (PyMethodObject *)obj; PyTypeObject *tp = obj->ob_type; PyObject *descr = NULL; { if (tp->tp_dict == NULL) { if (PyType_Ready(tp) < 0) return NULL; } descr = _PyType_Lookup(tp, name); } if (descr != NULL) { descrgetfunc f = TP_DESCR_GET(descr->ob_type); if (f != NULL) return f(descr, obj, (PyObject *)obj->ob_type); else { Py_INCREF(descr); return descr; } } return PyObject_GetAttr(im->im_func, name); }
Py_complex PyComplex_AsCComplex(PyObject *op) { Py_complex cv; PyObject *newop = NULL; static PyObject *complex_str = NULL; assert(op); /* If op is already of type PyComplex_Type, return its value */ if (PyComplex_Check(op)) { return ((PyComplexObject *)op)->cval; } /* If not, use op's __complex__ method, if it exists */ /* return -1 on failure */ cv.real = -1.; cv.imag = 0.; if (complex_str == NULL) { if (!(complex_str = PyUnicode_FromString("__complex__"))) return cv; } { PyObject *complexfunc; complexfunc = _PyType_Lookup(op->ob_type, complex_str); /* complexfunc is a borrowed reference */ if (complexfunc) { newop = PyObject_CallFunctionObjArgs(complexfunc, op, NULL); if (!newop) return cv; } } if (newop) { if (!PyComplex_Check(newop)) { PyErr_SetString(PyExc_TypeError, "__complex__ should return a complex object"); Py_DECREF(newop); return cv; } cv = ((PyComplexObject *)newop)->cval; Py_DECREF(newop); return cv; } /* If neither of the above works, interpret op as a float giving the real part of the result, and fill in the imaginary part as 0. */ else { /* PyFloat_AsDouble will return -1 on failure */ cv.real = PyFloat_AsDouble(op); return cv; } }
static PyObject * math_floor(PyObject *self, PyObject *number) { static PyObject *floor_str = NULL; PyObject *method; if (floor_str == NULL) { floor_str = PyUnicode_InternFromString("__floor__"); if (floor_str == NULL) return NULL; } method = _PyType_Lookup(Py_TYPE(number), floor_str); if (method == NULL) return math_1_to_int(number, floor, 0); else return PyObject_CallFunction(method, "O", number); }
static _pit * _ccode2pit(void *cco) { PyCFunctionObject *cfn; _hitem *it; PyObject *name; cfn = cco; // Issue #15: // Hashing cfn to the pits table causes different object methods // to be hashed into the same slot. Use cfn->m_ml for hashing the // Python C functions. it = hfind(current_ctx->pits, (uintptr_t)cfn->m_ml); if (!it) { _pit *pit = _create_pit(); if (!pit) return NULL; if (!hadd(current_ctx->pits, (uintptr_t)cfn->m_ml, (uintptr_t)pit)) return NULL; pit->builtin = 1; pit->modname = _pycfunction_module_name(cfn); pit->lineno = 0; // built-in method? if (cfn->m_self != NULL) { name = PyStr_FromString(cfn->m_ml->ml_name); if (name != NULL) { PyObject *obj_type = PyObject_Type(cfn->m_self); PyObject *mo = _PyType_Lookup((PyTypeObject *)obj_type, name); Py_XINCREF(mo); Py_XDECREF(obj_type); Py_DECREF(name); if (mo != NULL) { pit->name = PyObject_Repr(mo); Py_DECREF(mo); return pit; } } PyErr_Clear(); } pit->name = PyStr_FromString(cfn->m_ml->ml_name); return pit; } return ((_pit *)it->val); }
static PyObject * instancemethod_getattro(PyObject *self, PyObject *name) { PyTypeObject *tp = self->ob_type; PyObject *descr = NULL; if (tp->tp_dict == NULL) { if (PyType_Ready(tp) < 0) return NULL; } descr = _PyType_Lookup(tp, name); if (descr != NULL) { descrgetfunc f = TP_DESCR_GET(descr->ob_type); if (f != NULL) return f(descr, self, (PyObject *)self->ob_type); else { Py_INCREF(descr); return descr; } } return PyObject_GetAttr(PyInstanceMethod_GET_FUNCTION(self), name); }
PyObject * Base_getattro(PyObject *obj, PyObject *name) { /* This is a modified copy of PyObject_GenericGetAttr. See the change note below. */ PyTypeObject *tp = obj->ob_type; PyObject *descr = NULL; PyObject *res = NULL; descrgetfunc f; long dictoffset; PyObject **dictptr; if (!PyString_Check(name)){ #ifdef Py_USING_UNICODE /* The Unicode to string conversion is done here because the existing tp_setattro slots expect a string object as name and we wouldn't want to break those. */ if (PyUnicode_Check(name)) { name = PyUnicode_AsEncodedString(name, NULL, NULL); if (name == NULL) return NULL; } else #endif { PyErr_SetString(PyExc_TypeError, "attribute name must be string"); return NULL; } } else Py_INCREF(name); if (tp->tp_dict == NULL) { if (PyType_Ready(tp) < 0) goto done; } #if !defined(Py_TPFLAGS_HAVE_VERSION_TAG) /* Inline _PyType_Lookup */ /* this is not quite _PyType_Lookup anymore */ { int i, n; PyObject *mro, *base, *dict; /* Look in tp_dict of types in MRO */ mro = tp->tp_mro; assert(mro != NULL); assert(PyTuple_Check(mro)); n = PyTuple_GET_SIZE(mro); for (i = 0; i < n; i++) { base = PyTuple_GET_ITEM(mro, i); if (PyClass_Check(base)) dict = ((PyClassObject *)base)->cl_dict; else { assert(PyType_Check(base)); dict = ((PyTypeObject *)base)->tp_dict; } assert(dict && PyDict_Check(dict)); descr = PyDict_GetItem(dict, name); if (descr != NULL) break; } } #else descr = _PyType_Lookup(tp, name); #endif Py_XINCREF(descr); f = NULL; if (descr != NULL && PyType_HasFeature(descr->ob_type, Py_TPFLAGS_HAVE_CLASS)) { f = descr->ob_type->tp_descr_get; if (f != NULL && PyDescr_IsData(descr)) { res = f(descr, obj, (PyObject *)obj->ob_type); Py_DECREF(descr); goto done; } } /* Inline _PyObject_GetDictPtr */ dictoffset = tp->tp_dictoffset; if (dictoffset != 0) { PyObject *dict; if (dictoffset < 0) { int tsize; size_t size; tsize = ((PyVarObject *)obj)->ob_size; if (tsize < 0) tsize = -tsize; size = _PyObject_VAR_SIZE(tp, tsize); dictoffset += (long)size; assert(dictoffset > 0); assert(dictoffset % SIZEOF_VOID_P == 0); } dictptr = (PyObject **) ((char *)obj + dictoffset); dict = *dictptr; if (dict != NULL) { Py_INCREF(dict); res = PyDict_GetItem(dict, name); if (res != NULL) { Py_INCREF(res); Py_XDECREF(descr); Py_DECREF(dict); /* CHANGED! If the tp_descr_get of res is of_get, then call it. */ if ((strcmp(PyString_AsString(name), "__parent__") != 0) && PyObject_TypeCheck(res->ob_type, &ExtensionClassType) && res->ob_type->tp_descr_get != NULL) { PyObject *tres; tres = res->ob_type->tp_descr_get( res, obj, OBJECT(obj->ob_type)); Py_DECREF(res); res = tres; } goto done; } Py_DECREF(dict); } } if (f != NULL) { res = f(descr, obj, (PyObject *)obj->ob_type); Py_DECREF(descr); goto done; } if (descr != NULL) { res = descr; /* descr was already increfed above */ goto done; } /* CHANGED: Just use the name. Don't format. */ PyErr_SetObject(PyExc_AttributeError, name); done: Py_DECREF(name); return res; }
static PyObject * normalizeUserObj(PyObject *obj) { /* Replace built-in function objects with a descriptive string because of built-in methods -- keeping a reference to __self__ is probably not a good idea. */ PyCFunctionObject *fn = (PyCFunctionObject *)obj; if (PyCFunction_Check(obj) && fn->m_self == NULL) { /* built-in function: look up the module name */ PyObject *mod = fn->m_module; char *modname; if (mod && PyString_Check(mod)) { modname = PyString_AS_STRING(mod); } else if (mod && PyModule_Check(mod)) { modname = PyModule_GetName(mod); if (modname == NULL) { PyErr_Clear(); modname = "__builtin__"; } } else { modname = "__builtin__"; } if (strcmp(modname, "__builtin__") != 0) return PyString_FromFormat("<%s.%s>", modname, fn->m_ml->ml_name); else return PyString_FromFormat("<%s>", fn->m_ml->ml_name); } else if (PyCFunction_Check(obj) || PyMethodDescr_Check(obj)) { /* built-in method: try to return repr(getattr(type(__self__), __name__)) */ PyTypeObject *type; const char *name; PyObject *name_obj; if (PyCFunction_Check(obj)) { type = Py_TYPE(fn->m_self); name = fn->m_ml->ml_name; } else { PyMethodDescrObject *descr = (PyMethodDescrObject *)obj; type = descr->d_type; name = descr->d_method->ml_name; } name_obj = PyString_FromString(name); if (name_obj != NULL) { PyObject *mo = _PyType_Lookup(type, name_obj); Py_XINCREF(mo); Py_DECREF(name_obj); if (mo != NULL) { PyObject *res = PyObject_Repr(mo); Py_DECREF(mo); if (res != NULL) return res; } } PyErr_Clear(); return PyString_FromFormat("<built-in method %s>", name); } else { Py_INCREF(obj); return obj; } }
generate_id(NodeObject *node, PyObject *buffer) { NodeObject *parent; PyObject *typecode, *index; Py_ssize_t pos; assert(node != NULL && buffer != NULL && PyList_CheckExact(buffer)); parent = Node_GET_PARENT(node); if (parent != NULL) { if (generate_id(parent, buffer) < 0) return -1; typecode = _PyType_Lookup(node->ob_type, typecode_string); if (typecode == NULL) return -1; if (PyList_Append(buffer, typecode) < 0) return -1; if (Element_Check(parent)) { if (Attr_Check(node)) { PyObject *nodemap = Element_ATTRIBUTES(parent); AttrObject *attr; /* `nodemap` should not be NULL as the attribute `node` claims to be * owned by the element `parent`. */ assert(nodemap != NULL); pos = 0; while ((attr = AttributeMap_Next(nodemap, &pos)) != NULL) { if (attr == (AttrObject *)node) break; } assert(attr != NULL); } else if (Namespace_Check(node)) { PyObject *nodemap = Element_NAMESPACES(parent); NamespaceObject *decl; /* `nodemap` should not be NULL as the namespace `node` claims to be * owned by the element `parent`. */ assert(nodemap != NULL); pos = 0; while ((decl = NamespaceMap_Next(nodemap, &pos)) != NULL) { if (decl == (NamespaceObject *)node) break; } assert(decl != NULL); } else { pos = Container_Index(parent, node); } } else { pos = Container_Index(parent, node); } if (pos < 0) return -1; index = PyString_FromFormat("%zd", pos); if (index == NULL) return -1; if (PyList_Append(buffer, index) < 0) { Py_DECREF(index); return -1; } Py_DECREF(index); } else { /* the top of the tree */ typecode = _PyType_Lookup(node->ob_type, typecode_string); if (typecode == NULL) return -1; if (PyList_Append(buffer, typecode) < 0) return -1; if (Entity_Check(node)) { index = PyObject_Str(Entity_GET_INDEX(node)); } else { /* a tree fragment; just use its id() */ PyObject *id = PyLong_FromVoidPtr(node); if (id == NULL) return -1; index = PyObject_Str(id); Py_DECREF(id); } if (index == NULL) return -1; if (PyList_Append(buffer, index) < 0) { Py_DECREF(index); return -1; } Py_DECREF(index); } return 0; }
PyObject *LOOKUP_ATTRIBUTE_CLASS_SLOT(PyObject *source) { CHECK_OBJECT(source); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = _PyType_Lookup(type, const_str_plain___class__); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); #if PYTHON_VERSION < 300 if (PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS)) { #endif func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 300 } #endif } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) tsize = -tsize; size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *result = PyDict_GetItem(dict, const_str_plain___class__); if (result != NULL) { Py_INCREF(result); Py_XDECREF(descr); Py_DECREF(dict); CHECK_OBJECT(result); return result; } Py_DECREF(dict); } if (func != NULL) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); CHECK_OBJECT(result); return result; } if (descr != NULL) { CHECK_OBJECT(descr); return descr; } PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '__class__'", type->tp_name); return NULL; } #if PYTHON_VERSION < 300 else if (type->tp_getattro == PyInstance_Type.tp_getattro) { PyInstanceObject *source_instance = (PyInstanceObject *)source; PyObject *result = (PyObject *)source_instance->in_class; Py_INCREF(result); return result; } #endif else if (type->tp_getattro != NULL) { PyObject *result = (*type->tp_getattro)(source, const_str_plain___class__); if (unlikely(result == NULL)) { return NULL; } CHECK_OBJECT(result); return result; } else if (type->tp_getattr != NULL) { PyObject *result = (*type->tp_getattr)(source, (char *)"__class__"); return result; } else { PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '__class__'", type->tp_name); return NULL; } }
PyObject *LOOKUP_ATTRIBUTE(PyObject *source, PyObject *attr_name) { /* Note: There are 2 specializations of this function, that need to be * updated in line with this: LOOKUP_ATTRIBUTE_[DICT|CLASS]_SLOT */ CHECK_OBJECT(source); CHECK_OBJECT(attr_name); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = _PyType_Lookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); #if PYTHON_VERSION < 300 if (PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS)) { #endif func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 300 } #endif } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) tsize = -tsize; size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *result = PyDict_GetItem(dict, attr_name); if (result != NULL) { Py_INCREF(result); Py_XDECREF(descr); Py_DECREF(dict); CHECK_OBJECT(result); return result; } Py_DECREF(dict); } if (func != NULL) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); CHECK_OBJECT(result); return result; } if (descr != NULL) { CHECK_OBJECT(descr); return descr; } #if PYTHON_VERSION < 300 PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #if PYTHON_VERSION < 300 else if (type->tp_getattro == PyInstance_Type.tp_getattro) { PyObject *result = LOOKUP_INSTANCE(source, attr_name); return result; } #endif else if (type->tp_getattro != NULL) { PyObject *result = (*type->tp_getattro)(source, attr_name); if (unlikely(result == NULL)) { return NULL; } CHECK_OBJECT(result); return result; } else if (type->tp_getattr != NULL) { PyObject *result = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); return result; } else { PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } }
static PyObject * normalizeUserObj(PyObject *obj) { PyCFunctionObject *fn; if (!PyCFunction_Check(obj)) { Py_INCREF(obj); return obj; } /* Replace built-in function objects with a descriptive string because of built-in methods -- keeping a reference to __self__ is probably not a good idea. */ fn = (PyCFunctionObject *)obj; if (fn->m_self == NULL) { /* built-in function: look up the module name */ PyObject *mod = fn->m_module; const char *modname; if (mod && PyUnicode_Check(mod)) { /* XXX: The following will truncate module names with embedded * null-characters. It is unlikely that this can happen in * practice and the concequences are not serious enough to * introduce extra checks here. */ modname = _PyUnicode_AsString(mod); if (modname == NULL) { modname = "<encoding error>"; PyErr_Clear(); } } else if (mod && PyModule_Check(mod)) { modname = PyModule_GetName(mod); if (modname == NULL) { PyErr_Clear(); modname = "builtins"; } } else { modname = "builtins"; } if (strcmp(modname, "builtins") != 0) return PyUnicode_FromFormat("<%s.%s>", modname, fn->m_ml->ml_name); else return PyUnicode_FromFormat("<%s>", fn->m_ml->ml_name); } else { /* built-in method: try to return repr(getattr(type(__self__), __name__)) */ PyObject *self = fn->m_self; PyObject *name = PyUnicode_FromString(fn->m_ml->ml_name); if (name != NULL) { PyObject *mo = _PyType_Lookup(Py_TYPE(self), name); Py_XINCREF(mo); Py_DECREF(name); if (mo != NULL) { PyObject *res = PyObject_Repr(mo); Py_DECREF(mo); if (res != NULL) return res; } } PyErr_Clear(); return PyUnicode_FromFormat("<built-in method %s>", fn->m_ml->ml_name); } }
int PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value) { PyTypeObject *tp = obj->ob_type; PyObject *descr; descrsetfunc f; PyObject **dictptr; int res = -1; #ifdef Py_USING_UNICODE /* The Unicode to string conversion is done here because the existing tp_setattro slots expect a string object as name and we wouldn't want to break those. */ if (PyUnicode_Check(name)) { name = PyUnicode_AsEncodedString(name, NULL, NULL); if (name == NULL) return -1; } else #endif if (!PyString_Check(name)){ PyErr_SetString(PyExc_TypeError, "attribute name must be string"); return -1; } else Py_INCREF(name); if (tp->tp_dict == NULL) { if (PyType_Ready(tp) < 0) goto done; } descr = _PyType_Lookup(tp, name); f = NULL; if (descr != NULL) { f = descr->ob_type->tp_descr_set; if (f != NULL && PyDescr_IsData(descr)) { res = f(descr, obj, value); goto done; } } dictptr = _PyObject_GetDictPtr(obj); if (dictptr != NULL) { PyObject *dict = *dictptr; if (dict == NULL && value != NULL) { dict = PyDict_New(); if (dict == NULL) goto done; *dictptr = dict; } if (dict != NULL) { if (value == NULL) res = PyDict_DelItem(dict, name); else res = PyDict_SetItem(dict, name, value); if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) PyErr_SetObject(PyExc_AttributeError, name); goto done; } } if (f != NULL) { res = f(descr, obj, value); goto done; } if (descr == NULL) { PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", tp->tp_name, PyString_AS_STRING(name)); goto done; } PyErr_Format(PyExc_AttributeError, "'%.50s' object attribute '%.400s' is read-only", tp->tp_name, PyString_AS_STRING(name)); done: Py_DECREF(name); return res; }