|
I like the idea! (Sorry I am a bit slow with |
| @@ -536,6 +536,8 @@ PyAPI_FUNC(int) PyObject_SetAttr(PyObject *, PyObject *, PyObject *); | |||
| PyAPI_FUNC(int) PyObject_HasAttr(PyObject *, PyObject *); | |||
| #ifndef Py_LIMITED_API | |||
| PyAPI_FUNC(int) _PyObject_IsAbstract(PyObject *); | |||
| /* Same to PyObject_GetAttr(), but don't raise AttributeError. */ | |||
| @@ -567,7 +569,7 @@ PyAPI_FUNC(int) PyObject_CallFinalizerFromDealloc(PyObject *); | |||
| /* Same as PyObject_Generic{Get,Set}Attr, but passing the attributes | |||
| dict as the last parameter. */ | |||
| PyAPI_FUNC(PyObject *) | |||
| _PyObject_GenericGetAttrWithDict(PyObject *, PyObject *, PyObject *); | |||
| _PyObject_GenericGetAttrWithDict(PyObject *, PyObject *, PyObject *, int); | |||
Would this change be backward incompatible? Or is this function is not covered by the backwards compatibility guarantees?
AFAIK, APIs starting with underscore are private.
Third party libs shouldn't expect backward compatibility.
I don't know should I add Include/internal/object.h or not.
OK, I see. But I don't know about Include/internal/object.h either. Probably @serhiy-storchaka can advise on this.
Changing the signature of _PyObject_GenericGetAttrWithDict() LGTM. As for Include/internal/object.h, left this to other issue.
| ret = (*tp->tp_getattro)(v, name); | ||
| } | ||
| } | ||
| else if (tp->tp_getattr != NULL) { |
It looks like there is some code duplication with PyObject_GetAttr, does it make sense to factor it out?
Hm, how do you think this?
https://gist.github.com/methane/4adf85086798c2c2a8ee59181474fb29
|
Also I think we need a NEWS item for this. |
| } | ||
| if (tp->tp_getattro != NULL) { | ||
| if (tp->tp_getattro == PyObject_GenericGetAttr) { | ||
| ret = _PyObject_GenericGetAttrWithDict(v, name, NULL, 1); |
Can _PyObject_GenericGetAttrWithDict() raise an AttributeError? If can't, it is better to just return the result here. PyErr_ExceptionMatches(PyExc_AttributeError) has a non-zero cost, in some cases it can be significant. For example see bpo-31336.
Yes, it may call descriptor. Any exception can be raised.
suppress=1 only suppress AttributeError raised from _PyObject_GenericGetAttrWithDict
directly.
I changed _PyObject_GenericGetAttrWithDict() to suppress AttributeError
from descriptors too.
Since _PyObject_GenericGetAttrWithDict is performance critical function,
I'll run benchmark suite before merge this.
| @@ -0,0 +1,3 @@ | |||
| ``hasattr(obj, name)`` and ``getattr(obj, name, default)`` is about 4 times | |||
I am not a native speaker, but I would use "are" here instead of "is".
methane commentedJan 13, 2018
•
edited by bedevere-bot
Skip raising AttributeError when tp_getattro == PyObject_GenericGetAttr
https://bugs.python.org/issue32544