1""" 2Tests for the future.standard_library module 3""" 4 5from __future__ import absolute_import, print_function 6from future import standard_library 7from future import utils 8from future.tests.base import unittest, CodeHandler, expectedFailurePY2 9 10import sys 11import tempfile 12import os 13import copy 14import textwrap 15from subprocess import CalledProcessError 16 17 18class TestStandardLibraryReorganization(CodeHandler): 19 20 def setUp(self): 21 self.interpreter = sys.executable 22 standard_library.install_aliases() 23 super(TestStandardLibraryReorganization, self).setUp() 24 25 def tearDown(self): 26 # standard_library.remove_hooks() 27 pass 28 29 def test_can_import_several(self): 30 """ 31 This test failed in v0.12-pre if e.g. 32 future/standard_library/email/header.py contained: 33 34 from future import standard_library 35 standard_library.remove_hooks() 36 """ 37 38 import future.moves.urllib.parse as urllib_parse 39 import future.moves.urllib.request as urllib_request 40 41 import http.server 42 for m in [urllib_parse, urllib_request, http.server]: 43 self.assertTrue(m is not None) 44 45 def test_is_py2_stdlib_module(self): 46 """ 47 Tests whether the internal is_py2_stdlib_module function (called by the 48 sys.modules scrubbing functions) is reliable. 49 """ 50 externalmodules = [standard_library, utils] 51 self.assertTrue(not any([standard_library.is_py2_stdlib_module(module) 52 for module in externalmodules])) 53 54 py2modules = [sys, tempfile, copy, textwrap] 55 if utils.PY2: 56 # Debugging: 57 for module in py2modules: 58 if hasattr(module, '__file__'): 59 print(module.__file__, file=sys.stderr) 60 self.assertTrue(all([standard_library.is_py2_stdlib_module(module) 61 for module in py2modules])) 62 else: 63 self.assertTrue( 64 not any ([standard_library.is_py2_stdlib_module(module) 65 for module in py2modules])) 66 67 # @unittest.skip("No longer relevant") 68 # def test_all_modules_identical(self): 69 # """ 70 # Tests whether all of the old imports in RENAMES are accessible 71 # under their new names. 72 # """ 73 # for (oldname, newname) in standard_library.RENAMES.items(): 74 # if newname == 'winreg' and sys.platform not in ['win32', 'win64']: 75 # continue 76 # if newname in standard_library.REPLACED_MODULES: 77 # # Skip this check for e.g. the stdlib's ``test`` module, 78 # # which we have replaced completely. 79 # continue 80 # oldmod = __import__(oldname) 81 # newmod = __import__(newname) 82 # if '.' not in oldname: 83 # self.assertEqual(oldmod, newmod) 84 85 @expectedFailurePY2 86 def test_suspend_hooks(self): 87 """ 88 Code like the try/except block here appears in Pyflakes v0.6.1. This 89 method tests whether suspend_hooks() works as advertised. 90 """ 91 example_PY2_check = False 92 with standard_library.suspend_hooks(): 93 # An example of fragile import code that we don't want to break: 94 try: 95 import builtins 96 except ImportError: 97 example_PY2_check = True 98 if utils.PY2: 99 self.assertTrue(example_PY2_check) 100 else: 101 self.assertFalse(example_PY2_check) 102 # The import should succeed again now: 103 import builtins 104 105 @expectedFailurePY2 106 def test_disable_hooks(self): 107 """ 108 Tests the old (deprecated) names. These deprecated aliases should be 109 removed by version 1.0 110 """ 111 example_PY2_check = False 112 113 standard_library.enable_hooks() # deprecated name 114 old_meta_path = copy.copy(sys.meta_path) 115 116 standard_library.disable_hooks() 117 standard_library.scrub_future_sys_modules() 118 if utils.PY2: 119 self.assertTrue(len(old_meta_path) == len(sys.meta_path) + 1) 120 else: 121 self.assertTrue(len(old_meta_path) == len(sys.meta_path)) 122 123 # An example of fragile import code that we don't want to break: 124 try: 125 import builtins 126 except ImportError: 127 example_PY2_check = True 128 if utils.PY2: 129 self.assertTrue(example_PY2_check) 130 else: 131 self.assertFalse(example_PY2_check) 132 133 standard_library.install_hooks() 134 135 # Imports should succeed again now: 136 import builtins 137 import html 138 if utils.PY2: 139 self.assertTrue(standard_library.detect_hooks()) 140 self.assertTrue(len(old_meta_path) == len(sys.meta_path)) 141 142 @expectedFailurePY2 143 def test_remove_hooks2(self): 144 """ 145 As above, but with the new names 146 """ 147 example_PY2_check = False 148 149 standard_library.install_hooks() 150 old_meta_path = copy.copy(sys.meta_path) 151 152 standard_library.remove_hooks() 153 standard_library.scrub_future_sys_modules() 154 if utils.PY2: 155 self.assertTrue(len(old_meta_path) == len(sys.meta_path) + 1) 156 else: 157 self.assertTrue(len(old_meta_path) == len(sys.meta_path)) 158 159 # An example of fragile import code that we don't want to break: 160 try: 161 import builtins 162 except ImportError: 163 example_PY2_check = True 164 if utils.PY2: 165 self.assertTrue(example_PY2_check) 166 else: 167 self.assertFalse(example_PY2_check) 168 standard_library.install_hooks() 169 # The import should succeed again now: 170 import builtins 171 self.assertTrue(len(old_meta_path) == len(sys.meta_path)) 172 173 def test_detect_hooks(self): 174 """ 175 Tests whether the future.standard_library.detect_hooks is doing 176 its job. 177 """ 178 standard_library.install_hooks() 179 if utils.PY2: 180 self.assertTrue(standard_library.detect_hooks()) 181 182 meta_path = copy.copy(sys.meta_path) 183 184 standard_library.remove_hooks() 185 if utils.PY2: 186 self.assertEqual(len(meta_path), len(sys.meta_path) + 1) 187 self.assertFalse(standard_library.detect_hooks()) 188 189 @unittest.skipIf(utils.PY3, 'not testing for old urllib on Py3') 190 def test_old_urllib_import(self): 191 """ 192 Tests whether an imported module can import the old urllib package. 193 Importing future.standard_library in a script should be possible and 194 not disrupt any uses of the old Py2 standard library names in modules 195 imported by that script. 196 """ 197 code1 = ''' 198 from future import standard_library 199 with standard_library.suspend_hooks(): 200 import module_importing_old_urllib 201 ''' 202 self._write_test_script(code1, 'runme.py') 203 code2 = ''' 204 import urllib 205 assert 'urlopen' in dir(urllib) 206 print('Import succeeded!') 207 ''' 208 self._write_test_script(code2, 'module_importing_old_urllib.py') 209 output = self._run_test_script('runme.py') 210 print(output) 211 self.assertTrue(True) 212 213 def test_sys_intern(self): 214 """ 215 Py2's builtin intern() has been moved to the sys module. Tests 216 whether sys.intern is available. 217 """ 218 from sys import intern 219 if utils.PY3: 220 self.assertEqual(intern('hello'), 'hello') 221 else: 222 # intern() requires byte-strings on Py2: 223 self.assertEqual(intern(b'hello'), b'hello') 224 225 def test_sys_maxsize(self): 226 """ 227 Tests whether sys.maxsize is available. 228 """ 229 from sys import maxsize 230 self.assertTrue(maxsize > 0) 231 232 def test_itertools_filterfalse(self): 233 """ 234 Tests whether itertools.filterfalse is available. 235 """ 236 from itertools import filterfalse 237 not_div_by_3 = filterfalse(lambda x: x % 3 == 0, range(8)) 238 self.assertEqual(list(not_div_by_3), [1, 2, 4, 5, 7]) 239 240 def test_itertools_zip_longest(self): 241 """ 242 Tests whether itertools.zip_longest is available. 243 """ 244 from itertools import zip_longest 245 a = (1, 2) 246 b = [2, 4, 6] 247 self.assertEqual(list(zip_longest(a, b)), 248 [(1, 2), (2, 4), (None, 6)]) 249 250 def test_ChainMap(self): 251 """ 252 Tests whether collections.ChainMap is available. 253 """ 254 from collections import ChainMap 255 cm = ChainMap() 256 257 @unittest.expectedFailure 258 @unittest.skipIf(utils.PY3, 'generic import tests are for Py2 only') 259 def test_import_failure_from_module(self): 260 """ 261 Tests whether e.g. "import socketserver" succeeds in a module 262 imported by another module that has used and removed the stdlib hooks. 263 We want this to fail; the stdlib hooks should not bleed to imported 264 modules too without their explicitly invoking them. 265 """ 266 code1 = ''' 267 from future import standard_library 268 standard_library.install_hooks() 269 standard_library.remove_hooks() 270 import importme2 271 ''' 272 code2 = ''' 273 import socketserver 274 print('Uh oh. importme2 should have raised an ImportError.') 275 ''' 276 self._write_test_script(code1, 'importme1.py') 277 self._write_test_script(code2, 'importme2.py') 278 with self.assertRaises(CalledProcessError): 279 output = self._run_test_script('importme1.py') 280 281 # Disabled since v0.16.0: 282 # def test_configparser(self): 283 # import configparser 284 285 def test_copyreg(self): 286 import copyreg 287 288 def test_pickle(self): 289 import pickle 290 291 def test_profile(self): 292 import profile 293 294 def test_stringio(self): 295 from io import StringIO 296 s = StringIO(u'test') 297 for method in ['tell', 'read', 'seek', 'close', 'flush']: 298 self.assertTrue(hasattr(s, method)) 299 300 def test_bytesio(self): 301 from io import BytesIO 302 s = BytesIO(b'test') 303 for method in ['tell', 'read', 'seek', 'close', 'flush', 'getvalue']: 304 self.assertTrue(hasattr(s, method)) 305 306 def test_queue(self): 307 import queue 308 q = queue.Queue() 309 q.put('thing') 310 self.assertFalse(q.empty()) 311 312 def test_reprlib(self): 313 import reprlib 314 self.assertTrue(True) 315 316 def test_socketserver(self): 317 import socketserver 318 self.assertTrue(True) 319 320 @unittest.skip("Not testing tkinter import (it may be installed separately from Python)") 321 def test_tkinter(self): 322 import tkinter 323 self.assertTrue(True) 324 325 def test_builtins(self): 326 import builtins 327 self.assertTrue(hasattr(builtins, 'tuple')) 328 329 @unittest.skip("ssl redirect support on pypi isn't working as expected for now ...") 330 def test_urllib_request_ssl_redirect(self): 331 """ 332 This site redirects to https://... 333 It therefore requires ssl support. 334 """ 335 import future.moves.urllib.request as urllib_request 336 from pprint import pprint 337 URL = 'http://pypi.python.org/pypi/{0}/json' 338 package = 'future' 339 r = urllib_request.urlopen(URL.format(package)) 340 # pprint(r.read().decode('utf-8')) 341 self.assertTrue(True) 342 343 def test_moves_urllib_request_http(self): 344 """ 345 This site (python-future.org) uses plain http (as of 2014-09-23). 346 """ 347 import future.moves.urllib.request as urllib_request 348 from pprint import pprint 349 URL = 'http://python-future.org' 350 r = urllib_request.urlopen(URL) 351 data = r.read() 352 self.assertTrue(b'</html>' in data) 353 354 def test_urllib_request_http(self): 355 """ 356 This site (python-future.org) uses plain http (as of 2014-09-23). 357 """ 358 import urllib.request as urllib_request 359 from pprint import pprint 360 URL = 'http://python-future.org' 361 r = urllib_request.urlopen(URL) 362 data = r.read() 363 self.assertTrue(b'</html>' in data) 364 365 def test_html_import(self): 366 import html 367 import html.entities 368 import html.parser 369 self.assertTrue(True) 370 371 def test_http_client_import(self): 372 import http.client 373 self.assertTrue(True) 374 375 def test_other_http_imports(self): 376 import http 377 import http.server 378 import http.cookies 379 import http.cookiejar 380 self.assertTrue(True) 381 382 def test_urllib_imports_moves(self): 383 import future.moves.urllib 384 import future.moves.urllib.parse 385 import future.moves.urllib.request 386 import future.moves.urllib.robotparser 387 import future.moves.urllib.error 388 import future.moves.urllib.response 389 self.assertTrue(True) 390 391 def test_urllib_imports_install_aliases(self): 392 with standard_library.suspend_hooks(): 393 standard_library.install_aliases() 394 import urllib 395 import urllib.parse 396 import urllib.request 397 import urllib.robotparser 398 import urllib.error 399 import urllib.response 400 self.assertTrue(True) 401 402 def test_urllib_imports_cm(self): 403 with standard_library.hooks(): 404 import urllib 405 import urllib.parse 406 import urllib.request 407 import urllib.robotparser 408 import urllib.error 409 import urllib.response 410 self.assertTrue(True) 411 412 def test_urllib_imports_install_hooks(self): 413 standard_library.remove_hooks() 414 standard_library.install_hooks() 415 import urllib 416 import urllib.parse 417 import urllib.request 418 import urllib.robotparser 419 import urllib.error 420 import urllib.response 421 self.assertTrue(True) 422 423 def test_underscore_prefixed_modules(self): 424 import _thread 425 import _dummy_thread 426 import _markupbase 427 self.assertTrue(True) 428 429 def test_reduce(self): 430 """ 431 reduce has been moved to the functools module 432 """ 433 import functools 434 self.assertEqual(functools.reduce(lambda x, y: x+y, range(1, 6)), 15) 435 436 def test_collections_userstuff(self): 437 """ 438 UserDict, UserList, and UserString have been moved to the 439 collections module. 440 """ 441 from collections import UserDict 442 from collections import UserList 443 from collections import UserString 444 self.assertTrue(True) 445 446 def test_reload(self): 447 """ 448 reload has been moved to the imp module 449 """ 450 import imp 451 imp.reload(imp) 452 self.assertTrue(True) 453 454 def test_install_aliases(self): 455 """ 456 Does the install_aliases() interface monkey-patch urllib etc. successfully? 457 """ 458 from future.standard_library import remove_hooks, install_aliases 459 remove_hooks() 460 install_aliases() 461 462 from collections import Counter, OrderedDict # backported to Py2.6 463 from collections import UserDict, UserList, UserString 464 465 # Requires Python dbm support: 466 # import dbm 467 # import dbm.dumb 468 # import dbm.gnu 469 # import dbm.ndbm 470 471 from itertools import filterfalse, zip_longest 472 473 from subprocess import check_output # backported to Py2.6 474 from subprocess import getoutput, getstatusoutput 475 476 from sys import intern 477 478 # test_support may not be available (e.g. on Anaconda Py2.6): 479 # import test.support 480 481 import urllib.error 482 import urllib.parse 483 import urllib.request 484 import urllib.response 485 import urllib.robotparser 486 487 self.assertTrue('urlopen' in dir(urllib.request)) 488 489 490class TestFutureMoves(CodeHandler): 491 def test_future_moves_urllib_request(self): 492 from future.moves.urllib import request as urllib_request 493 functions = ['getproxies', 494 'pathname2url', 495 'proxy_bypass', 496 'quote', 497 'request_host', 498 'splitattr', 499 'splithost', 500 'splitpasswd', 501 'splitport', 502 'splitquery', 503 'splittag', 504 'splittype', 505 'splituser', 506 'splitvalue', 507 'thishost', 508 'to_bytes', 509 'unquote', 510 # 'unquote_to_bytes', # Is there an equivalent in the Py2 stdlib? 511 'unwrap', 512 'url2pathname', 513 'urlcleanup', 514 'urljoin', 515 'urlopen', 516 'urlparse', 517 'urlretrieve', 518 'urlsplit', 519 'urlunparse'] 520 self.assertTrue(all(fn in dir(urllib_request) for fn in functions)) 521 522 def test_future_moves(self): 523 """ 524 Ensure everything is available from the future.moves interface that we 525 claim and expect. (Issue #104). 526 """ 527 from future.moves.collections import Counter, OrderedDict # backported to Py2.6 528 from future.moves.collections import UserDict, UserList, UserString 529 530 from future.moves import configparser 531 from future.moves import copyreg 532 533 from future.moves.itertools import filterfalse, zip_longest 534 535 from future.moves import html 536 import future.moves.html.entities 537 import future.moves.html.parser 538 539 from future.moves import http 540 import future.moves.http.client 541 import future.moves.http.cookies 542 import future.moves.http.cookiejar 543 import future.moves.http.server 544 545 from future.moves import queue 546 547 from future.moves import socketserver 548 549 from future.moves.subprocess import check_output # even on Py2.6 550 from future.moves.subprocess import getoutput, getstatusoutput 551 552 from future.moves.sys import intern 553 554 from future.moves import urllib 555 import future.moves.urllib.error 556 import future.moves.urllib.parse 557 import future.moves.urllib.request 558 import future.moves.urllib.response 559 import future.moves.urllib.robotparser 560 561 try: 562 # Is _winreg available on Py2? If so, ensure future.moves._winreg is available too: 563 import _winreg 564 except ImportError: 565 pass 566 else: 567 from future.moves import winreg 568 569 from future.moves import xmlrpc 570 import future.moves.xmlrpc.client 571 import future.moves.xmlrpc.server 572 573 from future.moves import _dummy_thread 574 from future.moves import _markupbase 575 from future.moves import _thread 576 577 def test_future_moves_dbm(self): 578 """ 579 Do the dbm imports work? 580 """ 581 from future.moves import dbm 582 dbm.ndbm 583 from future.moves.dbm import dumb 584 try: 585 # Is gdbm available on Py2? If so, ensure dbm.gnu is available too: 586 import gdbm 587 except ImportError: 588 pass 589 else: 590 from future.moves.dbm import gnu 591 from future.moves.dbm import ndbm 592 593 594# Running the following tkinter test causes the following bizzare test failure: 595# 596# ====================================================================== 597# FAIL: test_open_default_encoding (future.tests.test_builtins.BuiltinTest) 598# ---------------------------------------------------------------------- 599# Traceback (most recent call last): 600# File "/home/user/Install/BleedingEdge/python-future/future/tests/test_builtins.py", line 1219, in test_open_default_encoding 601# self.assertEqual(fp.encoding, current_locale_encoding) 602# AssertionError: 'ANSI_X3.4-1968' != 'ISO-8859-1' 603# 604# ---------------------------------------------------------------------- 605# 606# def test_future_moves_tkinter(self): 607# """ 608# Do the tkinter imports work? 609# """ 610# from future.moves import tkinter 611# from future.moves.tkinter import dialog 612# from future.moves.tkinter import filedialog 613# from future.moves.tkinter import scrolledtext 614# from future.moves.tkinter import simpledialog 615# from future.moves.tkinter import tix 616# from future.moves.tkinter import constants 617# from future.moves.tkinter import dnd 618# from future.moves.tkinter import colorchooser 619# from future.moves.tkinter import commondialog 620# from future.moves.tkinter import font 621# from future.moves.tkinter import messagebox 622 623if __name__ == '__main__': 624 unittest.main() 625