diff options
author | Panu Matilainen <Panu Matilainen pmatilai@redhat.com> | 2011-07-06 11:05:42 +0300 |
---|---|---|
committer | Panu Matilainen <Panu Matilainen pmatilai@redhat.com> | 2011-07-15 12:25:19 +0300 |
commit | d740b2be6e0e725bfdfba41cb0d3d298c404e40a (patch) | |
tree | ec42d7c0d44389d88895d534839f024b71e7bb44 | |
parent | 38d300c16443b4f173067ea75cbe303fdd21618f (diff) | |
download | rpm-d740b2be6e0e725bfdfba41cb0d3d298c404e40a.tar.gz |
Fix the broken python header __getattr__() behavior, take 13 (or so)
- 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.
(cherry picked from commit 9d30318c0ad42e6a6c895d5a62bb209344d4f2da)
-rw-r--r-- | python/header-py.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/python/header-py.c b/python/header-py.c index b6e21ccd0..a790099ae 100644 --- a/python/header-py.c +++ b/python/header-py.c @@ -608,10 +608,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; |