##// END OF EJS Templates
remove special case for 'python' in find_cmd
MinRK -
Show More
@@ -1,125 +1,122 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for working with external processes.
3 Utilities for working with external processes.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 # Stdlib
18 # Stdlib
19 import os
19 import os
20 import sys
20 import sys
21 import shlex
21 import shlex
22
22
23 # Our own
23 # Our own
24 if sys.platform == 'win32':
24 if sys.platform == 'win32':
25 from ._process_win32 import _find_cmd, system, getoutput, AvoidUNCPath, arg_split
25 from ._process_win32 import _find_cmd, system, getoutput, AvoidUNCPath, arg_split
26 else:
26 else:
27 from ._process_posix import _find_cmd, system, getoutput, arg_split
27 from ._process_posix import _find_cmd, system, getoutput, arg_split
28
28
29
29
30 from ._process_common import getoutputerror
30 from ._process_common import getoutputerror
31
31
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
33 # Code
33 # Code
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35
35
36
36
37 class FindCmdError(Exception):
37 class FindCmdError(Exception):
38 pass
38 pass
39
39
40
40
41 def find_cmd(cmd):
41 def find_cmd(cmd):
42 """Find absolute path to executable cmd in a cross platform manner.
42 """Find absolute path to executable cmd in a cross platform manner.
43
43
44 This function tries to determine the full path to a command line program
44 This function tries to determine the full path to a command line program
45 using `which` on Unix/Linux/OS X and `win32api` on Windows. Most of the
45 using `which` on Unix/Linux/OS X and `win32api` on Windows. Most of the
46 time it will use the version that is first on the users `PATH`. If
46 time it will use the version that is first on the users `PATH`.
47 cmd is `python` return `sys.executable`.
48
47
49 Warning, don't use this to find IPython command line programs as there
48 Warning, don't use this to find IPython command line programs as there
50 is a risk you will find the wrong one. Instead find those using the
49 is a risk you will find the wrong one. Instead find those using the
51 following code and looking for the application itself::
50 following code and looking for the application itself::
52
51
53 from IPython.utils.path import get_ipython_module_path
52 from IPython.utils.path import get_ipython_module_path
54 from IPython.utils.process import pycmd2argv
53 from IPython.utils.process import pycmd2argv
55 argv = pycmd2argv(get_ipython_module_path('IPython.frontend.terminal.ipapp'))
54 argv = pycmd2argv(get_ipython_module_path('IPython.frontend.terminal.ipapp'))
56
55
57 Parameters
56 Parameters
58 ----------
57 ----------
59 cmd : str
58 cmd : str
60 The command line program to look for.
59 The command line program to look for.
61 """
60 """
62 if cmd in ('python', os.path.basename(sys.executable)):
63 return os.path.abspath(sys.executable)
64 try:
61 try:
65 path = _find_cmd(cmd).rstrip()
62 path = _find_cmd(cmd).rstrip()
66 except OSError:
63 except OSError:
67 raise FindCmdError('command could not be found: %s' % cmd)
64 raise FindCmdError('command could not be found: %s' % cmd)
68 # which returns empty if not found
65 # which returns empty if not found
69 if path == '':
66 if path == '':
70 raise FindCmdError('command could not be found: %s' % cmd)
67 raise FindCmdError('command could not be found: %s' % cmd)
71 return os.path.abspath(path)
68 return os.path.abspath(path)
72
69
73
70
74 def is_cmd_found(cmd):
71 def is_cmd_found(cmd):
75 """Check whether executable `cmd` exists or not and return a bool."""
72 """Check whether executable `cmd` exists or not and return a bool."""
76 try:
73 try:
77 find_cmd(cmd)
74 find_cmd(cmd)
78 return True
75 return True
79 except FindCmdError:
76 except FindCmdError:
80 return False
77 return False
81
78
82
79
83 def pycmd2argv(cmd):
80 def pycmd2argv(cmd):
84 r"""Take the path of a python command and return a list (argv-style).
81 r"""Take the path of a python command and return a list (argv-style).
85
82
86 This only works on Python based command line programs and will find the
83 This only works on Python based command line programs and will find the
87 location of the ``python`` executable using ``sys.executable`` to make
84 location of the ``python`` executable using ``sys.executable`` to make
88 sure the right version is used.
85 sure the right version is used.
89
86
90 For a given path ``cmd``, this returns [cmd] if cmd's extension is .exe,
87 For a given path ``cmd``, this returns [cmd] if cmd's extension is .exe,
91 .com or .bat, and [, cmd] otherwise.
88 .com or .bat, and [, cmd] otherwise.
92
89
93 Parameters
90 Parameters
94 ----------
91 ----------
95 cmd : string
92 cmd : string
96 The path of the command.
93 The path of the command.
97
94
98 Returns
95 Returns
99 -------
96 -------
100 argv-style list.
97 argv-style list.
101 """
98 """
102 ext = os.path.splitext(cmd)[1]
99 ext = os.path.splitext(cmd)[1]
103 if ext in ['.exe', '.com', '.bat']:
100 if ext in ['.exe', '.com', '.bat']:
104 return [cmd]
101 return [cmd]
105 else:
102 else:
106 return [sys.executable, cmd]
103 return [sys.executable, cmd]
107
104
108
105
109 def abbrev_cwd():
106 def abbrev_cwd():
110 """ Return abbreviated version of cwd, e.g. d:mydir """
107 """ Return abbreviated version of cwd, e.g. d:mydir """
111 cwd = os.getcwdu().replace('\\','/')
108 cwd = os.getcwdu().replace('\\','/')
112 drivepart = ''
109 drivepart = ''
113 tail = cwd
110 tail = cwd
114 if sys.platform == 'win32':
111 if sys.platform == 'win32':
115 if len(cwd) < 4:
112 if len(cwd) < 4:
116 return cwd
113 return cwd
117 drivepart,tail = os.path.splitdrive(cwd)
114 drivepart,tail = os.path.splitdrive(cwd)
118
115
119
116
120 parts = tail.split('/')
117 parts = tail.split('/')
121 if len(parts) > 2:
118 if len(parts) > 2:
122 tail = '/'.join(parts[-2:])
119 tail = '/'.join(parts[-2:])
123
120
124 return (drivepart + (
121 return (drivepart + (
125 cwd == '/' and '/' or tail))
122 cwd == '/' and '/' or tail))
@@ -1,138 +1,134 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Tests for platutils.py
3 Tests for platutils.py
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 import sys
17 import sys
18 import os
18 import os
19 from unittest import TestCase
19 from unittest import TestCase
20
20
21 import nose.tools as nt
21 import nose.tools as nt
22
22
23 from IPython.utils.process import (find_cmd, FindCmdError, arg_split,
23 from IPython.utils.process import (find_cmd, FindCmdError, arg_split,
24 system, getoutput, getoutputerror)
24 system, getoutput, getoutputerror)
25 from IPython.testing import decorators as dec
25 from IPython.testing import decorators as dec
26 from IPython.testing import tools as tt
26 from IPython.testing import tools as tt
27
27
28 python = os.path.basename(sys.executable)
28 python = os.path.basename(sys.executable)
29
29
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31 # Tests
31 # Tests
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
33
33
34 def test_find_cmd_python():
35 """Make sure we find sys.exectable for python."""
36 nt.assert_equal(find_cmd(python), sys.executable)
37
34
38
39 @dec.skip_win32
35 @dec.skip_win32
40 def test_find_cmd_ls():
36 def test_find_cmd_ls():
41 """Make sure we can find the full path to ls."""
37 """Make sure we can find the full path to ls."""
42 path = find_cmd('ls')
38 path = find_cmd('ls')
43 nt.assert_true(path.endswith('ls'))
39 nt.assert_true(path.endswith('ls'))
44
40
45
41
46 def has_pywin32():
42 def has_pywin32():
47 try:
43 try:
48 import win32api
44 import win32api
49 except ImportError:
45 except ImportError:
50 return False
46 return False
51 return True
47 return True
52
48
53
49
54 @dec.onlyif(has_pywin32, "This test requires win32api to run")
50 @dec.onlyif(has_pywin32, "This test requires win32api to run")
55 def test_find_cmd_pythonw():
51 def test_find_cmd_pythonw():
56 """Try to find pythonw on Windows."""
52 """Try to find pythonw on Windows."""
57 path = find_cmd('pythonw')
53 path = find_cmd('pythonw')
58 nt.assert_true(path.endswith('pythonw.exe'))
54 nt.assert_true(path.endswith('pythonw.exe'))
59
55
60
56
61 @dec.onlyif(lambda : sys.platform != 'win32' or has_pywin32(),
57 @dec.onlyif(lambda : sys.platform != 'win32' or has_pywin32(),
62 "This test runs on posix or in win32 with win32api installed")
58 "This test runs on posix or in win32 with win32api installed")
63 def test_find_cmd_fail():
59 def test_find_cmd_fail():
64 """Make sure that FindCmdError is raised if we can't find the cmd."""
60 """Make sure that FindCmdError is raised if we can't find the cmd."""
65 nt.assert_raises(FindCmdError,find_cmd,'asdfasdf')
61 nt.assert_raises(FindCmdError,find_cmd,'asdfasdf')
66
62
67
63
68 @dec.skip_win32
64 @dec.skip_win32
69 def test_arg_split():
65 def test_arg_split():
70 """Ensure that argument lines are correctly split like in a shell."""
66 """Ensure that argument lines are correctly split like in a shell."""
71 tests = [['hi', ['hi']],
67 tests = [['hi', ['hi']],
72 [u'hi', [u'hi']],
68 [u'hi', [u'hi']],
73 ['hello there', ['hello', 'there']],
69 ['hello there', ['hello', 'there']],
74 # \u01ce == \N{LATIN SMALL LETTER A WITH CARON}
70 # \u01ce == \N{LATIN SMALL LETTER A WITH CARON}
75 # Do not use \N because the tests crash with syntax error in
71 # Do not use \N because the tests crash with syntax error in
76 # some cases, for example windows python2.6.
72 # some cases, for example windows python2.6.
77 [u'h\u01cello', [u'h\u01cello']],
73 [u'h\u01cello', [u'h\u01cello']],
78 ['something "with quotes"', ['something', '"with quotes"']],
74 ['something "with quotes"', ['something', '"with quotes"']],
79 ]
75 ]
80 for argstr, argv in tests:
76 for argstr, argv in tests:
81 nt.assert_equal(arg_split(argstr), argv)
77 nt.assert_equal(arg_split(argstr), argv)
82
78
83 @dec.skip_if_not_win32
79 @dec.skip_if_not_win32
84 def test_arg_split_win32():
80 def test_arg_split_win32():
85 """Ensure that argument lines are correctly split like in a shell."""
81 """Ensure that argument lines are correctly split like in a shell."""
86 tests = [['hi', ['hi']],
82 tests = [['hi', ['hi']],
87 [u'hi', [u'hi']],
83 [u'hi', [u'hi']],
88 ['hello there', ['hello', 'there']],
84 ['hello there', ['hello', 'there']],
89 [u'h\u01cello', [u'h\u01cello']],
85 [u'h\u01cello', [u'h\u01cello']],
90 ['something "with quotes"', ['something', 'with quotes']],
86 ['something "with quotes"', ['something', 'with quotes']],
91 ]
87 ]
92 for argstr, argv in tests:
88 for argstr, argv in tests:
93 nt.assert_equal(arg_split(argstr), argv)
89 nt.assert_equal(arg_split(argstr), argv)
94
90
95
91
96 class SubProcessTestCase(TestCase, tt.TempFileMixin):
92 class SubProcessTestCase(TestCase, tt.TempFileMixin):
97 def setUp(self):
93 def setUp(self):
98 """Make a valid python temp file."""
94 """Make a valid python temp file."""
99 lines = ["from __future__ import print_function",
95 lines = ["from __future__ import print_function",
100 "import sys",
96 "import sys",
101 "print('on stdout', end='', file=sys.stdout)",
97 "print('on stdout', end='', file=sys.stdout)",
102 "print('on stderr', end='', file=sys.stderr)",
98 "print('on stderr', end='', file=sys.stderr)",
103 "sys.stdout.flush()",
99 "sys.stdout.flush()",
104 "sys.stderr.flush()"]
100 "sys.stderr.flush()"]
105 self.mktmp('\n'.join(lines))
101 self.mktmp('\n'.join(lines))
106
102
107 def test_system(self):
103 def test_system(self):
108 status = system('%s "%s"' % (python, self.fname))
104 status = system('%s "%s"' % (python, self.fname))
109 self.assertEqual(status, 0)
105 self.assertEqual(status, 0)
110
106
111 def test_system_quotes(self):
107 def test_system_quotes(self):
112 status = system('%s -c "import sys"' % python)
108 status = system('%s -c "import sys"' % python)
113 self.assertEqual(status, 0)
109 self.assertEqual(status, 0)
114
110
115 def test_getoutput(self):
111 def test_getoutput(self):
116 out = getoutput('%s "%s"' % (python, self.fname))
112 out = getoutput('%s "%s"' % (python, self.fname))
117 # we can't rely on the order the line buffered streams are flushed
113 # we can't rely on the order the line buffered streams are flushed
118 try:
114 try:
119 self.assertEqual(out, 'on stderron stdout')
115 self.assertEqual(out, 'on stderron stdout')
120 except AssertionError:
116 except AssertionError:
121 self.assertEqual(out, 'on stdouton stderr')
117 self.assertEqual(out, 'on stdouton stderr')
122
118
123 def test_getoutput_quoted(self):
119 def test_getoutput_quoted(self):
124 out = getoutput('%s -c "print (1)"' % python)
120 out = getoutput('%s -c "print (1)"' % python)
125 self.assertEqual(out.strip(), '1')
121 self.assertEqual(out.strip(), '1')
126
122
127 #Invalid quoting on windows
123 #Invalid quoting on windows
128 @dec.skip_win32
124 @dec.skip_win32
129 def test_getoutput_quoted2(self):
125 def test_getoutput_quoted2(self):
130 out = getoutput("%s -c 'print (1)'" % python)
126 out = getoutput("%s -c 'print (1)'" % python)
131 self.assertEqual(out.strip(), '1')
127 self.assertEqual(out.strip(), '1')
132 out = getoutput("%s -c 'print (\"1\")'" % python)
128 out = getoutput("%s -c 'print (\"1\")'" % python)
133 self.assertEqual(out.strip(), '1')
129 self.assertEqual(out.strip(), '1')
134
130
135 def test_getoutput_error(self):
131 def test_getoutput_error(self):
136 out, err = getoutputerror('%s "%s"' % (python, self.fname))
132 out, err = getoutputerror('%s "%s"' % (python, self.fname))
137 self.assertEqual(out, 'on stdout')
133 self.assertEqual(out, 'on stdout')
138 self.assertEqual(err, 'on stderr')
134 self.assertEqual(err, 'on stderr')
General Comments 0
You need to be logged in to leave comments. Login now