Fix the broken python header __getattr__() behavior, take 13 (or so)
authorPanu Matilainen <Panu Matilainen pmatilai@redhat.com>
Wed, 6 Jul 2011 08:05:42 +0000 (11:05 +0300)
committerPanu Matilainen <Panu Matilainen pmatilai@redhat.com>
Wed, 6 Jul 2011 08:05:42 +0000 (11:05 +0300)
- Tags as header attributes seemed like a nice idea at the time... but
  has been a PITA due to side-effects it causes, such as breaking
  getattr() use for "capability testing", eg:
      >>> h2 = copy.deepcopy(h)
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "/usr/lib64/python2.7/copy.py", line 172, in deepcopy
          copier = getattr(x, "__deepcopy__", None)
      ValueError: unknown header tag
- Since we can't really go removing the brainded feature (somebody might
  actually be using it) try harder to fix it: if its not an actual
  attribute, save the exception we got from PyObject_GenericGetAttr()
  and if its not a valid tag either, restore the original exception.
  This allows cases like the above __deepcopy__ to work properly.

python/header-py.c

index e594ebe..3482dd2 100644 (file)
@@ -623,10 +623,18 @@ static PyObject * hdr_getattro(hdrObject * s, PyObject * n)
 {
     PyObject *res = PyObject_GenericGetAttr((PyObject *) s, n);
     if (res == NULL) {
+       PyObject *type, *value, *traceback;
        rpmTagVal tag;
+
+       /* Save and restore original exception if it's not a valid tag either */
+       PyErr_Fetch(&type, &value, &traceback);
        if (tagNumFromPyObject(n, &tag)) {
-           PyErr_Clear();
+           Py_XDECREF(type);
+           Py_XDECREF(value);
+           Py_XDECREF(traceback);
            res = hdrGetTag(s->h, tag);
+       } else {
+           PyErr_Restore(type, value, traceback);
        }
     }
     return res;