""" Tests for the future.standard_library module """ from __future__ import absolute_import, print_function from future import standard_library from future import utils from future.tests.base import unittest, CodeHandler, expectedFailurePY2 import sys import tempfile import os import copy import textwrap from subprocess import CalledProcessError class TestStandardLibraryReorganization(CodeHandler): def setUp(self): self.interpreter = sys.executable standard_library.install_aliases() super(TestStandardLibraryReorganization, self).setUp() def tearDown(self): # standard_library.remove_hooks() pass def test_can_import_several(self): """ This test failed in v0.12-pre if e.g. future/standard_library/email/header.py contained: from future import standard_library standard_library.remove_hooks() """ import future.moves.urllib.parse as urllib_parse import future.moves.urllib.request as urllib_request import http.server for m in [urllib_parse, urllib_request, http.server]: self.assertTrue(m is not None) def test_is_py2_stdlib_module(self): """ Tests whether the internal is_py2_stdlib_module function (called by the sys.modules scrubbing functions) is reliable. """ externalmodules = [standard_library, utils] self.assertTrue(not any([standard_library.is_py2_stdlib_module(module) for module in externalmodules])) py2modules = [sys, tempfile, copy, textwrap] if utils.PY2: # Debugging: for module in py2modules: if hasattr(module, '__file__'): print(module.__file__, file=sys.stderr) self.assertTrue(all([standard_library.is_py2_stdlib_module(module) for module in py2modules])) else: self.assertTrue( not any ([standard_library.is_py2_stdlib_module(module) for module in py2modules])) # @unittest.skip("No longer relevant") # def test_all_modules_identical(self): # """ # Tests whether all of the old imports in RENAMES are accessible # under their new names. # """ # for (oldname, newname) in standard_library.RENAMES.items(): # if newname == 'winreg' and sys.platform not in ['win32', 'win64']: # continue # if newname in standard_library.REPLACED_MODULES: # # Skip this check for e.g. the stdlib's ``test`` module, # # which we have replaced completely. # continue # oldmod = __import__(oldname) # newmod = __import__(newname) # if '.' not in oldname: # self.assertEqual(oldmod, newmod) @expectedFailurePY2 def test_suspend_hooks(self): """ Code like the try/except block here appears in Pyflakes v0.6.1. This method tests whether suspend_hooks() works as advertised. """ example_PY2_check = False with standard_library.suspend_hooks(): # An example of fragile import code that we don't want to break: try: import builtins except ImportError: example_PY2_check = True if utils.PY2: self.assertTrue(example_PY2_check) else: self.assertFalse(example_PY2_check) # The import should succeed again now: import builtins @expectedFailurePY2 def test_disable_hooks(self): """ Tests the old (deprecated) names. These deprecated aliases should be removed by version 1.0 """ example_PY2_check = False standard_library.enable_hooks() # deprecated name old_meta_path = copy.copy(sys.meta_path) standard_library.disable_hooks() standard_library.scrub_future_sys_modules() if utils.PY2: self.assertTrue(len(old_meta_path) == len(sys.meta_path) + 1) else: self.assertTrue(len(old_meta_path) == len(sys.meta_path)) # An example of fragile import code that we don't want to break: try: import builtins except ImportError: example_PY2_check = True if utils.PY2: self.assertTrue(example_PY2_check) else: self.assertFalse(example_PY2_check) standard_library.install_hooks() # Imports should succeed again now: import builtins import configparser if utils.PY2: self.assertTrue(standard_library.detect_hooks()) self.assertTrue(len(old_meta_path) == len(sys.meta_path)) @expectedFailurePY2 def test_remove_hooks2(self): """ As above, but with the new names """ example_PY2_check = False standard_library.install_hooks() old_meta_path = copy.copy(sys.meta_path) standard_library.remove_hooks() standard_library.scrub_future_sys_modules() if utils.PY2: self.assertTrue(len(old_meta_path) == len(sys.meta_path) + 1) else: self.assertTrue(len(old_meta_path) == len(sys.meta_path)) # An example of fragile import code that we don't want to break: try: import builtins except ImportError: example_PY2_check = True if utils.PY2: self.assertTrue(example_PY2_check) else: self.assertFalse(example_PY2_check) standard_library.install_hooks() # The import should succeed again now: import builtins self.assertTrue(len(old_meta_path) == len(sys.meta_path)) def test_detect_hooks(self): """ Tests whether the future.standard_library.detect_hooks is doing its job. """ standard_library.install_hooks() if utils.PY2: self.assertTrue(standard_library.detect_hooks()) meta_path = copy.copy(sys.meta_path) standard_library.remove_hooks() if utils.PY2: self.assertEqual(len(meta_path), len(sys.meta_path) + 1) self.assertFalse(standard_library.detect_hooks()) @unittest.skipIf(utils.PY3, 'not testing for old urllib on Py3') def test_old_urllib_import(self): """ Tests whether an imported module can import the old urllib package. Importing future.standard_library in a script should be possible and not disrupt any uses of the old Py2 standard library names in modules imported by that script. """ code1 = ''' from future import standard_library with standard_library.suspend_hooks(): import module_importing_old_urllib ''' self._write_test_script(code1, 'runme.py') code2 = ''' import urllib assert 'urlopen' in dir(urllib) print('Import succeeded!') ''' self._write_test_script(code2, 'module_importing_old_urllib.py') output = self._run_test_script('runme.py') print(output) self.assertTrue(True) def test_sys_intern(self): """ Py2's builtin intern() has been moved to the sys module. Tests whether sys.intern is available. """ from sys import intern if utils.PY3: self.assertEqual(intern('hello'), 'hello') else: # intern() requires byte-strings on Py2: self.assertEqual(intern(b'hello'), b'hello') def test_sys_maxsize(self): """ Tests whether sys.maxsize is available. """ from sys import maxsize self.assertTrue(maxsize > 0) def test_itertools_filterfalse(self): """ Tests whether itertools.filterfalse is available. """ from itertools import filterfalse not_div_by_3 = filterfalse(lambda x: x % 3 == 0, range(8)) self.assertEqual(list(not_div_by_3), [1, 2, 4, 5, 7]) def test_itertools_zip_longest(self): """ Tests whether itertools.zip_longest is available. """ from itertools import zip_longest a = (1, 2) b = [2, 4, 6] self.assertEqual(list(zip_longest(a, b)), [(1, 2), (2, 4), (None, 6)]) @unittest.expectedFailure @unittest.skipIf(utils.PY3, 'generic import tests are for Py2 only') def test_import_failure_from_module(self): """ Tests whether e.g. "import socketserver" succeeds in a module imported by another module that has used and removed the stdlib hooks. We want this to fail; the stdlib hooks should not bleed to imported modules too without their explicitly invoking them. """ code1 = ''' from future import standard_library standard_library.install_hooks() standard_library.remove_hooks() import importme2 ''' code2 = ''' import socketserver print('Uh oh. importme2 should have raised an ImportError.') ''' self._write_test_script(code1, 'importme1.py') self._write_test_script(code2, 'importme2.py') with self.assertRaises(CalledProcessError): output = self._run_test_script('importme1.py') def test_configparser(self): import configparser def test_copyreg(self): import copyreg def test_pickle(self): import pickle def test_profile(self): import profile def test_stringio(self): from io import StringIO s = StringIO(u'test') for method in ['tell', 'read', 'seek', 'close', 'flush']: self.assertTrue(hasattr(s, method)) def test_bytesio(self): from io import BytesIO s = BytesIO(b'test') for method in ['tell', 'read', 'seek', 'close', 'flush', 'getvalue']: self.assertTrue(hasattr(s, method)) def test_queue(self): import queue q = queue.Queue() q.put('thing') self.assertFalse(q.empty()) def test_reprlib(self): import reprlib self.assertTrue(True) def test_socketserver(self): import socketserver self.assertTrue(True) @unittest.skip("Not testing tkinter import (it may be installed separately from Python)") def test_tkinter(self): import tkinter self.assertTrue(True) def test_builtins(self): import builtins self.assertTrue(hasattr(builtins, 'tuple')) # @unittest.skip("ssl support has been stripped out for now ...") def test_urllib_request_ssl_redirect(self): """ This site redirects to https://... It therefore requires ssl support. """ import future.moves.urllib.request as urllib_request from pprint import pprint URL = 'http://pypi.python.org/pypi/{0}/json' package = 'future' r = urllib_request.urlopen(URL.format(package)) # pprint(r.read().decode('utf-8')) self.assertTrue(True) def test_urllib_request_http(self): """ This site (python-future.org) uses plain http (as of 2014-09-23). """ import future.moves.urllib.request as urllib_request from pprint import pprint URL = 'http://python-future.org' r = urllib_request.urlopen(URL) data = r.read() self.assertTrue(b'</html>' in data) def test_html_import(self): import html import html.entities import html.parser self.assertTrue(True) def test_http_client_import(self): import http.client self.assertTrue(True) def test_other_http_imports(self): import http import http.server import http.cookies import http.cookiejar self.assertTrue(True) def test_urllib_imports_moves(self): import future.moves.urllib import future.moves.urllib.parse import future.moves.urllib.request import future.moves.urllib.robotparser import future.moves.urllib.error import future.moves.urllib.response self.assertTrue(True) def test_urllib_imports_install_aliases(self): with standard_library.suspend_hooks(): standard_library.install_aliases() import urllib import urllib.parse import urllib.request import urllib.robotparser import urllib.error import urllib.response self.assertTrue(True) def test_urllib_imports_cm(self): with standard_library.hooks(): import urllib import urllib.parse import urllib.request import urllib.robotparser import urllib.error import urllib.response self.assertTrue(True) def test_urllib_imports_install_hooks(self): standard_library.remove_hooks() standard_library.install_hooks() import urllib import urllib.parse import urllib.request import urllib.robotparser import urllib.error import urllib.response self.assertTrue(True) def test_underscore_prefixed_modules(self): import _thread import _dummy_thread import _markupbase self.assertTrue(True) def test_reduce(self): """ reduce has been moved to the functools module """ import functools self.assertEqual(functools.reduce(lambda x, y: x+y, range(1, 6)), 15) def test_collections_userstuff(self): """ UserDict, UserList, and UserString have been moved to the collections module. """ from collections import UserDict from collections import UserList from collections import UserString self.assertTrue(True) def test_reload(self): """ reload has been moved to the imp module """ import imp imp.reload(imp) self.assertTrue(True) def test_install_aliases(self): """ Does the install_aliases() interface monkey-patch urllib etc. successfully? """ from future.standard_library import remove_hooks, install_aliases remove_hooks() install_aliases() from collections import Counter, OrderedDict # backported to Py2.6 from collections import UserDict, UserList, UserString # Requires Python dbm support: # import dbm # import dbm.dumb # import dbm.gnu # import dbm.ndbm from itertools import filterfalse, zip_longest from subprocess import check_output # backported to Py2.6 from subprocess import getoutput, getstatusoutput from sys import intern # test_support may not be available (e.g. on Anaconda Py2.6): # import test.support import urllib.error import urllib.parse import urllib.request import urllib.response import urllib.robotparser self.assertTrue('urlopen' in dir(urllib.request)) class TestFutureMoves(CodeHandler): def test_future_moves_urllib_request(self): from future.moves.urllib import request as urllib_request functions = ['getproxies', 'pathname2url', 'proxy_bypass', 'quote', 'request_host', 'splitattr', 'splithost', 'splitpasswd', 'splitport', 'splitquery', 'splittag', 'splittype', 'splituser', 'splitvalue', 'thishost', 'to_bytes', 'unquote', # 'unquote_to_bytes', # Is there an equivalent in the Py2 stdlib? 'unwrap', 'url2pathname', 'urlcleanup', 'urljoin', 'urlopen', 'urlparse', 'urlretrieve', 'urlsplit', 'urlunparse'] self.assertTrue(all(fn in dir(urllib_request) for fn in functions)) def test_future_moves(self): """ Ensure everything is available from the future.moves interface that we claim and expect. (Issue #104). """ from future.moves.collections import Counter, OrderedDict # backported to Py2.6 from future.moves.collections import UserDict, UserList, UserString from future.moves import configparser from future.moves import copyreg from future.moves.itertools import filterfalse, zip_longest from future.moves import html import future.moves.html.entities import future.moves.html.parser from future.moves import http import future.moves.http.client import future.moves.http.cookies import future.moves.http.cookiejar import future.moves.http.server from future.moves import queue from future.moves import socketserver from future.moves.subprocess import check_output # even on Py2.6 from future.moves.subprocess import getoutput, getstatusoutput from future.moves.sys import intern from future.moves import urllib import future.moves.urllib.error import future.moves.urllib.parse import future.moves.urllib.request import future.moves.urllib.response import future.moves.urllib.robotparser try: # Is _winreg available on Py2? If so, ensure future.moves._winreg is available too: import _winreg except ImportError: pass else: from future.moves import winreg from future.moves import xmlrpc import future.moves.xmlrpc.client import future.moves.xmlrpc.server from future.moves import _dummy_thread from future.moves import _markupbase from future.moves import _thread def test_future_moves_dbm(self): """ Do the dbm imports work? """ from future.moves import dbm dbm.ndbm from future.moves.dbm import dumb try: # Is gdbm available on Py2? If so, ensure dbm.gnu is available too: import gdbm except ImportError: pass else: from future.moves.dbm import gnu from future.moves.dbm import ndbm # Running the following tkinter test causes the following bizzare test failure: # # ====================================================================== # FAIL: test_open_default_encoding (future.tests.test_builtins.BuiltinTest) # ---------------------------------------------------------------------- # Traceback (most recent call last): # File "/home/user/Install/BleedingEdge/python-future/future/tests/test_builtins.py", line 1219, in test_open_default_encoding # self.assertEqual(fp.encoding, current_locale_encoding) # AssertionError: 'ANSI_X3.4-1968' != 'ISO-8859-1' # # ---------------------------------------------------------------------- # # def test_future_moves_tkinter(self): # """ # Do the tkinter imports work? # """ # from future.moves import tkinter # from future.moves.tkinter import dialog # from future.moves.tkinter import filedialog # from future.moves.tkinter import scrolledtext # from future.moves.tkinter import simpledialog # from future.moves.tkinter import tix # from future.moves.tkinter import constants # from future.moves.tkinter import dnd # from future.moves.tkinter import colorchooser # from future.moves.tkinter import commondialog # from future.moves.tkinter import font # from future.moves.tkinter import messagebox if __name__ == '__main__': unittest.main()