##// END OF EJS Templates
Merge branch 'win32-shlex'
Thomas Kluyver -
r5539:d1997d96 merge
parent child Browse files
Show More
@@ -15,6 +15,7 of subprocess utilities, and it contains tools that are common to all of them.
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17 import subprocess
18 import shlex
18 19 import sys
19 20
20 21 from IPython.utils import py3compat
@@ -143,3 +144,27 def getoutputerror(cmd):
143 144 return '', ''
144 145 out, err = out_err
145 146 return py3compat.bytes_to_str(out), py3compat.bytes_to_str(err)
147
148
149 def arg_split(s, posix=False):
150 """Split a command line's arguments in a shell-like manner.
151
152 This is a modified version of the standard library's shlex.split()
153 function, but with a default of posix=False for splitting, so that quotes
154 in inputs are respected."""
155
156 # Unfortunately, python's shlex module is buggy with unicode input:
157 # http://bugs.python.org/issue1170
158 # At least encoding the input when it's unicode seems to help, but there
159 # may be more problems lurking. Apparently this is fixed in python3.
160 is_unicode = False
161 if (not py3compat.PY3) and isinstance(s, unicode):
162 is_unicode = True
163 s = s.encode('utf-8')
164 lex = shlex.shlex(s, posix=posix)
165 lex.whitespace_split = True
166 tokens = list(lex)
167 if is_unicode:
168 # Convert the tokens back to unicode.
169 tokens = [x.decode('utf-8') for x in tokens]
170 return tokens
@@ -23,7 +23,7 from IPython.external import pexpect
23 23
24 24 # Our own
25 25 from .autoattr import auto_attr
26 from ._process_common import getoutput
26 from ._process_common import getoutput, arg_split
27 27 from IPython.utils import text
28 28 from IPython.utils import py3compat
29 29
@@ -192,3 +192,6 class ProcessHandler(object):
192 192 # programs think they are talking to a tty and produce highly formatted output
193 193 # (ls is a good example) that makes them hard.
194 194 system = ProcessHandler().system
195
196
197
@@ -18,11 +18,15 from __future__ import print_function
18 18 # stdlib
19 19 import os
20 20 import sys
21 import ctypes
21 22
23 from ctypes import c_int, POINTER
24 from ctypes.wintypes import LPCWSTR, HLOCAL
22 25 from subprocess import STDOUT
23 26
24 27 # our own imports
25 28 from ._process_common import read_no_interrupt, process_handler
29 from . import py3compat
26 30 from . import text
27 31
28 32 #-----------------------------------------------------------------------------
@@ -146,3 +150,29 def getoutput(cmd):
146 150 if out is None:
147 151 out = ''
148 152 return out
153
154 try:
155 CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW
156 CommandLineToArgvW.arg_types = [LPCWSTR, POINTER(c_int)]
157 CommandLineToArgvW.res_types = [POINTER(LPCWSTR)]
158 LocalFree = ctypes.windll.kernel32.LocalFree
159 LocalFree.res_type = HLOCAL
160 LocalFree.arg_types = [HLOCAL]
161
162 def arg_split(commandline, posix=False):
163 """Split a command line's arguments in a shell-like manner.
164
165 This is a special version for windows that use a ctypes call to CommandLineToArgvW
166 to do the argv splitting. The posix paramter is ignored.
167 """
168 #CommandLineToArgvW returns path to executable if called with empty string.
169 if commandline.strip() == "":
170 return []
171 argvn = c_int()
172 result_pointer = CommandLineToArgvW(py3compat.cast_unicode(commandline.lstrip()), ctypes.byref(argvn))
173 result_array_type = LPCWSTR * argvn.value
174 result = [arg for arg in result_array_type.from_address(result_pointer)]
175 retval = LocalFree(result_pointer)
176 return result
177 except AttributeError:
178 from ._process_common import arg_split
@@ -22,9 +22,10 import shlex
22 22
23 23 # Our own
24 24 if sys.platform == 'win32':
25 from ._process_win32 import _find_cmd, system, getoutput, AvoidUNCPath
25 from ._process_win32 import _find_cmd, system, getoutput, AvoidUNCPath, arg_split
26 26 else:
27 from ._process_posix import _find_cmd, system, getoutput
27 from ._process_posix import _find_cmd, system, getoutput, arg_split
28
28 29
29 30 from ._process_common import getoutputerror
30 31 from IPython.utils import py3compat
@@ -103,31 +104,6 def pycmd2argv(cmd):
103 104 else:
104 105 return [sys.executable, cmd]
105 106
106
107 def arg_split(s, posix=False):
108 """Split a command line's arguments in a shell-like manner.
109
110 This is a modified version of the standard library's shlex.split()
111 function, but with a default of posix=False for splitting, so that quotes
112 in inputs are respected."""
113
114 # Unfortunately, python's shlex module is buggy with unicode input:
115 # http://bugs.python.org/issue1170
116 # At least encoding the input when it's unicode seems to help, but there
117 # may be more problems lurking. Apparently this is fixed in python3.
118 is_unicode = False
119 if (not py3compat.PY3) and isinstance(s, unicode):
120 is_unicode = True
121 s = s.encode('utf-8')
122 lex = shlex.shlex(s, posix=posix)
123 lex.whitespace_split = True
124 tokens = list(lex)
125 if is_unicode:
126 # Convert the tokens back to unicode.
127 tokens = [x.decode('utf-8') for x in tokens]
128 return tokens
129
130
131 107 def abbrev_cwd():
132 108 """ Return abbreviated version of cwd, e.g. d:mydir """
133 109 cwd = os.getcwdu().replace('\\','/')
@@ -62,17 +62,33 def test_find_cmd_fail():
62 62 nt.assert_raises(FindCmdError,find_cmd,'asdfasdf')
63 63
64 64
65 @dec.skip_win32
65 66 def test_arg_split():
66 67 """Ensure that argument lines are correctly split like in a shell."""
67 68 tests = [['hi', ['hi']],
68 69 [u'hi', [u'hi']],
69 70 ['hello there', ['hello', 'there']],
70 [u'h\N{LATIN SMALL LETTER A WITH CARON}llo', [u'h\N{LATIN SMALL LETTER A WITH CARON}llo']],
71 # \u01ce == \N{LATIN SMALL LETTER A WITH CARON}
72 # Do not use \N because the tests crash with syntax error in
73 # some cases, for example windows python2.6.
74 [u'h\u01cello', [u'h\u01cello']],
71 75 ['something "with quotes"', ['something', '"with quotes"']],
72 76 ]
73 77 for argstr, argv in tests:
74 78 nt.assert_equal(arg_split(argstr), argv)
75 79
80 @dec.skip_if_not_win32
81 def test_arg_split_win32():
82 """Ensure that argument lines are correctly split like in a shell."""
83 tests = [['hi', ['hi']],
84 [u'hi', [u'hi']],
85 ['hello there', ['hello', 'there']],
86 [u'h\u01cello', [u'h\u01cello']],
87 ['something "with quotes"', ['something', 'with quotes']],
88 ]
89 for argstr, argv in tests:
90 nt.assert_equal(arg_split(argstr), argv)
91
76 92
77 93 class SubProcessTestCase(TestCase, tt.TempFileMixin):
78 94 def setUp(self):
@@ -100,6 +116,10 class SubProcessTestCase(TestCase, tt.TempFileMixin):
100 116 def test_getoutput_quoted(self):
101 117 out = getoutput('python -c "print (1)"')
102 118 self.assertEquals(out.strip(), '1')
119
120 #Invalid quoting on windows
121 @dec.skip_win32
122 def test_getoutput_quoted2(self):
103 123 out = getoutput("python -c 'print (1)'")
104 124 self.assertEquals(out.strip(), '1')
105 125 out = getoutput("python -c 'print (\"1\")'")
General Comments 0
You need to be logged in to leave comments. Login now