resync with trunk

parent 6b66b978
Changelog 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) 2.13.5 (2010-09-29)
------------------- -------------------
......
...@@ -17,7 +17,7 @@ import os ...@@ -17,7 +17,7 @@ import os
from setuptools import setup, find_packages, Extension from setuptools import setup, find_packages, Extension
setup(name='Acquisition', setup(name='Acquisition',
version = '2.13.6dev', version = '2.13.8dev',
url='http://pypi.python.org/pypi/Acquisition', url='http://pypi.python.org/pypi/Acquisition',
license='ZPL 2.1', license='ZPL 2.1',
description="Acquisition is a mechanism that allows objects to obtain " description="Acquisition is a mechanism that allows objects to obtain "
......
...@@ -118,7 +118,7 @@ selected objects that smell like private objects. ...@@ -118,7 +118,7 @@ selected objects that smell like private objects.
Sometimes, you want to dynamically make an implicitly acquiring object Sometimes, you want to dynamically make an implicitly acquiring object
acquire explicitly. You can do this by getting the object's acquire explicitly. You can do this by getting the object's
aq_explicit attribute. This attribute provides the object with an 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 Filtered Acquisition
==================== ====================
......
...@@ -51,8 +51,8 @@ static PyObject *py__add__, *py__sub__, *py__mul__, *py__div__, ...@@ -51,8 +51,8 @@ static PyObject *py__add__, *py__sub__, *py__mul__, *py__div__,
*py__long__, *py__float__, *py__oct__, *py__hex__, *py__long__, *py__float__, *py__oct__, *py__hex__,
*py__getitem__, *py__setitem__, *py__delitem__, *py__getitem__, *py__setitem__, *py__delitem__,
*py__getslice__, *py__setslice__, *py__delslice__, *py__contains__, *py__getslice__, *py__setslice__, *py__delslice__, *py__contains__,
*py__len__, *py__of__, *py__call__, *py__repr__, *py__str__, *py__cmp__, *py__len__, *py__of__, *py__call__, *py__repr__, *py__str__, *py__unicode__,
*py__parent__, *py__iter__; *py__cmp__, *py__parent__, *py__iter__;
static PyObject *Acquired=0; static PyObject *Acquired=0;
...@@ -95,6 +95,7 @@ init_py_names(void) ...@@ -95,6 +95,7 @@ init_py_names(void)
INIT_PY_NAME(__call__); INIT_PY_NAME(__call__);
INIT_PY_NAME(__repr__); INIT_PY_NAME(__repr__);
INIT_PY_NAME(__str__); INIT_PY_NAME(__str__);
INIT_PY_NAME(__unicode__);
INIT_PY_NAME(__cmp__); INIT_PY_NAME(__cmp__);
INIT_PY_NAME(__parent__); INIT_PY_NAME(__parent__);
INIT_PY_NAME(__iter__); INIT_PY_NAME(__iter__);
...@@ -897,6 +898,23 @@ Wrapper_str(Wrapper *self) ...@@ -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 static long
Wrapper_hash(Wrapper *self) Wrapper_hash(Wrapper *self)
{ {
...@@ -1371,6 +1389,8 @@ static struct PyMethodDef Wrapper_methods[] = { ...@@ -1371,6 +1389,8 @@ static struct PyMethodDef Wrapper_methods[] = {
"Wrappers are not picklable"}, "Wrappers are not picklable"},
{"__reduce_ex__", (PyCFunction)Wrappers_are_not_picklable, METH_VARARGS, {"__reduce_ex__", (PyCFunction)Wrappers_are_not_picklable, METH_VARARGS,
"Wrappers are not picklable"}, "Wrappers are not picklable"},
{"__unicode__", (PyCFunction)Wrapper_unicode, METH_NOARGS,
"Unicode"},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
......
...@@ -62,3 +62,7 @@ class IAcquisitionWrapper(Interface): ...@@ -62,3 +62,7 @@ class IAcquisitionWrapper(Interface):
aq_chain = Attribute( aq_chain = Attribute(
"""Get a list of objects in the acquisition environment.""" """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(): ...@@ -2397,53 +2397,132 @@ def test___parent__aq_parent_circles():
Traceback (most recent call last): Traceback (most recent call last):
... ...
AttributeError: non_existant_attr 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() import unittest
>>> y = Impl2() from doctest import DocTestSuite, DocFileSuite
>>> x.__parent__ = y
>>> y.__parent__ = x
>>> x.__parent__.__parent__ is x
True
>>> Acquisition.aq_acquire(x, 'hello')
'world'
>>> Acquisition.aq_acquire(x, 'only')
'here'
>>> Acquisition.aq_acquire(x, 'non_existant_attr')
Traceback (most recent call last):
...
AttributeError: non_existant_attr
>>> Acquisition.aq_acquire(y, 'non_existant_attr') class TestParent(unittest.TestCase):
Traceback (most recent call last):
... def test_parent_parent_circles(self):
AttributeError: non_existant_attr 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(): def test_suite():
return unittest.TestSuite(( return unittest.TestSuite((
DocTestSuite(), DocTestSuite(),
DocTestSuite('Acquisition.test_dynamic_acquisition'), DocTestSuite('Acquisition.test_dynamic_acquisition'),
DocFileSuite('README.txt', package='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