diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index 07acf5b..27d65a4 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -2257,8 +2257,12 @@ class InteractiveShell(SingletonConfigurable, Magic): exit_ignore : bool (False) If True, then silence SystemExit for non-zero status (it is always silenced for zero status, as it is so common). + raise_exceptions : bool (False) + If True raise exceptions everywhere. Meant for testing. + """ kw.setdefault('exit_ignore', False) + kw.setdefault('raise_exceptions', False) fname = os.path.abspath(os.path.expanduser(fname)) @@ -2288,9 +2292,13 @@ class InteractiveShell(SingletonConfigurable, Magic): # 0 # For other exit status, we show the exception unless # explicitly silenced, but only in short form. + if kw['raise_exceptions']: + raise if status.code not in (0, None) and not kw['exit_ignore']: self.showtraceback(exception_only=True) except: + if kw['raise_exceptions']: + raise self.showtraceback() def safe_execfile_ipy(self, fname): diff --git a/IPython/core/tests/test_interactiveshell.py b/IPython/core/tests/test_interactiveshell.py index cf11845..f736936 100644 --- a/IPython/core/tests/test_interactiveshell.py +++ b/IPython/core/tests/test_interactiveshell.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """Tests for the key interactiveshell module. Historically the main classes in interactiveshell have been under-tested. This @@ -19,7 +20,11 @@ Authors # Imports #----------------------------------------------------------------------------- # stdlib +import os +import shutil +import tempfile import unittest +from os.path import join from StringIO import StringIO from IPython.testing import decorators as dec @@ -193,3 +198,25 @@ class InteractiveShellTestCase(unittest.TestCase): assert name not in ip.user_ns_hidden, name assert ip.user_ns['b'] == 12 ip.reset() + +class TestSafeExecfileNonAsciiPath(unittest.TestCase): + + def setUp(self): + self.BASETESTDIR = tempfile.mkdtemp() + self.TESTDIR = join(self.BASETESTDIR, u"åäö") + os.mkdir(self.TESTDIR) + with open(join(self.TESTDIR, u"åäötestscript.py"), "w") as sfile: + sfile.write("pass\n") + self.oldpath = os.getcwdu() + os.chdir(self.TESTDIR) + self.fname = u"åäötestscript.py" + + + def tearDown(self): + os.chdir(self.oldpath) + shutil.rmtree(self.BASETESTDIR) + + def test_1(self): + """Test safe_execfile with non-ascii path + """ + _ip.shell.safe_execfile(self.fname, raise_exceptions=True) diff --git a/IPython/utils/py3compat.py b/IPython/utils/py3compat.py index 1016e77..68a8681 100644 --- a/IPython/utils/py3compat.py +++ b/IPython/utils/py3compat.py @@ -1,5 +1,6 @@ # coding: utf-8 """Compatibility tricks for Python 3. Mainly to do with unicode.""" +import __builtin__ import functools import sys import re @@ -142,6 +143,7 @@ else: def doctest_refactor_print(func_or_str): return func_or_str + # Abstract u'abc' syntax: @_modify_str_or_docstring def u_format(s): @@ -149,3 +151,22 @@ else: 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): + loc = loc if (loc is not None) else glob + scripttext = __builtin__.open(fname).read() + # 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 + exec compile(scripttext, filename, 'exec') in glob, loc + else: + def execfile(fname, *where): + if isinstance(fname, unicode): + filename = fname.encode(sys.getfilesystemencoding()) + else: + filename = fname + __builtin__.execfile(filename, *where)