##// END OF EJS Templates
On Windows, quote paths instead of escaping them.
Antony Lee -
Show More
@@ -117,9 +117,14 def has_open_quotes(s):
117
117
118 def protect_filename(s):
118 def protect_filename(s):
119 """Escape a string to protect certain characters."""
119 """Escape a string to protect certain characters."""
120 if set(s) & set(PROTECTABLES):
121 if sys.platform == "win32":
122 return '"' + s + '"'
123 else:
124 return "".join("\\" + c if c in PROTECTABLES else c for c in s)
125 else:
126 return s
120
127
121 return "".join([(ch in PROTECTABLES and '\\' + ch or ch)
122 for ch in s])
123
128
124 def expand_user(path):
129 def expand_user(path):
125 """Expand '~'-style usernames in strings.
130 """Expand '~'-style usernames in strings.
@@ -67,7 +67,7 from IPython.utils.decorators import undoc
67 from IPython.utils.io import ask_yes_no
67 from IPython.utils.io import ask_yes_no
68 from IPython.utils.ipstruct import Struct
68 from IPython.utils.ipstruct import Struct
69 from IPython.paths import get_ipython_dir
69 from IPython.paths import get_ipython_dir
70 from IPython.utils.path import get_home_dir, get_py_filename, unquote_filename, ensure_dir_exists
70 from IPython.utils.path import get_home_dir, get_py_filename, ensure_dir_exists
71 from IPython.utils.process import system, getoutput
71 from IPython.utils.process import system, getoutput
72 from IPython.utils.py3compat import (builtin_mod, unicode_type, string_types,
72 from IPython.utils.py3compat import (builtin_mod, unicode_type, string_types,
73 with_metaclass, iteritems)
73 with_metaclass, iteritems)
@@ -3139,10 +3139,9 class InteractiveShell(SingletonConfigurable):
3139 code = self.extract_input_lines(target, raw=raw) # Grab history
3139 code = self.extract_input_lines(target, raw=raw) # Grab history
3140 if code:
3140 if code:
3141 return code
3141 return code
3142 utarget = unquote_filename(target)
3143 try:
3142 try:
3144 if utarget.startswith(('http://', 'https://')):
3143 if target.startswith(('http://', 'https://')):
3145 return openpy.read_py_url(utarget, skip_encoding_cookie=skip_encoding_cookie)
3144 return openpy.read_py_url(target, skip_encoding_cookie=skip_encoding_cookie)
3146 except UnicodeDecodeError:
3145 except UnicodeDecodeError:
3147 if not py_only :
3146 if not py_only :
3148 # Deferred import
3147 # Deferred import
@@ -3152,7 +3151,7 class InteractiveShell(SingletonConfigurable):
3152 from urllib import urlopen
3151 from urllib import urlopen
3153 response = urlopen(target)
3152 response = urlopen(target)
3154 return response.read().decode('latin1')
3153 return response.read().decode('latin1')
3155 raise ValueError(("'%s' seem to be unreadable.") % utarget)
3154 raise ValueError(("'%s' seem to be unreadable.") % target)
3156
3155
3157 potential_target = [target]
3156 potential_target = [target]
3158 try :
3157 try :
@@ -13,7 +13,6 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
13 from IPython.utils.text import format_screen, dedent, indent
13 from IPython.utils.text import format_screen, dedent, indent
14 from IPython.testing.skipdoctest import skip_doctest
14 from IPython.testing.skipdoctest import skip_doctest
15 from IPython.utils.ipstruct import Struct
15 from IPython.utils.ipstruct import Struct
16 from IPython.utils.path import unquote_filename
17 from IPython.utils.py3compat import unicode_type
16 from IPython.utils.py3compat import unicode_type
18 from warnings import warn
17 from warnings import warn
19 from logging import error
18 from logging import error
@@ -598,7 +597,6 Defaulting color scheme to 'NoColor'"""
598 args = magic_arguments.parse_argstring(self.notebook, s)
597 args = magic_arguments.parse_argstring(self.notebook, s)
599
598
600 from nbformat import write, v4
599 from nbformat import write, v4
601 args.filename = unquote_filename(args.filename)
602 if args.export:
600 if args.export:
603 cells = []
601 cells = []
604 hist = list(self.shell.history_manager.get_range())
602 hist = list(self.shell.history_manager.get_range())
@@ -32,7 +32,7 from IPython.testing.skipdoctest import skip_doctest
32 from IPython.utils import py3compat
32 from IPython.utils import py3compat
33 from IPython.utils.py3compat import string_types
33 from IPython.utils.py3compat import string_types
34 from IPython.utils.contexts import preserve_keys
34 from IPython.utils.contexts import preserve_keys
35 from IPython.utils.path import get_py_filename, unquote_filename
35 from IPython.utils.path import get_py_filename
36 from warnings import warn
36 from warnings import warn
37 from logging import error
37 from logging import error
38 from IPython.utils.text import get_text_list
38 from IPython.utils.text import get_text_list
@@ -189,7 +189,7 class CodeMagics(Magics):
189 append = 'a' in opts
189 append = 'a' in opts
190 mode = 'a' if append else 'w'
190 mode = 'a' if append else 'w'
191 ext = u'.ipy' if raw else u'.py'
191 ext = u'.ipy' if raw else u'.py'
192 fname, codefrom = unquote_filename(args[0]), " ".join(args[1:])
192 fname, codefrom = args[0], " ".join(args[1:])
193 if not fname.endswith((u'.py',u'.ipy')):
193 if not fname.endswith((u'.py',u'.ipy')):
194 fname += ext
194 fname += ext
195 file_exists = os.path.isfile(fname)
195 file_exists = os.path.isfile(fname)
@@ -369,7 +369,6 class CodeMagics(Magics):
369
369
370 def make_filename(arg):
370 def make_filename(arg):
371 "Make a filename from the given args"
371 "Make a filename from the given args"
372 arg = unquote_filename(arg)
373 try:
372 try:
374 filename = get_py_filename(arg)
373 filename = get_py_filename(arg)
375 except IOError:
374 except IOError:
@@ -42,7 +42,7 from IPython.utils.contexts import preserve_keys
42 from IPython.utils.capture import capture_output
42 from IPython.utils.capture import capture_output
43 from IPython.utils.ipstruct import Struct
43 from IPython.utils.ipstruct import Struct
44 from IPython.utils.module_paths import find_mod
44 from IPython.utils.module_paths import find_mod
45 from IPython.utils.path import get_py_filename, unquote_filename, shellglob
45 from IPython.utils.path import get_py_filename, shellglob
46 from IPython.utils.timing import clock, clock2
46 from IPython.utils.timing import clock, clock2
47 from warnings import warn
47 from warnings import warn
48 from logging import error
48 from logging import error
@@ -338,12 +338,10 python-profiler package from non-free.""")
338 dump_file = opts.D[0]
338 dump_file = opts.D[0]
339 text_file = opts.T[0]
339 text_file = opts.T[0]
340 if dump_file:
340 if dump_file:
341 dump_file = unquote_filename(dump_file)
342 prof.dump_stats(dump_file)
341 prof.dump_stats(dump_file)
343 print('\n*** Profile stats marshalled to file',\
342 print('\n*** Profile stats marshalled to file',\
344 repr(dump_file)+'.',sys_exit)
343 repr(dump_file)+'.',sys_exit)
345 if text_file:
344 if text_file:
346 text_file = unquote_filename(text_file)
347 pfile = open(text_file,'w')
345 pfile = open(text_file,'w')
348 pfile.write(output)
346 pfile.write(output)
349 pfile.close()
347 pfile.close()
@@ -34,7 +34,6 from IPython.core.magic import (
34 )
34 )
35 from IPython.testing.skipdoctest import skip_doctest
35 from IPython.testing.skipdoctest import skip_doctest
36 from IPython.utils.openpy import source_to_unicode
36 from IPython.utils.openpy import source_to_unicode
37 from IPython.utils.path import unquote_filename
38 from IPython.utils.process import abbrev_cwd
37 from IPython.utils.process import abbrev_cwd
39 from IPython.utils import py3compat
38 from IPython.utils import py3compat
40 from IPython.utils.py3compat import unicode_type
39 from IPython.utils.py3compat import unicode_type
@@ -324,10 +323,7 class OSMagics(Magics):
324
323
325
324
326 else:
325 else:
327 #turn all non-space-escaping backslashes to slashes,
326 opts, ps = self.parse_options(parameter_s, 'qb', mode='string')
328 # for c:\windows\directory\names\
329 parameter_s = re.sub(r'\\(?! )','/', parameter_s)
330 opts,ps = self.parse_options(parameter_s,'qb',mode='string')
331 # jump to previous
327 # jump to previous
332 if ps == '-':
328 if ps == '-':
333 try:
329 try:
@@ -348,8 +344,6 class OSMagics(Magics):
348 raise UsageError("Bookmark '%s' not found. "
344 raise UsageError("Bookmark '%s' not found. "
349 "Use '%%bookmark -l' to see your bookmarks." % ps)
345 "Use '%%bookmark -l' to see your bookmarks." % ps)
350
346
351 # strip extra quotes on Windows, because os.chdir doesn't like them
352 ps = unquote_filename(ps)
353 # at this point ps should point to the target dir
347 # at this point ps should point to the target dir
354 if ps:
348 if ps:
355 try:
349 try:
@@ -443,7 +437,7 class OSMagics(Magics):
443 """
437 """
444
438
445 dir_s = self.shell.dir_stack
439 dir_s = self.shell.dir_stack
446 tgt = os.path.expanduser(unquote_filename(parameter_s))
440 tgt = os.path.expanduser(parameter_s)
447 cwd = py3compat.getcwd().replace(self.shell.home_dir,'~')
441 cwd = py3compat.getcwd().replace(self.shell.home_dir,'~')
448 if tgt:
442 if tgt:
449 self.cd(parameter_s)
443 self.cd(parameter_s)
@@ -781,8 +775,8 class OSMagics(Magics):
781 The file will be overwritten unless the -a (--append) flag is specified.
775 The file will be overwritten unless the -a (--append) flag is specified.
782 """
776 """
783 args = magic_arguments.parse_argstring(self.writefile, line)
777 args = magic_arguments.parse_argstring(self.writefile, line)
784 filename = os.path.expanduser(unquote_filename(args.filename))
778 filename = os.path.expanduser(args.filename)
785
779
786 if os.path.exists(filename):
780 if os.path.exists(filename):
787 if args.append:
781 if args.append:
788 print("Appending to %s" % filename)
782 print("Appending to %s" % filename)
@@ -36,32 +36,38 def greedy_completion():
36 ip.Completer.greedy = greedy_original
36 ip.Completer.greedy = greedy_original
37
37
38 def test_protect_filename():
38 def test_protect_filename():
39 pairs = [ ('abc','abc'),
39 if sys.platform == 'win32':
40 (' abc',r'\ abc'),
40 pairs = [ ('abc','abc'),
41 ('a bc',r'a\ bc'),
41 (' abc',"' abc'"),
42 ('a bc',r'a\ \ bc'),
42 ('a bc',"'a bc'"),
43 (' bc',r'\ \ bc'),
43 ('a bc',"'a bc'"),
44 ]
44 (' bc',"' bc'"),
45 # On posix, we also protect parens and other special characters
45 ]
46 if sys.platform != 'win32':
46 else:
47 pairs.extend( [('a(bc',r'a\(bc'),
47 pairs = [ ('abc','abc'),
48 ('a)bc',r'a\)bc'),
48 (' abc',r'\ abc'),
49 ('a( )bc',r'a\(\ \)bc'),
49 ('a bc',r'a\ bc'),
50 ('a[1]bc', r'a\[1\]bc'),
50 ('a bc',r'a\ \ bc'),
51 ('a{1}bc', r'a\{1\}bc'),
51 (' bc',r'\ \ bc'),
52 ('a#bc', r'a\#bc'),
52 # On posix, we also protect parens and other special characters
53 ('a?bc', r'a\?bc'),
53 ('a(bc',r'a\(bc'),
54 ('a=bc', r'a\=bc'),
54 ('a)bc',r'a\)bc'),
55 ('a\\bc', r'a\\bc'),
55 ('a( )bc',r'a\(\ \)bc'),
56 ('a|bc', r'a\|bc'),
56 ('a[1]bc', r'a\[1\]bc'),
57 ('a;bc', r'a\;bc'),
57 ('a{1}bc', r'a\{1\}bc'),
58 ('a:bc', r'a\:bc'),
58 ('a#bc', r'a\#bc'),
59 ("a'bc", r"a\'bc"),
59 ('a?bc', r'a\?bc'),
60 ('a*bc', r'a\*bc'),
60 ('a=bc', r'a\=bc'),
61 ('a"bc', r'a\"bc'),
61 ('a\\bc', r'a\\bc'),
62 ('a^bc', r'a\^bc'),
62 ('a|bc', r'a\|bc'),
63 ('a&bc', r'a\&bc'),
63 ('a;bc', r'a\;bc'),
64 ] )
64 ('a:bc', r'a\:bc'),
65 ("a'bc", r"a\'bc"),
66 ('a*bc', r'a\*bc'),
67 ('a"bc', r'a\"bc'),
68 ('a^bc', r'a\^bc'),
69 ('a&bc', r'a\&bc'),
70 ]
65 # run the actual tests
71 # run the actual tests
66 for s1, s2 in pairs:
72 for s1, s2 in pairs:
67 s1p = completer.protect_filename(s1)
73 s1p = completer.protect_filename(s1)
@@ -74,11 +74,13 def get_long_path_name(path):
74 def unquote_filename(name, win32=(sys.platform=='win32')):
74 def unquote_filename(name, win32=(sys.platform=='win32')):
75 """ On Windows, remove leading and trailing quotes from filenames.
75 """ On Windows, remove leading and trailing quotes from filenames.
76 """
76 """
77 warn("'unquote_filename' is deprecated", DeprecationWarning)
77 if win32:
78 if win32:
78 if name.startswith(("'", '"')) and name.endswith(("'", '"')):
79 if name.startswith(("'", '"')) and name.endswith(("'", '"')):
79 name = name[1:-1]
80 name = name[1:-1]
80 return name
81 return name
81
82
83
82 def compress_user(path):
84 def compress_user(path):
83 """Reverse of :func:`os.path.expanduser`
85 """Reverse of :func:`os.path.expanduser`
84 """
86 """
@@ -302,19 +302,6 def test_not_writable_ipdir():
302 ipdir = paths.get_ipython_dir()
302 ipdir = paths.get_ipython_dir()
303 env.pop('IPYTHON_DIR', None)
303 env.pop('IPYTHON_DIR', None)
304
304
305 def test_unquote_filename():
306 for win32 in (True, False):
307 nt.assert_equal(path.unquote_filename('foo.py', win32=win32), 'foo.py')
308 nt.assert_equal(path.unquote_filename('foo bar.py', win32=win32), 'foo bar.py')
309 nt.assert_equal(path.unquote_filename('"foo.py"', win32=True), 'foo.py')
310 nt.assert_equal(path.unquote_filename('"foo bar.py"', win32=True), 'foo bar.py')
311 nt.assert_equal(path.unquote_filename("'foo.py'", win32=True), 'foo.py')
312 nt.assert_equal(path.unquote_filename("'foo bar.py'", win32=True), 'foo bar.py')
313 nt.assert_equal(path.unquote_filename('"foo.py"', win32=False), '"foo.py"')
314 nt.assert_equal(path.unquote_filename('"foo bar.py"', win32=False), '"foo bar.py"')
315 nt.assert_equal(path.unquote_filename("'foo.py'", win32=False), "'foo.py'")
316 nt.assert_equal(path.unquote_filename("'foo bar.py'", win32=False), "'foo bar.py'")
317
318 @with_environment
305 @with_environment
319 def test_get_py_filename():
306 def test_get_py_filename():
320 os.chdir(TMP_TEST_DIR)
307 os.chdir(TMP_TEST_DIR)
General Comments 0
You need to be logged in to leave comments. Login now