home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 June / maximum-cd-2011-06.iso / DiscContents / LibO_3.3.1_Win_x86_install_multi.exe / libreoffice1.cab / test_coercion.py < prev    next >
Encoding:
Python Source  |  2011-02-15  |  11.0 KB  |  348 lines

  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()
  348.