Commit 6fb96530 authored by Tres Seaver's avatar Tres Seaver

Make module-level 'aq_acquire' respect 'default'.

Fixes LP #1387363.

Cherry-pick cdfad147 and
ea7ef69d from master.
parent e5253424
......@@ -4,6 +4,9 @@ Changelog
2.13.9 (unreleased)
-------------------
- Make module-level ``aq_acquire`` API respect the ``default`` parameter.
LP #1387363.
- Don't raise an attribute error for ``__iter__`` if the fallback to
``__getitem__`` succeeds. LP #1155760.
......
......@@ -1489,12 +1489,14 @@ capi_aq_acquire(PyObject *self, PyObject *name, PyObject *filter,
if (filter==Py_None) filter=0;
/* We got a wrapped object, so business as usual */
if (isWrapper(self))
return Wrapper_findattr(
if (isWrapper(self)) {
result = Wrapper_findattr(
WRAPPER(self), name, filter, extra, OBJECT(self),1,
explicit ||
WRAPPER(self)->ob_type==(PyTypeObject*)&Wrappertype,
explicit, containment);
goto check_default;
}
/* Not wrapped; check if we have a __parent__ pointer. If that's
the case, create a wrapper and pretend it's business as usual. */
else if ((result = PyObject_GetAttr(self, py__parent__)))
......@@ -1505,7 +1507,7 @@ capi_aq_acquire(PyObject *self, PyObject *name, PyObject *filter,
OBJECT(self), 1, 1, explicit, containment);
/* Get rid of temporary wrapper */
Py_DECREF(self);
return result;
goto check_default;
}
/* No wrapper and no __parent__, so just getattr. */
else
......@@ -1520,7 +1522,10 @@ capi_aq_acquire(PyObject *self, PyObject *name, PyObject *filter,
}
Py_XDECREF(result); Py_XDECREF(v); Py_XDECREF(tb);
if (! filter) return PyObject_GetAttr(self, name);
if (! filter) {
result = PyObject_GetAttr(self, name);
goto check_default;
}
/* Crap, we've got to construct a wrapper so we can use
Wrapper_findattr */
......@@ -1532,8 +1537,22 @@ capi_aq_acquire(PyObject *self, PyObject *name, PyObject *filter,
/* Get rid of temporary wrapper */
Py_DECREF(self);
return result;
goto check_default;
}
check_default:
if (result == NULL && defalt != NULL) {
/* as "Python/bltinmodule.c:builtin_getattr" turn
only 'AttributeError' into a default value, such
that e.g. "ConflictError" and errors raised by the filter
are not mapped to the default value.
*/
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
Py_INCREF(defalt);
result = defalt;
}
}
return result;
}
static PyObject *
......
......@@ -2515,6 +2515,19 @@ class TestAcquire(unittest.TestCase):
def test_explicit_wrapper_false(self):
self.assertEqual(self.a.b.c.aq_acquire('z', explicit=False), 3)
def test_wrapper_falls_back_to_default(self):
self.assertEqual(self.acquire(self.a.b.c, 'nonesuch', default=4), 4)
def test_no_wrapper_but___parent___falls_back_to_default(self):
class NotWrapped(object):
pass
child = NotWrapped()
parent = child.__parent__ = NotWrapped()
self.assertEqual(self.acquire(child, 'nonesuch', default=4), 4)
def test_unwrapped_falls_back_to_default(self):
self.assertEqual(self.acquire(object(), 'nonesuch', default=4), 4)
class TestUnicode(unittest.TestCase):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment