From 25fd87aa3769ebf59d5becbf81dc45d7f1ac076a Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 9 Jul 2023 15:27:03 +0300 Subject: [PATCH] [3.11] gh-106303: Use _PyObject_LookupAttr() instead of PyObject_GetAttr() (GH-106304) It simplifies and speed up the code.. (cherry picked from commit 93d292c2b3f8e85ef562c37f59678c639b9b8fcb) Co-authored-by: Serhiy Storchaka --- Include/internal/pycore_global_strings.h | 1 + Include/internal/pycore_runtime_init.h | 1 + Objects/funcobject.c | 15 +++++---------- Python/ceval.c | 16 ++++++---------- 4 files changed, 13 insertions(+), 20 deletions(-) diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index ca970627cb2e17..55176c5317b6b3 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -142,6 +142,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(__lshift__) STRUCT_FOR_ID(__lt__) STRUCT_FOR_ID(__main__) + STRUCT_FOR_ID(__match_args__) STRUCT_FOR_ID(__matmul__) STRUCT_FOR_ID(__missing__) STRUCT_FOR_ID(__mod__) diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index 13eae1e4c88d8f..c59050eada2b60 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -765,6 +765,7 @@ extern "C" { INIT_ID(__lshift__), \ INIT_ID(__lt__), \ INIT_ID(__main__), \ + INIT_ID(__match_args__), \ INIT_ID(__matmul__), \ INIT_ID(__missing__), \ INIT_ID(__mod__), \ diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 3a0553261bf132..c8bfa1f8a6a436 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -801,17 +801,12 @@ PyTypeObject PyFunction_Type = { static int functools_copy_attr(PyObject *wrapper, PyObject *wrapped, PyObject *name) { - PyObject *value = PyObject_GetAttr(wrapped, name); - if (value == NULL) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - return 0; - } - return -1; + PyObject *value; + int res = _PyObject_LookupAttr(wrapped, name, &value); + if (value != NULL) { + res = PyObject_SetAttr(wrapper, name, value); + Py_DECREF(value); } - - int res = PyObject_SetAttr(wrapper, name, value); - Py_DECREF(value); return res; } diff --git a/Python/ceval.c b/Python/ceval.c index 47df353197094b..8ce733f1e1c254 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1001,10 +1001,8 @@ match_class_attr(PyThreadState *tstate, PyObject *subject, PyObject *type, } return NULL; } - PyObject *attr = PyObject_GetAttr(subject, name); - if (attr == NULL && _PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) { - _PyErr_Clear(tstate); - } + PyObject *attr; + (void)_PyObject_LookupAttr(subject, name, &attr); return attr; } @@ -1039,7 +1037,9 @@ match_class(PyThreadState *tstate, PyObject *subject, PyObject *type, // First, the positional subpatterns: if (nargs) { int match_self = 0; - match_args = PyObject_GetAttrString(type, "__match_args__"); + if (_PyObject_LookupAttr(type, &_Py_ID(__match_args__), &match_args) < 0) { + goto fail; + } if (match_args) { if (!PyTuple_CheckExact(match_args)) { const char *e = "%s.__match_args__ must be a tuple (got %s)"; @@ -1049,8 +1049,7 @@ match_class(PyThreadState *tstate, PyObject *subject, PyObject *type, goto fail; } } - else if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) { - _PyErr_Clear(tstate); + else { // _Py_TPFLAGS_MATCH_SELF is only acknowledged if the type does not // define __match_args__. This is natural behavior for subclasses: // it's as if __match_args__ is some "magic" value that is lost as @@ -1059,9 +1058,6 @@ match_class(PyThreadState *tstate, PyObject *subject, PyObject *type, match_self = PyType_HasFeature((PyTypeObject*)type, _Py_TPFLAGS_MATCH_SELF); } - else { - goto fail; - } assert(PyTuple_CheckExact(match_args)); Py_ssize_t allowed = match_self ? 1 : PyTuple_GET_SIZE(match_args); if (allowed < nargs) {