From e3bec8424582819bd44e8bdd0c455b930f31d468 2011-08-29 01:27:08 From: Robert Kern Date: 2011-08-29 01:27:08 Subject: [PATCH] BUG: break out the filename-unquoting from get_py_filename to be used in other contexts. Fix %save, in this respect. --- diff --git a/IPython/core/magic.py b/IPython/core/magic.py index c797cad..8b2d0cc 100644 --- a/IPython/core/magic.py +++ b/IPython/core/magic.py @@ -53,7 +53,7 @@ from IPython.core.prefilter import ESC_MAGIC from IPython.lib.pylabtools import mpl_runner from IPython.testing.skipdoctest import skip_doctest from IPython.utils.io import file_read, nlprint -from IPython.utils.path import get_py_filename +from IPython.utils.path import get_py_filename, unquote_filename from IPython.utils.process import arg_split, abbrev_cwd from IPython.utils.terminal import set_term_title from IPython.utils.text import LSString, SList, format_screen @@ -593,7 +593,7 @@ Currently the magic system has the following functions:\n""" # if not, try the input as a filename if out == 'not found': try: - filename = get_py_filename(parameter_s, sys.platform == 'win32') + filename = get_py_filename(parameter_s) except IOError,msg: print msg return @@ -1369,7 +1369,7 @@ Currently the magic system has the following functions:\n""" namespace = self.shell.user_ns else: # called to run a program by %run -p try: - filename = get_py_filename(arg_lst[0], sys.platform == 'win32') + filename = get_py_filename(arg_lst[0]) except IOError,msg: error(msg) return @@ -1426,10 +1426,12 @@ Currently the magic system has the following functions:\n""" dump_file = opts.D[0] text_file = opts.T[0] if dump_file: + dump_file = unquote_filename(dump_file) prof.dump_stats(dump_file) print '\n*** Profile stats marshalled to file',\ `dump_file`+'.',sys_exit if text_file: + text_file = unquote_filename(text_file) pfile = file(text_file,'w') pfile.write(output) pfile.close() @@ -1558,7 +1560,7 @@ Currently the magic system has the following functions:\n""" mode='list',list_all=1) try: - filename = file_finder(arg_lst[0], sys.platform == 'win32') + filename = file_finder(arg_lst[0]) except IndexError: warn('you must provide at least a filename.') print '\n%run:\n',oinspect.getdoc(self.magic_run) @@ -2071,7 +2073,7 @@ Currently the magic system has the following functions:\n""" it asks for confirmation before overwriting existing files.""" opts,args = self.parse_options(parameter_s,'r',mode='list') - fname, codefrom = args[0], " ".join(args[1:]) + fname, codefrom = unquote_filename(args[0]), " ".join(args[1:]) if not fname.endswith('.py'): fname += '.py' if os.path.isfile(fname): @@ -2111,6 +2113,7 @@ Currently the magic system has the following functions:\n""" %loadpy myscript.py %loadpy http://www.example.com/myscript.py """ + arg_s = unquote_filename(arg_s) if not arg_s.endswith('.py'): raise ValueError('%%load only works with .py files: %s' % arg_s) if arg_s.startswith('http'): @@ -2127,12 +2130,13 @@ Currently the magic system has the following functions:\n""" def make_filename(arg): "Make a filename from the given args" + arg = unquote_filename(arg) try: - filename = get_py_filename(arg, win32=sys.platform == 'win32') + filename = get_py_filename(arg) except IOError: # If it ends with .py but doesn't already exist, assume we want # a new file. - if args.endswith('.py'): + if arg.endswith('.py'): filename = arg else: filename = None @@ -2826,8 +2830,7 @@ Defaulting color scheme to 'NoColor'""" "Use '%%bookmark -l' to see your bookmarks." % ps) # strip extra quotes on Windows, because os.chdir doesn't like them - if sys.platform == 'win32': - ps = ps.strip('\'"') + ps = unquote_filename(ps) # at this point ps should point to the target dir if ps: try: @@ -2870,7 +2873,7 @@ Defaulting color scheme to 'NoColor'""" """ dir_s = self.shell.dir_stack - tgt = os.path.expanduser(parameter_s) + tgt = os.path.expanduser(unquote_filename(parameter_s)) cwd = os.getcwdu().replace(self.home_dir,'~') if tgt: self.magic_cd(parameter_s) @@ -3148,7 +3151,7 @@ Defaulting color scheme to 'NoColor'""" to be Python source and will show it with syntax highlighting. """ try: - filename = get_py_filename(parameter_s, sys.platform == 'win32') + filename = get_py_filename(parameter_s) cont = file_read(filename) except IOError: try: @@ -3531,6 +3534,7 @@ Defaulting color scheme to 'NoColor'""" args = magic_arguments.parse_argstring(self.magic_notebook, s) from IPython.nbformat import current + args.filename = unquote_filename(args.filename) if args.export: fname, name, format = current.parse_filename(args.filename) cells = [] diff --git a/IPython/utils/path.py b/IPython/utils/path.py index f91b12c..ee8d0e7 100644 --- a/IPython/utils/path.py +++ b/IPython/utils/path.py @@ -82,20 +82,32 @@ def get_long_path_name(path): return _get_long_path_name(path) -def get_py_filename(name, win32=False): +def unquote_filename(name, win32=(sys.platform=='win32')): + """ On Windows, remove leading and trailing quotes from filenames. + """ + if win32: + if name.startswith(("'", '"')) and name.endswith(("'", '"')): + name = name[1:-1] + return name + + +def get_py_filename(name, force_win32=None): """Return a valid python filename in the current directory. If the given name is not a file, it adds '.py' and searches again. Raises IOError with an informative message if the file isn't found. - If the win32 argument is True, then apply Windows semantics to the filename. - In particular, remove any quoting that has been applied to it. + On Windows, apply Windows semantics to the filename. In particular, remove + any quoting that has been applied to it. This option can be forced for + testing purposes. """ name = os.path.expanduser(name) - if win32: - if name.startswith(("'", '"')) and name.endswith(("'", '"')): - name = name[1:-1] + if force_win32 is None: + win32 = (sys.platform == 'win32') + else: + win32 = force_win32 + name = unquote_filename(name, win32=win32) if not os.path.isfile(name) and not name.endswith('.py'): name += '.py' if os.path.isfile(name): diff --git a/IPython/utils/tests/test_path.py b/IPython/utils/tests/test_path.py index 2e2a8e4..01ad730 100644 --- a/IPython/utils/tests/test_path.py +++ b/IPython/utils/tests/test_path.py @@ -406,25 +406,38 @@ def test_not_writable_ipdir(): nt.assert_true('WARNING' in pipe.getvalue()) env.pop('IPYTHON_DIR', None) +def test_unquote_filename(): + for win32 in (True, False): + nt.assert_equals(path.unquote_filename('foo.py', win32=win32), 'foo.py') + nt.assert_equals(path.unquote_filename('foo bar.py', win32=win32), 'foo bar.py') + nt.assert_equals(path.unquote_filename('"foo.py"', win32=True), 'foo.py') + nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=True), 'foo bar.py') + nt.assert_equals(path.unquote_filename("'foo.py'", win32=True), 'foo.py') + nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=True), 'foo bar.py') + nt.assert_equals(path.unquote_filename('"foo.py"', win32=False), '"foo.py"') + nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=False), '"foo bar.py"') + nt.assert_equals(path.unquote_filename("'foo.py'", win32=False), "'foo.py'") + nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=False), "'foo bar.py'") + @with_environment def test_get_py_filename(): os.chdir(TMP_TEST_DIR) for win32 in (True, False): with make_tempfile('foo.py'): - nt.assert_equals(path.get_py_filename('foo.py', win32=win32), 'foo.py') - nt.assert_equals(path.get_py_filename('foo', win32=win32), 'foo.py') + nt.assert_equals(path.get_py_filename('foo.py', force_win32=win32), 'foo.py') + nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo.py') with make_tempfile('foo'): - nt.assert_equals(path.get_py_filename('foo', win32=win32), 'foo') - nt.assert_raises(IOError, path.get_py_filename, 'foo.py', win32=win32) - nt.assert_raises(IOError, path.get_py_filename, 'foo', win32=win32) - nt.assert_raises(IOError, path.get_py_filename, 'foo.py', win32=win32) + nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo') + nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32) + nt.assert_raises(IOError, path.get_py_filename, 'foo', force_win32=win32) + nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32) true_fn = 'foo with spaces.py' with make_tempfile(true_fn): - nt.assert_equals(path.get_py_filename('foo with spaces', win32=win32), true_fn) - nt.assert_equals(path.get_py_filename('foo with spaces.py', win32=win32), true_fn) + nt.assert_equals(path.get_py_filename('foo with spaces', force_win32=win32), true_fn) + nt.assert_equals(path.get_py_filename('foo with spaces.py', force_win32=win32), true_fn) if win32: - nt.assert_equals(path.get_py_filename('"foo with spaces.py"', win32=True), true_fn) - nt.assert_equals(path.get_py_filename("'foo with spaces.py'", win32=True), true_fn) + nt.assert_equals(path.get_py_filename('"foo with spaces.py"', force_win32=True), true_fn) + nt.assert_equals(path.get_py_filename("'foo with spaces.py'", force_win32=True), true_fn) else: - nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"', win32=False) - nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'", win32=False) + nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"', force_win32=False) + nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'", force_win32=False)