@@ -283,15 +283,25 @@ exception() const {
283283 */
284284int PythonTask::
285285__setattr__ (PyObject *self, PyObject *attr, PyObject *v) {
286- if (PyObject_GenericSetAttr (self, attr, v) == 0 ) {
287- return 0 ;
288- }
289-
290- if (!PyErr_ExceptionMatches (PyExc_AttributeError)) {
286+ #if PY_MAJOR_VERSION >= 3
287+ if (!PyUnicode_Check (attr)) {
288+ #else
289+ if (!PyString_Check (attr)) {
290+ #endif
291+ PyErr_Format (PyExc_TypeError,
292+ " attribute name must be string, not '%.200s'" ,
293+ attr->ob_type ->tp_name );
291294 return -1 ;
292295 }
293296
294- PyErr_Clear ();
297+ PyObject *descr = _PyType_Lookup (Py_TYPE (self), attr);
298+ if (descr != nullptr ) {
299+ Py_INCREF (descr);
300+ descrsetfunc f = descr->ob_type ->tp_descr_set ;
301+ if (f != nullptr ) {
302+ return f (descr, self, v);
303+ }
304+ }
295305
296306 if (task_cat.is_debug ()) {
297307 PyObject *str = PyObject_Repr (v);
@@ -352,31 +362,18 @@ __delattr__(PyObject *self, PyObject *attr) {
352362 * object.
353363 */
354364PyObject *PythonTask::
355- __getattr__ (PyObject *attr) const {
356- // Note that with the new Interrogate behavior, this method behaves more
357- // like the Python __getattr__ rather than being directly assigned to the
358- // tp_getattro slot (a la __getattribute__). So, we won't get here when the
359- // attribute has already been found via other methods.
360-
365+ __getattribute__ (PyObject *self, PyObject *attr) const {
366+ // We consult the instance dict first, since the user may have overridden a
367+ // method or something.
361368 PyObject *item = PyDict_GetItem (__dict__, attr);
362369
363- if (item == nullptr ) {
364- // PyDict_GetItem does not raise an exception.
365- #if PY_MAJOR_VERSION < 3
366- PyErr_Format (PyExc_AttributeError,
367- " 'PythonTask' object has no attribute '%.400s'" ,
368- PyString_AS_STRING (attr));
369- #else
370- PyErr_Format (PyExc_AttributeError,
371- " 'PythonTask' object has no attribute '%U'" ,
372- attr);
373- #endif
374- return nullptr ;
370+ if (item != nullptr ) {
371+ // PyDict_GetItem returns a borrowed reference.
372+ Py_INCREF (item);
373+ return item;
375374 }
376375
377- // PyDict_GetItem returns a borrowed reference.
378- Py_INCREF (item);
379- return item;
376+ return PyObject_GenericGetAttr (self, attr);
380377}
381378
382379/* *
0 commit comments