summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Madden <jamadden@gmail.com>2015-05-07 15:22:14 -0500
committerJason Madden <jamadden@gmail.com>2015-05-07 15:22:14 -0500
commit934dc2fac1962e2c2443a1f62d18b0643c49201b (patch)
tree9efebfb921e844d1993db3f7652e5dfa5d2e9382 /src
parent65ebb9d1fba58423d11bb07d16684c693086db6b (diff)
downloadzope-proxy-934dc2fac1962e2c2443a1f62d18b0643c49201b.tar.gz
Make the C implementation proxy __unicode__, and make it use the standard methods to proxy int and float. Fixes #3 and Fixes #4.
Diffstat (limited to 'src')
-rw-r--r--src/zope/proxy/_compat.py6
-rw-r--r--src/zope/proxy/_zope_proxy_proxy.c52
-rw-r--r--src/zope/proxy/tests/test_proxy.py66
3 files changed, 95 insertions, 29 deletions
diff --git a/src/zope/proxy/_compat.py b/src/zope/proxy/_compat.py
index be8d867..4b9ed15 100644
--- a/src/zope/proxy/_compat.py
+++ b/src/zope/proxy/_compat.py
@@ -2,3 +2,9 @@ import sys
PY3 = sys.version_info[0] >= 3
+if PY3: # pragma NO COVER
+ def _u(s):
+ return s
+else:
+ def _u(s):
+ return unicode(s, 'unicode_escape')
diff --git a/src/zope/proxy/_zope_proxy_proxy.c b/src/zope/proxy/_zope_proxy_proxy.c
index 9166976..0df67b6 100644
--- a/src/zope/proxy/_zope_proxy_proxy.c
+++ b/src/zope/proxy/_zope_proxy_proxy.c
@@ -420,26 +420,18 @@ wrap_call(PyObject *self, PyObject *args, PyObject *kw)
static PyObject *
call_int(PyObject *self)
{
- PyNumberMethods *nb = self->ob_type->tp_as_number;
- if (nb == NULL || nb->nb_int == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "object can't be converted to int");
- return NULL;
- }
- return nb->nb_int(self);
+#if PY_MAJOR_VERSION < 3
+ return PyNumber_Int(self);
+#else
+ return PyNumber_Long(self);
+#endif
}
#if PY_MAJOR_VERSION < 3 // Python 3 has no long, oct or hex methods.
static PyObject *
call_long(PyObject *self)
{
- PyNumberMethods *nb = self->ob_type->tp_as_number;
- if (nb == NULL || nb->nb_long == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "object can't be converted to long");
- return NULL;
- }
- return nb->nb_long(self);
+ return PyNumber_Long(self);
}
static PyObject *
@@ -471,25 +463,13 @@ call_hex(PyObject *self)
static PyObject *
call_index(PyObject *self)
{
- PyNumberMethods *nb = self->ob_type->tp_as_number;
- if (nb == NULL || nb->nb_index == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "object can't be converted to index");
- return NULL;
- }
- return nb->nb_index(self);
+ return PyNumber_Index(self);
}
static PyObject *
call_float(PyObject *self)
{
- PyNumberMethods *nb = self->ob_type->tp_as_number;
- if (nb == NULL || nb->nb_float== NULL) {
- PyErr_SetString(PyExc_TypeError,
- "object can't be converted to float");
- return NULL;
- }
- return nb->nb_float(self);
+ return PyNumber_Float(self);
}
static PyObject *
@@ -499,6 +479,15 @@ call_ipow(PyObject *self, PyObject *other)
return PyNumber_InPlacePower(self, other, Py_None);
}
+#if PY_MAJOR_VERSION < 3
+static PyObject *
+call_unicode(PyObject *self)
+{
+ return PyObject_Unicode(self);
+}
+#endif
+
+
typedef PyObject *(*function1)(PyObject *);
static PyObject *
@@ -691,6 +680,10 @@ INPLACE(floordiv, PyNumber_InPlaceFloorDivide)
INPLACE(truediv, PyNumber_InPlaceTrueDivide)
UNOP(index, call_index)
+#if PY_MAJOR_VERSION < 3 // Python 3 has no __unicode__ method
+UNOP(unicode, call_unicode)
+#endif
+
static int
wrap_nonzero(PyObject *self)
{
@@ -874,6 +867,9 @@ wrap_as_mapping = {
static PyMethodDef
wrap_methods[] = {
{"__reduce__", (PyCFunction)wrap_reduce, METH_NOARGS, reduce__doc__},
+#if PY_MAJOR_VERSION < 3
+ {"__unicode__", (PyCFunction)wrap_unicode, METH_NOARGS, "" },
+#endif
{NULL, NULL},
};
diff --git a/src/zope/proxy/tests/test_proxy.py b/src/zope/proxy/tests/test_proxy.py
index bfd6c5b..0f2bc41 100644
--- a/src/zope/proxy/tests/test_proxy.py
+++ b/src/zope/proxy/tests/test_proxy.py
@@ -418,7 +418,7 @@ class PyProxyBaseTestCase(unittest.TestCase):
"complex(x)",
]
if not PY3: # long is gone in Python 3
- ops.append("long(x)")
+ ops.append("long(x)")
return ops
def test_unops(self):
@@ -581,6 +581,70 @@ class PyProxyBaseTestCase(unittest.TestCase):
w = self._makeOne(o)
self.assertTrue(w.__class__ is o.__class__)
+ def test_string_to_int(self):
+ # Strings don't have the tp_number.tp_int pointer
+ proxy = self._makeOne("14")
+ self.assertEqual(14, int(proxy))
+
+ def test_custom_int_to_int(self):
+ class CustomClass(object):
+ def __int__(self):
+ return 42
+ proxy = self._makeOne(CustomClass())
+ self.assertEqual(42, int(proxy))
+
+ def test_string_to_float(self):
+ proxy = self._makeOne("14")
+ self.assertEqual(float("14"), float(proxy))
+
+ def test_incorrect_string_to_int(self):
+ proxy = self._makeOne("")
+ self.assertRaises(ValueError, int, proxy)
+
+ def test_incorrect_string_to_float(self):
+ proxy = self._makeOne("")
+ self.assertRaises(ValueError, float, proxy)
+
+ def test_custom_float_to_float(self):
+ class CustomClass(object):
+ def __float__(self):
+ return 42.0
+ proxy = self._makeOne(CustomClass())
+ self.assertEqual(42.0, float(proxy))
+
+ def test___unicode__of_unicode(self):
+ from zope.proxy._compat import PY3, _u
+ if PY3: # Gone in Python 3:
+ return
+ s = _u('Hello, \u2603')
+ proxy = self._makeOne(s)
+ self.assertEqual(unicode(proxy), s)
+
+ def test___unicode__of_custom_class(self):
+ from zope.proxy._compat import PY3, _u
+ if PY3: # Gone in Python 3:
+ return
+ class CustomClass(object):
+ def __unicode__(self):
+ return _u('Hello, \u2603')
+ cc = CustomClass()
+ self.assertEqual(unicode(cc), _u('Hello, \u2603'))
+ proxy = self._makeOne(cc)
+ self.assertEqual(unicode(proxy), _u('Hello, \u2603'))
+
+ def test___unicode__of_custom_class_no_unicode(self):
+ # The default behaviour should be preserved
+ from zope.proxy._compat import PY3, _u
+ if PY3: # Gone in Python 3:
+ return
+ class CustomClass(object):
+ pass
+ cc = CustomClass()
+ cc_unicode = unicode(cc)
+ self.assertEqual(type(cc_unicode), unicode)
+ proxy = self._makeOne(cc)
+ self.assertEqual(unicode(proxy), cc_unicode)
+
class ProxyBaseTestCase(PyProxyBaseTestCase):