#include "Python.h"
#include "pycore_call.h"
#include "pycore_ceval.h"
#include "pycore_context.h"
#include "pycore_dict.h"
#include "pycore_floatobject.h"
#include "pycore_initconfig.h"
#include "pycore_namespace.h"
#include "pycore_object.h"
#include "pycore_pyerrors.h"
#include "pycore_pymem.h"
#include "pycore_pystate.h"
#include "pycore_symtable.h"
#include "pycore_typevarobject.h"
#include "pycore_typeobject.h"
#include "pycore_unionobject.h"
#include "interpreteridobject.h"
#ifdef Py_LIMITED_API
# error "Py_LIMITED_API macro must not be defined"
#endif
#ifdef __cplusplus
extern "C" {
#endif
extern void _PyMem_DumpTraceback(int fd, const void *ptr);
int
_PyObject_CheckConsistency(PyObject *op, int check_content)
{
#define CHECK(expr) \
do { if (!(expr)) { _PyObject_ASSERT_FAILED_MSG(op, Py_STRINGIFY(expr)); } } while (0)
CHECK(!_PyObject_IsFreed(op));
CHECK(Py_REFCNT(op) >= 1);
_PyType_CheckConsistency(Py_TYPE(op));
if (PyUnicode_Check(op)) {
_PyUnicode_CheckConsistency(op, check_content);
}
else if (PyDict_Check(op)) {
_PyDict_CheckConsistency(op, check_content);
}
return 1;
#undef CHECK
}
#ifdef Py_REF_DEBUG
Py_ssize_t _Py_RefTotal;
static inline Py_ssize_t
get_legacy_reftotal(void)
{
return _Py_RefTotal;
}
#endif
#ifdef Py_REF_DEBUG
# define REFTOTAL(interp) \
interp->object_state.reftotal
static inline void
reftotal_increment(PyInterpreterState *interp)
{
REFTOTAL(interp)++;
}
static inline void
reftotal_decrement(PyInterpreterState *interp)
{
REFTOTAL(interp)--;
}
static inline void
reftotal_add(PyInterpreterState *interp, Py_ssize_t n)
{
REFTOTAL(interp) += n;
}
static inline Py_ssize_t get_global_reftotal(_PyRuntimeState *);
static Py_ssize_t last_final_reftotal = 0;
void
_Py_FinalizeRefTotal(_PyRuntimeState *runtime)
{
last_final_reftotal = get_global_reftotal(runtime);
runtime->object_state.interpreter_leaks = 0;
}
void
_PyInterpreterState_FinalizeRefTotal(PyInterpreterState *interp)
{
interp->runtime->object_state.interpreter_leaks += REFTOTAL(interp);
REFTOTAL(interp) = 0;
}
static inline Py_ssize_t
get_reftotal(PyInterpreterState *interp)
{
return REFTOTAL(interp);
}
static inline Py_ssize_t
get_global_reftotal(_PyRuntimeState *runtime)
{
Py_ssize_t total = 0;
HEAD_LOCK(&_PyRuntime);
PyInterpreterState *interp = PyInterpreterState_Head();
for (; interp != NULL; interp = PyInterpreterState_Next(interp)) {
total += REFTOTAL(interp);
}
HEAD_UNLOCK(&_PyRuntime);
total += get_legacy_reftotal();
total += last_final_reftotal;
total += runtime->object_state.interpreter_leaks;
return total;
}
#undef REFTOTAL
void
_PyDebug_PrintTotalRefs(void) {
_PyRuntimeState *runtime = &_PyRuntime;
fprintf(stderr,
"[%zd refs, %zd blocks]\n",
get_global_reftotal(runtime), _Py_GetGlobalAllocatedBlocks());
}
#endif
#ifdef Py_TRACE_REFS
static PyObject refchain = {&refchain, &refchain};
void
_Py_AddToAllObjects(PyObject *op, int force)
{
#ifdef Py_DEBUG
if (!force) {
_PyObject_ASSERT(op, (op->_ob_prev == NULL) == (op->_ob_next == NULL));
}
#endif
if (force || op->_ob_prev == NULL) {
op->_ob_next = refchain._ob_next;
op->_ob_prev = &refchain;
refchain._ob_next->_ob_prev = op;
refchain._ob_next = op;
}
}
#endif
#ifdef Py_REF_DEBUG
void
_Py_NegativeRefcount(const char *filename, int lineno, PyObject *op)
{
_PyObject_AssertFailed(op, NULL, "object has negative ref count",
filename, lineno, __func__);
}
void
_Py_IncRefTotal_DO_NOT_USE_THIS(void)
{
reftotal_increment(_PyInterpreterState_GET());
}
void
_Py_DecRefTotal_DO_NOT_USE_THIS(void)
{
reftotal_decrement(_PyInterpreterState_GET());
}
void
_Py_IncRefTotal(PyInterpreterState *interp)
{
reftotal_increment(interp);
}
void
_Py_DecRefTotal(PyInterpreterState *interp)
{
reftotal_decrement(interp);
}
void
_Py_AddRefTotal(PyInterpreterState *interp, Py_ssize_t n)
{
reftotal_add(interp, n);
}
Py_ssize_t
_Py_GetGlobalRefTotal(void)
{
return get_global_reftotal(&_PyRuntime);
}
Py_ssize_t
_Py_GetLegacyRefTotal(void)
{
return get_legacy_reftotal();
}
Py_ssize_t
_PyInterpreterState_GetRefTotal(PyInterpreterState *interp)
{
return get_reftotal(interp);
}
#endif
void
Py_IncRef(PyObject *o)
{
Py_XINCREF(o);
}
void
Py_DecRef(PyObject *o)
{
Py_XDECREF(o);
}
void
_Py_IncRef(PyObject *o)
{
Py_INCREF(o);
}
void
_Py_DecRef(PyObject *o)
{
Py_DECREF(o);
}
PyObject *
PyObject_Init(PyObject *op, PyTypeObject *tp)
{
if (op == NULL) {
return PyErr_NoMemory();
}
_PyObject_Init(op, tp);
return op;
}
PyVarObject *
PyObject_InitVar(PyVarObject *op, PyTypeObject *tp, Py_ssize_t size)
{
if (op == NULL) {
return (PyVarObject *) PyErr_NoMemory();
}
_PyObject_InitVar(op, tp, size);
return op;
}
PyObject *
_PyObject_New(PyTypeObject *tp)
{
PyObject *op = (PyObject *) PyObject_Malloc(_PyObject_SIZE(tp));
if (op == NULL) {
return PyErr_NoMemory();
}
_PyObject_Init(op, tp);
return op;
}
PyVarObject *
_PyObject_NewVar(PyTypeObject *tp, Py_ssize_t nitems)
{
PyVarObject *op;
const size_t size = _PyObject_VAR_SIZE(tp, nitems);
op = (PyVarObject *) PyObject_Malloc(size);
if (op == NULL) {
return (PyVarObject *)PyErr_NoMemory();
}
_PyObject_InitVar(op, tp, nitems);
return op;
}
void
PyObject_CallFinalizer(PyObject *self)
{
PyTypeObject *tp = Py_TYPE(self);
if (tp->tp_finalize == NULL)
return;
if (_PyType_IS_GC(tp) && _PyGC_FINALIZED(self))
return;
tp->tp_finalize(self);
if (_PyType_IS_GC(tp)) {
_PyGC_SET_FINALIZED(self);
}
}
int
PyObject_CallFinalizerFromDealloc(PyObject *self)
{
if (Py_REFCNT(self) != 0) {
_PyObject_ASSERT_FAILED_MSG(self,
"PyObject_CallFinalizerFromDealloc called "
"on object with a non-zero refcount");
}
Py_SET_REFCNT(self, 1);
PyObject_CallFinalizer(self);
_PyObject_ASSERT_WITH_MSG(self,
Py_REFCNT(self) > 0,
"refcount is too small");
Py_SET_REFCNT(self, Py_REFCNT(self) - 1);
if (Py_REFCNT(self) == 0) {
return 0;
}
Py_ssize_t refcnt = Py_REFCNT(self);
_Py_NewReferenceNoTotal(self);
Py_SET_REFCNT(self, refcnt);
_PyObject_ASSERT(self,
(!_PyType_IS_GC(Py_TYPE(self))
|| _PyObject_GC_IS_TRACKED(self)));
return -1;
}
int
PyObject_Print(PyObject *op, FILE *fp, int flags)
{
int ret = 0;
if (PyErr_CheckSignals())
return -1;
#ifdef USE_STACKCHECK
if (PyOS_CheckStack()) {
PyErr_SetString(PyExc_MemoryError, "stack overflow");
return -1;
}
#endif
clearerr(fp);
if (op == NULL) {
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "<nil>");
Py_END_ALLOW_THREADS
}
else {
if (Py_REFCNT(op) <= 0) {
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "<refcnt %zd at %p>", Py_REFCNT(op), (void *)op);
Py_END_ALLOW_THREADS
}
else {
PyObject *s;
if (flags & Py_PRINT_RAW)
s = PyObject_Str(op);
else
s = PyObject_Repr(op);
if (s == NULL) {
ret = -1;
}
else {
assert(PyUnicode_Check(s));
const char *t;
Py_ssize_t len;
t = PyUnicode_AsUTF8AndSize(s, &len);
if (t == NULL) {
ret = -1;
}
else {
fwrite(t, 1, len, fp);
}
Py_DECREF(s);
}
}
}
if (ret == 0) {
if (ferror(fp)) {
PyErr_SetFromErrno(PyExc_OSError);
clearerr(fp);
ret = -1;
}
}
return ret;
}
void
_Py_BreakPoint(void)
{
}
int
_PyObject_IsFreed(PyObject *op)
{
if (_PyMem_IsPtrFreed(op) || _PyMem_IsPtrFreed(Py_TYPE(op))) {
return 1;
}
#ifdef Py_TRACE_REFS
if (op->_ob_next != NULL && _PyMem_IsPtrFreed(op->_ob_next)) {
return 1;
}
if (op->_ob_prev != NULL && _PyMem_IsPtrFreed(op->_ob_prev)) {
return 1;
}
#endif
return 0;
}
void
_PyObject_Dump(PyObject* op)
{
if (_PyObject_IsFreed(op)) {
fprintf(stderr, "<object at %p is freed>\n", op);
fflush(stderr);
return;
}
fprintf(stderr, "object address : %p\n", (void *)op);
fprintf(stderr, "object refcount : %zd\n", Py_REFCNT(op));
fflush(stderr);
PyTypeObject *type = Py_TYPE(op);
fprintf(stderr, "object type : %p\n", type);
fprintf(stderr, "object type name: %s\n",
type==NULL ? "NULL" : type->tp_name);
fprintf(stderr, "object repr : ");
fflush(stderr);
PyGILState_STATE gil = PyGILState_Ensure();
PyObject *exc = PyErr_GetRaisedException();
(void)PyObject_Print(op, stderr, 0);
fflush(stderr);
PyErr_SetRaisedException(exc);
PyGILState_Release(gil);
fprintf(stderr, "\n");
fflush(stderr);
}
PyObject *
PyObject_Repr(PyObject *v)
{
PyObject *res;
if (PyErr_CheckSignals())
return NULL;
#ifdef USE_STACKCHECK
if (PyOS_CheckStack()) {
PyErr_SetString(PyExc_MemoryError, "stack overflow");
return NULL;
}
#endif
if (v == NULL)
return PyUnicode_FromString("<NULL>");
if (Py_TYPE(v)->tp_repr == NULL)
return PyUnicode_FromFormat("<%s object at %p>",
Py_TYPE(v)->tp_name, v);
PyThreadState *tstate = _PyThreadState_GET();
#ifdef Py_DEBUG
assert(!_PyErr_Occurred(tstate));
#endif
if (_Py_EnterRecursiveCallTstate(tstate,
" while getting the repr of an object")) {
return NULL;
}
res = (*Py_TYPE(v)->tp_repr)(v);
_Py_LeaveRecursiveCallTstate(tstate);
if (res == NULL) {
return NULL;
}
if (!PyUnicode_Check(res)) {
_PyErr_Format(tstate, PyExc_TypeError,
"__repr__ returned non-string (type %.200s)",
Py_TYPE(res)->tp_name);
Py_DECREF(res);
return NULL;
}
return res;
}
PyObject *
PyObject_Str(PyObject *v)
{
PyObject *res;
if (PyErr_CheckSignals())
return NULL;
#ifdef USE_STACKCHECK
if (PyOS_CheckStack()) {
PyErr_SetString(PyExc_MemoryError, "stack overflow");
return NULL;
}
#endif
if (v == NULL)
return PyUnicode_FromString("<NULL>");
if (PyUnicode_CheckExact(v)) {
return Py_NewRef(v);
}
if (Py_TYPE(v)->tp_str == NULL)
return PyObject_Repr(v);
PyThreadState *tstate = _PyThreadState_GET();
#ifdef Py_DEBUG
assert(!_PyErr_Occurred(tstate));
#endif
if (_Py_EnterRecursiveCallTstate(tstate, " while getting the str of an object")) {
return NULL;
}
res = (*Py_TYPE(v)->tp_str)(v);
_Py_LeaveRecursiveCallTstate(tstate);
if (res == NULL) {
return NULL;
}
if (!PyUnicode_Check(res)) {
_PyErr_Format(tstate, PyExc_TypeError,
"__str__ returned non-string (type %.200s)",
Py_TYPE(res)->tp_name);
Py_DECREF(res);
return NULL;
}
assert(_PyUnicode_CheckConsistency(res, 1));
return res;
}
PyObject *
PyObject_ASCII(PyObject *v)
{
PyObject *repr, *ascii, *res;
repr = PyObject_Repr(v);
if (repr == NULL)
return NULL;
if (PyUnicode_IS_ASCII(repr))
return repr;
ascii = _PyUnicode_AsASCIIString(repr, "backslashreplace");
Py_DECREF(repr);
if (ascii == NULL)
return NULL;
res = PyUnicode_DecodeASCII(
PyBytes_AS_STRING(ascii),
PyBytes_GET_SIZE(ascii),
NULL);
Py_DECREF(ascii);
return res;
}
PyObject *
PyObject_Bytes(PyObject *v)
{
PyObject *result, *func;
if (v == NULL)
return PyBytes_FromString("<NULL>");
if (PyBytes_CheckExact(v)) {
return Py_NewRef(v);
}
func = _PyObject_LookupSpecial(v, &_Py_ID(__bytes__));
if (func != NULL) {
result = _PyObject_CallNoArgs(func);
Py_DECREF(func);
if (result == NULL)
return NULL;
if (!PyBytes_Check(result)) {
PyErr_Format(PyExc_TypeError,
"__bytes__ returned non-bytes (type %.200s)",
Py_TYPE(result)->tp_name);
Py_DECREF(result);
return NULL;
}
return result;
}
else if (PyErr_Occurred())
return NULL;
return PyBytes_FromObject(v);
}
PyObject *
_PyObject_FunctionStr(PyObject *x)
{
assert(!PyErr_Occurred());
PyObject *qualname;
int ret = _PyObject_LookupAttr(x, &_Py_ID(__qualname__), &qualname);
if (qualname == NULL) {
if (ret < 0) {
return NULL;
}
return PyObject_Str(x);
}
PyObject *module;
PyObject *result = NULL;
ret = _PyObject_LookupAttr(x, &_Py_ID(__module__), &module);
if (module != NULL && module != Py_None) {
ret = PyObject_RichCompareBool(module, &_Py_ID(builtins), Py_NE);
if (ret < 0) {
goto done;
}
if (ret > 0) {
result = PyUnicode_FromFormat("%S.%S()", module, qualname);
goto done;
}
}
else if (ret < 0) {
goto done;
}
result = PyUnicode_FromFormat("%S()", qualname);
done:
Py_DECREF(qualname);
Py_XDECREF(module);
return result;
}
int _Py_SwappedOp[] = {Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE};
static const char * const opstrings[] = {"<", "<=", "==", "!=", ">", ">="};
static PyObject *
do_richcompare(PyThreadState *tstate, PyObject *v, PyObject *w, int op)
{
richcmpfunc f;
PyObject *res;
int checked_reverse_op = 0;
if (!Py_IS_TYPE(v, Py_TYPE(w)) &&
PyType_IsSubtype(Py_TYPE(w), Py_TYPE(v)) &&
(f = Py_TYPE(w)->tp_richcompare) != NULL) {
checked_reverse_op = 1;
res = (*f)(w, v, _Py_SwappedOp[op]);
if (res != Py_NotImplemented)
return res;
Py_DECREF(res);
}
if ((f = Py_TYPE(v)->tp_richcompare) != NULL) {
res = (*f)(v, w, op);
if (res != Py_NotImplemented)
return res;
Py_DECREF(res);
}
if (!checked_reverse_op && (f = Py_TYPE(w)->tp_richcompare) != NULL) {
res = (*f)(w, v, _Py_SwappedOp[op]);
if (res != Py_NotImplemented)
return res;
Py_DECREF(res);
}
switch (op) {
case Py_EQ:
res = (v == w) ? Py_True : Py_False;
break;
case Py_NE:
res = (v != w) ? Py_True : Py_False;
break;
default:
_PyErr_Format(tstate, PyExc_TypeError,
"'%s' not supported between instances of '%.100s' and '%.100s'",
opstrings[op],
Py_TYPE(v)->tp_name,
Py_TYPE(w)->tp_name);
return NULL;
}
return Py_NewRef(res);
}
PyObject *
PyObject_RichCompare(PyObject *v, PyObject *w, int op)
{
PyThreadState *tstate = _PyThreadState_GET();
assert(Py_LT <= op && op <= Py_GE);
if (v == NULL || w == NULL) {
if (!_PyErr_Occurred(tstate)) {
PyErr_BadInternalCall();
}
return NULL;
}
if (_Py_EnterRecursiveCallTstate(tstate, " in comparison")) {
return NULL;
}
PyObject *res = do_richcompare(tstate, v, w, op);
_Py_LeaveRecursiveCallTstate(tstate);
return res;
}
int
PyObject_RichCompareBool(PyObject *v, PyObject *w, int op)
{
PyObject *res;
int ok;
if (v == w) {
if (op == Py_EQ)
return 1;
else if (op == Py_NE)
return 0;
}
res = PyObject_RichCompare(v, w, op);
if (res == NULL)
return -1;
if (PyBool_Check(res))
ok = (res == Py_True);
else
ok = PyObject_IsTrue(res);
Py_DECREF(res);
return ok;
}
Py_hash_t
PyObject_HashNotImplemented(PyObject *v)
{
PyErr_Format(PyExc_TypeError, "unhashable type: '%.200s'",
Py_TYPE(v)->tp_name);
return -1;
}
Py_hash_t
PyObject_Hash(PyObject *v)
{
PyTypeObject *tp = Py_TYPE(v);
if (tp->tp_hash != NULL)
return (*tp->tp_hash)(v);
if (!_PyType_IsReady(tp)) {
if (PyType_Ready(tp) < 0)
return -1;
if (tp->tp_hash != NULL)
return (*tp->tp_hash)(v);
}
return PyObject_HashNotImplemented(v);
}
PyObject *
PyObject_GetAttrString(PyObject *v, const char *name)
{
PyObject *w, *res;
if (Py_TYPE(v)->tp_getattr != NULL)
return (*Py_TYPE(v)->tp_getattr)(v, (char*)name);
w = PyUnicode_FromString(name);
if (w == NULL)
return NULL;
res = PyObject_GetAttr(v, w);
Py_DECREF(w);
return res;
}
int
PyObject_HasAttrString(PyObject *v, const char *name)
{
if (Py_TYPE(v)->tp_getattr != NULL) {
PyObject *res = (*Py_TYPE(v)->tp_getattr)(v, (char*)name);
if (res != NULL) {
Py_DECREF(res);
return 1;
}
PyErr_Clear();
return 0;
}
PyObject *attr_name = PyUnicode_FromString(name);
if (attr_name == NULL) {
PyErr_Clear();
return 0;
}
int ok = PyObject_HasAttr(v, attr_name);
Py_DECREF(attr_name);
return ok;
}
int
PyObject_SetAttrString(PyObject *v, const char *name, PyObject *w)
{
PyObject *s;
int res;
if (Py_TYPE(v)->tp_setattr != NULL)
return (*Py_TYPE(v)->tp_setattr)(v, (char*)name, w);
s = PyUnicode_InternFromString(name);
if (s == NULL)
return -1;
res = PyObject_SetAttr(v, s, w);
Py_XDECREF(s);
return res;
}
int
_PyObject_IsAbstract(PyObject *obj)
{
int res;
PyObject* isabstract;
if (obj == NULL)
return 0;
res = _PyObject_LookupAttr(obj, &_Py_ID(__isabstractmethod__), &isabstract);
if (res > 0) {
res = PyObject_IsTrue(isabstract);
Py_DECREF(isabstract);
}
return res;
}
PyObject *
_PyObject_GetAttrId(PyObject *v, _Py_Identifier *name)
{
PyObject *result;
PyObject *oname = _PyUnicode_FromId(name);
if (!oname)
return NULL;
result = PyObject_GetAttr(v, oname);
return result;
}
int
_PyObject_SetAttrId(PyObject *v, _Py_Identifier *name, PyObject *w)
{
int result;
PyObject *oname = _PyUnicode_FromId(name);
if (!oname)
return -1;
result = PyObject_SetAttr(v, oname, w);
return result;
}
static inline int
set_attribute_error_context(PyObject* v, PyObject* name)
{
assert(PyErr_Occurred());
if (!PyErr_ExceptionMatches(PyExc_AttributeError)){
return 0;
}
PyObject *exc = PyErr_GetRaisedException();
if (!PyErr_GivenExceptionMatches(exc, PyExc_AttributeError)) {
goto restore;
}
PyAttributeErrorObject* the_exc = (PyAttributeErrorObject*) exc;
if (the_exc->name || the_exc->obj) {
goto restore;
}
if (PyObject_SetAttr(exc, &_Py_ID(name), name) ||
PyObject_SetAttr(exc, &_Py_ID(obj), v)) {
return 1;
}
restore:
PyErr_SetRaisedException(exc);
return 0;
}
PyObject *
PyObject_GetAttr(PyObject *v, PyObject *name)
{
PyTypeObject *tp = Py_TYPE(v);
if (!PyUnicode_Check(name)) {
PyErr_Format(PyExc_TypeError,
"attribute name must be string, not '%.200s'",
Py_TYPE(name)->tp_name);
return NULL;
}
PyObject* result = NULL;
if (tp->tp_getattro != NULL) {
result = (*tp->tp_getattro)(v, name);
}
else if (tp->tp_getattr != NULL) {
const char *name_str = PyUnicode_AsUTF8(name);
if (name_str == NULL) {
return NULL;
}
result = (*tp->tp_getattr)(v, (char *)name_str);
}
else {
PyErr_Format(PyExc_AttributeError,
"'%.100s' object has no attribute '%U'",
tp->tp_name, name);
}
if (result == NULL) {
set_attribute_error_context(v, name);
}
return result;
}
int
_PyObject_LookupAttr(PyObject *v, PyObject *name, PyObject **result)
{
PyTypeObject *tp = Py_TYPE(v);
if (!PyUnicode_Check(name)) {
PyErr_Format(PyExc_TypeError,
"attribute name must be string, not '%.200s'",
Py_TYPE(name)->tp_name);
*result = NULL;
return -1;
}
if (tp->tp_getattro == PyObject_GenericGetAttr) {
*result = _PyObject_GenericGetAttrWithDict(v, name, NULL, 1);
if (*result != NULL) {
return 1;
}
if (PyErr_Occurred()) {
return -1;
}
return 0;
}
if (tp->tp_getattro == (getattrofunc)_Py_type_getattro) {
int supress_missing_attribute_exception = 0;
*result = _Py_type_getattro_impl((PyTypeObject*)v, name, &supress_missing_attribute_exception);
if (supress_missing_attribute_exception) {
return 0;
}
}
else if (tp->tp_getattro == (getattrofunc)_Py_module_getattro) {
*result = _Py_module_getattro_impl((PyModuleObject*)v, name, 1);
if (*result != NULL) {
return 1;
}
if (PyErr_Occurred()) {
return -1;
}
return 0;
}
else if (tp->tp_getattro != NULL) {
*result = (*tp->tp_getattro)(v, name);
}
else if (tp->tp_getattr != NULL) {
const char *name_str = PyUnicode_AsUTF8(name);
if (name_str == NULL) {
*result = NULL;
return -1;
}
*result = (*tp->tp_getattr)(v, (char *)name_str);
}
else {
*result = NULL;
return 0;
}
if (*result != NULL) {
return 1;
}
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
return -1;
}
PyErr_Clear();
return 0;
}
int
_PyObject_LookupAttrId(PyObject *v, _Py_Identifier *name, PyObject **result)
{
PyObject *oname = _PyUnicode_FromId(name);
if (!oname) {
*result = NULL;
return -1;
}
return _PyObject_LookupAttr(v, oname, result);
}
int
PyObject_HasAttr(PyObject *v, PyObject *name)
{
PyObject *res;
if (_PyObject_LookupAttr(v, name, &res) < 0) {
PyErr_Clear();
return 0;
}
if (res == NULL) {
return 0;
}
Py_DECREF(res);
return 1;
}
int
PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)
{
PyTypeObject *tp = Py_TYPE(v);
int err;
if (!PyUnicode_Check(name)) {
PyErr_Format(PyExc_TypeError,
"attribute name must be string, not '%.200s'",
Py_TYPE(name)->tp_name);
return -1;
}
Py_INCREF(name);
PyUnicode_InternInPlace(&name);
if (tp->tp_setattro != NULL) {
err = (*tp->tp_setattro)(v, name, value);
Py_DECREF(name);
return err;
}
if (tp->tp_setattr != NULL) {
const char *name_str = PyUnicode_AsUTF8(name);
if (name_str == NULL) {
Py_DECREF(name);
return -1;
}
err = (*tp->tp_setattr)(v, (char *)name_str, value);
Py_DECREF(name);
return err;
}
Py_DECREF(name);
_PyObject_ASSERT(name, Py_REFCNT(name) >= 1);
if (tp->tp_getattr == NULL && tp->tp_getattro == NULL)
PyErr_Format(PyExc_TypeError,
"'%.100s' object has no attributes "
"(%s .%U)",
tp->tp_name,
value==NULL ? "del" : "assign to",
name);
else
PyErr_Format(PyExc_TypeError,
"'%.100s' object has only read-only attributes "
"(%s .%U)",
tp->tp_name,
value==NULL ? "del" : "assign to",
name);
return -1;
}
PyObject **
_PyObject_ComputedDictPointer(PyObject *obj)
{
PyTypeObject *tp = Py_TYPE(obj);
assert((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0);
Py_ssize_t dictoffset = tp->tp_dictoffset;
if (dictoffset == 0) {
return NULL;
}
if (dictoffset < 0) {
assert(dictoffset != -1);
Py_ssize_t tsize = Py_SIZE(obj);
if (tsize < 0) {
tsize = -tsize;
}
size_t size = _PyObject_VAR_SIZE(tp, tsize);
assert(size <= (size_t)PY_SSIZE_T_MAX);
dictoffset += (Py_ssize_t)size;
_PyObject_ASSERT(obj, dictoffset > 0);
_PyObject_ASSERT(obj, dictoffset % SIZEOF_VOID_P == 0);
}
return (PyObject **) ((char *)obj + dictoffset);
}
PyObject **
_PyObject_GetDictPtr(PyObject *obj)
{
if ((Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
return _PyObject_ComputedDictPointer(obj);
}
PyDictOrValues *dorv_ptr = _PyObject_DictOrValuesPointer(obj);
if (_PyDictOrValues_IsValues(*dorv_ptr)) {
PyObject *dict = _PyObject_MakeDictFromInstanceAttributes(obj, _PyDictOrValues_GetValues(*dorv_ptr));
if (dict == NULL) {
PyErr_Clear();
return NULL;
}
dorv_ptr->dict = dict;
}
return &dorv_ptr->dict;
}
PyObject *
PyObject_SelfIter(PyObject *obj)
{
return Py_NewRef(obj);
}
PyObject *
_PyObject_NextNotImplemented(PyObject *self)
{
PyErr_Format(PyExc_TypeError,
"'%.200s' object is not iterable",
Py_TYPE(self)->tp_name);
return NULL;
}
int
_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method)
{
int meth_found = 0;
assert(*method == NULL);
PyTypeObject *tp = Py_TYPE(obj);
if (!_PyType_IsReady(tp)) {
if (PyType_Ready(tp) < 0) {
return 0;
}
}
if (tp->tp_getattro != PyObject_GenericGetAttr || !PyUnicode_CheckExact(name)) {
*method = PyObject_GetAttr(obj, name);
return 0;
}
PyObject *descr = _PyType_Lookup(tp, name);
descrgetfunc f = NULL;
if (descr != NULL) {
Py_INCREF(descr);
if (_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)) {
meth_found = 1;
} else {
f = Py_TYPE(descr)->tp_descr_get;
if (f != NULL && PyDescr_IsData(descr)) {
*method = f(descr, obj, (PyObject *)Py_TYPE(obj));
Py_DECREF(descr);
return 0;
}
}
}
PyObject *dict;
if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) {
PyDictOrValues* dorv_ptr = _PyObject_DictOrValuesPointer(obj);
if (_PyDictOrValues_IsValues(*dorv_ptr)) {
PyDictValues *values = _PyDictOrValues_GetValues(*dorv_ptr);
PyObject *attr = _PyObject_GetInstanceAttribute(obj, values, name);
if (attr != NULL) {
*method = attr;
Py_XDECREF(descr);
return 0;
}
dict = NULL;
}
else {
dict = dorv_ptr->dict;
}
}
else {
PyObject **dictptr = _PyObject_ComputedDictPointer(obj);
if (dictptr != NULL) {
dict = *dictptr;
}
else {
dict = NULL;
}
}
if (dict != NULL) {
Py_INCREF(dict);
PyObject *attr = PyDict_GetItemWithError(dict, name);
if (attr != NULL) {
*method = Py_NewRef(attr);
Py_DECREF(dict);
Py_XDECREF(descr);
return 0;
}
Py_DECREF(dict);
if (PyErr_Occurred()) {
Py_XDECREF(descr);
return 0;
}
}
if (meth_found) {
*method = descr;
return 1;
}
if (f != NULL) {
*method = f(descr, obj, (PyObject *)Py_TYPE(obj));
Py_DECREF(descr);
return 0;
}
if (descr != NULL) {
*method = descr;
return 0;
}
PyErr_Format(PyExc_AttributeError,
"'%.100s' object has no attribute '%U'",
tp->tp_name, name);
set_attribute_error_context(obj, name);
return 0;
}
PyObject *
_PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name,
PyObject *dict, int suppress)
{
PyTypeObject *tp = Py_TYPE(obj);
PyObject *descr = NULL;
PyObject *res = NULL;
descrgetfunc f;
if (!PyUnicode_Check(name)){
PyErr_Format(PyExc_TypeError,
"attribute name must be string, not '%.200s'",
Py_TYPE(name)->tp_name);
return NULL;
}
Py_INCREF(name);
if (!_PyType_IsReady(tp)) {
if (PyType_Ready(tp) < 0)
goto done;
}
descr = _PyType_Lookup(tp, name);
f = NULL;
if (descr != NULL) {
Py_INCREF(descr);
f = Py_TYPE(descr)->tp_descr_get;
if (f != NULL && PyDescr_IsData(descr)) {
res = f(descr, obj, (PyObject *)Py_TYPE(obj));
if (res == NULL && suppress &&
PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
}
goto done;
}
}
if (dict == NULL) {
if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) {
PyDictOrValues* dorv_ptr = _PyObject_DictOrValuesPointer(obj);
if (_PyDictOrValues_IsValues(*dorv_ptr)) {
PyDictValues *values = _PyDictOrValues_GetValues(*dorv_ptr);
if (PyUnicode_CheckExact(name)) {
res = _PyObject_GetInstanceAttribute(obj, values, name);
if (res != NULL) {
goto done;
}
}
else {
dict = _PyObject_MakeDictFromInstanceAttributes(obj, values);
if (dict == NULL) {
res = NULL;
goto done;
}
dorv_ptr->dict = dict;
}
}
else {
dict = _PyDictOrValues_GetDict(*dorv_ptr);
}
}
else {
PyObject **dictptr = _PyObject_ComputedDictPointer(obj);
if (dictptr) {
dict = *dictptr;
}
}
}
if (dict != NULL) {
Py_INCREF(dict);
res = PyDict_GetItemWithError(dict, name);
if (res != NULL) {
Py_INCREF(res);
Py_DECREF(dict);
goto done;
}
else {
Py_DECREF(dict);
if (PyErr_Occurred()) {
if (suppress && PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
}
else {
goto done;
}
}
}
}
if (f != NULL) {
res = f(descr, obj, (PyObject *)Py_TYPE(obj));
if (res == NULL && suppress &&
PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
}
goto done;
}
if (descr != NULL) {
res = descr;
descr = NULL;
goto done;
}
if (!suppress) {
PyErr_Format(PyExc_AttributeError,
"'%.100s' object has no attribute '%U'",
tp->tp_name, name);
set_attribute_error_context(obj, name);
}
done:
Py_XDECREF(descr);
Py_DECREF(name);
return res;
}
PyObject *
PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
{
return _PyObject_GenericGetAttrWithDict(obj, name, NULL, 0);
}
int
_PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
PyObject *value, PyObject *dict)
{
PyTypeObject *tp = Py_TYPE(obj);
PyObject *descr;
descrsetfunc f;
int res = -1;
if (!PyUnicode_Check(name)){
PyErr_Format(PyExc_TypeError,
"attribute name must be string, not '%.200s'",
Py_TYPE(name)->tp_name);
return -1;
}
if (!_PyType_IsReady(tp) && PyType_Ready(tp) < 0) {
return -1;
}
Py_INCREF(name);
Py_INCREF(tp);
descr = _PyType_Lookup(tp, name);
if (descr != NULL) {
Py_INCREF(descr);
f = Py_TYPE(descr)->tp_descr_set;
if (f != NULL) {
res = f(descr, obj, value);
goto done;
}
}
if (dict == NULL) {
PyObject **dictptr;
if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) {
PyDictOrValues *dorv_ptr = _PyObject_DictOrValuesPointer(obj);
if (_PyDictOrValues_IsValues(*dorv_ptr)) {
res = _PyObject_StoreInstanceAttribute(
obj, _PyDictOrValues_GetValues(*dorv_ptr), name, value);
goto error_check;
}
dictptr = &dorv_ptr->dict;
}
else {
dictptr = _PyObject_ComputedDictPointer(obj);
}
if (dictptr == NULL) {
if (descr == NULL) {
PyErr_Format(PyExc_AttributeError,
"'%.100s' object has no attribute '%U'",
tp->tp_name, name);
}
else {
PyErr_Format(PyExc_AttributeError,
"'%.100s' object attribute '%U' is read-only",
tp->tp_name, name);
}
goto done;
}
else {
res = _PyObjectDict_SetItem(tp, dictptr, name, value);
}
}
else {
Py_INCREF(dict);
if (value == NULL)
res = PyDict_DelItem(dict, name);
else
res = PyDict_SetItem(dict, name, value);
Py_DECREF(dict);
}
error_check:
if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) {
if (PyType_IsSubtype(tp, &PyType_Type)) {
PyErr_Format(PyExc_AttributeError,
"type object '%.50s' has no attribute '%U'",
((PyTypeObject*)obj)->tp_name, name);
}
else {
PyErr_Format(PyExc_AttributeError,
"'%.100s' object has no attribute '%U'",
tp->tp_name, name);
}
}
done:
Py_XDECREF(descr);
Py_DECREF(tp);
Py_DECREF(name);
return res;
}
int
PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
{
return _PyObject_GenericSetAttrWithDict(obj, name, value, NULL);
}
int
PyObject_GenericSetDict(PyObject *obj, PyObject *value, void *context)
{
PyObject **dictptr = _PyObject_GetDictPtr(obj);
if (dictptr == NULL) {
if (_PyType_HasFeature(Py_TYPE(obj), Py_TPFLAGS_MANAGED_DICT) &&
_PyDictOrValues_IsValues(*_PyObject_DictOrValuesPointer(obj)))
{
PyErr_NoMemory();
}
else {
PyErr_SetString(PyExc_AttributeError,
"This object has no __dict__");
}
return -1;
}
if (value == NULL) {
PyErr_SetString(PyExc_TypeError, "cannot delete __dict__");
return -1;
}
if (!PyDict_Check(value)) {
PyErr_Format(PyExc_TypeError,
"__dict__ must be set to a dictionary, "
"not a '%.200s'", Py_TYPE(value)->tp_name);
return -1;
}
Py_XSETREF(*dictptr, Py_NewRef(value));
return 0;
}
int
PyObject_IsTrue(PyObject *v)
{
Py_ssize_t res;
if (v == Py_True)
return 1;
if (v == Py_False)
return 0;
if (v == Py_None)
return 0;
else if (Py_TYPE(v)->tp_as_number != NULL &&
Py_TYPE(v)->tp_as_number->nb_bool != NULL)
res = (*Py_TYPE(v)->tp_as_number->nb_bool)(v);
else if (Py_TYPE(v)->tp_as_mapping != NULL &&
Py_TYPE(v)->tp_as_mapping->mp_length != NULL)
res = (*Py_TYPE(v)->tp_as_mapping->mp_length)(v);
else if (Py_TYPE(v)->tp_as_sequence != NULL &&
Py_TYPE(v)->tp_as_sequence->sq_length != NULL)
res = (*Py_TYPE(v)->tp_as_sequence->sq_length)(v);
else
return 1;
return (res > 0) ? 1 : Py_SAFE_DOWNCAST(res, Py_ssize_t, int);
}
int
PyObject_Not(PyObject *v)
{
int res;
res = PyObject_IsTrue(v);
if (res < 0)
return res;
return res == 0;
}
int
PyCallable_Check(PyObject *x)
{
if (x == NULL)
return 0;
return Py_TYPE(x)->tp_call != NULL;
}
static PyObject *
_dir_locals(void)
{
PyObject *names;
PyObject *locals;
locals = PyEval_GetLocals();
if (locals == NULL)
return NULL;
names = PyMapping_Keys(locals);
if (!names)
return NULL;
if (!PyList_Check(names)) {
PyErr_Format(PyExc_TypeError,
"dir(): expected keys() of locals to be a list, "
"not '%.200s'", Py_TYPE(names)->tp_name);
Py_DECREF(names);
return NULL;
}
if (PyList_Sort(names)) {
Py_DECREF(names);
return NULL;
}
return names;
}
static PyObject *
_dir_object(PyObject *obj)
{
PyObject *result, *sorted;
PyObject *dirfunc = _PyObject_LookupSpecial(obj, &_Py_ID(__dir__));
assert(obj != NULL);
if (dirfunc == NULL) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_TypeError, "object does not provide __dir__");
return NULL;
}
result = _PyObject_CallNoArgs(dirfunc);
Py_DECREF(dirfunc);
if (result == NULL)
return NULL;
sorted = PySequence_List(result);
Py_DECREF(result);
if (sorted == NULL)
return NULL;
if (PyList_Sort(sorted)) {
Py_DECREF(sorted);
return NULL;
}
return sorted;
}
PyObject *
PyObject_Dir(PyObject *obj)
{
return (obj == NULL) ? _dir_locals() : _dir_object(obj);
}
static PyObject *
none_repr(PyObject *op)
{
return PyUnicode_FromString("None");
}
static void
none_dealloc(PyObject* none)
{
_Py_SetImmortal(none);
}
static PyObject *
none_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) {
PyErr_SetString(PyExc_TypeError, "NoneType takes no arguments");
return NULL;
}
Py_RETURN_NONE;
}
static int
none_bool(PyObject *v)
{
return 0;
}
static Py_hash_t none_hash(PyObject *v)
{
return 0xFCA86420;
}
static PyNumberMethods none_as_number = {
0,
0,
0,
0,
0,
0,
0,
0,
0,
(inquiry)none_bool,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
};
PyTypeObject _PyNone_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"NoneType",
0,
0,
none_dealloc,
0,
0,
0,
0,
none_repr,
&none_as_number,
0,
0,
(hashfunc)none_hash,
0,
0,
0,
0,
0,
Py_TPFLAGS_DEFAULT,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
none_new,
};
PyObject _Py_NoneStruct = {
_PyObject_EXTRA_INIT
{ _Py_IMMORTAL_REFCNT },
&_PyNone_Type
};
static PyObject *
NotImplemented_repr(PyObject *op)
{
return PyUnicode_FromString("NotImplemented");
}
static PyObject *
NotImplemented_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
{
return PyUnicode_FromString("NotImplemented");
}
static PyMethodDef notimplemented_methods[] = {
{"__reduce__", NotImplemented_reduce, METH_NOARGS, NULL},
{NULL, NULL}
};
static PyObject *
notimplemented_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) {
PyErr_SetString(PyExc_TypeError, "NotImplementedType takes no arguments");
return NULL;
}
Py_RETURN_NOTIMPLEMENTED;
}
static void
notimplemented_dealloc(PyObject *notimplemented)
{
_Py_SetImmortal(notimplemented);
}
static int
notimplemented_bool(PyObject *v)
{
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"NotImplemented should not be used in a boolean context",
1) < 0)
{
return -1;
}
return 1;
}
static PyNumberMethods notimplemented_as_number = {
.nb_bool = notimplemented_bool,
};
PyTypeObject _PyNotImplemented_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"NotImplementedType",
0,
0,
notimplemented_dealloc,
0,
0,
0,
0,
NotImplemented_repr,
¬implemented_as_number,
0,
0,
0,
0,
0,
0,
0,
0,
Py_TPFLAGS_DEFAULT,
0,
0,
0,
0,
0,
0,
0,
notimplemented_methods,
0,
0,
0,
0,
0,
0,
0,
0,
0,
notimplemented_new,
};
PyObject _Py_NotImplementedStruct = {
_PyObject_EXTRA_INIT
{ _Py_IMMORTAL_REFCNT },
&_PyNotImplemented_Type
};
extern PyTypeObject _Py_GenericAliasIterType;
extern PyTypeObject _PyMemoryIter_Type;
extern PyTypeObject _PyLineIterator;
extern PyTypeObject _PyPositionsIterator;
extern PyTypeObject _PyLegacyEventHandler_Type;
static PyTypeObject* static_types[] = {
&PyBaseObject_Type,
&PyType_Type,
&PyAsyncGen_Type,
&PyByteArrayIter_Type,
&PyByteArray_Type,
&PyBytesIter_Type,
&PyBytes_Type,
&PyCFunction_Type,
&PyCallIter_Type,
&PyCapsule_Type,
&PyCell_Type,
&PyClassMethodDescr_Type,
&PyClassMethod_Type,
&PyCode_Type,
&PyComplex_Type,
&PyContextToken_Type,
&PyContextVar_Type,
&PyContext_Type,
&PyCoro_Type,
&PyDictItems_Type,
&PyDictIterItem_Type,
&PyDictIterKey_Type,
&PyDictIterValue_Type,
&PyDictKeys_Type,
&PyDictProxy_Type,
&PyDictRevIterItem_Type,
&PyDictRevIterKey_Type,
&PyDictRevIterValue_Type,
&PyDictValues_Type,
&PyDict_Type,
&PyEllipsis_Type,
&PyEnum_Type,
&PyFilter_Type,
&PyFloat_Type,
&PyFrame_Type,
&PyFrozenSet_Type,
&PyFunction_Type,
&PyGen_Type,
&PyGetSetDescr_Type,
&PyInstanceMethod_Type,
&PyListIter_Type,
&PyListRevIter_Type,
&PyList_Type,
&PyLongRangeIter_Type,
&PyLong_Type,
&PyMap_Type,
&PyMemberDescr_Type,
&PyMemoryView_Type,
&PyMethodDescr_Type,
&PyMethod_Type,
&PyModuleDef_Type,
&PyModule_Type,
&PyODictIter_Type,
&PyPickleBuffer_Type,
&PyProperty_Type,
&PyRangeIter_Type,
&PyRange_Type,
&PyReversed_Type,
&PySTEntry_Type,
&PySeqIter_Type,
&PySetIter_Type,
&PySet_Type,
&PySlice_Type,
&PyStaticMethod_Type,
&PyStdPrinter_Type,
&PySuper_Type,
&PyTraceBack_Type,
&PyTupleIter_Type,
&PyTuple_Type,
&PyUnicodeIter_Type,
&PyUnicode_Type,
&PyWrapperDescr_Type,
&PyZip_Type,
&Py_GenericAliasType,
&_PyAnextAwaitable_Type,
&_PyAsyncGenASend_Type,
&_PyAsyncGenAThrow_Type,
&_PyAsyncGenWrappedValue_Type,
&_PyBufferWrapper_Type,
&_PyContextTokenMissing_Type,
&_PyCoroWrapper_Type,
&_Py_GenericAliasIterType,
&_PyHamtItems_Type,
&_PyHamtKeys_Type,
&_PyHamtValues_Type,
&_PyHamt_ArrayNode_Type,
&_PyHamt_BitmapNode_Type,
&_PyHamt_CollisionNode_Type,
&_PyHamt_Type,
&_PyLegacyEventHandler_Type,
&_PyInterpreterID_Type,
&_PyLineIterator,
&_PyManagedBuffer_Type,
&_PyMemoryIter_Type,
&_PyMethodWrapper_Type,
&_PyNamespace_Type,
&_PyNone_Type,
&_PyNotImplemented_Type,
&_PyPositionsIterator,
&_PyUnicodeASCIIIter_Type,
&_PyUnion_Type,
&_PyWeakref_CallableProxyType,
&_PyWeakref_ProxyType,
&_PyWeakref_RefType,
&_PyTypeAlias_Type,
&PyBool_Type,
&PyCMethod_Type,
&PyODictItems_Type,
&PyODictKeys_Type,
&PyODictValues_Type,
&PyODict_Type,
};
PyStatus
_PyTypes_InitTypes(PyInterpreterState *interp)
{
for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) {
PyTypeObject *type = static_types[i];
if (_PyStaticType_InitBuiltin(interp, type) < 0) {
return _PyStatus_ERR("Can't initialize builtin type");
}
if (type == &PyType_Type) {
assert(PyBaseObject_Type.tp_base == NULL);
assert(PyType_Type.tp_base == &PyBaseObject_Type);
}
}
if (_Py_initialize_generic(interp) < 0) {
return _PyStatus_ERR("Can't initialize generic types");
}
return _PyStatus_OK();
}
void
_PyTypes_FiniTypes(PyInterpreterState *interp)
{
for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types)-1; i>=0; i--) {
PyTypeObject *type = static_types[i];
_PyStaticType_Dealloc(interp, type);
}
}
static inline void
new_reference(PyObject *op)
{
if (_PyRuntime.tracemalloc.config.tracing) {
_PyTraceMalloc_NewReference(op);
}
op->ob_refcnt = 1;
#ifdef Py_TRACE_REFS
_Py_AddToAllObjects(op, 1);
#endif
}
void
_Py_NewReference(PyObject *op)
{
#ifdef Py_REF_DEBUG
reftotal_increment(_PyInterpreterState_GET());
#endif
new_reference(op);
}
void
_Py_NewReferenceNoTotal(PyObject *op)
{
new_reference(op);
}
#ifdef Py_TRACE_REFS
void
_Py_ForgetReference(PyObject *op)
{
if (Py_REFCNT(op) < 0) {
_PyObject_ASSERT_FAILED_MSG(op, "negative refcnt");
}
if (op == &refchain ||
op->_ob_prev->_ob_next != op || op->_ob_next->_ob_prev != op)
{
_PyObject_ASSERT_FAILED_MSG(op, "invalid object chain");
}
#ifdef SLOW_UNREF_CHECK
PyObject *p;
for (p = refchain._ob_next; p != &refchain; p = p->_ob_next) {
if (p == op) {
break;
}
}
if (p == &refchain) {
_PyObject_ASSERT_FAILED_MSG(op,
"object not found in the objects list");
}
#endif
op->_ob_next->_ob_prev = op->_ob_prev;
op->_ob_prev->_ob_next = op->_ob_next;
op->_ob_next = op->_ob_prev = NULL;
}
void
_Py_PrintReferences(FILE *fp)
{
PyObject *op;
fprintf(fp, "Remaining objects:\n");
for (op = refchain._ob_next; op != &refchain; op = op->_ob_next) {
fprintf(fp, "%p [%zd] ", (void *)op, Py_REFCNT(op));
if (PyObject_Print(op, fp, 0) != 0) {
PyErr_Clear();
}
putc('\n', fp);
}
}
void
_Py_PrintReferenceAddresses(FILE *fp)
{
PyObject *op;
fprintf(fp, "Remaining object addresses:\n");
for (op = refchain._ob_next; op != &refchain; op = op->_ob_next)
fprintf(fp, "%p [%zd] %s\n", (void *)op,
Py_REFCNT(op), Py_TYPE(op)->tp_name);
}
PyObject *
_Py_GetObjects(PyObject *self, PyObject *args)
{
int i, n;
PyObject *t = NULL;
PyObject *res, *op;
if (!PyArg_ParseTuple(args, "i|O", &n, &t))
return NULL;
op = refchain._ob_next;
res = PyList_New(0);
if (res == NULL)
return NULL;
for (i = 0; (n == 0 || i < n) && op != &refchain; i++) {
while (op == self || op == args || op == res || op == t ||
(t != NULL && !Py_IS_TYPE(op, (PyTypeObject *) t))) {
op = op->_ob_next;
if (op == &refchain)
return res;
}
if (PyList_Append(res, op) < 0) {
Py_DECREF(res);
return NULL;
}
op = op->_ob_next;
}
return res;
}
#endif
Py_ssize_t (*_Py_abstract_hack)(PyObject *) = PyObject_Size;
void
_PyObject_DebugTypeStats(FILE *out)
{
_PyDict_DebugMallocStats(out);
_PyFloat_DebugMallocStats(out);
_PyList_DebugMallocStats(out);
_PyTuple_DebugMallocStats(out);
}
int
Py_ReprEnter(PyObject *obj)
{
PyObject *dict;
PyObject *list;
Py_ssize_t i;
dict = PyThreadState_GetDict();
if (dict == NULL)
return 0;
list = PyDict_GetItemWithError(dict, &_Py_ID(Py_Repr));
if (list == NULL) {
if (PyErr_Occurred()) {
return -1;
}
list = PyList_New(0);
if (list == NULL)
return -1;
if (PyDict_SetItem(dict, &_Py_ID(Py_Repr), list) < 0)
return -1;
Py_DECREF(list);
}
i = PyList_GET_SIZE(list);
while (--i >= 0) {
if (PyList_GET_ITEM(list, i) == obj)
return 1;
}
if (PyList_Append(list, obj) < 0)
return -1;
return 0;
}
void
Py_ReprLeave(PyObject *obj)
{
PyObject *dict;
PyObject *list;
Py_ssize_t i;
PyObject *exc = PyErr_GetRaisedException();
dict = PyThreadState_GetDict();
if (dict == NULL)
goto finally;
list = PyDict_GetItemWithError(dict, &_Py_ID(Py_Repr));
if (list == NULL || !PyList_Check(list))
goto finally;
i = PyList_GET_SIZE(list);
while (--i >= 0) {
if (PyList_GET_ITEM(list, i) == obj) {
PyList_SetSlice(list, i, i + 1, NULL);
break;
}
}
finally:
PyErr_SetRaisedException(exc);
}
#define _PyTrash_UNWIND_LEVEL 50
static void
_PyTrash_thread_deposit_object(struct _py_trashcan *trash, PyObject *op)
{
_PyObject_ASSERT(op, _PyObject_IS_GC(op));
_PyObject_ASSERT(op, !_PyObject_GC_IS_TRACKED(op));
_PyObject_ASSERT(op, Py_REFCNT(op) == 0);
_PyGCHead_SET_PREV(_Py_AS_GC(op), (PyGC_Head*)trash->delete_later);
trash->delete_later = op;
}
static void
_PyTrash_thread_destroy_chain(struct _py_trashcan *trash)
{
assert(trash->delete_nesting == 0);
++trash->delete_nesting;
while (trash->delete_later) {
PyObject *op = trash->delete_later;
destructor dealloc = Py_TYPE(op)->tp_dealloc;
trash->delete_later =
(PyObject*) _PyGCHead_PREV(_Py_AS_GC(op));
_PyObject_ASSERT(op, Py_REFCNT(op) == 0);
(*dealloc)(op);
assert(trash->delete_nesting == 1);
}
--trash->delete_nesting;
}
static struct _py_trashcan *
_PyTrash_get_state(PyThreadState *tstate)
{
if (tstate != NULL) {
return &tstate->trash;
}
assert(PyThread_tss_is_created(&_PyRuntime.trashTSSkey));
struct _py_trashcan *trash =
(struct _py_trashcan *)PyThread_tss_get(&_PyRuntime.trashTSSkey);
if (trash == NULL) {
trash = PyMem_RawMalloc(sizeof(struct _py_trashcan));
if (trash == NULL) {
Py_FatalError("Out of memory");
}
PyThread_tss_set(&_PyRuntime.trashTSSkey, (void *)trash);
}
return trash;
}
static void
_PyTrash_clear_state(PyThreadState *tstate)
{
if (tstate != NULL) {
assert(tstate->trash.delete_later == NULL);
return;
}
if (PyThread_tss_is_created(&_PyRuntime.trashTSSkey)) {
struct _py_trashcan *trash =
(struct _py_trashcan *)PyThread_tss_get(&_PyRuntime.trashTSSkey);
if (trash != NULL) {
PyThread_tss_set(&_PyRuntime.trashTSSkey, (void *)NULL);
PyMem_RawFree(trash);
}
}
}
int
_PyTrash_begin(PyThreadState *tstate, PyObject *op)
{
struct _py_trashcan *trash = _PyTrash_get_state(tstate);
if (trash->delete_nesting >= _PyTrash_UNWIND_LEVEL) {
_PyTrash_thread_deposit_object(trash, op);
return 1;
}
++trash->delete_nesting;
return 0;
}
void
_PyTrash_end(PyThreadState *tstate)
{
struct _py_trashcan *trash = _PyTrash_get_state(tstate);
--trash->delete_nesting;
if (trash->delete_nesting <= 0) {
if (trash->delete_later != NULL) {
_PyTrash_thread_destroy_chain(trash);
}
_PyTrash_clear_state(tstate);
}
}
int
_PyTrash_cond(PyObject *op, destructor dealloc)
{
return Py_TYPE(op)->tp_dealloc == dealloc;
}
void _Py_NO_RETURN
_PyObject_AssertFailed(PyObject *obj, const char *expr, const char *msg,
const char *file, int line, const char *function)
{
fprintf(stderr, "%s:%d: ", file, line);
if (function) {
fprintf(stderr, "%s: ", function);
}
fflush(stderr);
if (expr) {
fprintf(stderr, "Assertion \"%s\" failed", expr);
}
else {
fprintf(stderr, "Assertion failed");
}
fflush(stderr);
if (msg) {
fprintf(stderr, ": %s", msg);
}
fprintf(stderr, "\n");
fflush(stderr);
if (_PyObject_IsFreed(obj)) {
fprintf(stderr, "<object at %p is freed>\n", obj);
fflush(stderr);
}
else {
PyTypeObject *type = Py_TYPE(obj);
const size_t presize = _PyType_PreHeaderSize(type);
void *ptr = (void *)((char *)obj - presize);
_PyMem_DumpTraceback(fileno(stderr), ptr);
_PyObject_Dump(obj);
fprintf(stderr, "\n");
fflush(stderr);
}
Py_FatalError("_PyObject_AssertFailed");
}
void
_Py_Dealloc(PyObject *op)
{
PyTypeObject *type = Py_TYPE(op);
destructor dealloc = type->tp_dealloc;
#ifdef Py_DEBUG
PyThreadState *tstate = _PyThreadState_GET();
PyObject *old_exc = tstate != NULL ? tstate->current_exception : NULL;
Py_XINCREF(old_exc);
Py_INCREF(type);
#endif
#ifdef Py_TRACE_REFS
_Py_ForgetReference(op);
#endif
(*dealloc)(op);
#ifdef Py_DEBUG
if (tstate != NULL && tstate->current_exception != old_exc) {
const char *err;
if (old_exc == NULL) {
err = "Deallocator of type '%s' raised an exception";
}
else if (tstate->current_exception == NULL) {
err = "Deallocator of type '%s' cleared the current exception";
}
else {
err = "Deallocator of type '%s' overrode the current exception";
}
_Py_FatalErrorFormat(__func__, err, type->tp_name);
}
Py_XDECREF(old_exc);
Py_DECREF(type);
#endif
}
PyObject **
PyObject_GET_WEAKREFS_LISTPTR(PyObject *op)
{
return _PyObject_GET_WEAKREFS_LISTPTR(op);
}
#undef Py_NewRef
#undef Py_XNewRef
PyObject*
Py_NewRef(PyObject *obj)
{
return _Py_NewRef(obj);
}
PyObject*
Py_XNewRef(PyObject *obj)
{
return _Py_XNewRef(obj);
}
#undef Py_Is
#undef Py_IsNone
#undef Py_IsTrue
#undef Py_IsFalse
int Py_Is(PyObject *x, PyObject *y)
{
return (x == y);
}
int Py_IsNone(PyObject *x)
{
return Py_Is(x, Py_None);
}
int Py_IsTrue(PyObject *x)
{
return Py_Is(x, Py_True);
}
int Py_IsFalse(PyObject *x)
{
return Py_Is(x, Py_False);
}
#ifdef __cplusplus
}
#endif