##// END OF EJS Templates
inputhook: disable CTRL+C when a hook is active....
inputhook: disable CTRL+C when a hook is active. On systems with 'readline', it's very likely to intercept a signal during a select() call. The default SIGINT handler will schedule a KeyboardInterrupt exception to be raised as soon as possible. If ctypes is used to install a Python callback for PyOS_InputHook, this will happen as soon as the bytecode execution starts, so even if the first instruction of the callback is a `try: ... except KeyboardInterrupt` clause, it's actually too late. As ctypes doesn't allow a Python callback to raise an exception, this ends up with IPython detecting an internal error... not pretty. We must therefore ignore the SIGINT signals until we are sure the exception handler is active, in the Python callback.

File last commit:

r4783:6392cebc
r4944:0fc80df3
Show More
_process_win32.py
148 lines | 4.4 KiB | text/x-python | PythonLexer
Fernando Perez
Fully refactored subprocess handling on all platforms....
r2908 """Windows-specific implementation of process utilities.
This file is only meant to be imported by process.py, not by end-users.
"""
#-----------------------------------------------------------------------------
# Copyright (C) 2010 The IPython Development Team
#
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
from __future__ import print_function
# stdlib
import os
import sys
from subprocess import STDOUT
# our own imports
from ._process_common import read_no_interrupt, process_handler
MinRK
add text.getdefaultencoding() for central default encoding guess...
r4783 from . import text
Fernando Perez
Fully refactored subprocess handling on all platforms....
r2908
#-----------------------------------------------------------------------------
# Function definitions
#-----------------------------------------------------------------------------
class AvoidUNCPath(object):
"""A context manager to protect command execution from UNC paths.
In the Win32 API, commands can't be invoked with the cwd being a UNC path.
This context manager temporarily changes directory to the 'C:' drive on
entering, and restores the original working directory on exit.
The context manager returns the starting working directory *if* it made a
change and None otherwise, so that users can apply the necessary adjustment
to their system calls in the event of a change.
Example
-------
::
cmd = 'dir'
with AvoidUNCPath() as path:
if path is not None:
cmd = '"pushd %s &&"%s' % (path, cmd)
os.system(cmd)
"""
def __enter__(self):
Jörgen Stenarson
Search of getcwd and replace with getcwdu. Ignoring core/prompts.py
r4208 self.path = os.getcwdu()
Fernando Perez
Fully refactored subprocess handling on all platforms....
r2908 self.is_unc_path = self.path.startswith(r"\\")
if self.is_unc_path:
# change to c drive (as cmd.exe cannot handle UNC addresses)
os.chdir("C:")
Fernando Perez
Fix small bug in UNC path context manager.
r2909 return self.path
else:
# We return None to signal that there was no change in the working
# directory
return None
Fernando Perez
Fully refactored subprocess handling on all platforms....
r2908
def __exit__(self, exc_type, exc_value, traceback):
if self.is_unc_path:
os.chdir(self.path)
def _find_cmd(cmd):
"""Find the full path to a .bat or .exe using the win32api module."""
try:
from win32api import SearchPath
except ImportError:
raise ImportError('you need to have pywin32 installed for this to work')
else:
PATH = os.environ['PATH']
extensions = ['.exe', '.com', '.bat', '.py']
path = None
for ext in extensions:
try:
path = SearchPath(PATH, cmd + ext)[0]
except:
pass
if path is None:
raise OSError("command %r not found" % cmd)
else:
return path
def _system_body(p):
"""Callback for _system."""
MinRK
add text.getdefaultencoding() for central default encoding guess...
r4783 enc = text.getdefaultencoding()
Fernando Perez
Fully refactored subprocess handling on all platforms....
r2908 for line in read_no_interrupt(p.stdout).splitlines():
Thomas Kluyver
Improve robustness, as suggested by Min.
r3476 line = line.decode(enc, 'replace')
Fernando Perez
Fully refactored subprocess handling on all platforms....
r2908 print(line, file=sys.stdout)
for line in read_no_interrupt(p.stderr).splitlines():
Thomas Kluyver
Improve robustness, as suggested by Min.
r3476 line = line.decode(enc, 'replace')
Fernando Perez
Fully refactored subprocess handling on all platforms....
r2908 print(line, file=sys.stderr)
MinRK
store exit code in user_ns['_exit_code']...
r3910 # Wait to finish for returncode
return p.wait()
Fernando Perez
Fully refactored subprocess handling on all platforms....
r2908
def system(cmd):
"""Win32 version of os.system() that works with network shares.
Note that this implementation returns None, as meant for use in IPython.
Parameters
----------
cmd : str
A command to be executed in the system shell.
Returns
-------
None : we explicitly do NOT return the subprocess status code, as this
utility is meant to be used extensively in IPython, where any return value
would trigger :func:`sys.displayhook` calls.
"""
with AvoidUNCPath() as path:
if path is not None:
cmd = '"pushd %s &&"%s' % (path, cmd)
MinRK
store exit code in user_ns['_exit_code']...
r3910 return process_handler(cmd, _system_body)
Fernando Perez
Fully refactored subprocess handling on all platforms....
r2908
def getoutput(cmd):
"""Return standard output of executing cmd in a shell.
Accepts the same arguments as os.system().
Parameters
----------
cmd : str
A command to be executed in the system shell.
Returns
-------
stdout : str
"""
with AvoidUNCPath() as path:
if path is not None:
cmd = '"pushd %s &&"%s' % (path, cmd)
out = process_handler(cmd, lambda p: p.communicate()[0], STDOUT)
if out is None:
out = ''
return out