Show More
@@ -18,6 +18,7 b' from __future__ import print_function' | |||
|
18 | 18 | # Stdlib |
|
19 | 19 | import subprocess as sp |
|
20 | 20 | import sys |
|
21 | import shlex | |
|
21 | 22 | |
|
22 | 23 | from IPython.external import pexpect |
|
23 | 24 | |
@@ -192,3 +193,29 b' class ProcessHandler(object):' | |||
|
192 | 193 | # programs think they are talking to a tty and produce highly formatted output |
|
193 | 194 | # (ls is a good example) that makes them hard. |
|
194 | 195 | system = ProcessHandler().system |
|
196 | ||
|
197 | def arg_split(s, posix=False): | |
|
198 | """Split a command line's arguments in a shell-like manner. | |
|
199 | ||
|
200 | This is a modified version of the standard library's shlex.split() | |
|
201 | function, but with a default of posix=False for splitting, so that quotes | |
|
202 | in inputs are respected.""" | |
|
203 | ||
|
204 | # Unfortunately, python's shlex module is buggy with unicode input: | |
|
205 | # http://bugs.python.org/issue1170 | |
|
206 | # At least encoding the input when it's unicode seems to help, but there | |
|
207 | # may be more problems lurking. Apparently this is fixed in python3. | |
|
208 | is_unicode = False | |
|
209 | if (not py3compat.PY3) and isinstance(s, unicode): | |
|
210 | is_unicode = True | |
|
211 | s = s.encode('utf-8') | |
|
212 | lex = shlex.shlex(s, posix=posix) | |
|
213 | lex.whitespace_split = True | |
|
214 | tokens = list(lex) | |
|
215 | if is_unicode: | |
|
216 | # Convert the tokens back to unicode. | |
|
217 | tokens = [x.decode('utf-8') for x in tokens] | |
|
218 | return tokens | |
|
219 | ||
|
220 | ||
|
221 |
@@ -18,11 +18,15 b' 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,27 b' def getoutput(cmd):' | |||
|
146 | 150 | if out is None: |
|
147 | 151 | out = '' |
|
148 | 152 | return out |
|
153 | ||
|
154 | ||
|
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 |
@@ -22,18 +22,10 b' import shlex' | |||
|
22 | 22 | |
|
23 | 23 | # Our own |
|
24 | 24 | if sys.platform == 'win32': |
|
25 | import ctypes | |
|
26 | from ctypes.wintypes import LPCWSTR, HLOCAL | |
|
27 | from ctypes import c_int, POINTER | |
|
28 | from ._process_win32 import _find_cmd, system, getoutput, AvoidUNCPath | |
|
29 | CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW | |
|
30 | CommandLineToArgvW.arg_types = [LPCWSTR, POINTER(c_int)] | |
|
31 | CommandLineToArgvW.res_types = [POINTER(LPCWSTR)] | |
|
32 | LocalFree = ctypes.windll.kernel32.LocalFree | |
|
33 | LocalFree.res_type = HLOCAL | |
|
34 | LocalFree.arg_types = [HLOCAL] | |
|
25 | from ._process_win32 import _find_cmd, system, getoutput, AvoidUNCPath, arg_split | |
|
35 | 26 | else: |
|
36 | from ._process_posix import _find_cmd, system, getoutput | |
|
27 | from ._process_posix import _find_cmd, system, getoutput, arg_split | |
|
28 | ||
|
37 | 29 | |
|
38 | 30 | from ._process_common import getoutputerror |
|
39 | 31 | from IPython.utils import py3compat |
@@ -112,44 +104,6 b' def pycmd2argv(cmd):' | |||
|
112 | 104 | else: |
|
113 | 105 | return [sys.executable, cmd] |
|
114 | 106 | |
|
115 | if sys.platform == 'win32': | |
|
116 | def arg_split(commandline, posix=False): | |
|
117 | """Split a command line's arguments in a shell-like manner. | |
|
118 | ||
|
119 | This is a special version for windows that use a ctypes call to CommandLineToArgvW | |
|
120 | to do the argv splitting. The posix paramter is ignored. | |
|
121 | """ | |
|
122 | argvn = c_int() | |
|
123 | result_pointer = CommandLineToArgvW(py3compat.str_to_unicode(commandline.lstrip()), ctypes.byref(argvn)) | |
|
124 | result_array_type = LPCWSTR * argvn.value | |
|
125 | result = [arg for arg in result_array_type.from_address(result_pointer)] | |
|
126 | retval = LocalFree(result_pointer) | |
|
127 | return result | |
|
128 | else: | |
|
129 | def arg_split(s, posix=False): | |
|
130 | """Split a command line's arguments in a shell-like manner. | |
|
131 | ||
|
132 | This is a modified version of the standard library's shlex.split() | |
|
133 | function, but with a default of posix=False for splitting, so that quotes | |
|
134 | in inputs are respected.""" | |
|
135 | ||
|
136 | # Unfortunately, python's shlex module is buggy with unicode input: | |
|
137 | # http://bugs.python.org/issue1170 | |
|
138 | # At least encoding the input when it's unicode seems to help, but there | |
|
139 | # may be more problems lurking. Apparently this is fixed in python3. | |
|
140 | is_unicode = False | |
|
141 | if (not py3compat.PY3) and isinstance(s, unicode): | |
|
142 | is_unicode = True | |
|
143 | s = s.encode('utf-8') | |
|
144 | lex = shlex.shlex(s, posix=posix) | |
|
145 | lex.whitespace_split = True | |
|
146 | tokens = list(lex) | |
|
147 | if is_unicode: | |
|
148 | # Convert the tokens back to unicode. | |
|
149 | tokens = [x.decode('utf-8') for x in tokens] | |
|
150 | return tokens | |
|
151 | ||
|
152 | ||
|
153 | 107 | def abbrev_cwd(): |
|
154 | 108 | """ Return abbreviated version of cwd, e.g. d:mydir """ |
|
155 | 109 | cwd = os.getcwdu().replace('\\','/') |
@@ -68,7 +68,10 b' def test_arg_split():' | |||
|
68 | 68 | tests = [['hi', ['hi']], |
|
69 | 69 | [u'hi', [u'hi']], |
|
70 | 70 | ['hello there', ['hello', 'there']], |
|
71 | # [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']], | |
|
72 | 75 | ['something "with quotes"', ['something', '"with quotes"']], |
|
73 | 76 | ] |
|
74 | 77 | for argstr, argv in tests: |
@@ -80,7 +83,7 b' def test_arg_split_win32():' | |||
|
80 | 83 | tests = [['hi', ['hi']], |
|
81 | 84 | [u'hi', [u'hi']], |
|
82 | 85 | ['hello there', ['hello', 'there']], |
|
83 | # [u'h\N{LATIN SMALL LETTER A WITH CARON}llo', [u'h\N{LATIN SMALL LETTER A WITH CARON}llo']], | |
|
86 | [u'h\u01cello', [u'h\u01cello']], | |
|
84 | 87 | ['something "with quotes"', ['something', 'with quotes']], |
|
85 | 88 | ] |
|
86 | 89 | for argstr, argv in tests: |
General Comments 0
You need to be logged in to leave comments.
Login now