[pypy-svn] r62724 - in pypy/trunk/pypy/objspace/std: . test
arigo at codespeak.net
arigo at codespeak.net
Sat Mar 7 18:51:50 CET 2009
Author: arigo
Date: Sat Mar 7 18:51:49 2009
New Revision: 62724
Modified:
pypy/trunk/pypy/objspace/std/builtinshortcut.py
pypy/trunk/pypy/objspace/std/model.py
pypy/trunk/pypy/objspace/std/objspace.py
pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py
Log:
issue426 testing
Improve builtinshortcut to work also for inplace operations
that fallback to normal operations, like x += 5.
Modified: pypy/trunk/pypy/objspace/std/builtinshortcut.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/builtinshortcut.py (original)
+++ pypy/trunk/pypy/objspace/std/builtinshortcut.py Sat Mar 7 18:51:49 2009
@@ -50,7 +50,7 @@
% (_name,))
-def install(space, mm):
+def install(space, mm, fallback_mm=None):
"""Install a function <name>() on the space instance which invokes
a shortcut for built-in types. Returns the shortcutting multimethod
object or None.
@@ -79,6 +79,8 @@
# (and only these ones) never match the interp-level subclasses
# built in pypy.interpreter.typedef.get_unique_interplevel_subclass.
expanded_order = space.model.get_typeorder_with_empty_usersubcls()
+ if fallback_mm:
+ mm = mm.merge_with(fallback_mm)
shortcut_method = mm.install_not_sliced(expanded_order)
def operate(*args_w):
@@ -95,31 +97,21 @@
def install_is_true(space, mm_nonzero, mm_len):
- nonzero_shortcut = install(space, mm_nonzero)
- len_shortcut = install(space, mm_len)
+ shortcut = install(space, mm_nonzero, fallback_mm = mm_len)
assert 'is_true' not in space.__dict__
def is_true(w_obj):
# a bit of duplication of the logic from DescrOperation.is_true...
- # first try 'nonzero'
try:
- w_res = nonzero_shortcut(space, w_obj)
+ w_res = shortcut(space, w_obj)
except FailedToImplement:
pass
else:
# the __nonzero__ method of built-in objects should
- # always directly return a Bool
- assert isinstance(w_res, W_BoolObject)
- return w_res.boolval
-
- # then try 'len'
- try:
- w_res = len_shortcut(space, w_obj)
- except FailedToImplement:
- pass
- else:
- # the __len__ method of built-in objects typically
- # returns an unwrappable integer
+ # always directly return a Bool; however, the __len__ method
+ # of built-in objects typically returns an unwrappable integer
+ if isinstance(w_res, W_BoolObject):
+ return w_res.boolval
try:
return space.int_w(w_res) != 0
except OperationError:
Modified: pypy/trunk/pypy/objspace/std/model.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/model.py (original)
+++ pypy/trunk/pypy/objspace/std/model.py Sat Mar 7 18:51:49 2009
@@ -329,3 +329,29 @@
return self.install(prefix = '__mm_' + self.name,
list_of_typeorders = [typeorder]*self.arity,
baked_perform_call=baked_perform_call)
+
+ def merge_with(self, other):
+ # Make a new 'merged' multimethod including the union of the two
+ # tables. In case of conflict, pick the entry from 'self'.
+ if self.arity != other.arity:
+ return self # XXX that's the case of '**'
+ operatorsymbol = '%s_merge_%s' % (self.name, other.name)
+ assert self.extras == other.extras
+ mm = StdObjSpaceMultiMethod(operatorsymbol, self.arity, **self.extras)
+ #
+ def merge(node1, node2):
+ assert type(node1) is type(node2)
+ if isinstance(node1, dict):
+ d = node1.copy()
+ d.update(node2)
+ for key in node1:
+ if key in node2:
+ d[key] = merge(node1[key], node2[key])
+ return d
+ else:
+ assert isinstance(node1, list)
+ assert node1
+ return node1 # pick the entry from 'self'
+ #
+ mm.dispatch_tree = merge(self.dispatch_tree, other.dispatch_tree)
+ return mm
Modified: pypy/trunk/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/objspace.py (original)
+++ pypy/trunk/pypy/objspace/std/objspace.py Sat Mar 7 18:51:49 2009
@@ -286,7 +286,14 @@
setattr(self, name, boundmethod) # store into 'space' instance
elif self.config.objspace.std.builtinshortcut:
from pypy.objspace.std import builtinshortcut
- builtinshortcut.install(self, mm)
+ if name.startswith('inplace_'):
+ fallback_name = name[len('inplace_'):]
+ if fallback_name in ('or', 'and'):
+ fallback_name += '_'
+ fallback_mm = self.MM.__dict__[fallback_name]
+ else:
+ fallback_mm = None
+ builtinshortcut.install(self, mm, fallback_mm)
if self.config.objspace.std.builtinshortcut:
from pypy.objspace.std import builtinshortcut
Modified: pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py (original)
+++ pypy/trunk/pypy/objspace/std/test/test_builtinshortcut.py Sat Mar 7 18:51:49 2009
@@ -34,6 +34,34 @@
s.discard(F("abc"))
assert not s
+ def test_inplace_methods(self):
+ assert '__iadd__' not in int.__dict__
+ assert '__iadd__' not in float.__dict__
+ x = 5
+ x += 6.5
+ assert x == 11.5
+
+ def test_inplace_user_subclasses(self):
+ class I(int): pass
+ class F(float): pass
+ x = I(5)
+ x += F(6.5)
+ assert x == 11.5
+ assert type(x) is float
+
+ def test_inplace_override(self):
+ class I(int):
+ def __iadd__(self, other):
+ return 'foo'
+ x = I(5)
+ x += 6
+ assert x == 'foo'
+ x = I(5)
+ x += 6.5
+ assert x == 'foo'
+ assert 5 + 6.5 == 11.5
+
+
class AppTestSet(test_set.AppTestAppSetTest):
# this tests tons of funny comparison combinations that can easily go wrong
def setup_class(cls):
More information about the Pypy-commit
mailing list