test_py3kwarn.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. import unittest
  2. import sys
  3. from test.test_support import check_py3k_warnings, CleanImport, run_unittest
  4. import warnings
  5. from test import test_support
  6. if not sys.py3kwarning:
  7. raise unittest.SkipTest('%s must be run with the -3 flag' % __name__)
  8. try:
  9. from test.test_support import __warningregistry__ as _registry
  10. except ImportError:
  11. def check_deprecated_module(module_name):
  12. return False
  13. else:
  14. past_warnings = _registry.keys()
  15. del _registry
  16. def check_deprecated_module(module_name):
  17. """Lookup the past warnings for module already loaded using
  18. test_support.import_module(..., deprecated=True)
  19. """
  20. return any(module_name in msg and ' removed' in msg
  21. and issubclass(cls, DeprecationWarning)
  22. and (' module' in msg or ' package' in msg)
  23. for (msg, cls, line) in past_warnings)
  24. def reset_module_registry(module):
  25. try:
  26. registry = module.__warningregistry__
  27. except AttributeError:
  28. pass
  29. else:
  30. registry.clear()
  31. class TestPy3KWarnings(unittest.TestCase):
  32. def assertWarning(self, _, warning, expected_message):
  33. self.assertEqual(str(warning.message), expected_message)
  34. def assertNoWarning(self, _, recorder):
  35. self.assertEqual(len(recorder.warnings), 0)
  36. def test_backquote(self):
  37. expected = 'backquote not supported in 3.x; use repr()'
  38. with check_py3k_warnings((expected, SyntaxWarning)):
  39. exec "`2`" in {}
  40. def test_paren_arg_names(self):
  41. expected = 'parenthesized argument names are invalid in 3.x'
  42. def check(s):
  43. with check_py3k_warnings((expected, SyntaxWarning)):
  44. exec s in {}
  45. check("def f((x)): pass")
  46. check("def f((((x))), (y)): pass")
  47. check("def f((x), (((y))), m=32): pass")
  48. # Something like def f((a, (b))): pass will raise the tuple
  49. # unpacking warning.
  50. def test_forbidden_names(self):
  51. # So we don't screw up our globals
  52. def safe_exec(expr):
  53. def f(**kwargs): pass
  54. exec expr in {'f' : f}
  55. tests = [("True", "assignment to True or False is forbidden in 3.x"),
  56. ("False", "assignment to True or False is forbidden in 3.x"),
  57. ("nonlocal", "nonlocal is a keyword in 3.x")]
  58. with check_py3k_warnings(('', SyntaxWarning)) as w:
  59. for keyword, expected in tests:
  60. safe_exec("{0} = False".format(keyword))
  61. self.assertWarning(None, w, expected)
  62. w.reset()
  63. try:
  64. safe_exec("obj.{0} = True".format(keyword))
  65. except NameError:
  66. pass
  67. self.assertWarning(None, w, expected)
  68. w.reset()
  69. safe_exec("def {0}(): pass".format(keyword))
  70. self.assertWarning(None, w, expected)
  71. w.reset()
  72. safe_exec("class {0}: pass".format(keyword))
  73. self.assertWarning(None, w, expected)
  74. w.reset()
  75. safe_exec("def f({0}=43): pass".format(keyword))
  76. self.assertWarning(None, w, expected)
  77. w.reset()
  78. def test_type_inequality_comparisons(self):
  79. expected = 'type inequality comparisons not supported in 3.x'
  80. with check_py3k_warnings() as w:
  81. self.assertWarning(int < str, w, expected)
  82. w.reset()
  83. self.assertWarning(type < object, w, expected)
  84. def test_object_inequality_comparisons(self):
  85. expected = 'comparing unequal types not supported in 3.x'
  86. with check_py3k_warnings() as w:
  87. self.assertWarning(str < [], w, expected)
  88. w.reset()
  89. self.assertWarning(object() < (1, 2), w, expected)
  90. def test_dict_inequality_comparisons(self):
  91. expected = 'dict inequality comparisons not supported in 3.x'
  92. with check_py3k_warnings() as w:
  93. self.assertWarning({} < {2:3}, w, expected)
  94. w.reset()
  95. self.assertWarning({} <= {}, w, expected)
  96. w.reset()
  97. self.assertWarning({} > {2:3}, w, expected)
  98. w.reset()
  99. self.assertWarning({2:3} >= {}, w, expected)
  100. def test_cell_inequality_comparisons(self):
  101. expected = 'cell comparisons not supported in 3.x'
  102. def f(x):
  103. def g():
  104. return x
  105. return g
  106. cell0, = f(0).func_closure
  107. cell1, = f(1).func_closure
  108. with check_py3k_warnings() as w:
  109. self.assertWarning(cell0 == cell1, w, expected)
  110. w.reset()
  111. self.assertWarning(cell0 < cell1, w, expected)
  112. def test_code_inequality_comparisons(self):
  113. expected = 'code inequality comparisons not supported in 3.x'
  114. def f(x):
  115. pass
  116. def g(x):
  117. pass
  118. with check_py3k_warnings() as w:
  119. self.assertWarning(f.func_code < g.func_code, w, expected)
  120. w.reset()
  121. self.assertWarning(f.func_code <= g.func_code, w, expected)
  122. w.reset()
  123. self.assertWarning(f.func_code >= g.func_code, w, expected)
  124. w.reset()
  125. self.assertWarning(f.func_code > g.func_code, w, expected)
  126. def test_builtin_function_or_method_comparisons(self):
  127. expected = ('builtin_function_or_method '
  128. 'order comparisons not supported in 3.x')
  129. func = eval
  130. meth = {}.get
  131. with check_py3k_warnings() as w:
  132. self.assertWarning(func < meth, w, expected)
  133. w.reset()
  134. self.assertWarning(func > meth, w, expected)
  135. w.reset()
  136. self.assertWarning(meth <= func, w, expected)
  137. w.reset()
  138. self.assertWarning(meth >= func, w, expected)
  139. w.reset()
  140. self.assertNoWarning(meth == func, w)
  141. self.assertNoWarning(meth != func, w)
  142. lam = lambda x: x
  143. self.assertNoWarning(lam == func, w)
  144. self.assertNoWarning(lam != func, w)
  145. def test_frame_attributes(self):
  146. template = "%s has been removed in 3.x"
  147. f = sys._getframe(0)
  148. for attr in ("f_exc_traceback", "f_exc_value", "f_exc_type"):
  149. expected = template % attr
  150. with check_py3k_warnings() as w:
  151. self.assertWarning(getattr(f, attr), w, expected)
  152. w.reset()
  153. self.assertWarning(setattr(f, attr, None), w, expected)
  154. def test_sort_cmp_arg(self):
  155. expected = "the cmp argument is not supported in 3.x"
  156. lst = range(5)
  157. cmp = lambda x,y: -1
  158. with check_py3k_warnings() as w:
  159. self.assertWarning(lst.sort(cmp=cmp), w, expected)
  160. w.reset()
  161. self.assertWarning(sorted(lst, cmp=cmp), w, expected)
  162. w.reset()
  163. self.assertWarning(lst.sort(cmp), w, expected)
  164. w.reset()
  165. self.assertWarning(sorted(lst, cmp), w, expected)
  166. def test_sys_exc_clear(self):
  167. expected = 'sys.exc_clear() not supported in 3.x; use except clauses'
  168. with check_py3k_warnings() as w:
  169. self.assertWarning(sys.exc_clear(), w, expected)
  170. def test_methods_members(self):
  171. expected = '__members__ and __methods__ not supported in 3.x'
  172. class C:
  173. __methods__ = ['a']
  174. __members__ = ['b']
  175. c = C()
  176. with check_py3k_warnings() as w:
  177. self.assertWarning(dir(c), w, expected)
  178. def test_softspace(self):
  179. expected = 'file.softspace not supported in 3.x'
  180. with file(__file__) as f:
  181. with check_py3k_warnings() as w:
  182. self.assertWarning(f.softspace, w, expected)
  183. def set():
  184. f.softspace = 0
  185. with check_py3k_warnings() as w:
  186. self.assertWarning(set(), w, expected)
  187. def test_slice_methods(self):
  188. class Spam(object):
  189. def __getslice__(self, i, j): pass
  190. def __setslice__(self, i, j, what): pass
  191. def __delslice__(self, i, j): pass
  192. class Egg:
  193. def __getslice__(self, i, h): pass
  194. def __setslice__(self, i, j, what): pass
  195. def __delslice__(self, i, j): pass
  196. expected = "in 3.x, __{0}slice__ has been removed; use __{0}item__"
  197. for obj in (Spam(), Egg()):
  198. with check_py3k_warnings() as w:
  199. self.assertWarning(obj[1:2], w, expected.format('get'))
  200. w.reset()
  201. del obj[3:4]
  202. self.assertWarning(None, w, expected.format('del'))
  203. w.reset()
  204. obj[4:5] = "eggs"
  205. self.assertWarning(None, w, expected.format('set'))
  206. def test_tuple_parameter_unpacking(self):
  207. expected = "tuple parameter unpacking has been removed in 3.x"
  208. with check_py3k_warnings((expected, SyntaxWarning)):
  209. exec "def f((a, b)): pass"
  210. def test_buffer(self):
  211. expected = 'buffer() not supported in 3.x'
  212. with check_py3k_warnings() as w:
  213. self.assertWarning(buffer('a'), w, expected)
  214. def test_file_xreadlines(self):
  215. expected = ("f.xreadlines() not supported in 3.x, "
  216. "try 'for line in f' instead")
  217. with file(__file__) as f:
  218. with check_py3k_warnings() as w:
  219. self.assertWarning(f.xreadlines(), w, expected)
  220. def test_hash_inheritance(self):
  221. with check_py3k_warnings() as w:
  222. # With object as the base class
  223. class WarnOnlyCmp(object):
  224. def __cmp__(self, other): pass
  225. self.assertEqual(len(w.warnings), 0)
  226. w.reset()
  227. class WarnOnlyEq(object):
  228. def __eq__(self, other): pass
  229. self.assertEqual(len(w.warnings), 1)
  230. self.assertWarning(None, w,
  231. "Overriding __eq__ blocks inheritance of __hash__ in 3.x")
  232. w.reset()
  233. class WarnCmpAndEq(object):
  234. def __cmp__(self, other): pass
  235. def __eq__(self, other): pass
  236. self.assertEqual(len(w.warnings), 1)
  237. self.assertWarning(None, w,
  238. "Overriding __eq__ blocks inheritance of __hash__ in 3.x")
  239. w.reset()
  240. class NoWarningOnlyHash(object):
  241. def __hash__(self): pass
  242. self.assertEqual(len(w.warnings), 0)
  243. # With an intermediate class in the heirarchy
  244. class DefinesAllThree(object):
  245. def __cmp__(self, other): pass
  246. def __eq__(self, other): pass
  247. def __hash__(self): pass
  248. class WarnOnlyCmp(DefinesAllThree):
  249. def __cmp__(self, other): pass
  250. self.assertEqual(len(w.warnings), 0)
  251. w.reset()
  252. class WarnOnlyEq(DefinesAllThree):
  253. def __eq__(self, other): pass
  254. self.assertEqual(len(w.warnings), 1)
  255. self.assertWarning(None, w,
  256. "Overriding __eq__ blocks inheritance of __hash__ in 3.x")
  257. w.reset()
  258. class WarnCmpAndEq(DefinesAllThree):
  259. def __cmp__(self, other): pass
  260. def __eq__(self, other): pass
  261. self.assertEqual(len(w.warnings), 1)
  262. self.assertWarning(None, w,
  263. "Overriding __eq__ blocks inheritance of __hash__ in 3.x")
  264. w.reset()
  265. class NoWarningOnlyHash(DefinesAllThree):
  266. def __hash__(self): pass
  267. self.assertEqual(len(w.warnings), 0)
  268. def test_operator(self):
  269. from operator import isCallable, sequenceIncludes
  270. callable_warn = ("operator.isCallable() is not supported in 3.x. "
  271. "Use hasattr(obj, '__call__').")
  272. seq_warn = ("operator.sequenceIncludes() is not supported "
  273. "in 3.x. Use operator.contains().")
  274. with check_py3k_warnings() as w:
  275. self.assertWarning(isCallable(self), w, callable_warn)
  276. w.reset()
  277. self.assertWarning(sequenceIncludes(range(3), 2), w, seq_warn)
  278. def test_nonascii_bytes_literals(self):
  279. expected = "non-ascii bytes literals not supported in 3.x"
  280. with check_py3k_warnings((expected, SyntaxWarning)):
  281. exec "b'\xbd'"
  282. class TestStdlibRemovals(unittest.TestCase):
  283. # test.testall not tested as it executes all unit tests as an
  284. # import side-effect.
  285. all_platforms = ('audiodev', 'imputil', 'mutex', 'user', 'new', 'rexec',
  286. 'Bastion', 'compiler', 'dircache', 'mimetools',
  287. 'fpformat', 'ihooks', 'mhlib', 'statvfs', 'htmllib',
  288. 'sgmllib', 'rfc822', 'sunaudio')
  289. inclusive_platforms = {'irix' : ('pure', 'AL', 'al', 'CD', 'cd', 'cddb',
  290. 'cdplayer', 'CL', 'cl', 'DEVICE', 'GL',
  291. 'gl', 'ERRNO', 'FILE', 'FL', 'flp', 'fl',
  292. 'fm', 'GET', 'GLWS', 'imgfile', 'IN',
  293. 'IOCTL', 'jpeg', 'panel', 'panelparser',
  294. 'readcd', 'SV', 'torgb', 'WAIT'),
  295. 'darwin' : ('autoGIL', 'Carbon', 'OSATerminology',
  296. 'icglue', 'Nav',
  297. # MacOS should (and does) give a Py3kWarning, but one of the
  298. # earlier tests already imports the MacOS extension which causes
  299. # this test to fail. Disabling the test for 'MacOS' avoids this
  300. # spurious test failure.
  301. #'MacOS',
  302. 'aepack',
  303. 'aetools', 'aetypes', 'applesingle',
  304. 'appletrawmain', 'appletrunner',
  305. 'argvemulator', 'bgenlocations',
  306. 'EasyDialogs', 'macerrors', 'macostools',
  307. 'findertools', 'FrameWork', 'ic',
  308. 'gensuitemodule', 'icopen', 'macresource',
  309. 'MiniAEFrame', 'pimp', 'PixMapWrapper',
  310. 'terminalcommand', 'videoreader',
  311. '_builtinSuites', 'CodeWarrior',
  312. 'Explorer', 'Finder', 'Netscape',
  313. 'StdSuites', 'SystemEvents', 'Terminal',
  314. 'cfmfile', 'bundlebuilder', 'buildtools',
  315. 'ColorPicker', 'Audio_mac'),
  316. 'sunos5' : ('sunaudiodev', 'SUNAUDIODEV'),
  317. }
  318. optional_modules = ('bsddb185', 'Canvas', 'dl', 'linuxaudiodev', 'imageop',
  319. 'sv', 'bsddb', 'dbhash')
  320. def check_removal(self, module_name, optional=False):
  321. """Make sure the specified module, when imported, raises a
  322. DeprecationWarning and specifies itself in the message."""
  323. if module_name in sys.modules:
  324. mod = sys.modules[module_name]
  325. filename = getattr(mod, '__file__', '')
  326. mod = None
  327. # the module is not implemented in C?
  328. if not filename.endswith(('.py', '.pyc', '.pyo')):
  329. # Issue #23375: If the module was already loaded, reimporting
  330. # the module will not emit again the warning. The warning is
  331. # emited when the module is loaded, but C modules cannot
  332. # unloaded.
  333. if test_support.verbose:
  334. print("Cannot test the Python 3 DeprecationWarning of the "
  335. "%s module, the C module is already loaded"
  336. % module_name)
  337. return
  338. with CleanImport(module_name), warnings.catch_warnings():
  339. warnings.filterwarnings("error", ".+ (module|package) .+ removed",
  340. DeprecationWarning, __name__)
  341. warnings.filterwarnings("error", ".+ removed .+ (module|package)",
  342. DeprecationWarning, __name__)
  343. try:
  344. __import__(module_name, level=0)
  345. except DeprecationWarning as exc:
  346. self.assertIn(module_name, exc.args[0],
  347. "%s warning didn't contain module name"
  348. % module_name)
  349. except ImportError:
  350. if not optional:
  351. self.fail("Non-optional module {0} raised an "
  352. "ImportError.".format(module_name))
  353. else:
  354. # For extension modules, check the __warningregistry__.
  355. # They won't rerun their init code even with CleanImport.
  356. if not check_deprecated_module(module_name):
  357. self.fail("DeprecationWarning not raised for {0}"
  358. .format(module_name))
  359. def test_platform_independent_removals(self):
  360. # Make sure that the modules that are available on all platforms raise
  361. # the proper DeprecationWarning.
  362. for module_name in self.all_platforms:
  363. self.check_removal(module_name)
  364. def test_platform_specific_removals(self):
  365. # Test the removal of platform-specific modules.
  366. for module_name in self.inclusive_platforms.get(sys.platform, []):
  367. self.check_removal(module_name, optional=True)
  368. def test_optional_module_removals(self):
  369. # Test the removal of modules that may or may not be built.
  370. for module_name in self.optional_modules:
  371. self.check_removal(module_name, optional=True)
  372. def test_os_path_walk(self):
  373. msg = "In 3.x, os.path.walk is removed in favor of os.walk."
  374. def dumbo(where, names, args): pass
  375. for path_mod in ("ntpath", "macpath", "os2emxpath", "posixpath"):
  376. mod = __import__(path_mod)
  377. reset_module_registry(mod)
  378. with check_py3k_warnings() as w:
  379. mod.walk("crashers", dumbo, None)
  380. self.assertEqual(str(w.message), msg)
  381. def test_reduce_move(self):
  382. from operator import add
  383. # reduce tests may have already triggered this warning
  384. reset_module_registry(unittest.case)
  385. with warnings.catch_warnings():
  386. warnings.filterwarnings("error", "reduce")
  387. self.assertRaises(DeprecationWarning, reduce, add, range(10))
  388. def test_mutablestring_removal(self):
  389. # UserString.MutableString has been removed in 3.0.
  390. import UserString
  391. # UserString tests may have already triggered this warning
  392. reset_module_registry(UserString)
  393. with warnings.catch_warnings():
  394. warnings.filterwarnings("error", ".*MutableString",
  395. DeprecationWarning)
  396. self.assertRaises(DeprecationWarning, UserString.MutableString)
  397. def test_main():
  398. run_unittest(TestPy3KWarnings,
  399. TestStdlibRemovals)
  400. if __name__ == '__main__':
  401. test_main()