##// END OF EJS Templates
pycompat: define operating system constants...
Jun Wu -
r34645:c0a6c196 default
parent child Browse files
Show More
@@ -1,318 +1,322 b''
1 # pycompat.py - portability shim for python 3
1 # pycompat.py - portability shim for python 3
2 #
2 #
3 # This software may be used and distributed according to the terms of the
3 # This software may be used and distributed according to the terms of the
4 # GNU General Public License version 2 or any later version.
4 # GNU General Public License version 2 or any later version.
5
5
6 """Mercurial portability shim for python 3.
6 """Mercurial portability shim for python 3.
7
7
8 This contains aliases to hide python version-specific details from the core.
8 This contains aliases to hide python version-specific details from the core.
9 """
9 """
10
10
11 from __future__ import absolute_import
11 from __future__ import absolute_import
12
12
13 import getopt
13 import getopt
14 import os
14 import os
15 import shlex
15 import shlex
16 import sys
16 import sys
17
17
18 ispy3 = (sys.version_info[0] >= 3)
18 ispy3 = (sys.version_info[0] >= 3)
19 ispypy = (r'__pypy__' in sys.builtin_module_names)
19 ispypy = (r'__pypy__' in sys.builtin_module_names)
20
20
21 if not ispy3:
21 if not ispy3:
22 import cookielib
22 import cookielib
23 import cPickle as pickle
23 import cPickle as pickle
24 import httplib
24 import httplib
25 import Queue as _queue
25 import Queue as _queue
26 import SocketServer as socketserver
26 import SocketServer as socketserver
27 import xmlrpclib
27 import xmlrpclib
28 else:
28 else:
29 import http.cookiejar as cookielib
29 import http.cookiejar as cookielib
30 import http.client as httplib
30 import http.client as httplib
31 import pickle
31 import pickle
32 import queue as _queue
32 import queue as _queue
33 import socketserver
33 import socketserver
34 import xmlrpc.client as xmlrpclib
34 import xmlrpc.client as xmlrpclib
35
35
36 empty = _queue.Empty
36 empty = _queue.Empty
37 queue = _queue.Queue
37 queue = _queue.Queue
38
38
39 def identity(a):
39 def identity(a):
40 return a
40 return a
41
41
42 if ispy3:
42 if ispy3:
43 import builtins
43 import builtins
44 import functools
44 import functools
45 import io
45 import io
46 import struct
46 import struct
47
47
48 fsencode = os.fsencode
48 fsencode = os.fsencode
49 fsdecode = os.fsdecode
49 fsdecode = os.fsdecode
50 oslinesep = os.linesep.encode('ascii')
50 oslinesep = os.linesep.encode('ascii')
51 osname = os.name.encode('ascii')
51 osname = os.name.encode('ascii')
52 ospathsep = os.pathsep.encode('ascii')
52 ospathsep = os.pathsep.encode('ascii')
53 ossep = os.sep.encode('ascii')
53 ossep = os.sep.encode('ascii')
54 osaltsep = os.altsep
54 osaltsep = os.altsep
55 if osaltsep:
55 if osaltsep:
56 osaltsep = osaltsep.encode('ascii')
56 osaltsep = osaltsep.encode('ascii')
57 # os.getcwd() on Python 3 returns string, but it has os.getcwdb() which
57 # os.getcwd() on Python 3 returns string, but it has os.getcwdb() which
58 # returns bytes.
58 # returns bytes.
59 getcwd = os.getcwdb
59 getcwd = os.getcwdb
60 sysplatform = sys.platform.encode('ascii')
60 sysplatform = sys.platform.encode('ascii')
61 sysexecutable = sys.executable
61 sysexecutable = sys.executable
62 if sysexecutable:
62 if sysexecutable:
63 sysexecutable = os.fsencode(sysexecutable)
63 sysexecutable = os.fsencode(sysexecutable)
64 stringio = io.BytesIO
64 stringio = io.BytesIO
65 maplist = lambda *args: list(map(*args))
65 maplist = lambda *args: list(map(*args))
66 rawinput = input
66 rawinput = input
67
67
68 # TODO: .buffer might not exist if std streams were replaced; we'll need
68 # TODO: .buffer might not exist if std streams were replaced; we'll need
69 # a silly wrapper to make a bytes stream backed by a unicode one.
69 # a silly wrapper to make a bytes stream backed by a unicode one.
70 stdin = sys.stdin.buffer
70 stdin = sys.stdin.buffer
71 stdout = sys.stdout.buffer
71 stdout = sys.stdout.buffer
72 stderr = sys.stderr.buffer
72 stderr = sys.stderr.buffer
73
73
74 # Since Python 3 converts argv to wchar_t type by Py_DecodeLocale() on Unix,
74 # Since Python 3 converts argv to wchar_t type by Py_DecodeLocale() on Unix,
75 # we can use os.fsencode() to get back bytes argv.
75 # we can use os.fsencode() to get back bytes argv.
76 #
76 #
77 # https://hg.python.org/cpython/file/v3.5.1/Programs/python.c#l55
77 # https://hg.python.org/cpython/file/v3.5.1/Programs/python.c#l55
78 #
78 #
79 # TODO: On Windows, the native argv is wchar_t, so we'll need a different
79 # TODO: On Windows, the native argv is wchar_t, so we'll need a different
80 # workaround to simulate the Python 2 (i.e. ANSI Win32 API) behavior.
80 # workaround to simulate the Python 2 (i.e. ANSI Win32 API) behavior.
81 if getattr(sys, 'argv', None) is not None:
81 if getattr(sys, 'argv', None) is not None:
82 sysargv = list(map(os.fsencode, sys.argv))
82 sysargv = list(map(os.fsencode, sys.argv))
83
83
84 bytechr = struct.Struct('>B').pack
84 bytechr = struct.Struct('>B').pack
85
85
86 class bytestr(bytes):
86 class bytestr(bytes):
87 """A bytes which mostly acts as a Python 2 str
87 """A bytes which mostly acts as a Python 2 str
88
88
89 >>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1)
89 >>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1)
90 (b'', b'foo', b'ascii', b'1')
90 (b'', b'foo', b'ascii', b'1')
91 >>> s = bytestr(b'foo')
91 >>> s = bytestr(b'foo')
92 >>> assert s is bytestr(s)
92 >>> assert s is bytestr(s)
93
93
94 __bytes__() should be called if provided:
94 __bytes__() should be called if provided:
95
95
96 >>> class bytesable(object):
96 >>> class bytesable(object):
97 ... def __bytes__(self):
97 ... def __bytes__(self):
98 ... return b'bytes'
98 ... return b'bytes'
99 >>> bytestr(bytesable())
99 >>> bytestr(bytesable())
100 b'bytes'
100 b'bytes'
101
101
102 There's no implicit conversion from non-ascii str as its encoding is
102 There's no implicit conversion from non-ascii str as its encoding is
103 unknown:
103 unknown:
104
104
105 >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS
105 >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS
106 Traceback (most recent call last):
106 Traceback (most recent call last):
107 ...
107 ...
108 UnicodeEncodeError: ...
108 UnicodeEncodeError: ...
109
109
110 Comparison between bytestr and bytes should work:
110 Comparison between bytestr and bytes should work:
111
111
112 >>> assert bytestr(b'foo') == b'foo'
112 >>> assert bytestr(b'foo') == b'foo'
113 >>> assert b'foo' == bytestr(b'foo')
113 >>> assert b'foo' == bytestr(b'foo')
114 >>> assert b'f' in bytestr(b'foo')
114 >>> assert b'f' in bytestr(b'foo')
115 >>> assert bytestr(b'f') in b'foo'
115 >>> assert bytestr(b'f') in b'foo'
116
116
117 Sliced elements should be bytes, not integer:
117 Sliced elements should be bytes, not integer:
118
118
119 >>> s[1], s[:2]
119 >>> s[1], s[:2]
120 (b'o', b'fo')
120 (b'o', b'fo')
121 >>> list(s), list(reversed(s))
121 >>> list(s), list(reversed(s))
122 ([b'f', b'o', b'o'], [b'o', b'o', b'f'])
122 ([b'f', b'o', b'o'], [b'o', b'o', b'f'])
123
123
124 As bytestr type isn't propagated across operations, you need to cast
124 As bytestr type isn't propagated across operations, you need to cast
125 bytes to bytestr explicitly:
125 bytes to bytestr explicitly:
126
126
127 >>> s = bytestr(b'foo').upper()
127 >>> s = bytestr(b'foo').upper()
128 >>> t = bytestr(s)
128 >>> t = bytestr(s)
129 >>> s[0], t[0]
129 >>> s[0], t[0]
130 (70, b'F')
130 (70, b'F')
131
131
132 Be careful to not pass a bytestr object to a function which expects
132 Be careful to not pass a bytestr object to a function which expects
133 bytearray-like behavior.
133 bytearray-like behavior.
134
134
135 >>> t = bytes(t) # cast to bytes
135 >>> t = bytes(t) # cast to bytes
136 >>> assert type(t) is bytes
136 >>> assert type(t) is bytes
137 """
137 """
138
138
139 def __new__(cls, s=b''):
139 def __new__(cls, s=b''):
140 if isinstance(s, bytestr):
140 if isinstance(s, bytestr):
141 return s
141 return s
142 if (not isinstance(s, (bytes, bytearray))
142 if (not isinstance(s, (bytes, bytearray))
143 and not hasattr(s, u'__bytes__')): # hasattr-py3-only
143 and not hasattr(s, u'__bytes__')): # hasattr-py3-only
144 s = str(s).encode(u'ascii')
144 s = str(s).encode(u'ascii')
145 return bytes.__new__(cls, s)
145 return bytes.__new__(cls, s)
146
146
147 def __getitem__(self, key):
147 def __getitem__(self, key):
148 s = bytes.__getitem__(self, key)
148 s = bytes.__getitem__(self, key)
149 if not isinstance(s, bytes):
149 if not isinstance(s, bytes):
150 s = bytechr(s)
150 s = bytechr(s)
151 return s
151 return s
152
152
153 def __iter__(self):
153 def __iter__(self):
154 return iterbytestr(bytes.__iter__(self))
154 return iterbytestr(bytes.__iter__(self))
155
155
156 def iterbytestr(s):
156 def iterbytestr(s):
157 """Iterate bytes as if it were a str object of Python 2"""
157 """Iterate bytes as if it were a str object of Python 2"""
158 return map(bytechr, s)
158 return map(bytechr, s)
159
159
160 def sysbytes(s):
160 def sysbytes(s):
161 """Convert an internal str (e.g. keyword, __doc__) back to bytes
161 """Convert an internal str (e.g. keyword, __doc__) back to bytes
162
162
163 This never raises UnicodeEncodeError, but only ASCII characters
163 This never raises UnicodeEncodeError, but only ASCII characters
164 can be round-trip by sysstr(sysbytes(s)).
164 can be round-trip by sysstr(sysbytes(s)).
165 """
165 """
166 return s.encode(u'utf-8')
166 return s.encode(u'utf-8')
167
167
168 def sysstr(s):
168 def sysstr(s):
169 """Return a keyword str to be passed to Python functions such as
169 """Return a keyword str to be passed to Python functions such as
170 getattr() and str.encode()
170 getattr() and str.encode()
171
171
172 This never raises UnicodeDecodeError. Non-ascii characters are
172 This never raises UnicodeDecodeError. Non-ascii characters are
173 considered invalid and mapped to arbitrary but unique code points
173 considered invalid and mapped to arbitrary but unique code points
174 such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
174 such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
175 """
175 """
176 if isinstance(s, builtins.str):
176 if isinstance(s, builtins.str):
177 return s
177 return s
178 return s.decode(u'latin-1')
178 return s.decode(u'latin-1')
179
179
180 def strurl(url):
180 def strurl(url):
181 """Converts a bytes url back to str"""
181 """Converts a bytes url back to str"""
182 return url.decode(u'ascii')
182 return url.decode(u'ascii')
183
183
184 def bytesurl(url):
184 def bytesurl(url):
185 """Converts a str url to bytes by encoding in ascii"""
185 """Converts a str url to bytes by encoding in ascii"""
186 return url.encode(u'ascii')
186 return url.encode(u'ascii')
187
187
188 def raisewithtb(exc, tb):
188 def raisewithtb(exc, tb):
189 """Raise exception with the given traceback"""
189 """Raise exception with the given traceback"""
190 raise exc.with_traceback(tb)
190 raise exc.with_traceback(tb)
191
191
192 def getdoc(obj):
192 def getdoc(obj):
193 """Get docstring as bytes; may be None so gettext() won't confuse it
193 """Get docstring as bytes; may be None so gettext() won't confuse it
194 with _('')"""
194 with _('')"""
195 doc = getattr(obj, u'__doc__', None)
195 doc = getattr(obj, u'__doc__', None)
196 if doc is None:
196 if doc is None:
197 return doc
197 return doc
198 return sysbytes(doc)
198 return sysbytes(doc)
199
199
200 def _wrapattrfunc(f):
200 def _wrapattrfunc(f):
201 @functools.wraps(f)
201 @functools.wraps(f)
202 def w(object, name, *args):
202 def w(object, name, *args):
203 return f(object, sysstr(name), *args)
203 return f(object, sysstr(name), *args)
204 return w
204 return w
205
205
206 # these wrappers are automagically imported by hgloader
206 # these wrappers are automagically imported by hgloader
207 delattr = _wrapattrfunc(builtins.delattr)
207 delattr = _wrapattrfunc(builtins.delattr)
208 getattr = _wrapattrfunc(builtins.getattr)
208 getattr = _wrapattrfunc(builtins.getattr)
209 hasattr = _wrapattrfunc(builtins.hasattr)
209 hasattr = _wrapattrfunc(builtins.hasattr)
210 setattr = _wrapattrfunc(builtins.setattr)
210 setattr = _wrapattrfunc(builtins.setattr)
211 xrange = builtins.range
211 xrange = builtins.range
212 unicode = str
212 unicode = str
213
213
214 def open(name, mode='r', buffering=-1):
214 def open(name, mode='r', buffering=-1):
215 return builtins.open(name, sysstr(mode), buffering)
215 return builtins.open(name, sysstr(mode), buffering)
216
216
217 def getoptb(args, shortlist, namelist):
217 def getoptb(args, shortlist, namelist):
218 """
218 """
219 Takes bytes arguments, converts them to unicode, pass them to
219 Takes bytes arguments, converts them to unicode, pass them to
220 getopt.getopt(), convert the returned values back to bytes and then
220 getopt.getopt(), convert the returned values back to bytes and then
221 return them for Python 3 compatibility as getopt.getopt() don't accepts
221 return them for Python 3 compatibility as getopt.getopt() don't accepts
222 bytes on Python 3.
222 bytes on Python 3.
223 """
223 """
224 args = [a.decode('latin-1') for a in args]
224 args = [a.decode('latin-1') for a in args]
225 shortlist = shortlist.decode('latin-1')
225 shortlist = shortlist.decode('latin-1')
226 namelist = [a.decode('latin-1') for a in namelist]
226 namelist = [a.decode('latin-1') for a in namelist]
227 opts, args = getopt.getopt(args, shortlist, namelist)
227 opts, args = getopt.getopt(args, shortlist, namelist)
228 opts = [(a[0].encode('latin-1'), a[1].encode('latin-1'))
228 opts = [(a[0].encode('latin-1'), a[1].encode('latin-1'))
229 for a in opts]
229 for a in opts]
230 args = [a.encode('latin-1') for a in args]
230 args = [a.encode('latin-1') for a in args]
231 return opts, args
231 return opts, args
232
232
233 def strkwargs(dic):
233 def strkwargs(dic):
234 """
234 """
235 Converts the keys of a python dictonary to str i.e. unicodes so that
235 Converts the keys of a python dictonary to str i.e. unicodes so that
236 they can be passed as keyword arguments as dictonaries with bytes keys
236 they can be passed as keyword arguments as dictonaries with bytes keys
237 can't be passed as keyword arguments to functions on Python 3.
237 can't be passed as keyword arguments to functions on Python 3.
238 """
238 """
239 dic = dict((k.decode('latin-1'), v) for k, v in dic.iteritems())
239 dic = dict((k.decode('latin-1'), v) for k, v in dic.iteritems())
240 return dic
240 return dic
241
241
242 def byteskwargs(dic):
242 def byteskwargs(dic):
243 """
243 """
244 Converts keys of python dictonaries to bytes as they were converted to
244 Converts keys of python dictonaries to bytes as they were converted to
245 str to pass that dictonary as a keyword argument on Python 3.
245 str to pass that dictonary as a keyword argument on Python 3.
246 """
246 """
247 dic = dict((k.encode('latin-1'), v) for k, v in dic.iteritems())
247 dic = dict((k.encode('latin-1'), v) for k, v in dic.iteritems())
248 return dic
248 return dic
249
249
250 # TODO: handle shlex.shlex().
250 # TODO: handle shlex.shlex().
251 def shlexsplit(s):
251 def shlexsplit(s):
252 """
252 """
253 Takes bytes argument, convert it to str i.e. unicodes, pass that into
253 Takes bytes argument, convert it to str i.e. unicodes, pass that into
254 shlex.split(), convert the returned value to bytes and return that for
254 shlex.split(), convert the returned value to bytes and return that for
255 Python 3 compatibility as shelx.split() don't accept bytes on Python 3.
255 Python 3 compatibility as shelx.split() don't accept bytes on Python 3.
256 """
256 """
257 ret = shlex.split(s.decode('latin-1'))
257 ret = shlex.split(s.decode('latin-1'))
258 return [a.encode('latin-1') for a in ret]
258 return [a.encode('latin-1') for a in ret]
259
259
260 else:
260 else:
261 import cStringIO
261 import cStringIO
262
262
263 bytechr = chr
263 bytechr = chr
264 bytestr = str
264 bytestr = str
265 iterbytestr = iter
265 iterbytestr = iter
266 sysbytes = identity
266 sysbytes = identity
267 sysstr = identity
267 sysstr = identity
268 strurl = identity
268 strurl = identity
269 bytesurl = identity
269 bytesurl = identity
270
270
271 # this can't be parsed on Python 3
271 # this can't be parsed on Python 3
272 exec('def raisewithtb(exc, tb):\n'
272 exec('def raisewithtb(exc, tb):\n'
273 ' raise exc, None, tb\n')
273 ' raise exc, None, tb\n')
274
274
275 def fsencode(filename):
275 def fsencode(filename):
276 """
276 """
277 Partial backport from os.py in Python 3, which only accepts bytes.
277 Partial backport from os.py in Python 3, which only accepts bytes.
278 In Python 2, our paths should only ever be bytes, a unicode path
278 In Python 2, our paths should only ever be bytes, a unicode path
279 indicates a bug.
279 indicates a bug.
280 """
280 """
281 if isinstance(filename, str):
281 if isinstance(filename, str):
282 return filename
282 return filename
283 else:
283 else:
284 raise TypeError(
284 raise TypeError(
285 "expect str, not %s" % type(filename).__name__)
285 "expect str, not %s" % type(filename).__name__)
286
286
287 # In Python 2, fsdecode() has a very chance to receive bytes. So it's
287 # In Python 2, fsdecode() has a very chance to receive bytes. So it's
288 # better not to touch Python 2 part as it's already working fine.
288 # better not to touch Python 2 part as it's already working fine.
289 fsdecode = identity
289 fsdecode = identity
290
290
291 def getdoc(obj):
291 def getdoc(obj):
292 return getattr(obj, '__doc__', None)
292 return getattr(obj, '__doc__', None)
293
293
294 def getoptb(args, shortlist, namelist):
294 def getoptb(args, shortlist, namelist):
295 return getopt.getopt(args, shortlist, namelist)
295 return getopt.getopt(args, shortlist, namelist)
296
296
297 strkwargs = identity
297 strkwargs = identity
298 byteskwargs = identity
298 byteskwargs = identity
299
299
300 oslinesep = os.linesep
300 oslinesep = os.linesep
301 osname = os.name
301 osname = os.name
302 ospathsep = os.pathsep
302 ospathsep = os.pathsep
303 ossep = os.sep
303 ossep = os.sep
304 osaltsep = os.altsep
304 osaltsep = os.altsep
305 stdin = sys.stdin
305 stdin = sys.stdin
306 stdout = sys.stdout
306 stdout = sys.stdout
307 stderr = sys.stderr
307 stderr = sys.stderr
308 if getattr(sys, 'argv', None) is not None:
308 if getattr(sys, 'argv', None) is not None:
309 sysargv = sys.argv
309 sysargv = sys.argv
310 sysplatform = sys.platform
310 sysplatform = sys.platform
311 getcwd = os.getcwd
311 getcwd = os.getcwd
312 sysexecutable = sys.executable
312 sysexecutable = sys.executable
313 shlexsplit = shlex.split
313 shlexsplit = shlex.split
314 stringio = cStringIO.StringIO
314 stringio = cStringIO.StringIO
315 maplist = map
315 maplist = map
316 rawinput = raw_input
316 rawinput = raw_input
317
317
318 isjython = sysplatform.startswith('java')
318 isjython = sysplatform.startswith('java')
319
320 isdarwin = sysplatform == 'darwin'
321 isposix = osname == 'posix'
322 iswindows = osname == 'nt'
General Comments 0
You need to be logged in to leave comments. Login now