##// END OF EJS Templates
only get the default encoding one time...
Brandon Parsons -
Show More
@@ -1,184 +1,185 b''
1 """Windows-specific implementation of process utilities.
1 """Windows-specific implementation of process utilities.
2
2
3 This file is only meant to be imported by process.py, not by end-users.
3 This file is only meant to be imported by process.py, not by end-users.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2010-2011 The IPython Development Team
7 # Copyright (C) 2010-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 ctypes
21 import ctypes
22 import msvcrt
22 import msvcrt
23
23
24 from ctypes import c_int, POINTER
24 from ctypes import c_int, POINTER
25 from ctypes.wintypes import LPCWSTR, HLOCAL
25 from ctypes.wintypes import LPCWSTR, HLOCAL
26 from subprocess import STDOUT
26 from subprocess import STDOUT
27
27
28 # our own imports
28 # our own imports
29 from ._process_common import read_no_interrupt, process_handler, arg_split as py_arg_split
29 from ._process_common import read_no_interrupt, process_handler, arg_split as py_arg_split
30 from . import py3compat
30 from . import py3compat
31 from . import text
31 from . import text
32 from .encoding import getdefaultencoding
32
33
33 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
34 # Function definitions
35 # Function definitions
35 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
36
37
37 class AvoidUNCPath(object):
38 class AvoidUNCPath(object):
38 """A context manager to protect command execution from UNC paths.
39 """A context manager to protect command execution from UNC paths.
39
40
40 In the Win32 API, commands can't be invoked with the cwd being a UNC path.
41 In the Win32 API, commands can't be invoked with the cwd being a UNC path.
41 This context manager temporarily changes directory to the 'C:' drive on
42 This context manager temporarily changes directory to the 'C:' drive on
42 entering, and restores the original working directory on exit.
43 entering, and restores the original working directory on exit.
43
44
44 The context manager returns the starting working directory *if* it made a
45 The context manager returns the starting working directory *if* it made a
45 change and None otherwise, so that users can apply the necessary adjustment
46 change and None otherwise, so that users can apply the necessary adjustment
46 to their system calls in the event of a change.
47 to their system calls in the event of a change.
47
48
48 Example
49 Example
49 -------
50 -------
50 ::
51 ::
51 cmd = 'dir'
52 cmd = 'dir'
52 with AvoidUNCPath() as path:
53 with AvoidUNCPath() as path:
53 if path is not None:
54 if path is not None:
54 cmd = '"pushd %s &&"%s' % (path, cmd)
55 cmd = '"pushd %s &&"%s' % (path, cmd)
55 os.system(cmd)
56 os.system(cmd)
56 """
57 """
57 def __enter__(self):
58 def __enter__(self):
58 self.path = os.getcwdu()
59 self.path = os.getcwdu()
59 self.is_unc_path = self.path.startswith(r"\\")
60 self.is_unc_path = self.path.startswith(r"\\")
60 if self.is_unc_path:
61 if self.is_unc_path:
61 # change to c drive (as cmd.exe cannot handle UNC addresses)
62 # change to c drive (as cmd.exe cannot handle UNC addresses)
62 os.chdir("C:")
63 os.chdir("C:")
63 return self.path
64 return self.path
64 else:
65 else:
65 # We return None to signal that there was no change in the working
66 # We return None to signal that there was no change in the working
66 # directory
67 # directory
67 return None
68 return None
68
69
69 def __exit__(self, exc_type, exc_value, traceback):
70 def __exit__(self, exc_type, exc_value, traceback):
70 if self.is_unc_path:
71 if self.is_unc_path:
71 os.chdir(self.path)
72 os.chdir(self.path)
72
73
73
74
74 def _find_cmd(cmd):
75 def _find_cmd(cmd):
75 """Find the full path to a .bat or .exe using the win32api module."""
76 """Find the full path to a .bat or .exe using the win32api module."""
76 try:
77 try:
77 from win32api import SearchPath
78 from win32api import SearchPath
78 except ImportError:
79 except ImportError:
79 raise ImportError('you need to have pywin32 installed for this to work')
80 raise ImportError('you need to have pywin32 installed for this to work')
80 else:
81 else:
81 PATH = os.environ['PATH']
82 PATH = os.environ['PATH']
82 extensions = ['.exe', '.com', '.bat', '.py']
83 extensions = ['.exe', '.com', '.bat', '.py']
83 path = None
84 path = None
84 for ext in extensions:
85 for ext in extensions:
85 try:
86 try:
86 path = SearchPath(PATH, cmd + ext)[0]
87 path = SearchPath(PATH, cmd + ext)[0]
87 except:
88 except:
88 pass
89 pass
89 if path is None:
90 if path is None:
90 raise OSError("command %r not found" % cmd)
91 raise OSError("command %r not found" % cmd)
91 else:
92 else:
92 return path
93 return path
93
94
94
95
95 def _system_body(p):
96 def _system_body(p):
96 """Callback for _system."""
97 """Callback for _system."""
97 enc = py3compat.getdefaultencoding()
98 enc = getdefaultencoding()
98 for line in read_no_interrupt(p.stdout).splitlines():
99 for line in read_no_interrupt(p.stdout).splitlines():
99 line = line.decode(enc, 'replace')
100 line = line.decode(enc, 'replace')
100 print(line, file=sys.stdout)
101 print(line, file=sys.stdout)
101 for line in read_no_interrupt(p.stderr).splitlines():
102 for line in read_no_interrupt(p.stderr).splitlines():
102 line = line.decode(enc, 'replace')
103 line = line.decode(enc, 'replace')
103 print(line, file=sys.stderr)
104 print(line, file=sys.stderr)
104
105
105 # Wait to finish for returncode
106 # Wait to finish for returncode
106 return p.wait()
107 return p.wait()
107
108
108
109
109 def system(cmd):
110 def system(cmd):
110 """Win32 version of os.system() that works with network shares.
111 """Win32 version of os.system() that works with network shares.
111
112
112 Note that this implementation returns None, as meant for use in IPython.
113 Note that this implementation returns None, as meant for use in IPython.
113
114
114 Parameters
115 Parameters
115 ----------
116 ----------
116 cmd : str
117 cmd : str
117 A command to be executed in the system shell.
118 A command to be executed in the system shell.
118
119
119 Returns
120 Returns
120 -------
121 -------
121 None : we explicitly do NOT return the subprocess status code, as this
122 None : we explicitly do NOT return the subprocess status code, as this
122 utility is meant to be used extensively in IPython, where any return value
123 utility is meant to be used extensively in IPython, where any return value
123 would trigger :func:`sys.displayhook` calls.
124 would trigger :func:`sys.displayhook` calls.
124 """
125 """
125 # The controller provides interactivity with both
126 # The controller provides interactivity with both
126 # stdin and stdout
127 # stdin and stdout
127 import _process_win32_controller
128 import _process_win32_controller
128 _process_win32_controller.system(cmd)
129 _process_win32_controller.system(cmd)
129
130
130
131
131 def getoutput(cmd):
132 def getoutput(cmd):
132 """Return standard output of executing cmd in a shell.
133 """Return standard output of executing cmd in a shell.
133
134
134 Accepts the same arguments as os.system().
135 Accepts the same arguments as os.system().
135
136
136 Parameters
137 Parameters
137 ----------
138 ----------
138 cmd : str
139 cmd : str
139 A command to be executed in the system shell.
140 A command to be executed in the system shell.
140
141
141 Returns
142 Returns
142 -------
143 -------
143 stdout : str
144 stdout : str
144 """
145 """
145
146
146 with AvoidUNCPath() as path:
147 with AvoidUNCPath() as path:
147 if path is not None:
148 if path is not None:
148 cmd = '"pushd %s &&"%s' % (path, cmd)
149 cmd = '"pushd %s &&"%s' % (path, cmd)
149 out = process_handler(cmd, lambda p: p.communicate()[0], STDOUT)
150 out = process_handler(cmd, lambda p: p.communicate()[0], STDOUT)
150
151
151 if out is None:
152 if out is None:
152 out = ''
153 out = ''
153 return out
154 return out
154
155
155 try:
156 try:
156 CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW
157 CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW
157 CommandLineToArgvW.arg_types = [LPCWSTR, POINTER(c_int)]
158 CommandLineToArgvW.arg_types = [LPCWSTR, POINTER(c_int)]
158 CommandLineToArgvW.res_types = [POINTER(LPCWSTR)]
159 CommandLineToArgvW.res_types = [POINTER(LPCWSTR)]
159 LocalFree = ctypes.windll.kernel32.LocalFree
160 LocalFree = ctypes.windll.kernel32.LocalFree
160 LocalFree.res_type = HLOCAL
161 LocalFree.res_type = HLOCAL
161 LocalFree.arg_types = [HLOCAL]
162 LocalFree.arg_types = [HLOCAL]
162
163
163 def arg_split(commandline, posix=False, strict=True):
164 def arg_split(commandline, posix=False, strict=True):
164 """Split a command line's arguments in a shell-like manner.
165 """Split a command line's arguments in a shell-like manner.
165
166
166 This is a special version for windows that use a ctypes call to CommandLineToArgvW
167 This is a special version for windows that use a ctypes call to CommandLineToArgvW
167 to do the argv splitting. The posix paramter is ignored.
168 to do the argv splitting. The posix paramter is ignored.
168
169
169 If strict=False, process_common.arg_split(...strict=False) is used instead.
170 If strict=False, process_common.arg_split(...strict=False) is used instead.
170 """
171 """
171 #CommandLineToArgvW returns path to executable if called with empty string.
172 #CommandLineToArgvW returns path to executable if called with empty string.
172 if commandline.strip() == "":
173 if commandline.strip() == "":
173 return []
174 return []
174 if not strict:
175 if not strict:
175 # not really a cl-arg, fallback on _process_common
176 # not really a cl-arg, fallback on _process_common
176 return py_arg_split(commandline, posix=posix, strict=strict)
177 return py_arg_split(commandline, posix=posix, strict=strict)
177 argvn = c_int()
178 argvn = c_int()
178 result_pointer = CommandLineToArgvW(py3compat.cast_unicode(commandline.lstrip()), ctypes.byref(argvn))
179 result_pointer = CommandLineToArgvW(py3compat.cast_unicode(commandline.lstrip()), ctypes.byref(argvn))
179 result_array_type = LPCWSTR * argvn.value
180 result_array_type = LPCWSTR * argvn.value
180 result = [arg for arg in result_array_type.from_address(result_pointer)]
181 result = [arg for arg in result_array_type.from_address(result_pointer)]
181 retval = LocalFree(result_pointer)
182 retval = LocalFree(result_pointer)
182 return result
183 return result
183 except AttributeError:
184 except AttributeError:
184 arg_split = py_arg_split
185 arg_split = py_arg_split
@@ -1,178 +1,180 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Compatibility tricks for Python 3. Mainly to do with unicode."""
2 """Compatibility tricks for Python 3. Mainly to do with unicode."""
3 import __builtin__
3 import __builtin__
4 import functools
4 import functools
5 import sys
5 import sys
6 import re
6 import re
7 import types
7 import types
8
8
9 from IPython.utils.encoding import getdefaultencoding
9 from .encoding import getdefaultencoding
10
11 default_encoding = getdefaultencoding()
10
12
11 orig_open = open
13 orig_open = open
12
14
13 def no_code(x, encoding=None):
15 def no_code(x, encoding=None):
14 return x
16 return x
15
17
16 def decode(s, encoding=None):
18 def decode(s, encoding=None):
17 encoding = encoding or getdefaultencoding()
19 encoding = encoding or default_encoding
18 return s.decode(encoding, "replace")
20 return s.decode(encoding, "replace")
19
21
20 def encode(u, encoding=None):
22 def encode(u, encoding=None):
21 encoding = encoding or getdefaultencoding()
23 encoding = encoding or default_encoding
22 return u.encode(encoding, "replace")
24 return u.encode(encoding, "replace")
23
25
24
26
25 def cast_unicode(s, encoding=None):
27 def cast_unicode(s, encoding=None):
26 if isinstance(s, bytes):
28 if isinstance(s, bytes):
27 return decode(s, encoding)
29 return decode(s, encoding)
28 return s
30 return s
29
31
30 def cast_bytes(s, encoding=None):
32 def cast_bytes(s, encoding=None):
31 if not isinstance(s, bytes):
33 if not isinstance(s, bytes):
32 return encode(s, encoding)
34 return encode(s, encoding)
33 return s
35 return s
34
36
35 def _modify_str_or_docstring(str_change_func):
37 def _modify_str_or_docstring(str_change_func):
36 @functools.wraps(str_change_func)
38 @functools.wraps(str_change_func)
37 def wrapper(func_or_str):
39 def wrapper(func_or_str):
38 if isinstance(func_or_str, basestring):
40 if isinstance(func_or_str, basestring):
39 func = None
41 func = None
40 doc = func_or_str
42 doc = func_or_str
41 else:
43 else:
42 func = func_or_str
44 func = func_or_str
43 doc = func.__doc__
45 doc = func.__doc__
44
46
45 doc = str_change_func(doc)
47 doc = str_change_func(doc)
46
48
47 if func:
49 if func:
48 func.__doc__ = doc
50 func.__doc__ = doc
49 return func
51 return func
50 return doc
52 return doc
51 return wrapper
53 return wrapper
52
54
53 if sys.version_info[0] >= 3:
55 if sys.version_info[0] >= 3:
54 PY3 = True
56 PY3 = True
55
57
56 input = input
58 input = input
57 builtin_mod_name = "builtins"
59 builtin_mod_name = "builtins"
58
60
59 str_to_unicode = no_code
61 str_to_unicode = no_code
60 unicode_to_str = no_code
62 unicode_to_str = no_code
61 str_to_bytes = encode
63 str_to_bytes = encode
62 bytes_to_str = decode
64 bytes_to_str = decode
63 cast_bytes_py2 = no_code
65 cast_bytes_py2 = no_code
64
66
65 def isidentifier(s, dotted=False):
67 def isidentifier(s, dotted=False):
66 if dotted:
68 if dotted:
67 return all(isidentifier(a) for a in s.split("."))
69 return all(isidentifier(a) for a in s.split("."))
68 return s.isidentifier()
70 return s.isidentifier()
69
71
70 open = orig_open
72 open = orig_open
71
73
72 MethodType = types.MethodType
74 MethodType = types.MethodType
73
75
74 def execfile(fname, glob, loc=None):
76 def execfile(fname, glob, loc=None):
75 loc = loc if (loc is not None) else glob
77 loc = loc if (loc is not None) else glob
76 exec compile(open(fname, 'rb').read(), fname, 'exec') in glob, loc
78 exec compile(open(fname, 'rb').read(), fname, 'exec') in glob, loc
77
79
78 # Refactor print statements in doctests.
80 # Refactor print statements in doctests.
79 _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
81 _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
80 def _print_statement_sub(match):
82 def _print_statement_sub(match):
81 expr = match.groups('expr')
83 expr = match.groups('expr')
82 return "print(%s)" % expr
84 return "print(%s)" % expr
83
85
84 @_modify_str_or_docstring
86 @_modify_str_or_docstring
85 def doctest_refactor_print(doc):
87 def doctest_refactor_print(doc):
86 """Refactor 'print x' statements in a doctest to print(x) style. 2to3
88 """Refactor 'print x' statements in a doctest to print(x) style. 2to3
87 unfortunately doesn't pick up on our doctests.
89 unfortunately doesn't pick up on our doctests.
88
90
89 Can accept a string or a function, so it can be used as a decorator."""
91 Can accept a string or a function, so it can be used as a decorator."""
90 return _print_statement_re.sub(_print_statement_sub, doc)
92 return _print_statement_re.sub(_print_statement_sub, doc)
91
93
92 # Abstract u'abc' syntax:
94 # Abstract u'abc' syntax:
93 @_modify_str_or_docstring
95 @_modify_str_or_docstring
94 def u_format(s):
96 def u_format(s):
95 """"{u}'abc'" --> "'abc'" (Python 3)
97 """"{u}'abc'" --> "'abc'" (Python 3)
96
98
97 Accepts a string or a function, so it can be used as a decorator."""
99 Accepts a string or a function, so it can be used as a decorator."""
98 return s.format(u='')
100 return s.format(u='')
99
101
100 else:
102 else:
101 PY3 = False
103 PY3 = False
102
104
103 input = raw_input
105 input = raw_input
104 builtin_mod_name = "__builtin__"
106 builtin_mod_name = "__builtin__"
105
107
106 str_to_unicode = decode
108 str_to_unicode = decode
107 unicode_to_str = encode
109 unicode_to_str = encode
108 str_to_bytes = no_code
110 str_to_bytes = no_code
109 bytes_to_str = no_code
111 bytes_to_str = no_code
110 cast_bytes_py2 = cast_bytes
112 cast_bytes_py2 = cast_bytes
111
113
112 import re
114 import re
113 _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$")
115 _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$")
114 def isidentifier(s, dotted=False):
116 def isidentifier(s, dotted=False):
115 if dotted:
117 if dotted:
116 return all(isidentifier(a) for a in s.split("."))
118 return all(isidentifier(a) for a in s.split("."))
117 return bool(_name_re.match(s))
119 return bool(_name_re.match(s))
118
120
119 class open(object):
121 class open(object):
120 """Wrapper providing key part of Python 3 open() interface."""
122 """Wrapper providing key part of Python 3 open() interface."""
121 def __init__(self, fname, mode="r", encoding="utf-8"):
123 def __init__(self, fname, mode="r", encoding="utf-8"):
122 self.f = orig_open(fname, mode)
124 self.f = orig_open(fname, mode)
123 self.enc = encoding
125 self.enc = encoding
124
126
125 def write(self, s):
127 def write(self, s):
126 return self.f.write(s.encode(self.enc))
128 return self.f.write(s.encode(self.enc))
127
129
128 def read(self, size=-1):
130 def read(self, size=-1):
129 return self.f.read(size).decode(self.enc)
131 return self.f.read(size).decode(self.enc)
130
132
131 def close(self):
133 def close(self):
132 return self.f.close()
134 return self.f.close()
133
135
134 def __enter__(self):
136 def __enter__(self):
135 return self
137 return self
136
138
137 def __exit__(self, etype, value, traceback):
139 def __exit__(self, etype, value, traceback):
138 self.f.close()
140 self.f.close()
139
141
140 def MethodType(func, instance):
142 def MethodType(func, instance):
141 return types.MethodType(func, instance, type(instance))
143 return types.MethodType(func, instance, type(instance))
142
144
143 # don't override system execfile on 2.x:
145 # don't override system execfile on 2.x:
144 execfile = execfile
146 execfile = execfile
145
147
146 def doctest_refactor_print(func_or_str):
148 def doctest_refactor_print(func_or_str):
147 return func_or_str
149 return func_or_str
148
150
149
151
150 # Abstract u'abc' syntax:
152 # Abstract u'abc' syntax:
151 @_modify_str_or_docstring
153 @_modify_str_or_docstring
152 def u_format(s):
154 def u_format(s):
153 """"{u}'abc'" --> "u'abc'" (Python 2)
155 """"{u}'abc'" --> "u'abc'" (Python 2)
154
156
155 Accepts a string or a function, so it can be used as a decorator."""
157 Accepts a string or a function, so it can be used as a decorator."""
156 return s.format(u='u')
158 return s.format(u='u')
157
159
158 if sys.platform == 'win32':
160 if sys.platform == 'win32':
159 def execfile(fname, glob=None, loc=None):
161 def execfile(fname, glob=None, loc=None):
160 loc = loc if (loc is not None) else glob
162 loc = loc if (loc is not None) else glob
161 # The rstrip() is necessary b/c trailing whitespace in files will
163 # The rstrip() is necessary b/c trailing whitespace in files will
162 # cause an IndentationError in Python 2.6 (this was fixed in 2.7,
164 # cause an IndentationError in Python 2.6 (this was fixed in 2.7,
163 # but we still support 2.6). See issue 1027.
165 # but we still support 2.6). See issue 1027.
164 scripttext = __builtin__.open(fname).read().rstrip() + '\n'
166 scripttext = __builtin__.open(fname).read().rstrip() + '\n'
165 # compile converts unicode filename to str assuming
167 # compile converts unicode filename to str assuming
166 # ascii. Let's do the conversion before calling compile
168 # ascii. Let's do the conversion before calling compile
167 if isinstance(fname, unicode):
169 if isinstance(fname, unicode):
168 filename = unicode_to_str(fname)
170 filename = unicode_to_str(fname)
169 else:
171 else:
170 filename = fname
172 filename = fname
171 exec compile(scripttext, filename, 'exec') in glob, loc
173 exec compile(scripttext, filename, 'exec') in glob, loc
172 else:
174 else:
173 def execfile(fname, *where):
175 def execfile(fname, *where):
174 if isinstance(fname, unicode):
176 if isinstance(fname, unicode):
175 filename = fname.encode(sys.getfilesystemencoding())
177 filename = fname.encode(sys.getfilesystemencoding())
176 else:
178 else:
177 filename = fname
179 filename = fname
178 __builtin__.execfile(filename, *where)
180 __builtin__.execfile(filename, *where)
General Comments 0
You need to be logged in to leave comments. Login now