/* 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; }
/* Coerce two numeric types to the "larger" one. Increment the reference count on each argument. Return value: -1 if an error occurred; 0 if the coercion succeeded (and then the reference counts are increased); 1 if no coercion is possible (and no error is raised). */ int PyNumber_CoerceEx(PyObject **pv, PyObject **pw) { register PyObject *v = *pv; register PyObject *w = *pw; int res; /* Shortcut only for old-style types */ if (v->ob_type == w->ob_type && !PyType_HasFeature(v->ob_type, Py_TPFLAGS_CHECKTYPES)) { Py_INCREF(v); Py_INCREF(w); return 0; } if (v->ob_type->tp_as_number && v->ob_type->tp_as_number->nb_coerce) { res = (*v->ob_type->tp_as_number->nb_coerce)(pv, pw); if (res <= 0) return res; } if (w->ob_type->tp_as_number && w->ob_type->tp_as_number->nb_coerce) { res = (*w->ob_type->tp_as_number->nb_coerce)(pw, pv); if (res <= 0) return res; } return 1; }
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 ); }
/* Taken from http://bugs.python.org/issue8212 * A function to do the necessary adjustments if we find that code * run during a tp_dealloc or tp_free has resurrected an * object. It adjusts the total reference count and adds a new * reference to the type. */ static void resurrect_object(PyObject *self) { /* The object lives again. We must now undo the _Py_ForgetReference * done in _Py_Dealloc in object.c. */ Py_ssize_t refcnt = Py_REFCNT(self); ASSERT(Py_REFCNT(self) != 0); _Py_NewReference(self); Py_REFCNT(self) = refcnt; /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so * we need to undo that. */ _Py_DEC_REFTOTAL; /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object * chain, so no more to do there. * If COUNT_ALLOCS, the original decref bumped tp_frees, and * _Py_NewReference bumped tp_allocs: both of those need to be * undone. */ #ifdef COUNT_ALLOCS --Py_TYPE(self)->tp_frees; --Py_TYPE(self)->tp_allocs; #endif /* When called from a heap type's dealloc (subtype_dealloc avove), the type will be * decref'ed on return. This counteracts that. There is no way to otherwise * let subtype_dealloc know that calling a parent class' tp_dealloc slot caused * the instance to be resurrected. */ if (PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE)) Py_INCREF(Py_TYPE(self)); return; }
Py_ssize_t PyBuffer_GetMemory(PyObject* buffer, const char** pp) { PyBufferProcs* procs = buffer->ob_type->tp_as_buffer; if (!procs || !PyType_HasFeature(buffer->ob_type, Py_TPFLAGS_HAVE_GETCHARBUFFER)) { // Can't access the memory directly because the buffer object doesn't support it. return -1; } if (procs->bf_getsegcount(buffer, 0) != 1) { // Can't access the memory directly because there is more than one segment. return -1; } #if PY_VERSION_HEX >= 0x02050000 char* pT = 0; #else const char* pT = 0; #endif Py_ssize_t cb = procs->bf_getcharbuffer(buffer, 0, &pT); if (pp) *pp = pT; return cb; }
/* This function should be as fast as possible, so we don't call PyType_stgdict above but inline the code, and avoid the PyType_Check(). */ StgDictObject * PyObject_stgdict(PyObject *self) { PyTypeObject *type = self->ob_type; if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_CLASS)) return NULL; if (!type->tp_dict || !StgDict_CheckExact(type->tp_dict)) return NULL; return (StgDictObject *)type->tp_dict; }
static int wrap_setattro(PyObject *self, PyObject *name, PyObject *value) { PyObject *wrapped; PyObject *descriptor; const char *name_as_string; int res = -1; #if PY_MAJOR_VERSION < 3 && defined(Py_USING_UNICODE) /* The Unicode to string conversion is done here because the existing tp_setattro slots expect a string object as name (except under Python 3) 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 (!IS_STRING(name)){ PyErr_SetString(PyExc_TypeError, "attribute name must be string"); return -1; } else Py_INCREF(name); descriptor = WrapperType_Lookup(self->ob_type, name); if (descriptor != NULL #if PY_MAJOR_VERSION < 3 // This is always true in Python 3 (I think) && PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) #endif && descriptor->ob_type->tp_descr_set != NULL) { res = descriptor->ob_type->tp_descr_set(descriptor, self, value); goto finally; } name_as_string = MAKE_STRING(name); wrapped = Proxy_GET_OBJECT(self); if (wrapped == NULL) { PyErr_Format(PyExc_RuntimeError, "object is NULL; requested to set attribute '%s'", name_as_string); goto finally; } res = PyObject_SetAttr(wrapped, name, value); finally: Py_DECREF(name); return res; }
static PyObject *entity_setstate(PyObject *self, PyObject *state) { PyObject *dict, *public_id, *system_id, *unparsed_entities, *children, *temp; Py_ssize_t i, n; if (!PyArg_UnpackTuple(state, NULL, 5, 5, &dict, &public_id, &system_id, &unparsed_entities, &children)) return NULL; if (!convert_arg(0, &PyDict_Type, &dict)) return NULL; if (!convert_arg(3, &PyDict_Type, &unparsed_entities)) return NULL; if (!convert_arg(4, &PyTuple_Type, &children)) return NULL; if (dict) { if (PyType_HasFeature(self->ob_type, Py_TPFLAGS_HEAPTYPE)) { temp = PyObject_GetAttrString(self, "__dict__"); if (temp == NULL) return NULL; if (PyDict_Update(temp, dict) < 0) { Py_DECREF(temp); return NULL; } Py_DECREF(temp); } } temp = Entity_GET_PUBLIC_ID(self); Entity_SET_PUBLIC_ID(self, public_id); Py_INCREF(public_id); Py_DECREF(temp); temp = Entity_GET_SYSTEM_ID(self); Entity_SET_SYSTEM_ID(self, system_id); Py_INCREF(system_id); Py_DECREF(temp); if (unparsed_entities) { temp = Entity_GET_UNPARSED_ENTITIES(self); PyDict_Clear(temp); if (PyDict_Update(temp, unparsed_entities) < 0) return NULL; } if (children) { for (i = 0, n = PyTuple_GET_SIZE(children); i < n; i++) { NodeObject *node = (NodeObject *)PyTuple_GET_ITEM(children, i); if (Container_Append((NodeObject *)self, node) < 0) return NULL; } } Py_RETURN_NONE; }
/* Return true if object has a finalization method. * CAUTION: An instance of an old-style class has to be checked for a *__del__ method, and earlier versions of this used to call PyObject_HasAttr, * which in turn could call the class's __getattr__ hook (if any). That * could invoke arbitrary Python code, mutating the object graph in arbitrary * ways, and that was the source of some excruciatingly subtle bugs. */ static int has_finalizer(PyObject *op) { if (PyInstance_Check(op)) { assert(delstr != NULL); return _PyInstance_Lookup(op, delstr) != NULL; } else if (PyType_HasFeature(op->ob_type, Py_TPFLAGS_HEAPTYPE)) return op->ob_type->tp_del != NULL; else return 0; }
static PyObject *node_getstate(PyObject *self, PyObject *args) { PyObject *deep=Py_True; if (!PyArg_ParseTuple(args, "|O:__getstate__", &deep)) return NULL; if (PyType_HasFeature(self->ob_type, Py_TPFLAGS_HEAPTYPE)) return PyObject_GetAttrString(self, "__dict__"); Py_RETURN_NONE; }
static int wrap_setattro(PyObject *self, PyObject *name, PyObject *value) { PyObject *wrapped; PyObject *descriptor; 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); descriptor = WrapperType_Lookup(self->ob_type, name); if (descriptor != NULL) { if (PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) && descriptor->ob_type->tp_descr_set != NULL) { res = descriptor->ob_type->tp_descr_set(descriptor, self, value); } else { PyErr_Format(PyExc_TypeError, "Tried to set attribute '%s' on wrapper, but it is not" " a data descriptor", PyString_AS_STRING(name)); } goto finally; } wrapped = Proxy_GET_OBJECT(self); if (wrapped == NULL) { PyErr_Format(PyExc_RuntimeError, "object is NULL; requested to set attribute '%s'", PyString_AS_STRING(name)); goto finally; } res = PyObject_SetAttr(wrapped, name, value); finally: Py_DECREF(name); return res; }
/* May return NULL, but does not set an exception! */ StgDictObject * PyType_stgdict(PyObject *obj) { PyTypeObject *type; if (!PyType_Check(obj)) return NULL; type = (PyTypeObject *)obj; if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_CLASS)) return NULL; if (!type->tp_dict || !StgDict_CheckExact(type->tp_dict)) return NULL; return (StgDictObject *)type->tp_dict; }
static PyObject *node_setstate(PyObject *self, PyObject *state) { PyObject *dict; if (PyType_HasFeature(self->ob_type, Py_TPFLAGS_HEAPTYPE)) { dict = PyObject_GetAttrString(self, "__dict__"); if (dict == NULL) return NULL; if (PyDict_Update(dict, state) < 0) { Py_DECREF(dict); return NULL; } Py_DECREF(dict); } else if (state != Py_None) return PyErr_Format(PyExc_NotImplementedError, "subclass '%s' must override __setstate__()", self->ob_type->tp_name); Py_RETURN_NONE; }
static PyObject *entity_getstate(PyObject *self, PyObject *args) { PyObject *deep=Py_True, *dict, *unparsed_entities, *children; Py_ssize_t i; if (!PyArg_ParseTuple(args, "|O:__getstate__", &deep)) return NULL; if (PyType_HasFeature(self->ob_type, Py_TPFLAGS_HEAPTYPE)) { dict = PyObject_GetAttrString(self, "__dict__"); if (dict == NULL) return NULL; } else { dict = Py_None; Py_INCREF(Py_None); } /* save the child nodes in a tuple */ switch (PyObject_IsTrue(deep)) { case 0: unparsed_entities = Py_None; children = Py_None; Py_INCREF(children); break; case 1: unparsed_entities = Entity_GET_UNPARSED_ENTITIES(self); children = PyTuple_New(Container_GET_COUNT(self)); if (children != NULL) { for (i = 0; i < Container_GET_COUNT(self); i++) { PyObject *item = (PyObject *)Container_GET_CHILD(self, i); PyTuple_SET_ITEM(children, i, item); Py_INCREF(item); } break; } /* error; fall through */ default: Py_DECREF(dict); return NULL; } return Py_BuildValue("NOOON", dict, Entity_GET_PUBLIC_ID(self), Entity_GET_SYSTEM_ID(self), unparsed_entities, children); }
DEFINEFN vinfo_t* PsycoSequence_Contains(PsycoObject* po, vinfo_t* seq, vinfo_t* ob) { PyTypeObject* tp = Psyco_NeedType(po, seq); if (tp == NULL) return false; if (PyType_HasFeature(tp, Py_TPFLAGS_HAVE_SEQUENCE_IN)) { PySequenceMethods *sqm = tp->tp_as_sequence; if (sqm != NULL && sqm->sq_contains != NULL) return Psyco_META2(po, sqm->sq_contains, CfReturnNormal|CfPyErrIfNeg, "vv", seq, ob); } /* XXX implement me */ return psyco_generic_call(po, _PySequence_IterSearch, CfReturnNormal|CfPyErrIfNeg, "vvl", seq, ob, PY_ITERSEARCH_CONTAINS); }
int PySequence_Contains(PyObject *w, PyObject *v) /* v in w */ { int i, cmp; PyObject *x; PySequenceMethods *sq; if(PyType_HasFeature(w->ob_type, Py_TPFLAGS_HAVE_SEQUENCE_IN)) { sq = w->ob_type->tp_as_sequence; if(sq != NULL && sq->sq_contains != NULL) return (*sq->sq_contains)(w, v); } /* If there is no better way to check whether an item is is contained, do it the hard way */ sq = w->ob_type->tp_as_sequence; if (sq == NULL || sq->sq_item == NULL) { PyErr_SetString(PyExc_TypeError, "'in' or 'not in' needs sequence right argument"); return -1; } for (i = 0; ; i++) { x = (*sq->sq_item)(w, i); if (x == NULL) { if (PyErr_ExceptionMatches(PyExc_IndexError)) { PyErr_Clear(); break; } return -1; } cmp = PyObject_Compare(v, x); Py_XDECREF(x); if (cmp == 0) return 1; if (PyErr_Occurred()) return -1; } return 0; }
static void iobase_dealloc(iobase *self) { /* NOTE: since IOBaseObject has its own dict, Python-defined attributes are still available here for close() to use. However, if the derived class declares a __slots__, those slots are already gone. */ if (_PyIOBase_finalize((PyObject *) self) < 0) { /* When called from a heap type's dealloc, the type will be decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */ if (PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE)) Py_INCREF(Py_TYPE(self)); return; } _PyObject_GC_UNTRACK(self); if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); Py_CLEAR(self->dict); Py_TYPE(self)->tp_free((PyObject *) self); }
DEFINEFN vinfo_t* PsycoObject_GetIter(PsycoObject* po, vinfo_t* vi) { getiterfunc f; PyTypeObject* t = Psyco_NeedType(po, vi); if (t == NULL) return NULL; if (PyType_HasFeature(t, Py_TPFLAGS_HAVE_ITER)) f = t->tp_iter; else f = NULL; if (f == NULL) { if (PsycoSequence_Check(t)) return PsycoSeqIter_New(po, vi); PycException_SetString(po, PyExc_TypeError, "iteration over non-sequence"); return NULL; } else { return Psyco_META1(po, f, CfReturnRef|CfPyErrIfNull, "v", vi); } }
static PyObject * wrap_getattro(PyObject *self, PyObject *name) { PyObject *wrapped; PyObject *descriptor; PyObject *res = NULL; char *name_as_string; int maybe_special_name; #ifdef Py_USING_UNICODE /* The Unicode to string conversion is done here because the existing tp_getattro 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 if (!PyString_Check(name)){ PyErr_SetString(PyExc_TypeError, "attribute name must be string"); return NULL; } else Py_INCREF(name); name_as_string = PyString_AS_STRING(name); wrapped = Proxy_GET_OBJECT(self); if (wrapped == NULL) { PyErr_Format(PyExc_RuntimeError, "object is NULL; requested to get attribute '%s'", name_as_string); goto finally; } maybe_special_name = name_as_string[0] == '_' && name_as_string[1] == '_'; if (!(maybe_special_name && strcmp(name_as_string, "__class__") == 0)) { descriptor = WrapperType_Lookup(self->ob_type, name); if (descriptor != NULL) { if (PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) && descriptor->ob_type->tp_descr_get != NULL) { res = descriptor->ob_type->tp_descr_get( descriptor, self, (PyObject *)self->ob_type); } else { Py_INCREF(descriptor); res = descriptor; } goto finally; } } res = PyObject_GetAttr(wrapped, name); finally: Py_DECREF(name); return res; }
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; } }
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 * 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 int get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size, enum buffer_t buffer_type) { if (self->b_base == NULL) { assert (ptr != NULL); *ptr = self->b_ptr; *size = self->b_size; } else { Py_ssize_t count, offset; readbufferproc proc = 0; PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer; if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) { PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected"); return 0; } if ((buffer_type == READ_BUFFER) || ((buffer_type == ANY_BUFFER) && self->b_readonly)) proc = bp->bf_getreadbuffer; else if ((buffer_type == WRITE_BUFFER) || (buffer_type == ANY_BUFFER)) proc = (readbufferproc)bp->bf_getwritebuffer; else if (buffer_type == CHAR_BUFFER) { if (!PyType_HasFeature(self->ob_type, Py_TPFLAGS_HAVE_GETCHARBUFFER)) { PyErr_SetString(PyExc_TypeError, "Py_TPFLAGS_HAVE_GETCHARBUFFER needed"); return 0; } proc = (readbufferproc)bp->bf_getcharbuffer; } if (!proc) { char *buffer_type_name; switch (buffer_type) { case READ_BUFFER: buffer_type_name = "read"; break; case WRITE_BUFFER: buffer_type_name = "write"; break; case CHAR_BUFFER: buffer_type_name = "char"; break; default: buffer_type_name = "no"; break; } PyErr_Format(PyExc_TypeError, "%s buffer type not available", buffer_type_name); return 0; } if ((count = (*proc)(self->b_base, 0, ptr)) < 0) return 0; /* apply constraints to the start/end */ if (self->b_offset > count) offset = count; else offset = self->b_offset; *(char **)ptr = *(char **)ptr + offset; if (self->b_size == Py_END_OF_BUFFER) *size = count; else *size = self->b_size; if (offset + *size > count) *size = count - offset; } return 1; }
PyObject * PyObject_GenericGetAttr(PyObject *obj, PyObject *name) { PyTypeObject *tp = obj->ob_type; PyObject *descr = NULL; PyObject *res = NULL; descrgetfunc f; Py_ssize_t 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_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name); return NULL; } } else Py_INCREF(name); if (tp->tp_dict == NULL) { if (PyType_Ready(tp) < 0) goto done; } /* Inline _PyType_Lookup */ { Py_ssize_t 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; } } 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) { Py_ssize_t 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) { res = PyDict_GetItem(dict, name); if (res != NULL) { Py_INCREF(res); Py_XDECREF(descr); goto done; } } } 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; } PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", tp->tp_name, PyString_AS_STRING(name)); done: Py_DECREF(name); return res; }
int PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value) { PyTypeObject *tp = obj->ob_type; PyObject *descr; descrsetfunc f; PyObject **dictptr; int res = -1; 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 -1; } else #endif { PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name); 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 && PyType_HasFeature(descr->ob_type, Py_TPFLAGS_HAVE_CLASS)) { 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, "'%.100s' object has no attribute '%.200s'", 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; }