resync with trunk

parent 6b66b978
Changelog
=========
2.13.6 (unreleased)
2.13.8 (unreleased)
-------------------
2.13.7 (2011-03-02)
-------------------
- Fixed bug: When an object did not implement ``__unicode__``, calling
``unicode(wrapped)`` was calling ``__str__`` with an unwrapped ``self``.
2.13.6 (2011-02-19)
-------------------
- Add ``aq_explicit`` to ``IAcquisitionWrapper``.
- Fixed bug: ``unicode(wrapped)`` was not calling a ``__unicode__``
method on wrapped objects.
2.13.5 (2010-09-29)
-------------------
......
......@@ -17,7 +17,7 @@ import os
from setuptools import setup, find_packages, Extension
setup(name='Acquisition',
version = '2.13.6dev',
version = '2.13.8dev',
url='http://pypi.python.org/pypi/Acquisition',
license='ZPL 2.1',
description="Acquisition is a mechanism that allows objects to obtain "
......
......@@ -118,7 +118,7 @@ selected objects that smell like private objects.
Sometimes, you want to dynamically make an implicitly acquiring object
acquire explicitly. You can do this by getting the object's
aq_explicit attribute. This attribute provides the object with an
explicit wrapper that places the original implicit wrapper.
explicit wrapper that replaces the original implicit wrapper.
Filtered Acquisition
====================
......
......@@ -51,8 +51,8 @@ static PyObject *py__add__, *py__sub__, *py__mul__, *py__div__,
*py__long__, *py__float__, *py__oct__, *py__hex__,
*py__getitem__, *py__setitem__, *py__delitem__,
*py__getslice__, *py__setslice__, *py__delslice__, *py__contains__,
*py__len__, *py__of__, *py__call__, *py__repr__, *py__str__, *py__cmp__,
*py__parent__, *py__iter__;
*py__len__, *py__of__, *py__call__, *py__repr__, *py__str__, *py__unicode__,
*py__cmp__, *py__parent__, *py__iter__;
static PyObject *Acquired=0;
......@@ -95,6 +95,7 @@ init_py_names(void)
INIT_PY_NAME(__call__);
INIT_PY_NAME(__repr__);
INIT_PY_NAME(__str__);
INIT_PY_NAME(__unicode__);
INIT_PY_NAME(__cmp__);
INIT_PY_NAME(__parent__);
INIT_PY_NAME(__iter__);
......@@ -897,6 +898,23 @@ Wrapper_str(Wrapper *self)
}
}
static PyObject *
Wrapper_unicode(Wrapper *self)
{
PyObject *r;
if ((r=PyObject_GetAttr(OBJECT(self),py__unicode__)))
{
ASSIGN(r,PyObject_CallFunction(r,NULL,NULL));
return r;
}
else
{
PyErr_Clear();
return Wrapper_str(self);
}
}
static long
Wrapper_hash(Wrapper *self)
{
......@@ -1371,6 +1389,8 @@ static struct PyMethodDef Wrapper_methods[] = {
"Wrappers are not picklable"},
{"__reduce_ex__", (PyCFunction)Wrappers_are_not_picklable, METH_VARARGS,
"Wrappers are not picklable"},
{"__unicode__", (PyCFunction)Wrapper_unicode, METH_NOARGS,
"Unicode"},
{NULL, NULL} /* sentinel */
};
......
......@@ -62,3 +62,7 @@ class IAcquisitionWrapper(Interface):
aq_chain = Attribute(
"""Get a list of objects in the acquisition environment."""
)
aq_explicit = Attribute(
"""Get the object with an explicit acquisition wrapper."""
)
......@@ -2397,53 +2397,132 @@ def test___parent__aq_parent_circles():
Traceback (most recent call last):
...
AttributeError: non_existant_attr
"""
def test___parent__parent__circles():
"""
Acquisition won't follow circular __parent__ references:
>>> class Impl(Acquisition.Implicit):
... hello = 'world'
>>> class Impl2(Acquisition.Implicit):
... hello = 'world2'
... only = 'here'
>>> x = Impl()
>>> y = Impl2()
>>> x.__parent__ = y
>>> y.__parent__ = x
>>> x.__parent__.__parent__ is x
True
>>> Acquisition.aq_acquire(x, 'hello')
'world'
>>> Acquisition.aq_acquire(x, 'only')
'here'
import unittest
from doctest import DocTestSuite, DocFileSuite
>>> Acquisition.aq_acquire(x, 'non_existant_attr')
Traceback (most recent call last):
...
AttributeError: non_existant_attr
>>> Acquisition.aq_acquire(y, 'non_existant_attr')
Traceback (most recent call last):
...
AttributeError: non_existant_attr
"""
class TestParent(unittest.TestCase):
def test_parent_parent_circles(self):
class Impl(Acquisition.Implicit):
hello = 'world'
class Impl2(Acquisition.Implicit):
hello = 'world2'
only = 'here'
x = Impl()
y = Impl2()
x.__parent__ = y
y.__parent__ = x
self.assertTrue(x.__parent__.__parent__ is x)
self.assertEqual(Acquisition.aq_acquire(x, 'hello'), 'world')
self.assertEqual(Acquisition.aq_acquire(x, 'only'), 'here')
self.assertRaises(AttributeError, Acquisition.aq_acquire,
x, 'non_existant_attr')
self.assertRaises(AttributeError, Acquisition.aq_acquire,
y, 'non_existant_attr')
def test_parent_parent_parent_circles(self):
class Impl(Acquisition.Implicit):
hello = 'world'
class Impl2(Acquisition.Implicit):
hello = 'world'
class Impl3(Acquisition.Implicit):
hello = 'world2'
only = 'here'
a = Impl()
b = Impl2()
c = Impl3()
a.__parent__ = b
b.__parent__ = c
c.__parent__ = a
# This is not quite what you'd expect, an AQ circle with an
# intermediate object gives strange results
self.assertTrue(a.__parent__.__parent__ is a)
self.assertTrue(a.__parent__.__parent__.__parent__.aq_base is b)
self.assertTrue(b.__parent__.__parent__ is b)
self.assertTrue(c.__parent__.__parent__ is c)
self.assertEqual(Acquisition.aq_acquire(a, 'hello'), 'world')
self.assertEqual(Acquisition.aq_acquire(b, 'hello'), 'world')
self.assertEqual(Acquisition.aq_acquire(c, 'hello'), 'world2')
self.assertRaises(AttributeError, Acquisition.aq_acquire,
a, 'only')
self.assertEqual(Acquisition.aq_acquire(b, 'only'), 'here')
self.assertEqual(Acquisition.aq_acquire(c, 'only'), 'here')
self.assertRaises(AttributeError, Acquisition.aq_acquire,
a, 'non_existant_attr')
self.assertRaises(AttributeError, Acquisition.aq_acquire,
b, 'non_existant_attr')
self.assertRaises(AttributeError, Acquisition.aq_acquire,
c, 'non_existant_attr')
class TestUnicode(unittest.TestCase):
def test_implicit_aq_unicode_should_be_called(self):
class A(Acquisition.Implicit):
def __unicode__(self):
return u'unicode was called'
wrapped = A().__of__(A())
self.assertEqual(u'unicode was called', unicode(wrapped))
self.assertEqual(str(wrapped), repr(wrapped))
def test_explicit_aq_unicode_should_be_called(self):
class A(Acquisition.Explicit):
def __unicode__(self):
return u'unicode was called'
wrapped = A().__of__(A())
self.assertEqual(u'unicode was called', unicode(wrapped))
self.assertEqual(str(wrapped), repr(wrapped))
def test_implicit_should_fall_back_to_str(self):
class A(Acquisition.Implicit):
def __str__(self):
return 'str was called'
wrapped = A().__of__(A())
self.assertEqual(u'str was called', unicode(wrapped))
self.assertEqual('str was called', str(wrapped))
def test_explicit_should_fall_back_to_str(self):
class A(Acquisition.Explicit):
def __str__(self):
return 'str was called'
wrapped = A().__of__(A())
self.assertEqual(u'str was called', unicode(wrapped))
self.assertEqual('str was called', str(wrapped))
def test_str_fallback_should_be_called_with_wrapped_self(self):
class A(Acquisition.Implicit):
def __str__(self):
return str(self.aq_parent == outer)
outer = A()
inner = A().__of__(outer)
self.assertEqual(u'True', unicode(inner))
def test_unicode_should_be_called_with_wrapped_self(self):
class A(Acquisition.Implicit):
def __unicode__(self):
return str(self.aq_parent == outer)
outer = A()
inner = A().__of__(outer)
self.assertEqual(u'True', unicode(inner))
import unittest
from doctest import DocTestSuite, DocFileSuite
def test_suite():
return unittest.TestSuite((
DocTestSuite(),
DocTestSuite('Acquisition.test_dynamic_acquisition'),
DocFileSuite('README.txt', package='Acquisition'),
unittest.makeSuite(TestParent),
unittest.makeSuite(TestUnicode),
))
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
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