Author: Antonio Cuni <[email protected]>
Branch:
Changeset: r53053:bdff1d20bb98
Date: 2012-03-01 16:41 +0100
http://bitbucket.org/pypy/pypy/changeset/bdff1d20bb98/
Log: add a way to automatically define __gt__, __ge__, __le__ and __ne__
on top of the given __lt__ and __eq__
diff --git a/pypy/interpreter/test/test_typedef.py
b/pypy/interpreter/test/test_typedef.py
--- a/pypy/interpreter/test/test_typedef.py
+++ b/pypy/interpreter/test/test_typedef.py
@@ -304,6 +304,42 @@
assert_method(w_o1, "c", True)
assert_method(w_o2, "c", False)
+ def test_total_ordering(self):
+ class W_SomeType(Wrappable):
+ def __init__(self, space, x):
+ self.space = space
+ self.x = x
+
+ def descr__lt(self, w_other):
+ assert isinstance(w_other, W_SomeType)
+ return self.space.wrap(self.x < w_other.x)
+
+ def descr__eq(self, w_other):
+ assert isinstance(w_other, W_SomeType)
+ return self.space.wrap(self.x == w_other.x)
+
+ W_SomeType.typedef = typedef.TypeDef(
+ 'some_type',
+ __total_ordering__ = 'auto',
+ __lt__ = interp2app(W_SomeType.descr__lt),
+ __eq__ = interp2app(W_SomeType.descr__eq),
+ )
+ space = self.space
+ w_b = space.wrap(W_SomeType(space, 2))
+ w_c = space.wrap(W_SomeType(space, 2))
+ w_a = space.wrap(W_SomeType(space, 1))
+ # explicitly defined
+ assert space.is_true(space.lt(w_a, w_b))
+ assert not space.is_true(space.eq(w_a, w_b))
+ assert space.is_true(space.eq(w_b, w_c))
+ # automatically defined
+ assert space.is_true(space.le(w_a, w_b))
+ assert space.is_true(space.le(w_b, w_c))
+ assert space.is_true(space.gt(w_b, w_a))
+ assert space.is_true(space.ge(w_b, w_a))
+ assert space.is_true(space.ge(w_b, w_c))
+ assert space.is_true(space.ne(w_a, w_b))
+ assert not space.is_true(space.ne(w_b, w_c))
class AppTestTypeDef:
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -12,7 +12,7 @@
from pypy.rlib.jit import promote
class TypeDef:
- def __init__(self, __name, __base=None, **rawdict):
+ def __init__(self, __name, __base=None, __total_ordering__=None,
**rawdict):
"NOT_RPYTHON: initialization-time only"
self.name = __name
if __base is None:
@@ -34,6 +34,9 @@
# xxx used by faking
self.fakedcpytype = None
self.add_entries(**rawdict)
+ assert __total_ordering__ in (None, 'auto'), "Unknown value for
__total_ordering"
+ if __total_ordering__ == 'auto':
+ self.auto_total_ordering()
def add_entries(self, **rawdict):
# xxx fix the names of the methods to match what app-level expects
@@ -41,7 +44,15 @@
if isinstance(value, (interp2app, GetSetProperty)):
value.name = key
self.rawdict.update(rawdict)
-
+
+ def auto_total_ordering(self):
+ assert '__lt__' in self.rawdict, "__total_ordering='auto' requires
__lt__"
+ assert '__eq__' in self.rawdict, "__total_ordering='auto' requires
__eq__"
+ self.add_entries(__le__ = auto__le__,
+ __gt__ = auto__gt__,
+ __ge__ = auto__ge__,
+ __ne__ = auto__ne__)
+
def _freeze_(self):
# hint for the annotator: track individual constant instances of
TypeDef
return True
@@ -50,6 +61,27 @@
return "<%s name=%r>" % (self.__class__.__name__, self.name)
+# generic special cmp methods defined on top of __lt__ and __eq__, used by
+# automatic total ordering
+
+@interp2app
+def auto__le__(space, w_self, w_other):
+ return space.or_(space.lt(w_self, w_other),
+ space.eq(w_self, w_other))
+
+@interp2app
+def auto__gt__(space, w_self, w_other):
+ return space.not_(space.le(w_self, w_other))
+
+@interp2app
+def auto__ge__(space, w_self, w_other):
+ return space.not_(space.lt(w_self, w_other))
+
+@interp2app
+def auto__ne__(space, w_self, w_other):
+ return space.not_(space.eq(w_self, w_other))
+
+
# ____________________________________________________________
# Hash support
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit