From 7869d35d94e6f7475ce38477fe28f3bed1f2e4e4 Mon Sep 17 00:00:00 2001 From: thatbirdguythatuknownot Date: Mon, 21 Aug 2023 08:02:35 +0800 Subject: [PATCH] nicer reprs and stuff --- .../pycore_global_objects_fini_generated.h | 2 +- Include/internal/pycore_global_strings.h | 2 +- .../internal/pycore_runtime_init_generated.h | 2 +- Modules/_struct.c | 10 + Objects/descrobject.c | 202 ++++++++++++++++-- Objects/funcobject.c | 80 ++++++- Objects/methodobject.c | 32 ++- Objects/moduleobject.c | 13 +- Objects/typeobject.c | 69 ++++-- Python/compile.c | 21 +- 10 files changed, 364 insertions(+), 69 deletions(-) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 79d0438..dbe73e1 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -552,12 +552,12 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(anon_string)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(anon_unknown)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(close_br)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(comm_at)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dbl_close_br)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dbl_open_br)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dbl_percent)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(defaults)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dot)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dot_locals)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(empty)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(generic_base)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(json_decoder)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index ae80062..b9710e5 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -38,12 +38,12 @@ struct _Py_global_strings { STRUCT_FOR_STR(anon_string, "") STRUCT_FOR_STR(anon_unknown, "") STRUCT_FOR_STR(close_br, "}") + STRUCT_FOR_STR(comm_at, "@") STRUCT_FOR_STR(dbl_close_br, "}}") STRUCT_FOR_STR(dbl_open_br, "{{") STRUCT_FOR_STR(dbl_percent, "%%") STRUCT_FOR_STR(defaults, ".defaults") STRUCT_FOR_STR(dot, ".") - STRUCT_FOR_STR(dot_locals, ".") STRUCT_FOR_STR(empty, "") STRUCT_FOR_STR(generic_base, ".generic_base") STRUCT_FOR_STR(json_decoder, "json.decoder") diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index aaf70c6..e0a06a8 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -544,12 +544,12 @@ extern "C" { INIT_STR(anon_string, ""), \ INIT_STR(anon_unknown, ""), \ INIT_STR(close_br, "}"), \ + INIT_STR(comm_at, "@"), \ INIT_STR(dbl_close_br, "}}"), \ INIT_STR(dbl_open_br, "{{"), \ INIT_STR(dbl_percent, "%%"), \ INIT_STR(defaults, ".defaults"), \ INIT_STR(dot, "."), \ - INIT_STR(dot_locals, "."), \ INIT_STR(empty, ""), \ INIT_STR(generic_base, ".generic_base"), \ INIT_STR(json_decoder, "json.decoder"), \ diff --git a/Modules/_struct.c b/Modules/_struct.c index 425715a..747aed8 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -1902,6 +1902,15 @@ Struct_iter_unpack(PyStructObject *self, PyObject *buffer) } +static PyObject * +s_repr(PyStructObject *self) +{ + return PyUnicode_FromFormat("%R(%R)", + Py_TYPE(self), + self->s_format); +} + + /* * Guts of the pack function. * @@ -2197,6 +2206,7 @@ static PyType_Slot PyStructType_slots[] = { {Py_tp_getattro, PyObject_GenericGetAttr}, {Py_tp_setattro, PyObject_GenericSetAttr}, {Py_tp_doc, (void*)s__doc__}, + {Py_tp_repr, s_repr}, {Py_tp_traverse, s_traverse}, {Py_tp_clear, s_clear}, {Py_tp_methods, s_methods}, diff --git a/Objects/descrobject.c b/Objects/descrobject.c index a744c3d..7199630 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -53,6 +53,8 @@ descr_name(PyDescrObject *descr) return NULL; } +static PyObject *descr_get_qualname(PyDescrObject *descr, void *Py_UNUSED(ignored)); + static PyObject * descr_repr(PyDescrObject *descr, const char *format) { @@ -66,29 +68,94 @@ descr_repr(PyDescrObject *descr, const char *format) static PyObject * method_repr(PyMethodDescrObject *descr) { - return descr_repr((PyDescrObject *)descr, - ""); + PyObject *qualname = descr_get_qualname((PyDescrObject *)descr, NULL); + if (qualname == NULL) { + return NULL; + } + + PyObject *objclass = (PyObject *)descr->d_common.d_type; + if (objclass == NULL) { + return qualname; + } + + PyObject *mod; + int res = PyObject_GetOptionalAttr(objclass, &_Py_ID(__module__), &mod); + if (res < 0) { + Py_DECREF(qualname); + return NULL; + } + if (res == 0 || _PyUnicode_Equal(mod, &_Py_ID(builtins)) || + _PyUnicode_EqualToASCIIString(mod, "__main__")) + { + Py_DECREF(mod); + return qualname; + } + + PyObject *rtn = PyUnicode_FromFormat("%U.%U", mod, qualname); + Py_DECREF(mod); + Py_DECREF(qualname); + return rtn; } static PyObject * member_repr(PyMemberDescrObject *descr) { - return descr_repr((PyDescrObject *)descr, - ""); -} + PyObject *tpname = NULL, *name = NULL, *rtn = NULL; -static PyObject * -getset_repr(PyGetSetDescrObject *descr) -{ - return descr_repr((PyDescrObject *)descr, - ""); -} + name = descr_name((PyDescrObject *)descr); + if (name == NULL) { + name = PyUnicode_FromString("?"); + if (name == NULL) { + return NULL; + } + } + else { + Py_INCREF(name); + } -static PyObject * -wrapperdescr_repr(PyWrapperDescrObject *descr) -{ - return descr_repr((PyDescrObject *)descr, - ""); + PyObject *objclass = (PyObject *)descr->d_common.d_type; + if (objclass == NULL) { + tpname = PyUnicode_FromString("?"); + if (tpname == NULL) { + goto error; + } + } + else { + int res = PyObject_GetOptionalAttr(objclass, + &_Py_ID(__name__), &tpname); + if (res < 0) { + goto error; + } + if (res == 0) { + tpname = PyUnicode_FromString("?"); + if (tpname == NULL) { + goto error; + } + } + PyObject *mod; + res = PyObject_GetOptionalAttr(objclass, &_Py_ID(__module__), &mod); + if (res < 0) { + goto error; + } + if (res != 0 && !_PyUnicode_Equal(mod, &_Py_ID(builtins)) && + !_PyUnicode_EqualToASCIIString(mod, "__main__")) + { + PyObject *temp = PyUnicode_FromFormat("%U.%U", mod, tpname); + Py_DECREF(mod); + Py_DECREF(tpname); + tpname = NULL; + if (temp == NULL) { + goto error; + } + tpname = temp; + } + } + + rtn = PyUnicode_FromFormat("", tpname, name); + error: + Py_XDECREF(tpname); + Py_XDECREF(name); + return rtn; } static int @@ -836,7 +903,7 @@ PyTypeObject PyGetSetDescr_Type = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)getset_repr, /* tp_repr */ + (reprfunc)member_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -873,7 +940,7 @@ PyTypeObject PyWrapperDescr_Type = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)wrapperdescr_repr, /* tp_repr */ + (reprfunc)method_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -1339,10 +1406,30 @@ wrapper_hash(wrapperobject *wp) static PyObject * wrapper_repr(wrapperobject *wp) { - return PyUnicode_FromFormat("", - wp->descr->d_base->name, - Py_TYPE(wp->self)->tp_name, - wp->self); + PyObject *obj_repr; + + if (PyModule_Check(wp->self)) { + obj_repr = ((PyModuleObject *)wp->self)->md_name; + if (_PyUnicode_Equal(obj_repr, &_Py_ID(builtins)) || + _PyUnicode_EqualToASCIIString(obj_repr, "__main__")) + { + return PyUnicode_FromString(wp->descr->d_base->name); + } + } + else { + if (PyLong_CheckExact(wp->self)) { + return PyUnicode_FromFormat("%R .%s", + wp->self, wp->descr->d_base->name); + } + obj_repr = PyObject_Repr(wp->self); + if (obj_repr == NULL) { + return NULL; + } + } + PyObject *rtn = PyUnicode_FromFormat("%U.%s", + obj_repr, wp->descr->d_base->name); + Py_DECREF(obj_repr); + return rtn; } static PyObject * @@ -1587,6 +1674,75 @@ static PyMethodDef property_methods[] = { }; +static PyObject * +property_repr(propertyobject *self) +{ + _PyUnicodeWriter writer; + int comma = 0; + + PyObject *objrepr = PyObject_Repr((PyObject *)Py_TYPE(self)); + if (objrepr == NULL) { + return NULL; + } + + _PyUnicodeWriter_Init(&writer); + writer.min_length = PyUnicode_GET_LENGTH(objrepr) + 2; + writer.overallocate = 1; + + if (_PyUnicodeWriter_WriteStr(&writer, objrepr) == -1) { + Py_DECREF(objrepr); + goto error; + } + Py_DECREF(objrepr); + + if (_PyUnicodeWriter_WriteChar(&writer, '(') < 0) { + goto error; + } + +#define WRITE_FIELD(name, field) \ + if (self->field) { \ + if (comma) { \ + if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) { \ + goto error; \ + } \ + } \ + else { \ + comma = 1; \ + } \ + if (_PyUnicodeWriter_WriteASCIIString(&writer, name, \ + sizeof(name) - 1) < 0) { \ + goto error; \ + } \ + if (_PyUnicodeWriter_WriteChar(&writer, '=') < 0) { \ + goto error; \ + } \ + objrepr = PyObject_Repr(self->field); \ + if (objrepr == NULL) { \ + goto error; \ + } \ + if (_PyUnicodeWriter_WriteStr(&writer, objrepr) == -1) { \ + Py_DECREF(objrepr); \ + goto error; \ + } \ + Py_DECREF(objrepr); \ + } + + WRITE_FIELD("fget", prop_get) + WRITE_FIELD("fset", prop_set) + WRITE_FIELD("fdel", prop_del) + WRITE_FIELD("doc", prop_doc) + + if (_PyUnicodeWriter_WriteChar(&writer, ')') < 0) { + goto error; + } + + return _PyUnicodeWriter_Finish(&writer); + + error: + _PyUnicodeWriter_Dealloc(&writer); + return NULL; +} + static void property_dealloc(PyObject *self) { @@ -1972,7 +2128,7 @@ PyTypeObject PyProperty_Type = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - 0, /* tp_repr */ + (reprfunc)property_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 8c0bfac..2ffd3bc 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -862,8 +862,76 @@ func_dealloc(PyFunctionObject *op) static PyObject* func_repr(PyFunctionObject *op) { - return PyUnicode_FromFormat("", - op->func_qualname, op); +#define WRITE(type, ...) \ + if (_PyUnicodeWriter_Write##type(&writer, __VA_ARGS__) < 0) { \ + goto error; \ + } \ + + PyCodeObject *co; + _PyUnicodeWriter writer; + int index; + + if (op->func_closure == NULL) { + return + !_PyUnicode_EqualToASCIIString(op->func_module, "builtins") && + !_PyUnicode_EqualToASCIIString(op->func_module, "__main__") ? + PyUnicode_Concat(op->func_module, op->func_qualname) : + op->func_qualname; + } + + _PyUnicodeWriter_Init(&writer); + writer.min_length = PyUnicode_GET_LENGTH(op->func_qualname) + 9; + writer.overallocate = 1; + + if (!_PyUnicode_EqualToASCIIString(op->func_name, "")) { + WRITE(ASCIIString, "func_module, &_Py_ID(builtins)) && + !_PyUnicode_EqualToASCIIString(op->func_module, "__main__")) + { + WRITE(Str, op->func_module); + } + + WRITE(Str, op->func_qualname); + + co = (PyCodeObject *)op->func_code; + index = 0; + for (int offset = 0; offset < co->co_nlocalsplus; offset++) { + _PyLocals_Kind k = _PyLocals_GetKind(co->co_localspluskinds, offset); + if ((k & CO_FAST_FREE) == 0) { + continue; + } + + assert(index < PyTuple_GET_SIZE(op->func_closure)); + PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, offset); + PyObject *item = PyTuple_GET_ITEM(op->func_closure, index); + PyObject *repr_res = PyObject_Repr(PyCell_GET(item)); + if (repr_res == NULL) { + goto error; + } + + WRITE(Char, ' '); + WRITE(Str, name); + WRITE(Char, '='); + if (_PyUnicodeWriter_WriteStr(&writer, repr_res) == -1) { + Py_DECREF(repr_res); + goto error; + } + Py_DECREF(repr_res); + + index++; + } + + WRITE(Char, '>'); + return _PyUnicodeWriter_Finish(&writer); + + error: + _PyUnicodeWriter_Dealloc(&writer); + return NULL; } static int @@ -1091,7 +1159,9 @@ static PyGetSetDef cm_getsetlist[] = { static PyObject* cm_repr(classmethod *cm) { - return PyUnicode_FromFormat("", cm->cm_callable); + return PyUnicode_FromFormat("%R(%R)", + Py_TYPE(cm), + cm->cm_callable); } PyDoc_STRVAR(classmethod_doc, @@ -1286,7 +1356,9 @@ static PyGetSetDef sm_getsetlist[] = { static PyObject* sm_repr(staticmethod *sm) { - return PyUnicode_FromFormat("", sm->sm_callable); + return PyUnicode_FromFormat("%R(%R)", + Py_TYPE(sm), + sm->sm_callable); } PyDoc_STRVAR(staticmethod_doc, diff --git a/Objects/methodobject.c b/Objects/methodobject.c index 521c905..6bbe361 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -282,13 +282,31 @@ static PyMemberDef meth_members[] = { static PyObject * meth_repr(PyCFunctionObject *m) { - if (m->m_self == NULL || PyModule_Check(m->m_self)) - return PyUnicode_FromFormat("", - m->m_ml->ml_name); - return PyUnicode_FromFormat("", - m->m_ml->ml_name, - Py_TYPE(m->m_self)->tp_name, - m->m_self); + PyObject *obj_repr; + + if (m->m_self == NULL) + return PyUnicode_FromString(m->m_ml->ml_name); + if (PyModule_Check(m->m_self)) { + obj_repr = ((PyModuleObject *)m->m_self)->md_name; + if (_PyUnicode_Equal(obj_repr, &_Py_ID(builtins)) || + _PyUnicode_EqualToASCIIString(obj_repr, "__main__")) + { + return PyUnicode_FromString(m->m_ml->ml_name); + } + } + else { + if (PyLong_CheckExact(m->m_self)) { + return PyUnicode_FromFormat("%R .%s", + m->m_self, m->m_ml->ml_name); + } + obj_repr = PyObject_Repr(m->m_self); + if (obj_repr == NULL) { + return NULL; + } + } + PyObject *rtn = PyUnicode_FromFormat("%U.%s", obj_repr, m->m_ml->ml_name); + Py_DECREF(obj_repr); + return rtn; } static PyObject * diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 7e890d0..0a581ff 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -728,12 +728,21 @@ module_dealloc(PyModuleObject *m) } static PyObject * -module_repr(PyModuleObject *m) +module_str(PyModuleObject *m) { PyInterpreterState *interp = _PyInterpreterState_GET(); return _PyImport_ImportlibModuleRepr(interp, (PyObject *)m); } +static PyObject * +module_repr(PyModuleObject *m) +{ + return + m->md_name ? + Py_NewRef(m->md_name) : + PyUnicode_FromString(""); +} + /* Check if the "_initializing" attribute of the module spec is set to true. Clear the exception and return 0 if spec is NULL. */ @@ -1016,7 +1025,7 @@ PyTypeObject PyModule_Type = { 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ - 0, /* tp_str */ + (reprfunc)module_str, /* tp_str */ (getattrofunc)_Py_module_getattro, /* tp_getattro */ PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 779d80b..a19c799 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1634,10 +1634,47 @@ type_repr(PyTypeObject *type) return NULL; } - if (mod != NULL && !_PyUnicode_Equal(mod, &_Py_ID(builtins))) - rtn = PyUnicode_FromFormat("", mod, name); - else - rtn = PyUnicode_FromFormat("", type->tp_name); + if (!Py_IS_TYPE(type, &PyType_Type) || + !PyUnicode_IsIdentifier(name)) + { + if (!Py_IS_TYPE(type, &PyType_Type)) { + PyObject *meta_repr = type_repr(Py_TYPE(type)); + if (meta_repr == NULL) { + Py_XDECREF(mod); + return NULL; + } + if (mod && !_PyUnicode_Equal(mod, &_Py_ID(builtins)) && + !_PyUnicode_EqualToASCIIString(mod, "__main__")) + { + rtn = PyUnicode_FromFormat("<%U '%U.%U'>", + meta_repr, mod, name); + } + else { + rtn = PyUnicode_FromFormat("<%U '%U'>", meta_repr, name); + } + Py_DECREF(meta_repr); + } + else { + if (mod && !_PyUnicode_Equal(mod, &_Py_ID(builtins)) && + !_PyUnicode_EqualToASCIIString(mod, "__main__")) + { + rtn = PyUnicode_FromFormat("", mod, name); + } + else { + rtn = PyUnicode_FromFormat("", name); + } + } + } + else { + if (mod && !_PyUnicode_Equal(mod, &_Py_ID(builtins)) && + !_PyUnicode_EqualToASCIIString(mod, "__main__")) + { + rtn = PyUnicode_FromFormat("%U.%U", mod, name); + } + else { + rtn = PyUnicode_FromFormat("%U", name); + } + } Py_XDECREF(mod); Py_DECREF(name); @@ -5558,28 +5595,14 @@ object_dealloc(PyObject *self) static PyObject * object_repr(PyObject *self) { - PyTypeObject *type; - PyObject *mod, *name, *rtn; + PyObject *tprepr, *rtn; - type = Py_TYPE(self); - mod = type_module(type, NULL); - if (mod == NULL) - PyErr_Clear(); - else if (!PyUnicode_Check(mod)) { - Py_SETREF(mod, NULL); - } - name = type_qualname(type, NULL); - if (name == NULL) { - Py_XDECREF(mod); + tprepr = type_repr(Py_TYPE(self)); + if (tprepr == NULL) { return NULL; } - if (mod != NULL && !_PyUnicode_Equal(mod, &_Py_ID(builtins))) - rtn = PyUnicode_FromFormat("<%U.%U object at %p>", mod, name, self); - else - rtn = PyUnicode_FromFormat("<%s object at %p>", - type->tp_name, self); - Py_XDECREF(mod); - Py_DECREF(name); + rtn = PyUnicode_FromFormat("<%U at %p>", tprepr, self); + Py_DECREF(tprepr); return rtn; } diff --git a/Python/compile.c b/Python/compile.c index beb300d..ec83b4c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -682,6 +682,7 @@ compiler_set_qualname(struct compiler *c) Py_ssize_t stack_size; struct compiler_unit *u = c->u; PyObject *name, *base; + int name_has_comm = 0; base = NULL; stack_size = PyList_GET_SIZE(c->c_stack); @@ -729,12 +730,13 @@ compiler_set_qualname(struct compiler *c) || parent->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION || parent->u_scope_type == COMPILER_SCOPE_LAMBDA) { - _Py_DECLARE_STR(dot_locals, "."); + _Py_DECLARE_STR(comm_at, "@"); base = PyUnicode_Concat(parent->u_metadata.u_qualname, - &_Py_STR(dot_locals)); + &_Py_STR(comm_at)); if (base == NULL) { return ERROR; } + name_has_comm = 1; } else { base = Py_NewRef(parent->u_metadata.u_qualname); @@ -743,11 +745,16 @@ compiler_set_qualname(struct compiler *c) } if (base != NULL) { - _Py_DECLARE_STR(dot, "."); - name = PyUnicode_Concat(base, &_Py_STR(dot)); - Py_DECREF(base); - if (name == NULL) { - return ERROR; + if (!name_has_comm) { + _Py_DECLARE_STR(dot, "."); + name = PyUnicode_Concat(base, &_Py_STR(dot)); + Py_DECREF(base); + if (name == NULL) { + return ERROR; + } + } + else { + name = base; } PyUnicode_Append(&name, u->u_metadata.u_name); if (name == NULL) {