task: allow overriding methods of PythonTask

This commit is contained in:
rdb 2019-03-04 22:58:50 +01:00
parent ba256a8b07
commit 71b8bceb79
2 changed files with 25 additions and 28 deletions

View File

@ -283,15 +283,25 @@ exception() const {
*/
int PythonTask::
__setattr__(PyObject *self, PyObject *attr, PyObject *v) {
if (PyObject_GenericSetAttr(self, attr, v) == 0) {
return 0;
}
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
#if PY_MAJOR_VERSION >= 3
if (!PyUnicode_Check(attr)) {
#else
if (!PyString_Check(attr)) {
#endif
PyErr_Format(PyExc_TypeError,
"attribute name must be string, not '%.200s'",
attr->ob_type->tp_name);
return -1;
}
PyErr_Clear();
PyObject *descr = _PyType_Lookup(Py_TYPE(self), attr);
if (descr != nullptr) {
Py_INCREF(descr);
descrsetfunc f = descr->ob_type->tp_descr_set;
if (f != nullptr) {
return f(descr, self, v);
}
}
if (task_cat.is_debug()) {
PyObject *str = PyObject_Repr(v);
@ -352,31 +362,18 @@ __delattr__(PyObject *self, PyObject *attr) {
* object.
*/
PyObject *PythonTask::
__getattr__(PyObject *attr) const {
// Note that with the new Interrogate behavior, this method behaves more
// like the Python __getattr__ rather than being directly assigned to the
// tp_getattro slot (a la __getattribute__). So, we won't get here when the
// attribute has already been found via other methods.
__getattribute__(PyObject *self, PyObject *attr) const {
// We consult the instance dict first, since the user may have overridden a
// method or something.
PyObject *item = PyDict_GetItem(__dict__, attr);
if (item == nullptr) {
// PyDict_GetItem does not raise an exception.
#if PY_MAJOR_VERSION < 3
PyErr_Format(PyExc_AttributeError,
"'PythonTask' object has no attribute '%.400s'",
PyString_AS_STRING(attr));
#else
PyErr_Format(PyExc_AttributeError,
"'PythonTask' object has no attribute '%U'",
attr);
#endif
return nullptr;
if (item != nullptr) {
// PyDict_GetItem returns a borrowed reference.
Py_INCREF(item);
return item;
}
// PyDict_GetItem returns a borrowed reference.
Py_INCREF(item);
return item;
return PyObject_GenericGetAttr(self, attr);
}
/**

View File

@ -55,7 +55,7 @@ public:
PUBLISHED:
int __setattr__(PyObject *self, PyObject *attr, PyObject *v);
int __delattr__(PyObject *self, PyObject *attr);
PyObject *__getattr__(PyObject *attr) const;
PyObject *__getattribute__(PyObject *self, PyObject *attr) const;
int __traverse__(visitproc visit, void *arg);
int __clear__();