text: # expected: fail
  import copy
  import unittest
  from test.test_support import run_unittest, TestFailed, check_warnings
  
  
  # Fake a number that implements numeric methods through __coerce__
  class CoerceNumber:
      def __init__(self, arg):
          self.arg = arg
  
      def __repr__(self):
          return '<CoerceNumber %s>' % repr(self.arg)
  
      def __coerce__(self, other):
          if isinstance(other, CoerceNumber):
              return self.arg, other.arg
          else:
              return (self.arg, other)
  
  # New-style class version of CoerceNumber
  class CoerceTo(object):
      def __init__(self, arg):
          self.arg = arg
      def __coerce__(self, other):
          if isinstance(other, CoerceTo):
              return self.arg, other.arg
          else:
              return self.arg, other
  
  
  # Fake a number that implements numeric ops through methods.
  class MethodNumber:
      def __init__(self,arg):
          self.arg = arg
  
      def __repr__(self):
          return '<MethodNumber %s>' % repr(self.arg)
  
      def __add__(self,other):
          return self.arg + other
  
      def __radd__(self,other):
          return other + self.arg
  
      def __sub__(self,other):
          return self.arg - other
  
      def __rsub__(self,other):
          return other - self.arg
  
      def __mul__(self,other):
          return self.arg * other
  
      def __rmul__(self,other):
          return other * self.arg
  
      def __div__(self,other):
          return self.arg / other
  
      def __rdiv__(self,other):
          return other / self.arg
  
      def __truediv__(self,other):
          return self.arg / other
  
      def __rtruediv__(self,other):
          return other / self.arg
  
      def __floordiv__(self,other):
          return self.arg // other
  
      def __rfloordiv__(self,other):
          return other // self.arg
  
      def __pow__(self,other):
          return self.arg ** other
  
      def __rpow__(self,other):
          return other ** self.arg
  
      def __mod__(self,other):
          return self.arg % other
  
      def __rmod__(self,other):
          return other % self.arg
  
      def __cmp__(self, other):
          return cmp(self.arg, other)
  
  
  candidates = [2, 2L, 4.0, 2+0j, [1], (2,), None,
                MethodNumber(2), CoerceNumber(2)]
  
  infix_binops = [ '+', '-', '*', '**', '%', '//', '/' ]
  
  TE = TypeError
  # b = both normal and augmented give same result list
  # s = single result lists for normal and augmented
  # e = equals other results
  # result lists: ['+', '-', '*', '**', '%', '//', ('classic /', 'new /')]
  #                                                ^^^^^^^^^^^^^^^^^^^^^^
  #                                               2-tuple if results differ
  #                                                 else only one value
  infix_results = {
      # 2
      (0,0): ('b', [4, 0, 4, 4, 0, 1, (1, 1.0)]),
      (0,1): ('e', (0,0)),
      (0,2): ('b', [6.0, -2.0, 8.0, 16.0, 2.0, 0.0, 0.5]),
      (0,3): ('b', [4+0j, 0+0j, 4+0j, 4+0j, 0+0j, 1+0j, 1+0j]),
      (0,4): ('b', [TE, TE, [1, 1], TE, TE, TE, TE]),
      (0,5): ('b', [TE, TE, (2, 2), TE, TE, TE, TE]),
      (0,6): ('b', [TE, TE, TE, TE, TE, TE, TE]),
      (0,7): ('e', (0,0)),
      (0,8): ('e', (0,0)),
  
      # 2L
      (1,0): ('e', (0,0)),
      (1,1): ('e', (0,1)),
      (1,2): ('e', (0,2)),
      (1,3): ('e', (0,3)),
      (1,4): ('e', (0,4)),
      (1,5): ('e', (0,5)),
      (1,6): ('e', (0,6)),
      (1,7): ('e', (0,7)),
      (1,8): ('e', (0,8)),
  
      # 4.0
      (2,0): ('b', [6.0, 2.0, 8.0, 16.0, 0.0, 2.0, 2.0]),
      (2,1): ('e', (2,0)),
      (2,2): ('b', [8.0, 0.0, 16.0, 256.0, 0.0, 1.0, 1.0]),
      (2,3): ('b', [6+0j, 2+0j, 8+0j, 16+0j, 0+0j, 2+0j, 2+0j]),
      (2,4): ('b', [TE, TE, TE, TE, TE, TE, TE]),
      (2,5): ('e', (2,4)),
      (2,6): ('e', (2,4)),
      (2,7): ('e', (2,0)),
      (2,8): ('e', (2,0)),
  
      # (2+0j)
      (3,0): ('b', [4+0j, 0+0j, 4+0j, 4+0j, 0+0j, 1+0j, 1+0j]),
      (3,1): ('e', (3,0)),
      (3,2): ('b', [6+0j, -2+0j, 8+0j, 16+0j, 2+0j, 0+0j, 0.5+0j]),
      (3,3): ('b', [4+0j, 0+0j, 4+0j, 4+0j, 0+0j, 1+0j, 1+0j]),
      (3,4): ('b', [TE, TE, TE, TE, TE, TE, TE]),
      (3,5): ('e', (3,4)),
      (3,6): ('e', (3,4)),
      (3,7): ('e', (3,0)),
      (3,8): ('e', (3,0)),
  
      # [1]
      (4,0): ('b', [TE, TE, [1, 1], TE, TE, TE, TE]),
      (4,1): ('e', (4,0)),
      (4,2): ('b', [TE, TE, TE, TE, TE, TE, TE]),
      (4,3): ('b', [TE, TE, TE, TE, TE, TE, TE]),
      (4,4): ('b', [[1, 1], TE, TE, TE, TE, TE, TE]),
      (4,5): ('s', [TE, TE, TE, TE, TE, TE, TE], [[1, 2], TE, TE, TE, TE, TE, TE]),
      (4,6): ('b', [TE, TE, TE, TE, TE, TE, TE]),
      (4,7): ('e', (4,0)),
      (4,8): ('e', (4,0)),
  
      # (2,)
      (5,0): ('b', [TE, TE, (2, 2), TE, TE, TE, TE]),
      (5,1): ('e', (5,0)),
      (5,2): ('b', [TE, TE, TE, TE, TE, TE, TE]),
      (5,3): ('e', (5,2)),
      (5,4): ('e', (5,2)),
      (5,5): ('b', [(2, 2), TE, TE, TE, TE, TE, TE]),
      (5,6): ('b', [TE, TE, TE, TE, TE, TE, TE]),
      (5,7): ('e', (5,0)),
      (5,8): ('e', (5,0)),
  
      # None
      (6,0): ('b', [TE, TE, TE, TE, TE, TE, TE]),
      (6,1): ('e', (6,0)),
      (6,2): ('e', (6,0)),
      (6,3): ('e', (6,0)),
      (6,4): ('e', (6,0)),
      (6,5): ('e', (6,0)),
      (6,6): ('e', (6,0)),
      (6,7): ('e', (6,0)),
      (6,8): ('e', (6,0)),
  
      # MethodNumber(2)
      (7,0): ('e', (0,0)),
      (7,1): ('e', (0,1)),
      (7,2): ('e', (0,2)),
      (7,3): ('e', (0,3)),
      (7,4): ('e', (0,4)),
      (7,5): ('e', (0,5)),
      (7,6): ('e', (0,6)),
      (7,7): ('e', (0,7)),
      (7,8): ('e', (0,8)),
  
      # CoerceNumber(2)
      (8,0): ('e', (0,0)),
      (8,1): ('e', (0,1)),
      (8,2): ('e', (0,2)),
      (8,3): ('e', (0,3)),
      (8,4): ('e', (0,4)),
      (8,5): ('e', (0,5)),
      (8,6): ('e', (0,6)),
      (8,7): ('e', (0,7)),
      (8,8): ('e', (0,8)),
  }
  
  def process_infix_results():
      for key in sorted(infix_results):
          val = infix_results[key]
          if val[0] == 'e':
              infix_results[key] = infix_results[val[1]]
          else:
              if val[0] == 's':
                  res = (val[1], val[2])
              elif val[0] == 'b':
                  res = (val[1], val[1])
              for i in range(1):
                  if isinstance(res[i][6], tuple):
                      if 1/2 == 0:
                          # testing with classic (floor) division
                          res[i][6] = res[i][6][0]
                      else:
                          # testing with -Qnew
                          res[i][6] = res[i][6][1]
              infix_results[key] = res
  
  
  with check_warnings(("classic (int|long) division", DeprecationWarning),
                      quiet=True):
      process_infix_results()
      # now infix_results has two lists of results for every pairing.
  
  prefix_binops = [ 'divmod' ]
  prefix_results = [
      [(1,0), (1L,0L), (0.0,2.0), ((1+0j),0j), TE, TE, TE, TE, (1,0)],
      [(1L,0L), (1L,0L), (0.0,2.0), ((1+0j),0j), TE, TE, TE, TE, (1L,0L)],
      [(2.0,0.0), (2.0,0.0), (1.0,0.0), ((2+0j),0j), TE, TE, TE, TE, (2.0,0.0)],
      [((1+0j),0j), ((1+0j),0j), (0j,(2+0j)), ((1+0j),0j), TE, TE, TE, TE, ((1+0j),0j)],
      [TE, TE, TE, TE, TE, TE, TE, TE, TE],
      [TE, TE, TE, TE, TE, TE, TE, TE, TE],
      [TE, TE, TE, TE, TE, TE, TE, TE, TE],
      [TE, TE, TE, TE, TE, TE, TE, TE, TE],
      [(1,0), (1L,0L), (0.0,2.0), ((1+0j),0j), TE, TE, TE, TE, (1,0)]
  ]
  
  def format_float(value):
      if abs(value) < 0.01:
          return '0.0'
      else:
          return '%.1f' % value
  
  # avoid testing platform fp quirks
  def format_result(value):
      if isinstance(value, complex):
          return '(%s + %sj)' % (format_float(value.real),
                                 format_float(value.imag))
      elif isinstance(value, float):
          return format_float(value)
      return str(value)
  
  class CoercionTest(unittest.TestCase):
      def test_infix_binops(self):
          for ia, a in enumerate(candidates):
              for ib, b in enumerate(candidates):
                  results = infix_results[(ia, ib)]
                  for op, res, ires in zip(infix_binops, results[0], results[1]):
                      if res is TE:
                          self.assertRaises(TypeError, eval,
                                            'a %s b' % op, {'a': a, 'b': b})
                      else:
                          self.assertEqual(format_result(res),
                                           format_result(eval('a %s b' % op)),
                                           '%s %s %s == %s failed' % (a, op, b, res))
                      try:
                          z = copy.copy(a)
                      except copy.Error:
                          z = a # assume it has no inplace ops
                      if ires is TE:
                          try:
                              exec 'z %s= b' % op
                          except TypeError:
                              pass
                          else:
                              self.fail("TypeError not raised")
                      else:
                          exec('z %s= b' % op)
                          self.assertEqual(ires, z)
  
      def test_prefix_binops(self):
          for ia, a in enumerate(candidates):
              for ib, b in enumerate(candidates):
                  for op in prefix_binops:
                      res = prefix_results[ia][ib]
                      if res is TE:
                          self.assertRaises(TypeError, eval,
                                            '%s(a, b)' % op, {'a': a, 'b': b})
                      else:
                          self.assertEqual(format_result(res),
                                           format_result(eval('%s(a, b)' % op)),
                                           '%s(%s, %s) == %s failed' % (op, a, b, res))
  
      def test_cmptypes(self):
          # Built-in tp_compare slots expect their arguments to have the
          # same type, but a user-defined __coerce__ doesn't have to obey.
          # SF #980352
          evil_coercer = CoerceTo(42)
          # Make sure these don't crash any more
          self.assertNotEqual(cmp(u'fish', evil_coercer), 0)
          self.assertNotEqual(cmp(slice(1), evil_coercer), 0)
          # ...but that this still works
          class WackyComparer(object):
              def __cmp__(slf, other):
                  self.assertTrue(other == 42, 'expected evil_coercer, got %r' % other)
                  return 0
              __hash__ = None # Invalid cmp makes this unhashable
          self.assertEqual(cmp(WackyComparer(), evil_coercer), 0)
          # ...and classic classes too, since that code path is a little different
          class ClassicWackyComparer:
              def __cmp__(slf, other):
                  self.assertTrue(other == 42, 'expected evil_coercer, got %r' % other)
                  return 0
          self.assertEqual(cmp(ClassicWackyComparer(), evil_coercer), 0)
  
      def test_infinite_rec_classic_classes(self):
          # if __coerce__() returns its arguments reversed it causes an infinite
          # recursion for classic classes.
          class Tester:
              def __coerce__(self, other):
                  return other, self
  
          exc = TestFailed("__coerce__() returning its arguments reverse "
                                  "should raise RuntimeError")
          try:
              Tester() + 1
          except (RuntimeError, TypeError):
              return
          except:
              raise exc
          else:
              raise exc
  
  def test_main():
      with check_warnings(("complex divmod.., // and % are deprecated",
                           DeprecationWarning),
                          ("classic (int|long) division", DeprecationWarning),
                          quiet=True):
          run_unittest(CoercionTest)
  
  if __name__ == "__main__":
      test_main()
  