symbian-qemu-0.9.1-12/python-2.6.1/Lib/test/test_coercion.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 import copy
       
     2 import warnings
       
     3 import unittest
       
     4 from test.test_support import run_unittest, TestFailed
       
     5 
       
     6 # Fake a number that implements numeric methods through __coerce__
       
     7 class CoerceNumber:
       
     8     def __init__(self, arg):
       
     9         self.arg = arg
       
    10 
       
    11     def __repr__(self):
       
    12         return '<CoerceNumber %s>' % repr(self.arg)
       
    13 
       
    14     def __coerce__(self, other):
       
    15         if isinstance(other, CoerceNumber):
       
    16             return self.arg, other.arg
       
    17         else:
       
    18             return (self.arg, other)
       
    19 
       
    20 # New-style class version of CoerceNumber
       
    21 class CoerceTo(object):
       
    22     def __init__(self, arg):
       
    23         self.arg = arg
       
    24     def __coerce__(self, other):
       
    25         if isinstance(other, CoerceTo):
       
    26             return self.arg, other.arg
       
    27         else:
       
    28             return self.arg, other
       
    29 
       
    30 
       
    31 # Fake a number that implements numeric ops through methods.
       
    32 class MethodNumber:
       
    33     def __init__(self,arg):
       
    34         self.arg = arg
       
    35 
       
    36     def __repr__(self):
       
    37         return '<MethodNumber %s>' % repr(self.arg)
       
    38 
       
    39     def __add__(self,other):
       
    40         return self.arg + other
       
    41 
       
    42     def __radd__(self,other):
       
    43         return other + self.arg
       
    44 
       
    45     def __sub__(self,other):
       
    46         return self.arg - other
       
    47 
       
    48     def __rsub__(self,other):
       
    49         return other - self.arg
       
    50 
       
    51     def __mul__(self,other):
       
    52         return self.arg * other
       
    53 
       
    54     def __rmul__(self,other):
       
    55         return other * self.arg
       
    56 
       
    57     def __div__(self,other):
       
    58         return self.arg / other
       
    59 
       
    60     def __rdiv__(self,other):
       
    61         return other / self.arg
       
    62 
       
    63     def __truediv__(self,other):
       
    64         return self.arg / other
       
    65 
       
    66     def __rtruediv__(self,other):
       
    67         return other / self.arg
       
    68 
       
    69     def __floordiv__(self,other):
       
    70         return self.arg // other
       
    71 
       
    72     def __rfloordiv__(self,other):
       
    73         return other // self.arg
       
    74 
       
    75     def __pow__(self,other):
       
    76         return self.arg ** other
       
    77 
       
    78     def __rpow__(self,other):
       
    79         return other ** self.arg
       
    80 
       
    81     def __mod__(self,other):
       
    82         return self.arg % other
       
    83 
       
    84     def __rmod__(self,other):
       
    85         return other % self.arg
       
    86 
       
    87     def __cmp__(self, other):
       
    88         return cmp(self.arg, other)
       
    89 
       
    90 
       
    91 candidates = [2, 2L, 4.0, 2+0j, [1], (2,), None,
       
    92               MethodNumber(2), CoerceNumber(2)]
       
    93 
       
    94 infix_binops = [ '+', '-', '*', '**', '%', '//', '/' ]
       
    95 
       
    96 TE = TypeError
       
    97 # b = both normal and augmented give same result list
       
    98 # s = single result lists for normal and augmented
       
    99 # e = equals other results
       
   100 # result lists: ['+', '-', '*', '**', '%', '//', ('classic /', 'new /')]
       
   101 #                                                ^^^^^^^^^^^^^^^^^^^^^^
       
   102 #                                               2-tuple if results differ
       
   103 #                                                 else only one value
       
   104 infix_results = {
       
   105     # 2
       
   106     (0,0): ('b', [4, 0, 4, 4, 0, 1, (1, 1.0)]),
       
   107     (0,1): ('e', (0,0)),
       
   108     (0,2): ('b', [6.0, -2.0, 8.0, 16.0, 2.0, 0.0, 0.5]),
       
   109     (0,3): ('b', [4+0j, 0+0j, 4+0j, 4+0j, 0+0j, 1+0j, 1+0j]),
       
   110     (0,4): ('b', [TE, TE, [1, 1], TE, TE, TE, TE]),
       
   111     (0,5): ('b', [TE, TE, (2, 2), TE, TE, TE, TE]),
       
   112     (0,6): ('b', [TE, TE, TE, TE, TE, TE, TE]),
       
   113     (0,7): ('e', (0,0)),
       
   114     (0,8): ('e', (0,0)),
       
   115 
       
   116     # 2L
       
   117     (1,0): ('e', (0,0)),
       
   118     (1,1): ('e', (0,1)),
       
   119     (1,2): ('e', (0,2)),
       
   120     (1,3): ('e', (0,3)),
       
   121     (1,4): ('e', (0,4)),
       
   122     (1,5): ('e', (0,5)),
       
   123     (1,6): ('e', (0,6)),
       
   124     (1,7): ('e', (0,7)),
       
   125     (1,8): ('e', (0,8)),
       
   126 
       
   127     # 4.0
       
   128     (2,0): ('b', [6.0, 2.0, 8.0, 16.0, 0.0, 2.0, 2.0]),
       
   129     (2,1): ('e', (2,0)),
       
   130     (2,2): ('b', [8.0, 0.0, 16.0, 256.0, 0.0, 1.0, 1.0]),
       
   131     (2,3): ('b', [6+0j, 2+0j, 8+0j, 16+0j, 0+0j, 2+0j, 2+0j]),
       
   132     (2,4): ('b', [TE, TE, TE, TE, TE, TE, TE]),
       
   133     (2,5): ('e', (2,4)),
       
   134     (2,6): ('e', (2,4)),
       
   135     (2,7): ('e', (2,0)),
       
   136     (2,8): ('e', (2,0)),
       
   137 
       
   138     # (2+0j)
       
   139     (3,0): ('b', [4+0j, 0+0j, 4+0j, 4+0j, 0+0j, 1+0j, 1+0j]),
       
   140     (3,1): ('e', (3,0)),
       
   141     (3,2): ('b', [6+0j, -2+0j, 8+0j, 16+0j, 2+0j, 0+0j, 0.5+0j]),
       
   142     (3,3): ('b', [4+0j, 0+0j, 4+0j, 4+0j, 0+0j, 1+0j, 1+0j]),
       
   143     (3,4): ('b', [TE, TE, TE, TE, TE, TE, TE]),
       
   144     (3,5): ('e', (3,4)),
       
   145     (3,6): ('e', (3,4)),
       
   146     (3,7): ('e', (3,0)),
       
   147     (3,8): ('e', (3,0)),
       
   148 
       
   149     # [1]
       
   150     (4,0): ('b', [TE, TE, [1, 1], TE, TE, TE, TE]),
       
   151     (4,1): ('e', (4,0)),
       
   152     (4,2): ('b', [TE, TE, TE, TE, TE, TE, TE]),
       
   153     (4,3): ('b', [TE, TE, TE, TE, TE, TE, TE]),
       
   154     (4,4): ('b', [[1, 1], TE, TE, TE, TE, TE, TE]),
       
   155     (4,5): ('s', [TE, TE, TE, TE, TE, TE, TE], [[1, 2], TE, TE, TE, TE, TE, TE]),
       
   156     (4,6): ('b', [TE, TE, TE, TE, TE, TE, TE]),
       
   157     (4,7): ('e', (4,0)),
       
   158     (4,8): ('e', (4,0)),
       
   159 
       
   160     # (2,)
       
   161     (5,0): ('b', [TE, TE, (2, 2), TE, TE, TE, TE]),
       
   162     (5,1): ('e', (5,0)),
       
   163     (5,2): ('b', [TE, TE, TE, TE, TE, TE, TE]),
       
   164     (5,3): ('e', (5,2)),
       
   165     (5,4): ('e', (5,2)),
       
   166     (5,5): ('b', [(2, 2), TE, TE, TE, TE, TE, TE]),
       
   167     (5,6): ('b', [TE, TE, TE, TE, TE, TE, TE]),
       
   168     (5,7): ('e', (5,0)),
       
   169     (5,8): ('e', (5,0)),
       
   170 
       
   171     # None
       
   172     (6,0): ('b', [TE, TE, TE, TE, TE, TE, TE]),
       
   173     (6,1): ('e', (6,0)),
       
   174     (6,2): ('e', (6,0)),
       
   175     (6,3): ('e', (6,0)),
       
   176     (6,4): ('e', (6,0)),
       
   177     (6,5): ('e', (6,0)),
       
   178     (6,6): ('e', (6,0)),
       
   179     (6,7): ('e', (6,0)),
       
   180     (6,8): ('e', (6,0)),
       
   181 
       
   182     # MethodNumber(2)
       
   183     (7,0): ('e', (0,0)),
       
   184     (7,1): ('e', (0,1)),
       
   185     (7,2): ('e', (0,2)),
       
   186     (7,3): ('e', (0,3)),
       
   187     (7,4): ('e', (0,4)),
       
   188     (7,5): ('e', (0,5)),
       
   189     (7,6): ('e', (0,6)),
       
   190     (7,7): ('e', (0,7)),
       
   191     (7,8): ('e', (0,8)),
       
   192 
       
   193     # CoerceNumber(2)
       
   194     (8,0): ('e', (0,0)),
       
   195     (8,1): ('e', (0,1)),
       
   196     (8,2): ('e', (0,2)),
       
   197     (8,3): ('e', (0,3)),
       
   198     (8,4): ('e', (0,4)),
       
   199     (8,5): ('e', (0,5)),
       
   200     (8,6): ('e', (0,6)),
       
   201     (8,7): ('e', (0,7)),
       
   202     (8,8): ('e', (0,8)),
       
   203 }
       
   204 
       
   205 def process_infix_results():
       
   206     for key in sorted(infix_results):
       
   207         val = infix_results[key]
       
   208         if val[0] == 'e':
       
   209             infix_results[key] = infix_results[val[1]]
       
   210         else:
       
   211             if val[0] == 's':
       
   212                 res = (val[1], val[2])
       
   213             elif val[0] == 'b':
       
   214                 res = (val[1], val[1])
       
   215             for i in range(1):
       
   216                 if isinstance(res[i][6], tuple):
       
   217                     if 1/2 == 0:
       
   218                         # testing with classic (floor) division
       
   219                         res[i][6] = res[i][6][0]
       
   220                     else:
       
   221                         # testing with -Qnew
       
   222                         res[i][6] = res[i][6][1]
       
   223             infix_results[key] = res
       
   224 
       
   225 
       
   226 
       
   227 process_infix_results()
       
   228 # now infix_results has two lists of results for every pairing.
       
   229 
       
   230 prefix_binops = [ 'divmod' ]
       
   231 prefix_results = [
       
   232     [(1,0), (1L,0L), (0.0,2.0), ((1+0j),0j), TE, TE, TE, TE, (1,0)],
       
   233     [(1L,0L), (1L,0L), (0.0,2.0), ((1+0j),0j), TE, TE, TE, TE, (1L,0L)],
       
   234     [(2.0,0.0), (2.0,0.0), (1.0,0.0), ((2+0j),0j), TE, TE, TE, TE, (2.0,0.0)],
       
   235     [((1+0j),0j), ((1+0j),0j), (0j,(2+0j)), ((1+0j),0j), TE, TE, TE, TE, ((1+0j),0j)],
       
   236     [TE, TE, TE, TE, TE, TE, TE, TE, TE],
       
   237     [TE, TE, TE, TE, TE, TE, TE, TE, TE],
       
   238     [TE, TE, TE, TE, TE, TE, TE, TE, TE],
       
   239     [TE, TE, TE, TE, TE, TE, TE, TE, TE],
       
   240     [(1,0), (1L,0L), (0.0,2.0), ((1+0j),0j), TE, TE, TE, TE, (1,0)]
       
   241 ]
       
   242 
       
   243 def format_float(value):
       
   244     if abs(value) < 0.01:
       
   245         return '0.0'
       
   246     else:
       
   247         return '%.1f' % value
       
   248 
       
   249 # avoid testing platform fp quirks
       
   250 def format_result(value):
       
   251     if isinstance(value, complex):
       
   252         return '(%s + %sj)' % (format_float(value.real),
       
   253                                format_float(value.imag))
       
   254     elif isinstance(value, float):
       
   255         return format_float(value)
       
   256     return str(value)
       
   257 
       
   258 class CoercionTest(unittest.TestCase):
       
   259     def test_infix_binops(self):
       
   260         for ia, a in enumerate(candidates):
       
   261             for ib, b in enumerate(candidates):
       
   262                 results = infix_results[(ia, ib)]
       
   263                 for op, res, ires in zip(infix_binops, results[0], results[1]):
       
   264                     if res is TE:
       
   265                         self.assertRaises(TypeError, eval,
       
   266                                           'a %s b' % op, {'a': a, 'b': b})
       
   267                     else:
       
   268                         self.assertEquals(format_result(res),
       
   269                                           format_result(eval('a %s b' % op)),
       
   270                                           '%s %s %s == %s failed' % (a, op, b, res))
       
   271                     try:
       
   272                         z = copy.copy(a)
       
   273                     except copy.Error:
       
   274                         z = a # assume it has no inplace ops
       
   275                     if ires is TE:
       
   276                         try:
       
   277                             exec 'z %s= b' % op
       
   278                         except TypeError:
       
   279                             pass
       
   280                         else:
       
   281                             self.fail("TypeError not raised")
       
   282                     else:
       
   283                         exec('z %s= b' % op)
       
   284                         self.assertEquals(ires, z)
       
   285 
       
   286     def test_prefix_binops(self):
       
   287         for ia, a in enumerate(candidates):
       
   288             for ib, b in enumerate(candidates):
       
   289                 for op in prefix_binops:
       
   290                     res = prefix_results[ia][ib]
       
   291                     if res is TE:
       
   292                         self.assertRaises(TypeError, eval,
       
   293                                           '%s(a, b)' % op, {'a': a, 'b': b})
       
   294                     else:
       
   295                         self.assertEquals(format_result(res),
       
   296                                           format_result(eval('%s(a, b)' % op)),
       
   297                                           '%s(%s, %s) == %s failed' % (op, a, b, res))
       
   298 
       
   299     def test_cmptypes(self):
       
   300         # Built-in tp_compare slots expect their arguments to have the
       
   301         # same type, but a user-defined __coerce__ doesn't have to obey.
       
   302         # SF #980352
       
   303         evil_coercer = CoerceTo(42)
       
   304         # Make sure these don't crash any more
       
   305         self.assertNotEquals(cmp(u'fish', evil_coercer), 0)
       
   306         self.assertNotEquals(cmp(slice(1), evil_coercer), 0)
       
   307         # ...but that this still works
       
   308         class WackyComparer(object):
       
   309             def __cmp__(slf, other):
       
   310                 self.assert_(other == 42, 'expected evil_coercer, got %r' % other)
       
   311                 return 0
       
   312             __hash__ = None # Invalid cmp makes this unhashable
       
   313         self.assertEquals(cmp(WackyComparer(), evil_coercer), 0)
       
   314         # ...and classic classes too, since that code path is a little different
       
   315         class ClassicWackyComparer:
       
   316             def __cmp__(slf, other):
       
   317                 self.assert_(other == 42, 'expected evil_coercer, got %r' % other)
       
   318                 return 0
       
   319         self.assertEquals(cmp(ClassicWackyComparer(), evil_coercer), 0)
       
   320 
       
   321     def test_infinite_rec_classic_classes(self):
       
   322         # if __coerce__() returns its arguments reversed it causes an infinite
       
   323         # recursion for classic classes.
       
   324         class Tester:
       
   325             def __coerce__(self, other):
       
   326                 return other, self
       
   327 
       
   328         exc = TestFailed("__coerce__() returning its arguments reverse "
       
   329                                 "should raise RuntimeError")
       
   330         try:
       
   331             Tester() + 1
       
   332         except (RuntimeError, TypeError):
       
   333             return
       
   334         except:
       
   335             raise exc
       
   336         else:
       
   337             raise exc
       
   338 
       
   339 def test_main():
       
   340     warnings.filterwarnings("ignore",
       
   341                             r'complex divmod\(\), // and % are deprecated',
       
   342                             DeprecationWarning,
       
   343                             r'test.test_coercion$')
       
   344     run_unittest(CoercionTest)
       
   345 
       
   346 if __name__ == "__main__":
       
   347     test_main()