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

View File

@ -55,7 +55,7 @@ public:
PUBLISHED: PUBLISHED:
int __setattr__(PyObject *self, PyObject *attr, PyObject *v); int __setattr__(PyObject *self, PyObject *attr, PyObject *v);
int __delattr__(PyObject *self, PyObject *attr); 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 __traverse__(visitproc visit, void *arg);
int __clear__(); int __clear__();