diff options
Diffstat (limited to 'Objects/object.c')
-rw-r--r-- | Objects/object.c | 550 |
1 files changed, 314 insertions, 236 deletions
diff --git a/Objects/object.c b/Objects/object.c index 28bb9c1..949e7dc 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1,5 +1,5 @@ -/* Generic object operations; and implementation of None (NoObject) */ +/* Generic object operations; and implementation of None */ #include "Python.h" #include "frameobject.h" @@ -29,8 +29,6 @@ _Py_GetRefTotal(void) } #endif /* Py_REF_DEBUG */ -int Py_DivisionWarningFlag; - /* 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! */ @@ -297,9 +295,7 @@ PyObject_Print(PyObject *op, FILE *fp, int flags) } else if (PyUnicode_Check(s)) { PyObject *t; - t = PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(s), - PyUnicode_GET_SIZE(s), - "backslashreplace"); + t = PyUnicode_AsEncodedString(s, "utf-8", "backslashreplace"); if (t == NULL) ret = 0; else { @@ -382,13 +378,19 @@ PyObject_Repr(PyObject *v) return PyUnicode_FromFormat("<%s object at %p>", v->ob_type->tp_name, v); res = (*v->ob_type->tp_repr)(v); - if (res != NULL && !PyUnicode_Check(res)) { + if (res == NULL) + return NULL; + if (!PyUnicode_Check(res)) { PyErr_Format(PyExc_TypeError, "__repr__ returned non-string (type %.200s)", res->ob_type->tp_name); Py_DECREF(res); return NULL; } +#ifndef Py_DEBUG + if (PyUnicode_READY(res) < 0) + return NULL; +#endif return res; } @@ -407,6 +409,10 @@ PyObject_Str(PyObject *v) 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; } @@ -428,6 +434,11 @@ PyObject_Str(PyObject *v) Py_DECREF(res); return NULL; } +#ifndef Py_DEBUG + if (PyUnicode_READY(res) < 0) + return NULL; +#endif + assert(_PyUnicode_CheckConsistency(res, 1)); return res; } @@ -441,11 +452,7 @@ PyObject_ASCII(PyObject *v) return NULL; /* repr is guaranteed to be a PyUnicode object by PyObject_Repr */ - ascii = PyUnicode_EncodeASCII( - PyUnicode_AS_UNICODE(repr), - PyUnicode_GET_SIZE(repr), - "backslashreplace"); - + ascii = _PyUnicode_AsASCIIString(repr, "backslashreplace"); Py_DECREF(repr); if (ascii == NULL) return NULL; @@ -463,7 +470,7 @@ PyObject * PyObject_Bytes(PyObject *v) { PyObject *result, *func; - static PyObject *bytesstring = NULL; + _Py_IDENTIFIER(__bytes__); if (v == NULL) return PyBytes_FromString("<NULL>"); @@ -473,7 +480,7 @@ PyObject_Bytes(PyObject *v) return v; } - func = _PyObject_LookupSpecial(v, "__bytes__", &bytesstring); + func = _PyObject_LookupSpecial(v, &PyId___bytes__); if (func != NULL) { result = PyObject_CallFunctionObjArgs(func, NULL); Py_DECREF(func); @@ -747,6 +754,33 @@ _Py_HashPointer(void *p) } Py_hash_t +_Py_HashBytes(unsigned char *p, Py_ssize_t len) +{ + Py_uhash_t x; + Py_ssize_t i; + + /* + We make the hash of the empty string be 0, rather than using + (prefix ^ suffix), since this slightly obfuscates the hash secret + */ +#ifdef Py_DEBUG + assert(_Py_HashSecret_Initialized); +#endif + if (len == 0) { + return 0; + } + x = (Py_uhash_t) _Py_HashSecret.prefix; + x ^= (Py_uhash_t) *p << 7; + for (i = 0; i < len; i++) + x = (_PyHASH_MULTIPLIER * x) ^ (Py_uhash_t) *p++; + x ^= (Py_uhash_t) len; + x ^= (Py_uhash_t) _Py_HashSecret.suffix; + if (x == -1) + x = -2; + return x; +} + +Py_hash_t PyObject_HashNotImplemented(PyObject *v) { PyErr_Format(PyExc_TypeError, "unhashable type: '%.200s'", @@ -788,7 +822,7 @@ PyObject_GetAttrString(PyObject *v, const char *name) if (w == NULL) return NULL; res = PyObject_GetAttr(v, w); - Py_XDECREF(w); + Py_DECREF(w); return res; } @@ -820,6 +854,62 @@ PyObject_SetAttrString(PyObject *v, const char *name, PyObject *w) return res; } +int +_PyObject_IsAbstract(PyObject *obj) +{ + int res; + PyObject* isabstract; + _Py_IDENTIFIER(__isabstractmethod__); + + if (obj == NULL) + return 0; + + isabstract = _PyObject_GetAttrId(obj, &PyId___isabstractmethod__); + if (isabstract == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + return 0; + } + return -1; + } + 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_HasAttrId(PyObject *v, _Py_Identifier *name) +{ + int result; + PyObject *oname = _PyUnicode_FromId(name); /* borrowed */ + if (!oname) + return -1; + result = PyObject_HasAttr(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; +} + PyObject * PyObject_GetAttr(PyObject *v, PyObject *name) { @@ -938,6 +1028,19 @@ PyObject_SelfIter(PyObject *obj) return obj; } +/* Convenience function to get a builtin from its name */ +PyObject * +_PyObject_GetBuiltin(const char *name) +{ + PyObject *mod, *attr; + mod = PyImport_ImportModule("builtins"); + if (mod == NULL) + return NULL; + attr = PyObject_GetAttrString(mod, name); + Py_DECREF(mod); + return attr; +} + /* 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. @@ -986,7 +1089,6 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) f = descr->ob_type->tp_descr_get; if (f != NULL && PyDescr_IsData(descr)) { res = f(descr, obj, (PyObject *)obj->ob_type); - Py_DECREF(descr); goto done; } } @@ -1017,7 +1119,6 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) res = PyDict_GetItem(dict, name); if (res != NULL) { Py_INCREF(res); - Py_XDECREF(descr); Py_DECREF(dict); goto done; } @@ -1026,13 +1127,12 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) if (f != NULL) { res = f(descr, obj, (PyObject *)Py_TYPE(obj)); - Py_DECREF(descr); goto done; } if (descr != NULL) { res = descr; - /* descr was already increfed above */ + descr = NULL; goto done; } @@ -1040,6 +1140,7 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) "'%.50s' object has no attribute '%U'", tp->tp_name, name); done: + Py_XDECREF(descr); Py_DECREF(name); return res; } @@ -1066,15 +1167,15 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name, name->ob_type->tp_name); return -1; } - else - Py_INCREF(name); - if (tp->tp_dict == NULL) { - if (PyType_Ready(tp) < 0) - goto done; - } + if (tp->tp_dict == NULL && PyType_Ready(tp) < 0) + return -1; + + Py_INCREF(name); descr = _PyType_Lookup(tp, name); + Py_XINCREF(descr); + f = NULL; if (descr != NULL) { f = descr->ob_type->tp_descr_set; @@ -1087,13 +1188,10 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name, if (dict == NULL) { dictptr = _PyObject_GetDictPtr(obj); if (dictptr != NULL) { - dict = *dictptr; - if (dict == NULL && value != NULL) { - dict = PyDict_New(); - if (dict == NULL) - goto done; - *dictptr = dict; - } + res = _PyObjectDict_SetItem(Py_TYPE(obj), dictptr, name, value); + if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) + PyErr_SetObject(PyExc_AttributeError, name); + goto done; } } if (dict != NULL) { @@ -1102,9 +1200,9 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name, 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); - Py_DECREF(dict); goto done; } @@ -1124,6 +1222,7 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name, "'%.50s' object attribute '%U' is read-only", tp->tp_name, name); done: + Py_XDECREF(descr); Py_DECREF(name); return res; } @@ -1134,6 +1233,32 @@ 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 *dict, **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; + } + dict = *dictptr; + Py_XINCREF(value); + *dictptr = value; + Py_XDECREF(dict); + return 0; +} + /* Test a value used as condition, e.g., in a for or if statement. Return -1 if an error occurred */ @@ -1186,66 +1311,6 @@ PyCallable_Check(PyObject *x) return x->ob_type->tp_call != NULL; } -/* ------------------------- PyObject_Dir() helpers ------------------------- */ - -/* Helper for PyObject_Dir. - Merge the __dict__ of aclass into dict, and recursively also all - the __dict__s of aclass's base classes. The order of merging isn't - defined, as it's expected that only the final set of dict keys is - interesting. - Return 0 on success, -1 on error. -*/ - -static int -merge_class_dict(PyObject* dict, PyObject* aclass) -{ - PyObject *classdict; - PyObject *bases; - - assert(PyDict_Check(dict)); - assert(aclass); - - /* Merge in the type's dict (if any). */ - classdict = PyObject_GetAttrString(aclass, "__dict__"); - if (classdict == NULL) - PyErr_Clear(); - else { - int status = PyDict_Update(dict, classdict); - Py_DECREF(classdict); - if (status < 0) - return -1; - } - - /* Recursively merge in the base types' (if any) dicts. */ - bases = PyObject_GetAttrString(aclass, "__bases__"); - if (bases == NULL) - PyErr_Clear(); - else { - /* We have no guarantee that bases is a real tuple */ - Py_ssize_t i, n; - n = PySequence_Size(bases); /* This better be right */ - if (n < 0) - PyErr_Clear(); - else { - for (i = 0; i < n; i++) { - int status; - PyObject *base = PySequence_GetItem(bases, i); - if (base == NULL) { - Py_DECREF(bases); - return -1; - } - status = merge_class_dict(dict, base); - Py_DECREF(base); - if (status < 0) { - Py_DECREF(bases); - return -1; - } - } - } - Py_DECREF(bases); - } - return 0; -} /* Helper for PyObject_Dir without arguments: returns the local scope. */ static PyObject * @@ -1269,140 +1334,43 @@ _dir_locals(void) 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 of type objects: returns __dict__ and __bases__. - We deliberately don't suck up its __class__, as methods belonging to the - metaclass would probably be more confusing than helpful. -*/ -static PyObject * -_specialized_dir_type(PyObject *obj) -{ - PyObject *result = NULL; - PyObject *dict = PyDict_New(); - - if (dict != NULL && merge_class_dict(dict, obj) == 0) - result = PyDict_Keys(dict); - - Py_XDECREF(dict); - return result; -} - -/* Helper for PyObject_Dir of module objects: returns the module's __dict__. */ -static PyObject * -_specialized_dir_module(PyObject *obj) -{ - PyObject *result = NULL; - PyObject *dict = PyObject_GetAttrString(obj, "__dict__"); - - if (dict != NULL) { - if (PyDict_Check(dict)) - result = PyDict_Keys(dict); - else { - const char *name = PyModule_GetName(obj); - if (name) - PyErr_Format(PyExc_TypeError, - "%.200s.__dict__ is not a dictionary", - name); - } - } - - Py_XDECREF(dict); - return result; -} - -/* Helper for PyObject_Dir of generic objects: returns __dict__, __class__, - and recursively up the __class__.__bases__ chain. -*/ -static PyObject * -_generic_dir(PyObject *obj) -{ - PyObject *result = NULL; - PyObject *dict = NULL; - PyObject *itsclass = NULL; - - /* Get __dict__ (which may or may not be a real dict...) */ - dict = PyObject_GetAttrString(obj, "__dict__"); - if (dict == NULL) { - PyErr_Clear(); - dict = PyDict_New(); - } - else if (!PyDict_Check(dict)) { - Py_DECREF(dict); - dict = PyDict_New(); - } - else { - /* Copy __dict__ to avoid mutating it. */ - PyObject *temp = PyDict_Copy(dict); - Py_DECREF(dict); - dict = temp; - } - - if (dict == NULL) - goto error; - - /* Merge in attrs reachable from its class. */ - itsclass = PyObject_GetAttrString(obj, "__class__"); - if (itsclass == NULL) - /* XXX(tomer): Perhaps fall back to obj->ob_type if no - __class__ exists? */ - PyErr_Clear(); - else { - if (merge_class_dict(dict, itsclass) != 0) - goto error; - } - - result = PyDict_Keys(dict); - /* fall through */ -error: - Py_XDECREF(itsclass); - Py_XDECREF(dict); - return result; -} - -/* Helper for PyObject_Dir: object introspection. - This calls one of the above specialized versions if no __dir__ method - exists. */ +/* Helper for PyObject_Dir: object introspection. */ static PyObject * _dir_object(PyObject *obj) { - PyObject *result = NULL; - static PyObject *dir_str = NULL; - PyObject *dirfunc = _PyObject_LookupSpecial(obj, "__dir__", &dir_str); + PyObject *result, *sorted; + _Py_IDENTIFIER(__dir__); + PyObject *dirfunc = _PyObject_LookupSpecial(obj, &PyId___dir__); assert(obj); if (dirfunc == NULL) { - if (PyErr_Occurred()) - return NULL; - /* use default implementation */ - if (PyModule_Check(obj)) - result = _specialized_dir_module(obj); - else if (PyType_Check(obj)) - result = _specialized_dir_type(obj); - else - result = _generic_dir(obj); + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_TypeError, "object does not provide __dir__"); + return NULL; } - else { - /* use __dir__ */ - result = PyObject_CallFunctionObjArgs(dirfunc, NULL); - Py_DECREF(dirfunc); - if (result == NULL) - return NULL; - - /* result must be a list */ - /* XXX(gbrandl): could also check if all items are strings */ - if (!PyList_Check(result)) { - PyErr_Format(PyExc_TypeError, - "__dir__() must return a list, not %.200s", - Py_TYPE(result)->tp_name); - Py_DECREF(result); - result = NULL; - } + /* use __dir__ */ + result = PyObject_CallFunctionObjArgs(dirfunc, NULL); + 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 result; + return sorted; } /* Implementation of dir() -- if obj is NULL, returns the names in the current @@ -1412,31 +1380,13 @@ _dir_object(PyObject *obj) PyObject * PyObject_Dir(PyObject *obj) { - PyObject * result; - - if (obj == NULL) - /* no object -- introspect the locals */ - result = _dir_locals(); - else - /* object -- introspect the object */ - result = _dir_object(obj); - - assert(result == NULL || PyList_Check(result)); - - if (result != NULL && PyList_Sort(result) != 0) { - /* sorting the list failed */ - Py_DECREF(result); - result = NULL; - } - - return result; + return (obj == NULL) ? _dir_locals() : _dir_object(obj); } /* -NoObject is usable as a non-NULL undefined value, used by the macro None. +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). -(XXX This type and the type of NotImplemented below should be unified.) */ /* ARGSUSED */ @@ -1456,6 +1406,58 @@ none_dealloc(PyObject* ignore) Py_FatalError("deallocating None"); } +static PyObject * +none_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_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 */ +}; static PyTypeObject PyNone_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) @@ -1468,10 +1470,34 @@ static PyTypeObject PyNone_Type = { 0, /*tp_setattr*/ 0, /*tp_reserved*/ none_repr, /*tp_repr*/ - 0, /*tp_as_number*/ + &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 = { @@ -1488,6 +1514,16 @@ NotImplemented_repr(PyObject *op) return PyUnicode_FromString("NotImplemented"); } +static PyObject * +notimplemented_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_Size(kwargs))) { + PyErr_SetString(PyExc_TypeError, "NotImplementedType takes no arguments"); + return NULL; + } + Py_RETURN_NOTIMPLEMENTED; +} + static PyTypeObject PyNotImplemented_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "NotImplementedType", @@ -1503,6 +1539,30 @@ static PyTypeObject PyNotImplemented_Type = { 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 */ + notimplemented_new, /*tp_new */ }; PyObject _Py_NotImplementedStruct = { @@ -1585,6 +1645,9 @@ _Py_ReadyTypes(void) if (PyType_Ready(&PyProperty_Type) < 0) Py_FatalError("Can't initialize property type"); + if (PyType_Ready(&_PyManagedBuffer_Type) < 0) + Py_FatalError("Can't initialize managed buffer type"); + if (PyType_Ready(&PyMemoryView_Type) < 0) Py_FatalError("Can't initialize memoryview type"); @@ -1645,6 +1708,9 @@ _Py_ReadyTypes(void) if (PyType_Ready(&PyZip_Type) < 0) Py_FatalError("Can't initialize zip type"); + if (PyType_Ready(&_PyNamespace_Type) < 0) + Py_FatalError("Can't initialize namespace type"); + if (PyType_Ready(&PyCapsule_Type) < 0) Py_FatalError("Can't initialize capsule type"); @@ -1810,6 +1876,18 @@ PyMem_Free(void *p) PyMem_FREE(p); } +void +_PyObject_DebugTypeStats(FILE *out) +{ + _PyCFunction_DebugMallocStats(out); + _PyDict_DebugMallocStats(out); + _PyFloat_DebugMallocStats(out); + _PyFrame_DebugMallocStats(out); + _PyList_DebugMallocStats(out); + _PyMethod_DebugMallocStats(out); + _PySet_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, |