14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport unittest 24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport sys 34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom test.test_support import check_py3k_warnings, CleanImport, run_unittest 44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport warnings 54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmif not sys.py3kwarning: 74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise unittest.SkipTest('%s must be run with the -3 flag' % __name__) 84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtry: 104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm from test.test_support import __warningregistry__ as _registry 114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmexcept ImportError: 124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def check_deprecated_module(module_name): 134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return False 144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmelse: 154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm past_warnings = _registry.keys() 164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm del _registry 174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def check_deprecated_module(module_name): 184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Lookup the past warnings for module already loaded using 194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm test_support.import_module(..., deprecated=True) 204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return any(module_name in msg and ' removed' in msg 224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm and issubclass(cls, DeprecationWarning) 234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm and (' module' in msg or ' package' in msg) 244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for (msg, cls, line) in past_warnings) 254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef reset_module_registry(module): 274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm registry = module.__warningregistry__ 294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except AttributeError: 304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm registry.clear() 334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestPy3KWarnings(unittest.TestCase): 354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def assertWarning(self, _, warning, expected_message): 374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(str(warning.message), expected_message) 384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def assertNoWarning(self, _, recorder): 404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(len(recorder.warnings), 0) 414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_backquote(self): 434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = 'backquote not supported in 3.x; use repr()' 444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings((expected, SyntaxWarning)): 454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm exec "`2`" in {} 464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_paren_arg_names(self): 484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = 'parenthesized argument names are invalid in 3.x' 494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def check(s): 504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings((expected, SyntaxWarning)): 514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm exec s in {} 524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm check("def f((x)): pass") 534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm check("def f((((x))), (y)): pass") 544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm check("def f((x), (((y))), m=32): pass") 554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Something like def f((a, (b))): pass will raise the tuple 564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # unpacking warning. 574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_forbidden_names(self): 594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # So we don't screw up our globals 604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def safe_exec(expr): 614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def f(**kwargs): pass 624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm exec expr in {'f' : f} 634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm tests = [("True", "assignment to True or False is forbidden in 3.x"), 654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ("False", "assignment to True or False is forbidden in 3.x"), 664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ("nonlocal", "nonlocal is a keyword in 3.x")] 674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings(('', SyntaxWarning)) as w: 684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for keyword, expected in tests: 694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm safe_exec("{0} = False".format(keyword)) 704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(None, w, expected) 714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm safe_exec("obj.{0} = True".format(keyword)) 744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except NameError: 754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(None, w, expected) 774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm safe_exec("def {0}(): pass".format(keyword)) 794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(None, w, expected) 804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm safe_exec("class {0}: pass".format(keyword)) 824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(None, w, expected) 834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm safe_exec("def f({0}=43): pass".format(keyword)) 854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(None, w, expected) 864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_type_inequality_comparisons(self): 904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = 'type inequality comparisons not supported in 3.x' 914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(int < str, w, expected) 934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(type < object, w, expected) 954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_object_inequality_comparisons(self): 974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = 'comparing unequal types not supported in 3.x' 984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(str < [], w, expected) 1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(object() < (1, 2), w, expected) 1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_dict_inequality_comparisons(self): 1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = 'dict inequality comparisons not supported in 3.x' 1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning({} < {2:3}, w, expected) 1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning({} <= {}, w, expected) 1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning({} > {2:3}, w, expected) 1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning({2:3} >= {}, w, expected) 1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_cell_inequality_comparisons(self): 1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = 'cell comparisons not supported in 3.x' 1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def f(x): 1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def g(): 1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return x 1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return g 1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm cell0, = f(0).func_closure 1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm cell1, = f(1).func_closure 1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(cell0 == cell1, w, expected) 1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(cell0 < cell1, w, expected) 1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_code_inequality_comparisons(self): 1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = 'code inequality comparisons not supported in 3.x' 1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def f(x): 1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def g(x): 1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(f.func_code < g.func_code, w, expected) 1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(f.func_code <= g.func_code, w, expected) 1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(f.func_code >= g.func_code, w, expected) 1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(f.func_code > g.func_code, w, expected) 1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_builtin_function_or_method_comparisons(self): 1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = ('builtin_function_or_method ' 1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'order comparisons not supported in 3.x') 1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm func = eval 1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm meth = {}.get 1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(func < meth, w, expected) 1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(func > meth, w, expected) 1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(meth <= func, w, expected) 1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(meth >= func, w, expected) 1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertNoWarning(meth == func, w) 1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertNoWarning(meth != func, w) 1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lam = lambda x: x 1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertNoWarning(lam == func, w) 1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertNoWarning(lam != func, w) 1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_frame_attributes(self): 1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm template = "%s has been removed in 3.x" 1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f = sys._getframe(0) 1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for attr in ("f_exc_traceback", "f_exc_value", "f_exc_type"): 1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = template % attr 1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(getattr(f, attr), w, expected) 1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(setattr(f, attr, None), w, expected) 1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_sort_cmp_arg(self): 1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = "the cmp argument is not supported in 3.x" 1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lst = range(5) 1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm cmp = lambda x,y: -1 1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(lst.sort(cmp=cmp), w, expected) 1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(sorted(lst, cmp=cmp), w, expected) 1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(lst.sort(cmp), w, expected) 1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(sorted(lst, cmp), w, expected) 1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_sys_exc_clear(self): 1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = 'sys.exc_clear() not supported in 3.x; use except clauses' 1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(sys.exc_clear(), w, expected) 1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_methods_members(self): 1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = '__members__ and __methods__ not supported in 3.x' 1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class C: 1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm __methods__ = ['a'] 1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm __members__ = ['b'] 1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm c = C() 1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(dir(c), w, expected) 1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_softspace(self): 2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = 'file.softspace not supported in 3.x' 2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with file(__file__) as f: 2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(f.softspace, w, expected) 2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def set(): 2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.softspace = 0 2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(set(), w, expected) 2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_slice_methods(self): 2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class Spam(object): 2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __getslice__(self, i, j): pass 2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __setslice__(self, i, j, what): pass 2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __delslice__(self, i, j): pass 2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class Egg: 2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __getslice__(self, i, h): pass 2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __setslice__(self, i, j, what): pass 2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __delslice__(self, i, j): pass 2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = "in 3.x, __{0}slice__ has been removed; use __{0}item__" 2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for obj in (Spam(), Egg()): 2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(obj[1:2], w, expected.format('get')) 2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm del obj[3:4] 2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(None, w, expected.format('del')) 2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm obj[4:5] = "eggs" 2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(None, w, expected.format('set')) 2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_tuple_parameter_unpacking(self): 2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = "tuple parameter unpacking has been removed in 3.x" 2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings((expected, SyntaxWarning)): 2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm exec "def f((a, b)): pass" 2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_buffer(self): 2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = 'buffer() not supported in 3.x' 2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(buffer('a'), w, expected) 2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_file_xreadlines(self): 2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm expected = ("f.xreadlines() not supported in 3.x, " 2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "try 'for line in f' instead") 2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with file(__file__) as f: 2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(f.xreadlines(), w, expected) 2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_hash_inheritance(self): 2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # With object as the base class 2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class WarnOnlyCmp(object): 2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __cmp__(self, other): pass 2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(len(w.warnings), 0) 2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class WarnOnlyEq(object): 2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __eq__(self, other): pass 2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(len(w.warnings), 1) 2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(None, w, 2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Overriding __eq__ blocks inheritance of __hash__ in 3.x") 2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class WarnCmpAndEq(object): 2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __cmp__(self, other): pass 2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __eq__(self, other): pass 2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(len(w.warnings), 1) 2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(None, w, 2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Overriding __eq__ blocks inheritance of __hash__ in 3.x") 2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class NoWarningOnlyHash(object): 2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __hash__(self): pass 2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(len(w.warnings), 0) 2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # With an intermediate class in the heirarchy 2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class DefinesAllThree(object): 2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __cmp__(self, other): pass 2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __eq__(self, other): pass 2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __hash__(self): pass 2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class WarnOnlyCmp(DefinesAllThree): 2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __cmp__(self, other): pass 2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(len(w.warnings), 0) 2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class WarnOnlyEq(DefinesAllThree): 2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __eq__(self, other): pass 2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(len(w.warnings), 1) 2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(None, w, 2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Overriding __eq__ blocks inheritance of __hash__ in 3.x") 2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class WarnCmpAndEq(DefinesAllThree): 2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __cmp__(self, other): pass 2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __eq__(self, other): pass 2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(len(w.warnings), 1) 2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(None, w, 2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Overriding __eq__ blocks inheritance of __hash__ in 3.x") 2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class NoWarningOnlyHash(DefinesAllThree): 2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __hash__(self): pass 2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(len(w.warnings), 0) 2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_operator(self): 2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm from operator import isCallable, sequenceIncludes 3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm callable_warn = ("operator.isCallable() is not supported in 3.x. " 3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Use hasattr(obj, '__call__').") 3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm seq_warn = ("operator.sequenceIncludes() is not supported " 3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "in 3.x. Use operator.contains().") 3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(isCallable(self), w, callable_warn) 3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm w.reset() 3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertWarning(sequenceIncludes(range(3), 2), w, seq_warn) 3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestStdlibRemovals(unittest.TestCase): 3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # test.testall not tested as it executes all unit tests as an 3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # import side-effect. 3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm all_platforms = ('audiodev', 'imputil', 'mutex', 'user', 'new', 'rexec', 3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'Bastion', 'compiler', 'dircache', 'mimetools', 3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'fpformat', 'ihooks', 'mhlib', 'statvfs', 'htmllib', 3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'sgmllib', 'rfc822', 'sunaudio') 3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm inclusive_platforms = {'irix' : ('pure', 'AL', 'al', 'CD', 'cd', 'cddb', 3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'cdplayer', 'CL', 'cl', 'DEVICE', 'GL', 3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'gl', 'ERRNO', 'FILE', 'FL', 'flp', 'fl', 3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'fm', 'GET', 'GLWS', 'imgfile', 'IN', 3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'IOCTL', 'jpeg', 'panel', 'panelparser', 3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'readcd', 'SV', 'torgb', 'WAIT'), 3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'darwin' : ('autoGIL', 'Carbon', 'OSATerminology', 3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'icglue', 'Nav', 3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # MacOS should (and does) give a Py3kWarning, but one of the 3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # earlier tests already imports the MacOS extension which causes 3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # this test to fail. Disabling the test for 'MacOS' avoids this 3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # spurious test failure. 3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm #'MacOS', 3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'aepack', 3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'aetools', 'aetypes', 'applesingle', 3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'appletrawmain', 'appletrunner', 3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'argvemulator', 'bgenlocations', 3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'EasyDialogs', 'macerrors', 'macostools', 3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'findertools', 'FrameWork', 'ic', 3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'gensuitemodule', 'icopen', 'macresource', 3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'MiniAEFrame', 'pimp', 'PixMapWrapper', 3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'terminalcommand', 'videoreader', 3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '_builtinSuites', 'CodeWarrior', 3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'Explorer', 'Finder', 'Netscape', 3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'StdSuites', 'SystemEvents', 'Terminal', 3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'cfmfile', 'bundlebuilder', 'buildtools', 3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'ColorPicker', 'Audio_mac'), 3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'sunos5' : ('sunaudiodev', 'SUNAUDIODEV'), 3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm optional_modules = ('bsddb185', 'Canvas', 'dl', 'linuxaudiodev', 'imageop', 3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'sv', 'bsddb', 'dbhash') 3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def check_removal(self, module_name, optional=False): 3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Make sure the specified module, when imported, raises a 3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm DeprecationWarning and specifies itself in the message.""" 3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with CleanImport(module_name), warnings.catch_warnings(): 3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm warnings.filterwarnings("error", ".+ (module|package) .+ removed", 3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm DeprecationWarning, __name__) 3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm warnings.filterwarnings("error", ".+ removed .+ (module|package)", 3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm DeprecationWarning, __name__) 3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm __import__(module_name, level=0) 3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except DeprecationWarning as exc: 3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertIn(module_name, exc.args[0], 3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "%s warning didn't contain module name" 3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm % module_name) 3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except ImportError: 3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not optional: 3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.fail("Non-optional module {0} raised an " 3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "ImportError.".format(module_name)) 3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # For extension modules, check the __warningregistry__. 3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # They won't rerun their init code even with CleanImport. 3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not check_deprecated_module(module_name): 3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.fail("DeprecationWarning not raised for {0}" 3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm .format(module_name)) 3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_platform_independent_removals(self): 3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Make sure that the modules that are available on all platforms raise 3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # the proper DeprecationWarning. 3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for module_name in self.all_platforms: 3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.check_removal(module_name) 3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_platform_specific_removals(self): 3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the removal of platform-specific modules. 3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for module_name in self.inclusive_platforms.get(sys.platform, []): 3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.check_removal(module_name, optional=True) 3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_optional_module_removals(self): 3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the removal of modules that may or may not be built. 3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for module_name in self.optional_modules: 3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.check_removal(module_name, optional=True) 3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_os_path_walk(self): 3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = "In 3.x, os.path.walk is removed in favor of os.walk." 3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def dumbo(where, names, args): pass 3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for path_mod in ("ntpath", "macpath", "os2emxpath", "posixpath"): 3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm mod = __import__(path_mod) 3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm reset_module_registry(mod) 3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with check_py3k_warnings() as w: 3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm mod.walk("crashers", dumbo, None) 4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(str(w.message), msg) 4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_reduce_move(self): 4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm from operator import add 4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # reduce tests may have already triggered this warning 4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm reset_module_registry(unittest.case) 4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with warnings.catch_warnings(): 4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm warnings.filterwarnings("error", "reduce") 4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertRaises(DeprecationWarning, reduce, add, range(10)) 4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_mutablestring_removal(self): 4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # UserString.MutableString has been removed in 3.0. 4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm import UserString 4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # UserString tests may have already triggered this warning 4144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm reset_module_registry(UserString) 4154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm with warnings.catch_warnings(): 4164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm warnings.filterwarnings("error", ".*MutableString", 4174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm DeprecationWarning) 4184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertRaises(DeprecationWarning, UserString.MutableString) 4194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef test_main(): 4224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm run_unittest(TestPy3KWarnings, 4234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm TestStdlibRemovals) 4244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmif __name__ == '__main__': 4264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm test_main() 427