diff options
author | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
---|---|---|
committer | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
commit | 06e5c21a835c0e923506c4ff27929f34e00761c2 (patch) | |
tree | 75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/tools/python3/src/Objects/object.c | |
parent | 03f024c4412e3aa613bb543cf1660176320ba8f4 (diff) | |
download | ydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz |
fix ya.make
Diffstat (limited to 'contrib/tools/python3/src/Objects/object.c')
-rw-r--r-- | contrib/tools/python3/src/Objects/object.c | 2354 |
1 files changed, 0 insertions, 2354 deletions
diff --git a/contrib/tools/python3/src/Objects/object.c b/contrib/tools/python3/src/Objects/object.c deleted file mode 100644 index 47c352e3d6..0000000000 --- a/contrib/tools/python3/src/Objects/object.c +++ /dev/null @@ -1,2354 +0,0 @@ - -/* Generic object operations; and implementation of None */ - -#include "Python.h" -#include "pycore_ceval.h" // _Py_EnterRecursiveCall() -#include "pycore_context.h" -#include "pycore_initconfig.h" -#include "pycore_object.h" -#include "pycore_pyerrors.h" -#include "pycore_pylifecycle.h" -#include "pycore_pymem.h" // _PyMem_IsPtrFreed() -#include "pycore_pystate.h" // _PyThreadState_GET() -#include "pycore_symtable.h" // PySTEntry_Type -#include "pycore_unionobject.h" // _PyUnion_Type -#include "frameobject.h" -#include "interpreteridobject.h" - -#ifdef Py_LIMITED_API - // Prevent recursive call _Py_IncRef() <=> Py_INCREF() -# error "Py_LIMITED_API macro must not be defined" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Defined in tracemalloc.c */ -extern void _PyMem_DumpTraceback(int fd, const void *ptr); - -_Py_IDENTIFIER(Py_Repr); -_Py_IDENTIFIER(__bytes__); -_Py_IDENTIFIER(__dir__); -_Py_IDENTIFIER(__isabstractmethod__); - - -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; - -Py_ssize_t -_Py_GetRefTotal(void) -{ - PyObject *o; - Py_ssize_t total = _Py_RefTotal; - o = _PySet_Dummy; - if (o != NULL) - total -= Py_REFCNT(o); - return total; -} - -void -_PyDebug_PrintTotalRefs(void) { - fprintf(stderr, - "[%zd refs, %zd blocks]\n", - _Py_GetRefTotal(), _Py_GetAllocatedBlocks()); -} -#endif /* Py_REF_DEBUG */ - -/* Object allocation routines used by NEWOBJ and NEWVAROBJ macros. - These are used by the individual routines for object creation. - Do not call them otherwise, they do not initialize the object! */ - -#ifdef Py_TRACE_REFS -/* Head of circular doubly-linked list of all objects. These are linked - * together via the _ob_prev and _ob_next members of a PyObject, which - * exist only in a Py_TRACE_REFS build. - */ -static PyObject refchain = {&refchain, &refchain}; - -/* Insert op at the front of the list of all objects. If force is true, - * op is added even if _ob_prev and _ob_next are non-NULL already. If - * force is false amd _ob_prev or _ob_next are non-NULL, do nothing. - * force should be true if and only if op points to freshly allocated, - * uninitialized memory, or you've unlinked op from the list and are - * relinking it into the front. - * Note that objects are normally added to the list via _Py_NewReference, - * which is called by PyObject_Init. Not all objects are initialized that - * way, though; exceptions include statically allocated type objects, and - * statically allocated singletons (like Py_True and Py_None). - */ -void -_Py_AddToAllObjects(PyObject *op, int force) -{ -#ifdef Py_DEBUG - if (!force) { - /* If it's initialized memory, op must be in or out of - * the list unambiguously. - */ - _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 /* Py_TRACE_REFS */ - -#ifdef Py_REF_DEBUG -/* Log a fatal error; doesn't return. */ -void -_Py_NegativeRefcount(const char *filename, int lineno, PyObject *op) -{ - _PyObject_AssertFailed(op, NULL, "object has negative ref count", - filename, lineno, __func__); -} - -#endif /* Py_REF_DEBUG */ - -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; - /* tp_finalize should only be called once. */ - 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"); - } - - /* Temporarily resurrect the object. */ - Py_SET_REFCNT(self, 1); - - PyObject_CallFinalizer(self); - - _PyObject_ASSERT_WITH_MSG(self, - Py_REFCNT(self) > 0, - "refcount is too small"); - - /* Undo the temporary resurrection; can't use DECREF here, it would - * cause a recursive call. */ - Py_SET_REFCNT(self, Py_REFCNT(self) - 1); - if (Py_REFCNT(self) == 0) { - return 0; /* this is the normal path out */ - } - - /* tp_finalize resurrected it! Make it look like the original Py_DECREF - * never happened. */ - Py_ssize_t refcnt = Py_REFCNT(self); - _Py_NewReference(self); - Py_SET_REFCNT(self, refcnt); - - _PyObject_ASSERT(self, - (!_PyType_IS_GC(Py_TYPE(self)) - || _PyObject_GC_IS_TRACKED(self))); - /* If Py_REF_DEBUG macro is defined, _Py_NewReference() increased - _Py_RefTotal, so we need to undo that. */ -#ifdef Py_REF_DEBUG - _Py_RefTotal--; -#endif - 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); /* Clear any previous error condition */ - if (op == NULL) { - Py_BEGIN_ALLOW_THREADS - fprintf(fp, "<nil>"); - Py_END_ALLOW_THREADS - } - else { - if (Py_REFCNT(op) <= 0) { - /* XXX(twouters) cast refcount to long until %zd is - universally available */ - Py_BEGIN_ALLOW_THREADS - fprintf(fp, "<refcnt %ld at %p>", - (long)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 if (PyBytes_Check(s)) { - fwrite(PyBytes_AS_STRING(s), 1, - PyBytes_GET_SIZE(s), fp); - } - else if (PyUnicode_Check(s)) { - PyObject *t; - t = PyUnicode_AsEncodedString(s, "utf-8", "backslashreplace"); - if (t == NULL) { - ret = -1; - } - else { - fwrite(PyBytes_AS_STRING(t), 1, - PyBytes_GET_SIZE(t), fp); - Py_DECREF(t); - } - } - else { - PyErr_Format(PyExc_TypeError, - "str() or repr() returned '%.100s'", - Py_TYPE(s)->tp_name); - ret = -1; - } - Py_XDECREF(s); - } - } - if (ret == 0) { - if (ferror(fp)) { - PyErr_SetFromErrno(PyExc_OSError); - clearerr(fp); - ret = -1; - } - } - return ret; -} - -/* For debugging convenience. Set a breakpoint here and call it from your DLL */ -void -_Py_BreakPoint(void) -{ -} - - -/* Heuristic checking if the object memory is uninitialized or deallocated. - Rely on the debug hooks on Python memory allocators: - see _PyMem_IsPtrFreed(). - - The function can be used to prevent segmentation fault on dereferencing - pointers like 0xDDDDDDDDDDDDDDDD. */ -int -_PyObject_IsFreed(PyObject *op) -{ - if (_PyMem_IsPtrFreed(op) || _PyMem_IsPtrFreed(Py_TYPE(op))) { - return 1; - } - /* ignore op->ob_ref: its value can have be modified - by Py_INCREF() and Py_DECREF(). */ -#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; -} - - -/* For debugging convenience. See Misc/gdbinit for some useful gdb hooks */ -void -_PyObject_Dump(PyObject* op) -{ - if (_PyObject_IsFreed(op)) { - /* It seems like the object memory has been freed: - don't access it to prevent a segmentation fault. */ - fprintf(stderr, "<object at %p is freed>\n", op); - fflush(stderr); - return; - } - - /* first, write fields which are the least likely to crash */ - fprintf(stderr, "object address : %p\n", (void *)op); - /* XXX(twouters) cast refcount to long until %zd is - universally available */ - fprintf(stderr, "object refcount : %ld\n", (long)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); - - /* the most dangerous part */ - fprintf(stderr, "object repr : "); - fflush(stderr); - - PyGILState_STATE gil = PyGILState_Ensure(); - PyObject *error_type, *error_value, *error_traceback; - PyErr_Fetch(&error_type, &error_value, &error_traceback); - - (void)PyObject_Print(op, stderr, 0); - fflush(stderr); - - PyErr_Restore(error_type, error_value, error_traceback); - 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 - /* PyObject_Repr() must not be called with an exception set, - because it can clear it (directly or indirectly) and so the - caller loses its exception */ - assert(!_PyErr_Occurred(tstate)); -#endif - - /* It is possible for a type to have a tp_repr representation that loops - infinitely. */ - if (_Py_EnterRecursiveCall(tstate, - " while getting the repr of an object")) { - return NULL; - } - res = (*Py_TYPE(v)->tp_repr)(v); - _Py_LeaveRecursiveCall(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; - } -#ifndef Py_DEBUG - if (PyUnicode_READY(res) < 0) { - return NULL; - } -#endif - 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)) { -#ifndef Py_DEBUG - if (PyUnicode_READY(v) < 0) - return NULL; -#endif - Py_INCREF(v); - return v; - } - if (Py_TYPE(v)->tp_str == NULL) - return PyObject_Repr(v); - - PyThreadState *tstate = _PyThreadState_GET(); -#ifdef Py_DEBUG - /* PyObject_Str() must not be called with an exception set, - because it can clear it (directly or indirectly) and so the - caller loses its exception */ - assert(!_PyErr_Occurred(tstate)); -#endif - - /* It is possible for a type to have a tp_str representation that loops - infinitely. */ - if (_Py_EnterRecursiveCall(tstate, " while getting the str of an object")) { - return NULL; - } - res = (*Py_TYPE(v)->tp_str)(v); - _Py_LeaveRecursiveCall(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; - } -#ifndef Py_DEBUG - if (PyUnicode_READY(res) < 0) { - return NULL; - } -#endif - 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; - - /* repr is guaranteed to be a PyUnicode object by PyObject_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)) { - Py_INCREF(v); - return v; - } - - func = _PyObject_LookupSpecial(v, &PyId___bytes__); - if (func != NULL) { - result = _PyObject_CallNoArg(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); -} - - -/* -def _PyObject_FunctionStr(x): - try: - qualname = x.__qualname__ - except AttributeError: - return str(x) - try: - mod = x.__module__ - if mod is not None and mod != 'builtins': - return f"{x.__module__}.{qualname}()" - except AttributeError: - pass - return qualname -*/ -PyObject * -_PyObject_FunctionStr(PyObject *x) -{ - _Py_IDENTIFIER(__module__); - _Py_IDENTIFIER(__qualname__); - _Py_IDENTIFIER(builtins); - assert(!PyErr_Occurred()); - PyObject *qualname; - int ret = _PyObject_LookupAttrId(x, &PyId___qualname__, &qualname); - if (qualname == NULL) { - if (ret < 0) { - return NULL; - } - return PyObject_Str(x); - } - PyObject *module; - PyObject *result = NULL; - ret = _PyObject_LookupAttrId(x, &PyId___module__, &module); - if (module != NULL && module != Py_None) { - PyObject *builtinsname = _PyUnicode_FromId(&PyId_builtins); - if (builtinsname == NULL) { - goto done; - } - ret = PyObject_RichCompareBool(module, builtinsname, Py_NE); - if (ret < 0) { - // error - 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; -} - -/* For Python 3.0.1 and later, the old three-way comparison has been - completely removed in favour of rich comparisons. PyObject_Compare() and - PyObject_Cmp() are gone, and the builtin cmp function no longer exists. - The old tp_compare slot has been renamed to tp_as_async, and should no - longer be used. Use tp_richcompare instead. - - See (*) below for practical amendments. - - tp_richcompare gets called with a first argument of the appropriate type - and a second object of an arbitrary type. We never do any kind of - coercion. - - The tp_richcompare slot should return an object, as follows: - - NULL if an exception occurred - NotImplemented if the requested comparison is not implemented - any other false value if the requested comparison is false - any other true value if the requested comparison is true - - The PyObject_RichCompare[Bool]() wrappers raise TypeError when they get - NotImplemented. - - (*) Practical amendments: - - - If rich comparison returns NotImplemented, == and != are decided by - comparing the object pointer (i.e. falling back to the base object - implementation). - -*/ - -/* Map rich comparison operators to their swapped version, e.g. LT <--> GT */ -int _Py_SwappedOp[] = {Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE}; - -static const char * const opstrings[] = {"<", "<=", "==", "!=", ">", ">="}; - -/* Perform a rich comparison, raising TypeError when the requested comparison - operator is not supported. */ -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); - } - /* If neither object implements it, provide a sensible default - for == and !=, but raise an exception for ordering. */ - 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; - } - Py_INCREF(res); - return res; -} - -/* Perform a rich comparison with object result. This wraps do_richcompare() - with a check for NULL arguments and a recursion check. */ - -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_EnterRecursiveCall(tstate, " in comparison")) { - return NULL; - } - PyObject *res = do_richcompare(tstate, v, w, op); - _Py_LeaveRecursiveCall(tstate); - return res; -} - -/* Perform a rich comparison with integer result. This wraps - PyObject_RichCompare(), returning -1 for error, 0 for false, 1 for true. */ -int -PyObject_RichCompareBool(PyObject *v, PyObject *w, int op) -{ - PyObject *res; - int ok; - - /* Quick result when objects are the same. - Guarantees that identity implies equality. */ - 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); - /* To keep to the general practice that inheriting - * solely from object in C code should work without - * an explicit call to PyType_Ready, we implicitly call - * PyType_Ready here and then check the tp_hash slot again - */ - if (tp->tp_dict == NULL) { - if (PyType_Ready(tp) < 0) - return -1; - if (tp->tp_hash != NULL) - return (*tp->tp_hash)(v); - } - /* Otherwise, the object can't be hashed */ - 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) -{ - PyObject *res = PyObject_GetAttrString(v, name); - if (res != NULL) { - Py_DECREF(res); - return 1; - } - PyErr_Clear(); - return 0; -} - -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_LookupAttrId(obj, &PyId___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); /* borrowed */ - 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); /* borrowed */ - 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()); - _Py_IDENTIFIER(name); - _Py_IDENTIFIER(obj); - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { - return 0; - } - // Intercept AttributeError exceptions and augment them to offer suggestions later. - PyObject *type, *value, *traceback; - PyErr_Fetch(&type, &value, &traceback); - PyErr_NormalizeException(&type, &value, &traceback); - // Check if the normalized exception is indeed an AttributeError - if (!PyErr_GivenExceptionMatches(value, PyExc_AttributeError)) { - goto restore; - } - PyAttributeErrorObject* the_exc = (PyAttributeErrorObject*) value; - // Check if this exception was already augmented - if (the_exc->name || the_exc->obj) { - goto restore; - } - // Augment the exception with the name and object - if (_PyObject_SetAttrId(value, &PyId_name, name) || - _PyObject_SetAttrId(value, &PyId_obj, v)) { - return 1; - } -restore: - PyErr_Restore(type, value, traceback); - 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, - "'%.50s' 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 != 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); /* borrowed */ - 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; -} - -/* Helper to get a pointer to an object's __dict__ slot, if any */ - -PyObject ** -_PyObject_GetDictPtr(PyObject *obj) -{ - Py_ssize_t dictoffset; - PyTypeObject *tp = Py_TYPE(obj); - - dictoffset = tp->tp_dictoffset; - if (dictoffset == 0) - return NULL; - if (dictoffset < 0) { - Py_ssize_t tsize = Py_SIZE(obj); - if (tsize < 0) { - tsize = -tsize; - } - size_t size = _PyObject_VAR_SIZE(tp, tsize); - - dictoffset += (long)size; - _PyObject_ASSERT(obj, dictoffset > 0); - _PyObject_ASSERT(obj, dictoffset % SIZEOF_VOID_P == 0); - } - return (PyObject **) ((char *)obj + dictoffset); -} - -PyObject * -PyObject_SelfIter(PyObject *obj) -{ - Py_INCREF(obj); - return obj; -} - -/* Helper used when the __next__ method is removed from a type: - tp_iternext is never NULL and can be safely called without checking - on every iteration. - */ - -PyObject * -_PyObject_NextNotImplemented(PyObject *self) -{ - PyErr_Format(PyExc_TypeError, - "'%.200s' object is not iterable", - Py_TYPE(self)->tp_name); - return NULL; -} - - -/* Specialized version of _PyObject_GenericGetAttrWithDict - specifically for the LOAD_METHOD opcode. - - Return 1 if a method is found, 0 if it's a regular attribute - from __dict__ or something returned by using a descriptor - protocol. - - `method` will point to the resolved attribute or NULL. In the - latter case, an error will be set. -*/ -int -_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) -{ - PyTypeObject *tp = Py_TYPE(obj); - PyObject *descr; - descrgetfunc f = NULL; - PyObject **dictptr, *dict; - PyObject *attr; - int meth_found = 0; - - assert(*method == NULL); - - if (Py_TYPE(obj)->tp_getattro != PyObject_GenericGetAttr - || !PyUnicode_Check(name)) { - *method = PyObject_GetAttr(obj, name); - return 0; - } - - if (tp->tp_dict == NULL && PyType_Ready(tp) < 0) - return 0; - - descr = _PyType_Lookup(tp, name); - 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; - } - } - } - - dictptr = _PyObject_GetDictPtr(obj); - if (dictptr != NULL && (dict = *dictptr) != NULL) { - Py_INCREF(dict); - attr = PyDict_GetItemWithError(dict, name); - if (attr != NULL) { - Py_INCREF(attr); - *method = attr; - Py_DECREF(dict); - Py_XDECREF(descr); - return 0; - } - else { - 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, - "'%.50s' object has no attribute '%U'", - tp->tp_name, name); - - set_attribute_error_context(obj, name); - return 0; -} - -/* Generic GetAttr functions - put these in your tp_[gs]etattro slot. */ - -PyObject * -_PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, - PyObject *dict, int suppress) -{ - /* Make sure the logic of _PyObject_GetMethod is in sync with - this method. - - When suppress=1, this function suppresses AttributeError. - */ - - PyTypeObject *tp = Py_TYPE(obj); - PyObject *descr = NULL; - PyObject *res = NULL; - descrgetfunc f; - Py_ssize_t dictoffset; - PyObject **dictptr; - - 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 (tp->tp_dict == NULL) { - 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) { - /* Inline _PyObject_GetDictPtr */ - dictoffset = tp->tp_dictoffset; - if (dictoffset != 0) { - if (dictoffset < 0) { - Py_ssize_t tsize = Py_SIZE(obj); - if (tsize < 0) { - tsize = -tsize; - } - size_t size = _PyObject_VAR_SIZE(tp, tsize); - _PyObject_ASSERT(obj, size <= PY_SSIZE_T_MAX); - - dictoffset += (Py_ssize_t)size; - _PyObject_ASSERT(obj, dictoffset > 0); - _PyObject_ASSERT(obj, dictoffset % SIZEOF_VOID_P == 0); - } - dictptr = (PyObject **) ((char *)obj + dictoffset); - 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, - "'%.50s' object has no attribute '%U'", - tp->tp_name, 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; - PyObject **dictptr; - 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 (tp->tp_dict == NULL && PyType_Ready(tp) < 0) - return -1; - - Py_INCREF(name); - - 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; - } - } - - /* XXX [Steve Dower] These are really noisy - worth it? */ - /*if (PyType_Check(obj) || PyModule_Check(obj)) { - if (value && PySys_Audit("object.__setattr__", "OOO", obj, name, value) < 0) - return -1; - if (!value && PySys_Audit("object.__delattr__", "OO", obj, name) < 0) - return -1; - }*/ - - if (dict == NULL) { - dictptr = _PyObject_GetDictPtr(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, - "'%.50s' object attribute '%U' is read-only", - tp->tp_name, name); - } - goto done; - } - 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); - } - if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) - PyErr_SetObject(PyExc_AttributeError, name); - - done: - Py_XDECREF(descr); - 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) { - 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_INCREF(value); - Py_XSETREF(*dictptr, value); - return 0; -} - - -/* Test a value used as condition, e.g., in a while or if statement. - Return -1 if an error occurred */ - -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; - /* if it is negative, it should be either -1 or -2 */ - return (res > 0) ? 1 : Py_SAFE_DOWNCAST(res, Py_ssize_t, int); -} - -/* equivalent of 'not v' - Return -1 if an error occurred */ - -int -PyObject_Not(PyObject *v) -{ - int res; - res = PyObject_IsTrue(v); - if (res < 0) - return res; - return res == 0; -} - -/* Test whether an object can be called */ - -int -PyCallable_Check(PyObject *x) -{ - if (x == NULL) - return 0; - return Py_TYPE(x)->tp_call != NULL; -} - - -/* Helper for PyObject_Dir without arguments: returns the local scope. */ -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; - } - /* the locals don't need to be DECREF'd */ - return names; -} - -/* Helper for PyObject_Dir: object introspection. */ -static PyObject * -_dir_object(PyObject *obj) -{ - PyObject *result, *sorted; - PyObject *dirfunc = _PyObject_LookupSpecial(obj, &PyId___dir__); - - assert(obj != NULL); - if (dirfunc == NULL) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_TypeError, "object does not provide __dir__"); - return NULL; - } - /* use __dir__ */ - result = _PyObject_CallNoArg(dirfunc); - Py_DECREF(dirfunc); - if (result == NULL) - return NULL; - /* return sorted(result) */ - sorted = PySequence_List(result); - Py_DECREF(result); - if (sorted == NULL) - return NULL; - if (PyList_Sort(sorted)) { - Py_DECREF(sorted); - return NULL; - } - return sorted; -} - -/* Implementation of dir() -- if obj is NULL, returns the names in the current - (local) scope. Otherwise, performs introspection of the object: returns a - sorted list of attribute names (supposedly) accessible from the object -*/ -PyObject * -PyObject_Dir(PyObject *obj) -{ - return (obj == NULL) ? _dir_locals() : _dir_object(obj); -} - -/* -None is a non-NULL undefined value. -There is (and should be!) no way to create other objects of this type, -so there is exactly one (which is indestructible, by the way). -*/ - -/* ARGSUSED */ -static PyObject * -none_repr(PyObject *op) -{ - return PyUnicode_FromString("None"); -} - -/* ARGUSED */ -static void _Py_NO_RETURN -none_dealloc(PyObject* ignore) -{ - /* This should never get called, but we also don't want to SEGV if - * we accidentally decref None out of existence. - */ - Py_FatalError("deallocating 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 PyNumberMethods none_as_number = { - 0, /* nb_add */ - 0, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - (inquiry)none_bool, /* nb_bool */ - 0, /* nb_invert */ - 0, /* nb_lshift */ - 0, /* nb_rshift */ - 0, /* nb_and */ - 0, /* nb_xor */ - 0, /* nb_or */ - 0, /* nb_int */ - 0, /* nb_reserved */ - 0, /* nb_float */ - 0, /* nb_inplace_add */ - 0, /* nb_inplace_subtract */ - 0, /* nb_inplace_multiply */ - 0, /* nb_inplace_remainder */ - 0, /* nb_inplace_power */ - 0, /* nb_inplace_lshift */ - 0, /* nb_inplace_rshift */ - 0, /* nb_inplace_and */ - 0, /* nb_inplace_xor */ - 0, /* nb_inplace_or */ - 0, /* nb_floor_divide */ - 0, /* nb_true_divide */ - 0, /* nb_inplace_floor_divide */ - 0, /* nb_inplace_true_divide */ - 0, /* nb_index */ -}; - -PyTypeObject _PyNone_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "NoneType", - 0, - 0, - none_dealloc, /*tp_dealloc*/ /*never called*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - none_repr, /*tp_repr*/ - &none_as_number, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call */ - 0, /*tp_str */ - 0, /*tp_getattro */ - 0, /*tp_setattro */ - 0, /*tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /*tp_flags */ - 0, /*tp_doc */ - 0, /*tp_traverse */ - 0, /*tp_clear */ - 0, /*tp_richcompare */ - 0, /*tp_weaklistoffset */ - 0, /*tp_iter */ - 0, /*tp_iternext */ - 0, /*tp_methods */ - 0, /*tp_members */ - 0, /*tp_getset */ - 0, /*tp_base */ - 0, /*tp_dict */ - 0, /*tp_descr_get */ - 0, /*tp_descr_set */ - 0, /*tp_dictoffset */ - 0, /*tp_init */ - 0, /*tp_alloc */ - none_new, /*tp_new */ -}; - -PyObject _Py_NoneStruct = { - _PyObject_EXTRA_INIT - 1, &_PyNone_Type -}; - -/* NotImplemented is an object that can be used to signal that an - operation is not implemented for the given type combination. */ - -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 _Py_NO_RETURN -notimplemented_dealloc(PyObject* ignore) -{ - /* This should never get called, but we also don't want to SEGV if - * we accidentally decref NotImplemented out of existence. - */ - Py_FatalError("deallocating 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, /*tp_dealloc*/ /*never called*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - NotImplemented_repr, /*tp_repr*/ - ¬implemented_as_number, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call */ - 0, /*tp_str */ - 0, /*tp_getattro */ - 0, /*tp_setattro */ - 0, /*tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /*tp_flags */ - 0, /*tp_doc */ - 0, /*tp_traverse */ - 0, /*tp_clear */ - 0, /*tp_richcompare */ - 0, /*tp_weaklistoffset */ - 0, /*tp_iter */ - 0, /*tp_iternext */ - notimplemented_methods, /*tp_methods */ - 0, /*tp_members */ - 0, /*tp_getset */ - 0, /*tp_base */ - 0, /*tp_dict */ - 0, /*tp_descr_get */ - 0, /*tp_descr_set */ - 0, /*tp_dictoffset */ - 0, /*tp_init */ - 0, /*tp_alloc */ - notimplemented_new, /*tp_new */ -}; - -PyObject _Py_NotImplementedStruct = { - _PyObject_EXTRA_INIT - 1, &_PyNotImplemented_Type -}; - -PyStatus -_PyTypes_Init(void) -{ - PyStatus status = _PyTypes_InitSlotDefs(); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - -#define INIT_TYPE(TYPE) \ - do { \ - if (PyType_Ready(&(TYPE)) < 0) { \ - return _PyStatus_ERR("Can't initialize " #TYPE " type"); \ - } \ - } while (0) - - // Base types - INIT_TYPE(PyBaseObject_Type); - INIT_TYPE(PyType_Type); - assert(PyBaseObject_Type.tp_base == NULL); - assert(PyType_Type.tp_base == &PyBaseObject_Type); - - // All other static types - INIT_TYPE(PyAsyncGen_Type); - INIT_TYPE(PyBool_Type); - INIT_TYPE(PyByteArrayIter_Type); - INIT_TYPE(PyByteArray_Type); - INIT_TYPE(PyBytesIter_Type); - INIT_TYPE(PyBytes_Type); - INIT_TYPE(PyCFunction_Type); - INIT_TYPE(PyCMethod_Type); - INIT_TYPE(PyCallIter_Type); - INIT_TYPE(PyCapsule_Type); - INIT_TYPE(PyCell_Type); - INIT_TYPE(PyClassMethodDescr_Type); - INIT_TYPE(PyClassMethod_Type); - INIT_TYPE(PyCode_Type); - INIT_TYPE(PyComplex_Type); - INIT_TYPE(PyCoro_Type); - INIT_TYPE(PyDictItems_Type); - INIT_TYPE(PyDictIterItem_Type); - INIT_TYPE(PyDictIterKey_Type); - INIT_TYPE(PyDictIterValue_Type); - INIT_TYPE(PyDictKeys_Type); - INIT_TYPE(PyDictProxy_Type); - INIT_TYPE(PyDictRevIterItem_Type); - INIT_TYPE(PyDictRevIterKey_Type); - INIT_TYPE(PyDictRevIterValue_Type); - INIT_TYPE(PyDictValues_Type); - INIT_TYPE(PyDict_Type); - INIT_TYPE(PyEllipsis_Type); - INIT_TYPE(PyEnum_Type); - INIT_TYPE(PyFloat_Type); - INIT_TYPE(PyFrame_Type); - INIT_TYPE(PyFrozenSet_Type); - INIT_TYPE(PyFunction_Type); - INIT_TYPE(PyGen_Type); - INIT_TYPE(PyGetSetDescr_Type); - INIT_TYPE(PyInstanceMethod_Type); - INIT_TYPE(PyListIter_Type); - INIT_TYPE(PyListRevIter_Type); - INIT_TYPE(PyList_Type); - INIT_TYPE(PyLongRangeIter_Type); - INIT_TYPE(PyLong_Type); - INIT_TYPE(PyMemberDescr_Type); - INIT_TYPE(PyMemoryView_Type); - INIT_TYPE(PyMethodDescr_Type); - INIT_TYPE(PyMethod_Type); - INIT_TYPE(PyModuleDef_Type); - INIT_TYPE(PyModule_Type); - INIT_TYPE(PyODictItems_Type); - INIT_TYPE(PyODictIter_Type); - INIT_TYPE(PyODictKeys_Type); - INIT_TYPE(PyODictValues_Type); - INIT_TYPE(PyODict_Type); - INIT_TYPE(PyPickleBuffer_Type); - INIT_TYPE(PyProperty_Type); - INIT_TYPE(PyRangeIter_Type); - INIT_TYPE(PyRange_Type); - INIT_TYPE(PyReversed_Type); - INIT_TYPE(PySTEntry_Type); - INIT_TYPE(PySeqIter_Type); - INIT_TYPE(PySetIter_Type); - INIT_TYPE(PySet_Type); - INIT_TYPE(PySlice_Type); - INIT_TYPE(PyStaticMethod_Type); - INIT_TYPE(PyStdPrinter_Type); - INIT_TYPE(PySuper_Type); - INIT_TYPE(PyTraceBack_Type); - INIT_TYPE(PyTupleIter_Type); - INIT_TYPE(PyTuple_Type); - INIT_TYPE(PyUnicodeIter_Type); - INIT_TYPE(PyUnicode_Type); - INIT_TYPE(PyWrapperDescr_Type); - INIT_TYPE(Py_GenericAliasType); - INIT_TYPE(_PyAnextAwaitable_Type); - INIT_TYPE(_PyAsyncGenASend_Type); - INIT_TYPE(_PyAsyncGenAThrow_Type); - INIT_TYPE(_PyAsyncGenWrappedValue_Type); - INIT_TYPE(_PyCoroWrapper_Type); - INIT_TYPE(_PyInterpreterID_Type); - INIT_TYPE(_PyManagedBuffer_Type); - INIT_TYPE(_PyMethodWrapper_Type); - INIT_TYPE(_PyNamespace_Type); - INIT_TYPE(_PyNone_Type); - INIT_TYPE(_PyNotImplemented_Type); - INIT_TYPE(_PyWeakref_CallableProxyType); - INIT_TYPE(_PyWeakref_ProxyType); - INIT_TYPE(_PyWeakref_RefType); - INIT_TYPE(_PyUnion_Type); - - return _PyStatus_OK(); -#undef INIT_TYPE -} - - -void -_Py_NewReference(PyObject *op) -{ - if (_Py_tracemalloc_config.tracing) { - _PyTraceMalloc_NewReference(op); - } -#ifdef Py_REF_DEBUG - _Py_RefTotal++; -#endif - Py_SET_REFCNT(op, 1); -#ifdef Py_TRACE_REFS - _Py_AddToAllObjects(op, 1); -#endif -} - - -#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) { - /* Not found */ - _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; -} - -/* Print all live objects. Because PyObject_Print is called, the - * interpreter must be in a healthy state. - */ -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); - } -} - -/* Print the addresses of all live objects. Unlike _Py_PrintReferences, this - * doesn't make any calls to the Python C API, so is always safe to call. - */ -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 - - -/* Hack to force loading of abstract.o */ -Py_ssize_t (*_Py_abstract_hack)(PyObject *) = PyObject_Size; - - -void -_PyObject_DebugTypeStats(FILE *out) -{ - _PyDict_DebugMallocStats(out); - _PyFloat_DebugMallocStats(out); - _PyFrame_DebugMallocStats(out); - _PyList_DebugMallocStats(out); - _PyTuple_DebugMallocStats(out); -} - -/* These methods are used to control infinite recursion in repr, str, print, - etc. Container objects that may recursively contain themselves, - e.g. builtin dictionaries and lists, should use Py_ReprEnter() and - Py_ReprLeave() to avoid infinite recursion. - - Py_ReprEnter() returns 0 the first time it is called for a particular - object and 1 every time thereafter. It returns -1 if an exception - occurred. Py_ReprLeave() has no return value. - - See dictobject.c and listobject.c for examples of use. -*/ - -int -Py_ReprEnter(PyObject *obj) -{ - PyObject *dict; - PyObject *list; - Py_ssize_t i; - - dict = PyThreadState_GetDict(); - /* Ignore a missing thread-state, so that this function can be called - early on startup. */ - if (dict == NULL) - return 0; - list = _PyDict_GetItemIdWithError(dict, &PyId_Py_Repr); - if (list == NULL) { - if (PyErr_Occurred()) { - return -1; - } - list = PyList_New(0); - if (list == NULL) - return -1; - if (_PyDict_SetItemId(dict, &PyId_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 *error_type, *error_value, *error_traceback; - - PyErr_Fetch(&error_type, &error_value, &error_traceback); - - dict = PyThreadState_GetDict(); - if (dict == NULL) - goto finally; - - list = _PyDict_GetItemIdWithError(dict, &PyId_Py_Repr); - if (list == NULL || !PyList_Check(list)) - goto finally; - - i = PyList_GET_SIZE(list); - /* Count backwards because we always expect obj to be list[-1] */ - while (--i >= 0) { - if (PyList_GET_ITEM(list, i) == obj) { - PyList_SetSlice(list, i, i + 1, NULL); - break; - } - } - -finally: - /* ignore exceptions because there is no way to report them. */ - PyErr_Restore(error_type, error_value, error_traceback); -} - -/* Trashcan support. */ - -/* Add op to the _PyTrash_delete_later list. Called when the current - * call-stack depth gets large. op must be a currently untracked gc'ed - * object, with refcount 0. Py_DECREF must already have been called on it. - */ -void -_PyTrash_deposit_object(PyObject *op) -{ - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _gc_runtime_state *gcstate = &interp->gc; - - _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), gcstate->trash_delete_later); - gcstate->trash_delete_later = op; -} - -/* The equivalent API, using per-thread state recursion info */ -void -_PyTrash_thread_deposit_object(PyObject *op) -{ - PyThreadState *tstate = _PyThreadState_GET(); - _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), tstate->trash_delete_later); - tstate->trash_delete_later = op; -} - -/* Deallocate all the objects in the _PyTrash_delete_later list. Called when - * the call-stack unwinds again. - */ -void -_PyTrash_destroy_chain(void) -{ - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _gc_runtime_state *gcstate = &interp->gc; - - while (gcstate->trash_delete_later) { - PyObject *op = gcstate->trash_delete_later; - destructor dealloc = Py_TYPE(op)->tp_dealloc; - - gcstate->trash_delete_later = - (PyObject*) _PyGCHead_PREV(_Py_AS_GC(op)); - - /* Call the deallocator directly. This used to try to - * fool Py_DECREF into calling it indirectly, but - * Py_DECREF was already called on this object, and in - * assorted non-release builds calling Py_DECREF again ends - * up distorting allocation statistics. - */ - _PyObject_ASSERT(op, Py_REFCNT(op) == 0); - ++gcstate->trash_delete_nesting; - (*dealloc)(op); - --gcstate->trash_delete_nesting; - } -} - -/* The equivalent API, using per-thread state recursion info */ -void -_PyTrash_thread_destroy_chain(void) -{ - PyThreadState *tstate = _PyThreadState_GET(); - /* We need to increase trash_delete_nesting here, otherwise, - _PyTrash_thread_destroy_chain will be called recursively - and then possibly crash. An example that may crash without - increase: - N = 500000 # need to be large enough - ob = object() - tups = [(ob,) for i in range(N)] - for i in range(49): - tups = [(tup,) for tup in tups] - del tups - */ - assert(tstate->trash_delete_nesting == 0); - ++tstate->trash_delete_nesting; - while (tstate->trash_delete_later) { - PyObject *op = tstate->trash_delete_later; - destructor dealloc = Py_TYPE(op)->tp_dealloc; - - tstate->trash_delete_later = - (PyObject*) _PyGCHead_PREV(_Py_AS_GC(op)); - - /* Call the deallocator directly. This used to try to - * fool Py_DECREF into calling it indirectly, but - * Py_DECREF was already called on this object, and in - * assorted non-release builds calling Py_DECREF again ends - * up distorting allocation statistics. - */ - _PyObject_ASSERT(op, Py_REFCNT(op) == 0); - (*dealloc)(op); - assert(tstate->trash_delete_nesting == 1); - } - --tstate->trash_delete_nesting; -} - - -int -_PyTrash_begin(PyThreadState *tstate, PyObject *op) -{ - if (tstate->trash_delete_nesting >= PyTrash_UNWIND_LEVEL) { - /* Store the object (to be deallocated later) and jump past - * Py_TRASHCAN_END, skipping the body of the deallocator */ - _PyTrash_thread_deposit_object(op); - return 1; - } - ++tstate->trash_delete_nesting; - return 0; -} - - -void -_PyTrash_end(PyThreadState *tstate) -{ - --tstate->trash_delete_nesting; - if (tstate->trash_delete_later && tstate->trash_delete_nesting <= 0) { - _PyTrash_thread_destroy_chain(); - } -} - - -/* bpo-40170: It's only be used in Py_TRASHCAN_BEGIN macro to hide - implementation details. */ -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)) { - /* It seems like the object memory has been freed: - don't access it to prevent a segmentation fault. */ - fprintf(stderr, "<object at %p is freed>\n", obj); - fflush(stderr); - } - else { - /* Display the traceback where the object has been allocated. - Do it before dumping repr(obj), since repr() is more likely - to crash than dumping the traceback. */ - void *ptr; - PyTypeObject *type = Py_TYPE(obj); - if (_PyType_IS_GC(type)) { - ptr = (void *)((char *)obj - sizeof(PyGC_Head)); - } - else { - ptr = (void *)obj; - } - _PyMem_DumpTraceback(fileno(stderr), ptr); - - /* This might succeed or fail, but we're about to abort, so at least - try to provide any extra info we can: */ - _PyObject_Dump(obj); - - fprintf(stderr, "\n"); - fflush(stderr); - } - - Py_FatalError("_PyObject_AssertFailed"); -} - - -void -_Py_Dealloc(PyObject *op) -{ - destructor dealloc = Py_TYPE(op)->tp_dealloc; -#ifdef Py_TRACE_REFS - _Py_ForgetReference(op); -#endif - (*dealloc)(op); -} - - -PyObject ** -PyObject_GET_WEAKREFS_LISTPTR(PyObject *op) -{ - return _PyObject_GET_WEAKREFS_LISTPTR(op); -} - - -#undef Py_NewRef -#undef Py_XNewRef - -// Export Py_NewRef() and Py_XNewRef() as regular functions for the stable ABI. -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 - -// Export Py_Is(), Py_IsNone(), Py_IsTrue(), Py_IsFalse() as regular functions -// for the stable ABI. -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 |