Show More
@@ -1872,22 +1872,44 b' class InteractiveShell(SingletonConfigurable, Magic):' | |||
|
1872 | 1872 | # Things related to the running of system commands |
|
1873 | 1873 | #------------------------------------------------------------------------- |
|
1874 | 1874 | |
|
1875 | def system(self, cmd): | |
|
1876 |
"""Call the given cmd in a subprocess |
|
|
1875 | def system_piped(self, cmd): | |
|
1876 | """Call the given cmd in a subprocess, piping stdout/err | |
|
1877 | 1877 | |
|
1878 | 1878 | Parameters |
|
1879 | 1879 | ---------- |
|
1880 | 1880 | cmd : str |
|
1881 | Command to execute (can not end in '&', as bacground processes are | |
|
1882 | not supported. | |
|
1881 | Command to execute (can not end in '&', as background processes are | |
|
1882 | not supported. Should not be a command that expects input | |
|
1883 | other than simple text. | |
|
1883 | 1884 | """ |
|
1885 | if cmd.rstrip().endswith('&'): | |
|
1886 | # this is *far* from a rigorous test | |
|
1884 | 1887 | # We do not support backgrounding processes because we either use |
|
1885 | 1888 | # pexpect or pipes to read from. Users can always just call |
|
1886 | # os.system() if they really want a background process. | |
|
1887 | if cmd.endswith('&'): | |
|
1889 | # os.system() or use ip.system=ip.system_raw | |
|
1890 | # if they really want a background process. | |
|
1888 | 1891 | raise OSError("Background processes not supported.") |
|
1889 | 1892 | |
|
1890 | return system(self.var_expand(cmd, depth=2)) | |
|
1893 | # we explicitly do NOT return the subprocess status code, because | |
|
1894 | # a non-None value would trigger :func:`sys.displayhook` calls. | |
|
1895 | # Instead, we store the exit_code in user_ns. | |
|
1896 | self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=2)) | |
|
1897 | ||
|
1898 | def system_raw(self, cmd): | |
|
1899 | """Call the given cmd in a subprocess using os.system | |
|
1900 | ||
|
1901 | Parameters | |
|
1902 | ---------- | |
|
1903 | cmd : str | |
|
1904 | Command to execute. | |
|
1905 | """ | |
|
1906 | # We explicitly do NOT return the subprocess status code, because | |
|
1907 | # a non-None value would trigger :func:`sys.displayhook` calls. | |
|
1908 | # Instead, we store the exit_code in user_ns. | |
|
1909 | self.user_ns['_exit_code'] = os.system(self.var_expand(cmd, depth=2)) | |
|
1910 | ||
|
1911 | # use piped system by default, because it is better behaved | |
|
1912 | system = system_piped | |
|
1891 | 1913 | |
|
1892 | 1914 | def getoutput(self, cmd, split=True): |
|
1893 | 1915 | """Get output (possibly including stderr) from a subprocess. |
@@ -1905,7 +1927,8 b' class InteractiveShell(SingletonConfigurable, Magic):' | |||
|
1905 | 1927 | manipulation of line-based output. You can use '?' on them for |
|
1906 | 1928 | details. |
|
1907 | 1929 | """ |
|
1908 | if cmd.endswith('&'): | |
|
1930 | if cmd.rstrip().endswith('&'): | |
|
1931 | # this is *far* from a rigorous test | |
|
1909 | 1932 | raise OSError("Background processes not supported.") |
|
1910 | 1933 | out = getoutput(self.var_expand(cmd, depth=2)) |
|
1911 | 1934 | if split: |
@@ -2172,7 +2195,9 b' class InteractiveShell(SingletonConfigurable, Magic):' | |||
|
2172 | 2195 | prefilter_failed = False |
|
2173 | 2196 | if len(cell.splitlines()) == 1: |
|
2174 | 2197 | try: |
|
2175 | cell = self.prefilter_manager.prefilter_line(cell) | |
|
2198 | # use prefilter_lines to handle trailing newlines | |
|
2199 | # restore trailing newline for ast.parse | |
|
2200 | cell = self.prefilter_manager.prefilter_lines(cell) + '\n' | |
|
2176 | 2201 | except AliasError as e: |
|
2177 | 2202 | error(e) |
|
2178 | 2203 | prefilter_failed=True |
@@ -107,3 +107,10 b' class InteractiveShellTestCase(unittest.TestCase):' | |||
|
107 | 107 | io.stderr = save_err |
|
108 | 108 | self.assertEquals(err.split(':')[0], 'ERROR') |
|
109 | 109 | |
|
110 | def test_trailing_newline(self): | |
|
111 | """test that running !(command) does not raise a SyntaxError""" | |
|
112 | ip = get_ipython() | |
|
113 | ip.run_cell('!(true)\n', False) | |
|
114 | ip.run_cell('!(true)\n\n\n', False) | |
|
115 | ||
|
116 |
@@ -86,6 +86,12 b' class TerminalInteractiveShell(InteractiveShell):' | |||
|
86 | 86 | config=config, ipython_dir=ipython_dir, user_ns=user_ns, |
|
87 | 87 | user_global_ns=user_global_ns, custom_exceptions=custom_exceptions |
|
88 | 88 | ) |
|
89 | # use os.system instead of utils.process.system by default, except on Windows | |
|
90 | if os.name == 'nt': | |
|
91 | self.system = self.system_piped | |
|
92 | else: | |
|
93 | self.system = self.system_raw | |
|
94 | ||
|
89 | 95 | self.init_term_title() |
|
90 | 96 | self.init_usage(usage) |
|
91 | 97 | self.init_banner(banner1, banner2, display_banner) |
@@ -130,9 +130,7 b' class ProcessHandler(object):' | |||
|
130 | 130 | |
|
131 | 131 | Returns |
|
132 | 132 | ------- |
|
133 | None : we explicitly do NOT return the subprocess status code, as this | |
|
134 | utility is meant to be used extensively in IPython, where any return | |
|
135 | value would trigger :func:`sys.displayhook` calls. | |
|
133 | int : child's exitstatus | |
|
136 | 134 | """ |
|
137 | 135 | pcmd = self._make_cmd(cmd) |
|
138 | 136 | # Patterns to match on the output, for pexpect. We read input and |
@@ -181,6 +179,7 b' class ProcessHandler(object):' | |||
|
181 | 179 | finally: |
|
182 | 180 | # Ensure the subprocess really is terminated |
|
183 | 181 | child.terminate(force=True) |
|
182 | return child.exitstatus | |
|
184 | 183 | |
|
185 | 184 | def _make_cmd(self, cmd): |
|
186 | 185 | return '%s -c "%s"' % (self.sh, cmd) |
@@ -96,6 +96,9 b' def _system_body(p):' | |||
|
96 | 96 | line = line.decode(enc, 'replace') |
|
97 | 97 | print(line, file=sys.stderr) |
|
98 | 98 | |
|
99 | # Wait to finish for returncode | |
|
100 | return p.wait() | |
|
101 | ||
|
99 | 102 | |
|
100 | 103 | def system(cmd): |
|
101 | 104 | """Win32 version of os.system() that works with network shares. |
@@ -116,7 +119,7 b' def system(cmd):' | |||
|
116 | 119 | with AvoidUNCPath() as path: |
|
117 | 120 | if path is not None: |
|
118 | 121 | cmd = '"pushd %s &&"%s' % (path, cmd) |
|
119 | process_handler(cmd, _system_body) | |
|
122 | return process_handler(cmd, _system_body) | |
|
120 | 123 | |
|
121 | 124 | |
|
122 | 125 | def getoutput(cmd): |
General Comments 0
You need to be logged in to leave comments.
Login now