##// END OF EJS Templates
Moved arg_split to _process_win32.py and _process_posix.py.
Jörgen Stenarson -
Show More
@@ -1,194 +1,221 b''
1 1 """Posix-specific implementation of process utilities.
2 2
3 3 This file is only meant to be imported by process.py, not by end-users.
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2010-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from __future__ import print_function
17 17
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
24 25 # Our own
25 26 from .autoattr import auto_attr
26 27 from ._process_common import getoutput
27 28 from IPython.utils import text
28 29 from IPython.utils import py3compat
29 30
30 31 #-----------------------------------------------------------------------------
31 32 # Function definitions
32 33 #-----------------------------------------------------------------------------
33 34
34 35 def _find_cmd(cmd):
35 36 """Find the full path to a command using which."""
36 37
37 38 path = sp.Popen(['/usr/bin/env', 'which', cmd],
38 39 stdout=sp.PIPE).communicate()[0]
39 40 return py3compat.bytes_to_str(path)
40 41
41 42
42 43 class ProcessHandler(object):
43 44 """Execute subprocesses under the control of pexpect.
44 45 """
45 46 # Timeout in seconds to wait on each reading of the subprocess' output.
46 47 # This should not be set too low to avoid cpu overusage from our side,
47 48 # since we read in a loop whose period is controlled by this timeout.
48 49 read_timeout = 0.05
49 50
50 51 # Timeout to give a process if we receive SIGINT, between sending the
51 52 # SIGINT to the process and forcefully terminating it.
52 53 terminate_timeout = 0.2
53 54
54 55 # File object where stdout and stderr of the subprocess will be written
55 56 logfile = None
56 57
57 58 # Shell to call for subprocesses to execute
58 59 sh = None
59 60
60 61 @auto_attr
61 62 def sh(self):
62 63 sh = pexpect.which('sh')
63 64 if sh is None:
64 65 raise OSError('"sh" shell not found')
65 66 return sh
66 67
67 68 def __init__(self, logfile=None, read_timeout=None, terminate_timeout=None):
68 69 """Arguments are used for pexpect calls."""
69 70 self.read_timeout = (ProcessHandler.read_timeout if read_timeout is
70 71 None else read_timeout)
71 72 self.terminate_timeout = (ProcessHandler.terminate_timeout if
72 73 terminate_timeout is None else
73 74 terminate_timeout)
74 75 self.logfile = sys.stdout if logfile is None else logfile
75 76
76 77 def getoutput(self, cmd):
77 78 """Run a command and return its stdout/stderr as a string.
78 79
79 80 Parameters
80 81 ----------
81 82 cmd : str
82 83 A command to be executed in the system shell.
83 84
84 85 Returns
85 86 -------
86 87 output : str
87 88 A string containing the combination of stdout and stderr from the
88 89 subprocess, in whatever order the subprocess originally wrote to its
89 90 file descriptors (so the order of the information in this string is the
90 91 correct order as would be seen if running the command in a terminal).
91 92 """
92 93 try:
93 94 return pexpect.run(self.sh, args=['-c', cmd]).replace('\r\n', '\n')
94 95 except KeyboardInterrupt:
95 96 print('^C', file=sys.stderr, end='')
96 97
97 98 def getoutput_pexpect(self, cmd):
98 99 """Run a command and return its stdout/stderr as a string.
99 100
100 101 Parameters
101 102 ----------
102 103 cmd : str
103 104 A command to be executed in the system shell.
104 105
105 106 Returns
106 107 -------
107 108 output : str
108 109 A string containing the combination of stdout and stderr from the
109 110 subprocess, in whatever order the subprocess originally wrote to its
110 111 file descriptors (so the order of the information in this string is the
111 112 correct order as would be seen if running the command in a terminal).
112 113 """
113 114 try:
114 115 return pexpect.run(self.sh, args=['-c', cmd]).replace('\r\n', '\n')
115 116 except KeyboardInterrupt:
116 117 print('^C', file=sys.stderr, end='')
117 118
118 119 def system(self, cmd):
119 120 """Execute a command in a subshell.
120 121
121 122 Parameters
122 123 ----------
123 124 cmd : str
124 125 A command to be executed in the system shell.
125 126
126 127 Returns
127 128 -------
128 129 int : child's exitstatus
129 130 """
130 131 # Get likely encoding for the output.
131 132 enc = text.getdefaultencoding()
132 133
133 134 # Patterns to match on the output, for pexpect. We read input and
134 135 # allow either a short timeout or EOF
135 136 patterns = [pexpect.TIMEOUT, pexpect.EOF]
136 137 # the index of the EOF pattern in the list.
137 138 # even though we know it's 1, this call means we don't have to worry if
138 139 # we change the above list, and forget to change this value:
139 140 EOF_index = patterns.index(pexpect.EOF)
140 141 # The size of the output stored so far in the process output buffer.
141 142 # Since pexpect only appends to this buffer, each time we print we
142 143 # record how far we've printed, so that next time we only print *new*
143 144 # content from the buffer.
144 145 out_size = 0
145 146 try:
146 147 # Since we're not really searching the buffer for text patterns, we
147 148 # can set pexpect's search window to be tiny and it won't matter.
148 149 # We only search for the 'patterns' timeout or EOF, which aren't in
149 150 # the text itself.
150 151 #child = pexpect.spawn(pcmd, searchwindowsize=1)
151 152 if hasattr(pexpect, 'spawnb'):
152 153 child = pexpect.spawnb(self.sh, args=['-c', cmd]) # Pexpect-U
153 154 else:
154 155 child = pexpect.spawn(self.sh, args=['-c', cmd]) # Vanilla Pexpect
155 156 flush = sys.stdout.flush
156 157 while True:
157 158 # res is the index of the pattern that caused the match, so we
158 159 # know whether we've finished (if we matched EOF) or not
159 160 res_idx = child.expect_list(patterns, self.read_timeout)
160 161 print(child.before[out_size:].decode(enc, 'replace'), end='')
161 162 flush()
162 163 if res_idx==EOF_index:
163 164 break
164 165 # Update the pointer to what we've already printed
165 166 out_size = len(child.before)
166 167 except KeyboardInterrupt:
167 168 # We need to send ^C to the process. The ascii code for '^C' is 3
168 169 # (the character is known as ETX for 'End of Text', see
169 170 # curses.ascii.ETX).
170 171 child.sendline(chr(3))
171 172 # Read and print any more output the program might produce on its
172 173 # way out.
173 174 try:
174 175 out_size = len(child.before)
175 176 child.expect_list(patterns, self.terminate_timeout)
176 177 print(child.before[out_size:].decode(enc, 'replace'), end='')
177 178 sys.stdout.flush()
178 179 except KeyboardInterrupt:
179 180 # Impatient users tend to type it multiple times
180 181 pass
181 182 finally:
182 183 # Ensure the subprocess really is terminated
183 184 child.terminate(force=True)
184 185 # add isalive check, to ensure exitstatus is set:
185 186 child.isalive()
186 187 return child.exitstatus
187 188
188 189
189 190 # Make system() with a functional interface for outside use. Note that we use
190 191 # getoutput() from the _common utils, which is built on top of popen(). Using
191 192 # pexpect to get subprocess output produces difficult to parse output, since
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
@@ -1,148 +1,176 b''
1 1 """Windows-specific implementation of process utilities.
2 2
3 3 This file is only meant to be imported by process.py, not by end-users.
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2010-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from __future__ import print_function
17 17
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 #-----------------------------------------------------------------------------
29 33 # Function definitions
30 34 #-----------------------------------------------------------------------------
31 35
32 36 class AvoidUNCPath(object):
33 37 """A context manager to protect command execution from UNC paths.
34 38
35 39 In the Win32 API, commands can't be invoked with the cwd being a UNC path.
36 40 This context manager temporarily changes directory to the 'C:' drive on
37 41 entering, and restores the original working directory on exit.
38 42
39 43 The context manager returns the starting working directory *if* it made a
40 44 change and None otherwise, so that users can apply the necessary adjustment
41 45 to their system calls in the event of a change.
42 46
43 47 Example
44 48 -------
45 49 ::
46 50 cmd = 'dir'
47 51 with AvoidUNCPath() as path:
48 52 if path is not None:
49 53 cmd = '"pushd %s &&"%s' % (path, cmd)
50 54 os.system(cmd)
51 55 """
52 56 def __enter__(self):
53 57 self.path = os.getcwdu()
54 58 self.is_unc_path = self.path.startswith(r"\\")
55 59 if self.is_unc_path:
56 60 # change to c drive (as cmd.exe cannot handle UNC addresses)
57 61 os.chdir("C:")
58 62 return self.path
59 63 else:
60 64 # We return None to signal that there was no change in the working
61 65 # directory
62 66 return None
63 67
64 68 def __exit__(self, exc_type, exc_value, traceback):
65 69 if self.is_unc_path:
66 70 os.chdir(self.path)
67 71
68 72
69 73 def _find_cmd(cmd):
70 74 """Find the full path to a .bat or .exe using the win32api module."""
71 75 try:
72 76 from win32api import SearchPath
73 77 except ImportError:
74 78 raise ImportError('you need to have pywin32 installed for this to work')
75 79 else:
76 80 PATH = os.environ['PATH']
77 81 extensions = ['.exe', '.com', '.bat', '.py']
78 82 path = None
79 83 for ext in extensions:
80 84 try:
81 85 path = SearchPath(PATH, cmd + ext)[0]
82 86 except:
83 87 pass
84 88 if path is None:
85 89 raise OSError("command %r not found" % cmd)
86 90 else:
87 91 return path
88 92
89 93
90 94 def _system_body(p):
91 95 """Callback for _system."""
92 96 enc = text.getdefaultencoding()
93 97 for line in read_no_interrupt(p.stdout).splitlines():
94 98 line = line.decode(enc, 'replace')
95 99 print(line, file=sys.stdout)
96 100 for line in read_no_interrupt(p.stderr).splitlines():
97 101 line = line.decode(enc, 'replace')
98 102 print(line, file=sys.stderr)
99 103
100 104 # Wait to finish for returncode
101 105 return p.wait()
102 106
103 107
104 108 def system(cmd):
105 109 """Win32 version of os.system() that works with network shares.
106 110
107 111 Note that this implementation returns None, as meant for use in IPython.
108 112
109 113 Parameters
110 114 ----------
111 115 cmd : str
112 116 A command to be executed in the system shell.
113 117
114 118 Returns
115 119 -------
116 120 None : we explicitly do NOT return the subprocess status code, as this
117 121 utility is meant to be used extensively in IPython, where any return value
118 122 would trigger :func:`sys.displayhook` calls.
119 123 """
120 124 with AvoidUNCPath() as path:
121 125 if path is not None:
122 126 cmd = '"pushd %s &&"%s' % (path, cmd)
123 127 return process_handler(cmd, _system_body)
124 128
125 129
126 130 def getoutput(cmd):
127 131 """Return standard output of executing cmd in a shell.
128 132
129 133 Accepts the same arguments as os.system().
130 134
131 135 Parameters
132 136 ----------
133 137 cmd : str
134 138 A command to be executed in the system shell.
135 139
136 140 Returns
137 141 -------
138 142 stdout : str
139 143 """
140 144
141 145 with AvoidUNCPath() as path:
142 146 if path is not None:
143 147 cmd = '"pushd %s &&"%s' % (path, cmd)
144 148 out = process_handler(cmd, lambda p: p.communicate()[0], STDOUT)
145 149
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
@@ -1,169 +1,123 b''
1 1 # encoding: utf-8
2 2 """
3 3 Utilities for working with external processes.
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from __future__ import print_function
17 17
18 18 # Stdlib
19 19 import os
20 20 import sys
21 21 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
40 32
41 33 #-----------------------------------------------------------------------------
42 34 # Code
43 35 #-----------------------------------------------------------------------------
44 36
45 37
46 38 class FindCmdError(Exception):
47 39 pass
48 40
49 41
50 42 def find_cmd(cmd):
51 43 """Find absolute path to executable cmd in a cross platform manner.
52 44
53 45 This function tries to determine the full path to a command line program
54 46 using `which` on Unix/Linux/OS X and `win32api` on Windows. Most of the
55 47 time it will use the version that is first on the users `PATH`. If
56 48 cmd is `python` return `sys.executable`.
57 49
58 50 Warning, don't use this to find IPython command line programs as there
59 51 is a risk you will find the wrong one. Instead find those using the
60 52 following code and looking for the application itself::
61 53
62 54 from IPython.utils.path import get_ipython_module_path
63 55 from IPython.utils.process import pycmd2argv
64 56 argv = pycmd2argv(get_ipython_module_path('IPython.frontend.terminal.ipapp'))
65 57
66 58 Parameters
67 59 ----------
68 60 cmd : str
69 61 The command line program to look for.
70 62 """
71 63 if cmd == 'python':
72 64 return os.path.abspath(sys.executable)
73 65 try:
74 66 path = _find_cmd(cmd).rstrip()
75 67 except OSError:
76 68 raise FindCmdError('command could not be found: %s' % cmd)
77 69 # which returns empty if not found
78 70 if path == '':
79 71 raise FindCmdError('command could not be found: %s' % cmd)
80 72 return os.path.abspath(path)
81 73
82 74
83 75 def pycmd2argv(cmd):
84 76 r"""Take the path of a python command and return a list (argv-style).
85 77
86 78 This only works on Python based command line programs and will find the
87 79 location of the ``python`` executable using ``sys.executable`` to make
88 80 sure the right version is used.
89 81
90 82 For a given path ``cmd``, this returns [cmd] if cmd's extension is .exe,
91 83 .com or .bat, and [, cmd] otherwise.
92 84
93 85 Parameters
94 86 ----------
95 87 cmd : string
96 88 The path of the command.
97 89
98 90 Returns
99 91 -------
100 92 argv-style list.
101 93 """
102 94 ext = os.path.splitext(cmd)[1]
103 95 if ext in ['.exe', '.com', '.bat']:
104 96 return [cmd]
105 97 else:
106 98 if sys.platform == 'win32':
107 99 # The -u option here turns on unbuffered output, which is required
108 100 # on Win32 to prevent wierd conflict and problems with Twisted.
109 101 # Also, use sys.executable to make sure we are picking up the
110 102 # right python exe.
111 103 return [sys.executable, '-u', 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('\\','/')
156 110 drivepart = ''
157 111 tail = cwd
158 112 if sys.platform == 'win32':
159 113 if len(cwd) < 4:
160 114 return cwd
161 115 drivepart,tail = os.path.splitdrive(cwd)
162 116
163 117
164 118 parts = tail.split('/')
165 119 if len(parts) > 2:
166 120 tail = '/'.join(parts[-2:])
167 121
168 122 return (drivepart + (
169 123 cwd == '/' and '/' or tail))
@@ -1,128 +1,131 b''
1 1 # encoding: utf-8
2 2 """
3 3 Tests for platutils.py
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 import sys
18 18 from unittest import TestCase
19 19
20 20 import nose.tools as nt
21 21
22 22 from IPython.utils.process import (find_cmd, FindCmdError, arg_split,
23 23 system, getoutput, getoutputerror)
24 24 from IPython.testing import decorators as dec
25 25 from IPython.testing import tools as tt
26 26
27 27 #-----------------------------------------------------------------------------
28 28 # Tests
29 29 #-----------------------------------------------------------------------------
30 30
31 31 def test_find_cmd_python():
32 32 """Make sure we find sys.exectable for python."""
33 33 nt.assert_equals(find_cmd('python'), sys.executable)
34 34
35 35
36 36 @dec.skip_win32
37 37 def test_find_cmd_ls():
38 38 """Make sure we can find the full path to ls."""
39 39 path = find_cmd('ls')
40 40 nt.assert_true(path.endswith('ls'))
41 41
42 42
43 43 def has_pywin32():
44 44 try:
45 45 import win32api
46 46 except ImportError:
47 47 return False
48 48 return True
49 49
50 50
51 51 @dec.onlyif(has_pywin32, "This test requires win32api to run")
52 52 def test_find_cmd_pythonw():
53 53 """Try to find pythonw on Windows."""
54 54 path = find_cmd('pythonw')
55 55 nt.assert_true(path.endswith('pythonw.exe'))
56 56
57 57
58 58 @dec.onlyif(lambda : sys.platform != 'win32' or has_pywin32(),
59 59 "This test runs on posix or in win32 with win32api installed")
60 60 def test_find_cmd_fail():
61 61 """Make sure that FindCmdError is raised if we can't find the cmd."""
62 62 nt.assert_raises(FindCmdError,find_cmd,'asdfasdf')
63 63
64 64
65 65 @dec.skip_win32
66 66 def test_arg_split():
67 67 """Ensure that argument lines are correctly split like in a shell."""
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:
75 78 nt.assert_equal(arg_split(argstr), argv)
76 79
77 80 @dec.skip_if_not_win32
78 81 def test_arg_split_win32():
79 82 """Ensure that argument lines are correctly split like in a shell."""
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:
87 90 nt.assert_equal(arg_split(argstr), argv)
88 91
89 92
90 93 class SubProcessTestCase(TestCase, tt.TempFileMixin):
91 94 def setUp(self):
92 95 """Make a valid python temp file."""
93 96 lines = ["from __future__ import print_function",
94 97 "import sys",
95 98 "print('on stdout', end='', file=sys.stdout)",
96 99 "print('on stderr', end='', file=sys.stderr)",
97 100 "sys.stdout.flush()",
98 101 "sys.stderr.flush()"]
99 102 self.mktmp('\n'.join(lines))
100 103
101 104 def test_system(self):
102 105 status = system('python "%s"' % self.fname)
103 106 self.assertEquals(status, 0)
104 107
105 108 def test_system_quotes(self):
106 109 status = system('python -c "import sys"')
107 110 self.assertEquals(status, 0)
108 111
109 112 def test_getoutput(self):
110 113 out = getoutput('python "%s"' % self.fname)
111 114 self.assertEquals(out, 'on stdout')
112 115
113 116 def test_getoutput_quoted(self):
114 117 out = getoutput('python -c "print (1)"')
115 118 self.assertEquals(out.strip(), '1')
116 119
117 120 #Invalid quoting on windows
118 121 @dec.skip_win32
119 122 def test_getoutput_quoted2(self):
120 123 out = getoutput("python -c 'print (1)'")
121 124 self.assertEquals(out.strip(), '1')
122 125 out = getoutput("python -c 'print (\"1\")'")
123 126 self.assertEquals(out.strip(), '1')
124 127
125 128 def test_getoutput(self):
126 129 out, err = getoutputerror('python "%s"' % self.fname)
127 130 self.assertEquals(out, 'on stdout')
128 131 self.assertEquals(err, 'on stderr')
General Comments 0
You need to be logged in to leave comments. Login now