diff --git a/.gitignore b/.gitignore index e697112..e2f217b 100644 --- a/.gitignore +++ b/.gitignore @@ -21,5 +21,6 @@ __pycache__ .DS_Store \#*# .#* +.cache .coverage *.swp diff --git a/IPython/core/magics/script.py b/IPython/core/magics/script.py index 2ed3112..c0ad8d3 100644 --- a/IPython/core/magics/script.py +++ b/IPython/core/magics/script.py @@ -218,8 +218,8 @@ class ScriptMagics(Magics): print("Error while terminating subprocess (pid=%i): %s" \ % (p.pid, e)) return - out = py3compat.bytes_to_str(out) - err = py3compat.bytes_to_str(err) + out = py3compat.decode(out) + err = py3compat.decode(err) if args.out: self.shell.user_ns[args.out] = out else: diff --git a/IPython/core/tests/test_application.py b/IPython/core/tests/test_application.py index 34cab5b..45d4272 100644 --- a/IPython/core/tests/test_application.py +++ b/IPython/core/tests/test_application.py @@ -10,7 +10,6 @@ from traitlets import Unicode from IPython.core.application import BaseIPythonApplication from IPython.testing import decorators as dec -from IPython.utils import py3compat from IPython.utils.tempdir import TemporaryDirectory diff --git a/IPython/core/tests/test_compilerop.py b/IPython/core/tests/test_compilerop.py index 89c0672..f1f88e4 100644 --- a/IPython/core/tests/test_compilerop.py +++ b/IPython/core/tests/test_compilerop.py @@ -22,7 +22,6 @@ import nose.tools as nt # Our own imports from IPython.core import compilerop -from IPython.utils import py3compat #----------------------------------------------------------------------------- # Test functions diff --git a/IPython/core/tests/test_completerlib.py b/IPython/core/tests/test_completerlib.py index 97b561d..6e2a540 100644 --- a/IPython/core/tests/test_completerlib.py +++ b/IPython/core/tests/test_completerlib.py @@ -17,7 +17,6 @@ from os.path import join import nose.tools as nt from IPython.core.completerlib import magic_run_completer, module_completion -from IPython.utils import py3compat from IPython.utils.tempdir import TemporaryDirectory from IPython.testing.decorators import onlyif_unicode_paths diff --git a/IPython/core/tests/test_history.py b/IPython/core/tests/test_history.py index b292a64..fcc22f1 100644 --- a/IPython/core/tests/test_history.py +++ b/IPython/core/tests/test_history.py @@ -19,7 +19,6 @@ import nose.tools as nt from traitlets.config.loader import Config from IPython.utils.tempdir import TemporaryDirectory from IPython.core.history import HistoryManager, extract_hist_ranges -from IPython.utils import py3compat def setUp(): nt.assert_equal(sys.getdefaultencoding(), "utf-8") diff --git a/IPython/core/tests/test_interactiveshell.py b/IPython/core/tests/test_interactiveshell.py index d275f96..8b93405 100644 --- a/IPython/core/tests/test_interactiveshell.py +++ b/IPython/core/tests/test_interactiveshell.py @@ -17,7 +17,6 @@ import sys import tempfile import unittest from unittest import mock -from io import StringIO from os.path import join @@ -30,7 +29,6 @@ from IPython.testing.decorators import ( ) from IPython.testing import tools as tt from IPython.utils.process import find_cmd -from IPython.utils import py3compat #----------------------------------------------------------------------------- # Globals diff --git a/IPython/core/tests/test_oinspect.py b/IPython/core/tests/test_oinspect.py index b7c2742..d94bbf1 100644 --- a/IPython/core/tests/test_oinspect.py +++ b/IPython/core/tests/test_oinspect.py @@ -19,10 +19,8 @@ from IPython.core.magic import (Magics, magics_class, line_magic, register_line_cell_magic) from decorator import decorator from IPython import get_ipython -from IPython.testing.decorators import skipif from IPython.testing.tools import AssertPrints, AssertNotPrints from IPython.utils.path import compress_user -from IPython.utils import py3compat #----------------------------------------------------------------------------- @@ -40,14 +38,14 @@ ip = get_ipython() # defined, if any code is inserted above, the following line will need to be # updated. Do NOT insert any whitespace between the next line and the function # definition below. -THIS_LINE_NUMBER = 43 # Put here the actual number of this line +THIS_LINE_NUMBER = 41 # Put here the actual number of this line from unittest import TestCase class Test(TestCase): def test_find_source_lines(self): - self.assertEqual(oinspect.find_source_lines(Test.test_find_source_lines), + self.assertEqual(oinspect.find_source_lines(Test.test_find_source_lines), THIS_LINE_NUMBER+6) diff --git a/IPython/core/tests/test_splitinput.py b/IPython/core/tests/test_splitinput.py index 170d923..98b4189 100644 --- a/IPython/core/tests/test_splitinput.py +++ b/IPython/core/tests/test_splitinput.py @@ -3,7 +3,6 @@ import nose.tools as nt from IPython.core.splitinput import split_user_input, LineInfo from IPython.testing import tools as tt -from IPython.utils import py3compat tests = [ ('x=1', ('', '', 'x', '=1')), diff --git a/IPython/core/ultratb.py b/IPython/core/ultratb.py index bce01e9..e1c1cae 100644 --- a/IPython/core/ultratb.py +++ b/IPython/core/ultratb.py @@ -1136,35 +1136,32 @@ class VerboseTB(TBTools): colorsnormal = colors.Normal # used a lot head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal) structured_traceback_parts = [head] - if py3compat.PY3: - chained_exceptions_tb_offset = 0 - lines_of_context = 3 - formatted_exceptions = formatted_exception + chained_exceptions_tb_offset = 0 + lines_of_context = 3 + formatted_exceptions = formatted_exception + exception = self.get_parts_of_chained_exception(evalue) + if exception: + formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__) + etype, evalue, etb = exception + else: + evalue = None + chained_exc_ids = set() + while evalue: + formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context, + chained_exceptions_tb_offset) exception = self.get_parts_of_chained_exception(evalue) - if exception: + + if exception and not id(exception[1]) in chained_exc_ids: + chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__) etype, evalue, etb = exception else: evalue = None - chained_exc_ids = set() - while evalue: - formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context, - chained_exceptions_tb_offset) - exception = self.get_parts_of_chained_exception(evalue) - - if exception and not id(exception[1]) in chained_exc_ids: - chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop - formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__) - etype, evalue, etb = exception - else: - evalue = None - # we want to see exceptions in a reversed order: - # the first exception should be on top - for formatted_exception in reversed(formatted_exceptions): - structured_traceback_parts += formatted_exception - else: - structured_traceback_parts += formatted_exception[0] + # we want to see exceptions in a reversed order: + # the first exception should be on top + for formatted_exception in reversed(formatted_exceptions): + structured_traceback_parts += formatted_exception return structured_traceback_parts diff --git a/IPython/extensions/autoreload.py b/IPython/extensions/autoreload.py index 207d03a..a248c1d 100644 --- a/IPython/extensions/autoreload.py +++ b/IPython/extensions/autoreload.py @@ -116,7 +116,6 @@ import traceback import types import weakref from importlib import import_module -from IPython.utils.py3compat import PY3 from imp import reload from IPython.utils import openpy diff --git a/IPython/lib/security.py b/IPython/lib/security.py index 8429c2a..91a2344 100644 --- a/IPython/lib/security.py +++ b/IPython/lib/security.py @@ -11,7 +11,7 @@ import random # Our own from IPython.core.error import UsageError -from IPython.utils.py3compat import cast_bytes, str_to_bytes +from IPython.utils.py3compat import encode #----------------------------------------------------------------------------- # Globals @@ -65,7 +65,7 @@ def passwd(passphrase=None, algorithm='sha1'): h = hashlib.new(algorithm) salt = ('%0' + str(salt_len) + 'x') % random.getrandbits(4 * salt_len) - h.update(cast_bytes(passphrase, 'utf-8') + str_to_bytes(salt, 'ascii')) + h.update(encode(passphrase, 'utf-8') + encode(salt, 'ascii')) return ':'.join((algorithm, salt, h.hexdigest())) @@ -109,6 +109,6 @@ def passwd_check(hashed_passphrase, passphrase): if len(pw_digest) == 0: return False - h.update(cast_bytes(passphrase, 'utf-8') + cast_bytes(salt, 'ascii')) + h.update(encode(passphrase, 'utf-8') + encode(salt, 'ascii')) return h.hexdigest() == pw_digest diff --git a/IPython/terminal/interactiveshell.py b/IPython/terminal/interactiveshell.py index a7ca2b2..3ebd087 100644 --- a/IPython/terminal/interactiveshell.py +++ b/IPython/terminal/interactiveshell.py @@ -7,7 +7,7 @@ from warnings import warn from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC from IPython.utils import io -from IPython.utils.py3compat import input, cast_unicode_py2 +from IPython.utils.py3compat import input from IPython.utils.terminal import toggle_set_term_title, set_term_title from IPython.utils.process import abbrev_cwd from traitlets import ( @@ -233,7 +233,7 @@ class TerminalInteractiveShell(InteractiveShell): prompt_text = "".join(x[1] for x in self.prompts.in_prompt_tokens()) prompt_continuation = "".join(x[1] for x in self.prompts.continuation_prompt_tokens()) while isp.push_accepts_more(): - line = cast_unicode_py2(input(prompt_text)) + line = input(prompt_text) isp.push(line) prompt_text = prompt_continuation return isp.source_reset() diff --git a/IPython/testing/decorators.py b/IPython/testing/decorators.py index 4dd8a7e..4f13ce5 100644 --- a/IPython/testing/decorators.py +++ b/IPython/testing/decorators.py @@ -31,8 +31,9 @@ we've copied verbatim from numpy. # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. -import sys import os +import shutil +import sys import tempfile import unittest import warnings @@ -48,9 +49,6 @@ from .ipunittest import ipdoctest, ipdocstring # numpy.testing.decorators, we expose all of it here. from IPython.external.decorators import * -# For onlyif_cmd_exists decorator -from IPython.utils.py3compat import which - #----------------------------------------------------------------------------- # Classes and functions #----------------------------------------------------------------------------- @@ -360,7 +358,7 @@ def onlyif_cmds_exist(*commands): Decorator to skip test when at least one of `commands` is not found. """ for cmd in commands: - if not which(cmd): + if not shutil.which(cmd): return skip("This test runs only if command '{0}' " "is installed".format(cmd)) return null_deco @@ -372,7 +370,7 @@ def onlyif_any_cmd_exists(*commands): warnings.warn("The function `onlyif_any_cmd_exists` is deprecated since IPython 4.0", DeprecationWarning, stacklevel=2) for cmd in commands: - if which(cmd): + if shutil.which(cmd): return null_deco return skip("This test runs only if one of the commands {0} " "is installed".format(commands)) diff --git a/IPython/testing/globalipapp.py b/IPython/testing/globalipapp.py index f9b1d3a..bd57adf 100644 --- a/IPython/testing/globalipapp.py +++ b/IPython/testing/globalipapp.py @@ -11,13 +11,13 @@ done. import builtins as builtin_mod import sys +import types import warnings from . import tools from IPython.core import page from IPython.utils import io -from IPython.utils import py3compat from IPython.terminal.interactiveshell import TerminalInteractiveShell @@ -104,9 +104,9 @@ def start_ipython(): # Modify the IPython system call with one that uses getoutput, so that we # can capture subcommands and print them to Python's stdout, otherwise the # doctest machinery would miss them. - shell.system = py3compat.MethodType(xsys, shell) - - shell._showtraceback = py3compat.MethodType(_showtraceback, shell) + shell.system = types.MethodType(xsys, shell) + + shell._showtraceback = types.MethodType(_showtraceback, shell) # IPython is ready, now clean up some global state... diff --git a/IPython/testing/iptest.py b/IPython/testing/iptest.py index c9e9d36..1a302b9 100644 --- a/IPython/testing/iptest.py +++ b/IPython/testing/iptest.py @@ -34,7 +34,7 @@ from nose.plugins import Plugin from nose.util import safe_str from IPython import version_info -from IPython.utils.py3compat import bytes_to_str +from IPython.utils.py3compat import decode from IPython.utils.importstring import import_item from IPython.testing.plugin.ipdoctest import IPythonDoctest from IPython.external.decorators import KnownFailure, knownfailureif @@ -299,8 +299,8 @@ class StreamCapturer(Thread): with self.buffer_lock: self.buffer.write(chunk) if self.echo: - sys.stdout.write(bytes_to_str(chunk)) - + sys.stdout.write(decode(chunk)) + os.close(self.readfd) os.close(self.writefd) diff --git a/IPython/testing/iptestcontroller.py b/IPython/testing/iptestcontroller.py index cbbb91b..ab76f83 100644 --- a/IPython/testing/iptestcontroller.py +++ b/IPython/testing/iptestcontroller.py @@ -24,7 +24,7 @@ from .iptest import ( have, test_group_names as py_test_group_names, test_sections, StreamCapturer, ) from IPython.utils.path import compress_user -from IPython.utils.py3compat import bytes_to_str +from IPython.utils.py3compat import decode from IPython.utils.sysinfo import get_sys_info from IPython.utils.tempdir import TemporaryDirectory @@ -371,7 +371,7 @@ def run_iptestall(options): print(justify('Test group: ' + controller.section, res_string)) if res: controller.print_extra_info() - print(bytes_to_str(controller.stdout)) + print(decode(controller.stdout)) failed.append(controller) if res == -signal.SIGINT: print("Interrupted") diff --git a/IPython/testing/tools.py b/IPython/testing/tools.py index 8eca4f9..b4e570b 100644 --- a/IPython/testing/tools.py +++ b/IPython/testing/tools.py @@ -33,7 +33,6 @@ from IPython.utils.process import get_output_error_code from IPython.utils.text import list_strings from IPython.utils.io import temp_pyfile, Tee from IPython.utils import py3compat -from IPython.utils.encoding import DEFAULT_ENCODING from . import decorators as dec from . import skipdoctest @@ -210,8 +209,8 @@ def ipexec(fname, options=None, commands=()): if not isinstance(v, str): print(k, v) p = Popen(full_cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE, env=env) - out, err = p.communicate(input=py3compat.str_to_bytes('\n'.join(commands)) or None) - out, err = py3compat.bytes_to_str(out), py3compat.bytes_to_str(err) + out, err = p.communicate(input=py3compat.encode('\n'.join(commands)) or None) + out, err = py3compat.decode(out), py3compat.decode(err) # `import readline` causes 'ESC[?1034h' to be output sometimes, # so strip that out before doing comparisons if out: diff --git a/IPython/utils/_process_cli.py b/IPython/utils/_process_cli.py index a7b7b90..89a31c3 100644 --- a/IPython/utils/_process_cli.py +++ b/IPython/utils/_process_cli.py @@ -28,7 +28,7 @@ def _find_cmd(cmd): for path in paths: filename = os.path.join(path, cmd) if System.IO.File.Exists(filename): - return py3compat.bytes_to_str(filename) + return py3compat.decode(filename) raise OSError("command %r not found" % cmd) def system(cmd): diff --git a/IPython/utils/_process_common.py b/IPython/utils/_process_common.py index 204092b..2a647dc 100644 --- a/IPython/utils/_process_common.py +++ b/IPython/utils/_process_common.py @@ -130,7 +130,7 @@ def getoutput(cmd): out = process_handler(cmd, lambda p: p.communicate()[0], subprocess.STDOUT) if out is None: return '' - return py3compat.bytes_to_str(out) + return py3compat.decode(out) def getoutputerror(cmd): @@ -172,7 +172,7 @@ def get_output_error_code(cmd): if out_err is None: return '', '', p.returncode out, err = out_err - return py3compat.bytes_to_str(out), py3compat.bytes_to_str(err), p.returncode + return py3compat.decode(out), py3compat.decode(err), p.returncode def arg_split(s, posix=False, strict=True): """Split a command line's arguments in a shell-like manner. diff --git a/IPython/utils/_process_posix.py b/IPython/utils/_process_posix.py index 5907e7d..f3f93f7 100644 --- a/IPython/utils/_process_posix.py +++ b/IPython/utils/_process_posix.py @@ -36,7 +36,7 @@ def _find_cmd(cmd): path = sp.Popen(['/usr/bin/env', 'which', cmd], stdout=sp.PIPE, stderr=sp.PIPE).communicate()[0] - return py3compat.bytes_to_str(path) + return py3compat.decode(path) class ProcessHandler(object): diff --git a/IPython/utils/_process_win32.py b/IPython/utils/_process_win32.py index bfad1b5..115d412 100644 --- a/IPython/utils/_process_win32.py +++ b/IPython/utils/_process_win32.py @@ -152,7 +152,7 @@ def getoutput(cmd): if out is None: out = b'' - return py3compat.bytes_to_str(out) + return py3compat.decode(out) try: CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW diff --git a/IPython/utils/_process_win32_controller.py b/IPython/utils/_process_win32_controller.py index 4fd2e3c..c2e2329 100644 --- a/IPython/utils/_process_win32_controller.py +++ b/IPython/utils/_process_win32_controller.py @@ -15,9 +15,6 @@ This file is meant to be used by process.py import os, sys, threading import ctypes, msvcrt -# local imports -from . import py3compat - # Win32 API types needed for the API calls from ctypes import POINTER from ctypes.wintypes import HANDLE, HLOCAL, LPVOID, WORD, DWORD, BOOL, \ diff --git a/IPython/utils/process.py b/IPython/utils/process.py index 77b2064..489b7c1 100644 --- a/IPython/utils/process.py +++ b/IPython/utils/process.py @@ -8,6 +8,7 @@ Utilities for working with external processes. import os +import shutil import sys if sys.platform == 'win32': @@ -18,7 +19,6 @@ else: from ._process_posix import system, getoutput, arg_split, check_pid from ._process_common import getoutputerror, get_output_error_code, process_handler -from . import py3compat class FindCmdError(Exception): @@ -44,7 +44,7 @@ def find_cmd(cmd): cmd : str The command line program to look for. """ - path = py3compat.which(cmd) + path = shutil.which(cmd) if path is None: raise FindCmdError('command could not be found: %s' % cmd) return path diff --git a/IPython/utils/py3compat.py b/IPython/utils/py3compat.py index 88602e5..cda007a 100644 --- a/IPython/utils/py3compat.py +++ b/IPython/utils/py3compat.py @@ -143,153 +143,72 @@ def _shutil_which(cmd, mode=os.F_OK | os.X_OK, path=None): return name return None -if sys.version_info[0] >= 3: - PY3 = True - - # keep reference to builtin_mod because the kernel overrides that value - # to forward requests to a frontend. - def input(prompt=''): - return builtin_mod.input(prompt) - - builtin_mod_name = "builtins" - import builtins as builtin_mod - - str_to_unicode = no_code - unicode_to_str = no_code - str_to_bytes = encode - bytes_to_str = decode - cast_bytes_py2 = no_code - cast_unicode_py2 = no_code - buffer_to_bytes_py2 = no_code - - string_types = (str,) - unicode_type = str - - which = shutil.which - - def isidentifier(s, dotted=False): - if dotted: - return all(isidentifier(a) for a in s.split(".")) - return s.isidentifier() - - xrange = range - def iteritems(d): return iter(d.items()) - def itervalues(d): return iter(d.values()) - getcwd = os.getcwd - - MethodType = types.MethodType - - def execfile(fname, glob, loc=None, compiler=None): - loc = loc if (loc is not None) else glob - with open(fname, 'rb') as f: - compiler = compiler or compile - exec(compiler(f.read(), fname, 'exec'), glob, loc) - - # Refactor print statements in doctests. - _print_statement_re = re.compile(r"\bprint (?P.*)$", re.MULTILINE) - def _print_statement_sub(match): - expr = match.groups('expr') - return "print(%s)" % expr - - @_modify_str_or_docstring - def doctest_refactor_print(doc): - """Refactor 'print x' statements in a doctest to print(x) style. 2to3 - unfortunately doesn't pick up on our doctests. - - Can accept a string or a function, so it can be used as a decorator.""" - return _print_statement_re.sub(_print_statement_sub, doc) - - # Abstract u'abc' syntax: - @_modify_str_or_docstring - def u_format(s): - """"{u}'abc'" --> "'abc'" (Python 3) - - Accepts a string or a function, so it can be used as a decorator.""" - return s.format(u='') - - def get_closure(f): - """Get a function's closure attribute""" - return f.__closure__ - -else: - PY3 = False - - # keep reference to builtin_mod because the kernel overrides that value - # to forward requests to a frontend. - def input(prompt=''): - return builtin_mod.raw_input(prompt) - - builtin_mod_name = "__builtin__" - import __builtin__ as builtin_mod - - str_to_unicode = decode - unicode_to_str = encode - str_to_bytes = no_code - bytes_to_str = no_code - cast_bytes_py2 = cast_bytes - cast_unicode_py2 = cast_unicode - buffer_to_bytes_py2 = buffer_to_bytes - - string_types = (str, unicode) - unicode_type = unicode - - import re - _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$") - def isidentifier(s, dotted=False): - if dotted: - return all(isidentifier(a) for a in s.split(".")) - return bool(_name_re.match(s)) - - xrange = xrange - def iteritems(d): return d.iteritems() - def itervalues(d): return d.itervalues() - getcwd = os.getcwdu - - def MethodType(func, instance): - return types.MethodType(func, instance, type(instance)) - - def doctest_refactor_print(func_or_str): - return func_or_str - - def get_closure(f): - """Get a function's closure attribute""" - return f.func_closure - - which = _shutil_which - - # Abstract u'abc' syntax: - @_modify_str_or_docstring - def u_format(s): - """"{u}'abc'" --> "u'abc'" (Python 2) - - Accepts a string or a function, so it can be used as a decorator.""" - return s.format(u='u') - - if sys.platform == 'win32': - def execfile(fname, glob=None, loc=None, compiler=None): - loc = loc if (loc is not None) else glob - scripttext = builtin_mod.open(fname).read()+ '\n' - # compile converts unicode filename to str assuming - # ascii. Let's do the conversion before calling compile - if isinstance(fname, unicode): - filename = unicode_to_str(fname) - else: - filename = fname - compiler = compiler or compile - exec(compiler(scripttext, filename, 'exec'), glob, loc) - - else: - def execfile(fname, glob=None, loc=None, compiler=None): - if isinstance(fname, unicode): - filename = fname.encode(sys.getfilesystemencoding()) - else: - filename = fname - where = [ns for ns in [glob, loc] if ns is not None] - if compiler is None: - builtin_mod.execfile(filename, *where) - else: - scripttext = builtin_mod.open(fname).read().rstrip() + '\n' - exec(compiler(scripttext, filename, 'exec'), glob, loc) +PY3 = True + +# keep reference to builtin_mod because the kernel overrides that value +# to forward requests to a frontend. +def input(prompt=''): + return builtin_mod.input(prompt) + +builtin_mod_name = "builtins" +import builtins as builtin_mod + +str_to_unicode = no_code +unicode_to_str = no_code +str_to_bytes = encode +bytes_to_str = decode +cast_bytes_py2 = no_code +cast_unicode_py2 = no_code +buffer_to_bytes_py2 = no_code + +string_types = (str,) +unicode_type = str + +which = shutil.which + +def isidentifier(s, dotted=False): + if dotted: + return all(isidentifier(a) for a in s.split(".")) + return s.isidentifier() + +xrange = range +def iteritems(d): return iter(d.items()) +def itervalues(d): return iter(d.values()) +getcwd = os.getcwd + +MethodType = types.MethodType + +def execfile(fname, glob, loc=None, compiler=None): + loc = loc if (loc is not None) else glob + with open(fname, 'rb') as f: + compiler = compiler or compile + exec(compiler(f.read(), fname, 'exec'), glob, loc) + +# Refactor print statements in doctests. +_print_statement_re = re.compile(r"\bprint (?P.*)$", re.MULTILINE) +def _print_statement_sub(match): + expr = match.groups('expr') + return "print(%s)" % expr + +@_modify_str_or_docstring +def doctest_refactor_print(doc): + """Refactor 'print x' statements in a doctest to print(x) style. 2to3 + unfortunately doesn't pick up on our doctests. + + Can accept a string or a function, so it can be used as a decorator.""" + return _print_statement_re.sub(_print_statement_sub, doc) + +# Abstract u'abc' syntax: +@_modify_str_or_docstring +def u_format(s): + """"{u}'abc'" --> "'abc'" (Python 3) + + Accepts a string or a function, so it can be used as a decorator.""" + return s.format(u='') + +def get_closure(f): + """Get a function's closure attribute""" + return f.__closure__ PY2 = not PY3 diff --git a/IPython/utils/tokenize2.py b/IPython/utils/tokenize2.py index 9da7f3c..3f653bb 100644 --- a/IPython/utils/tokenize2.py +++ b/IPython/utils/tokenize2.py @@ -91,11 +91,7 @@ Expfloat = r'[0-9]+' + Exponent Floatnumber = group(Pointfloat, Expfloat) Imagnumber = group(r'[0-9]+[jJ]', Floatnumber + r'[jJ]') Number = group(Imagnumber, Floatnumber, Intnumber) - -if sys.version_info.minor >= 3: - StringPrefix = r'(?:[bB][rR]?|[rR][bB]?|[uU])?' -else: - StringPrefix = r'(?:[bB]?[rR]?)?' +StringPrefix = r'(?:[bB][rR]?|[rR][bB]?|[uU])?' # Tail end of ' string. Single = r"[^'\\]*(?:\\.[^'\\]*)*'" @@ -165,20 +161,18 @@ for t in ("'", '"', "bR'", 'bR"', "BR'", 'BR"' ): single_quoted[t] = t -if sys.version_info.minor >= 3: - # Python 3.3 - for _prefix in ['rb', 'rB', 'Rb', 'RB', 'u', 'U']: - _t2 = _prefix+'"""' - endprogs[_t2] = double3prog - triple_quoted[_t2] = _t2 - _t1 = _prefix + "'''" - endprogs[_t1] = single3prog - triple_quoted[_t1] = _t1 - single_quoted[_prefix+'"'] = _prefix+'"' - single_quoted[_prefix+"'"] = _prefix+"'" - del _prefix, _t2, _t1 - endprogs['u'] = None - endprogs['U'] = None +for _prefix in ['rb', 'rB', 'Rb', 'RB', 'u', 'U']: + _t2 = _prefix+'"""' + endprogs[_t2] = double3prog + triple_quoted[_t2] = _t2 + _t1 = _prefix + "'''" + endprogs[_t1] = single3prog + triple_quoted[_t1] = _t1 + single_quoted[_prefix+'"'] = _prefix+'"' + single_quoted[_prefix+"'"] = _prefix+"'" +del _prefix, _t2, _t1 +endprogs['u'] = None +endprogs['U'] = None del _compile diff --git a/setupbase.py b/setupbase.py index 0fedf16..23b3c89 100644 --- a/setupbase.py +++ b/setupbase.py @@ -40,15 +40,9 @@ def oscmd(s): print(">", s) os.system(s) -# Py3 compatibility hacks, without assuming IPython itself is installed with -# the full py3compat machinery. - -try: - execfile -except NameError: - def execfile(fname, globs, locs=None): - locs = locs or globs - exec(compile(open(fname).read(), fname, "exec"), globs, locs) +def execfile(fname, globs, locs=None): + locs = locs or globs + exec(compile(open(fname).read(), fname, "exec"), globs, locs) # A little utility we'll need below, since glob() does NOT allow you to do # exclusion on multiple endings! diff --git a/tox.ini b/tox.ini index 1668ce6..163f8dc 100644 --- a/tox.ini +++ b/tox.ini @@ -10,7 +10,7 @@ ; tox -- --all -j # Runs "iptest --all -j" in every environment [tox] -envlist = py{36,35,34,33,27,py} +envlist = py{36,35,34,33,py} skip_missing_interpreters = True toxworkdir = /tmp/tox_ipython @@ -19,7 +19,7 @@ toxworkdir = /tmp/tox_ipython ; Other IPython/testing dependencies should be in setup.py, not here deps = pypy: https://bitbucket.org/pypy/numpy/get/master.zip - py{36,35,34,33,27}: matplotlib + py{36,35,34,33}: matplotlib .[test] ; It's just to avoid loading the IPython package in the current directory