##// END OF EJS Templates
pycompat: deprecate using bytes...
marmoute -
r51817:9bffc6c4 default
parent child Browse files
Show More
@@ -1,498 +1,505 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
11
12 import builtins
12 import builtins
13 import codecs
13 import codecs
14 import concurrent.futures as futures
14 import concurrent.futures as futures
15 import functools
15 import functools
16 import getopt
16 import getopt
17 import http.client as httplib
17 import http.client as httplib
18 import http.cookiejar as cookielib
18 import http.cookiejar as cookielib
19 import inspect
19 import inspect
20 import io
20 import io
21 import json
21 import json
22 import os
22 import os
23 import queue
23 import queue
24 import shlex
24 import shlex
25 import socketserver
25 import socketserver
26 import struct
26 import struct
27 import sys
27 import sys
28 import tempfile
28 import tempfile
29 import xmlrpc.client as xmlrpclib
29 import xmlrpc.client as xmlrpclib
30
30
31 from typing import (
31 from typing import (
32 Any,
32 Any,
33 AnyStr,
33 AnyStr,
34 BinaryIO,
34 BinaryIO,
35 Callable,
35 Callable,
36 Dict,
36 Dict,
37 Iterable,
37 Iterable,
38 Iterator,
38 Iterator,
39 List,
39 List,
40 Mapping,
40 Mapping,
41 NoReturn,
41 NoReturn,
42 Optional,
42 Optional,
43 Sequence,
43 Sequence,
44 Tuple,
44 Tuple,
45 Type,
45 Type,
46 TypeVar,
46 TypeVar,
47 cast,
47 cast,
48 overload,
48 overload,
49 )
49 )
50
50
51 ispy3 = sys.version_info[0] >= 3
51 ispy3 = sys.version_info[0] >= 3
52 ispypy = '__pypy__' in sys.builtin_module_names
52 ispypy = '__pypy__' in sys.builtin_module_names
53 TYPE_CHECKING = False
53 TYPE_CHECKING = False
54
54
55 if not globals(): # hide this from non-pytype users
55 if not globals(): # hide this from non-pytype users
56 import typing
56 import typing
57
57
58 TYPE_CHECKING = typing.TYPE_CHECKING
58 TYPE_CHECKING = typing.TYPE_CHECKING
59
59
60 _GetOptResult = Tuple[List[Tuple[bytes, bytes]], List[bytes]]
60 _GetOptResult = Tuple[List[Tuple[bytes, bytes]], List[bytes]]
61 _T0 = TypeVar('_T0')
61 _T0 = TypeVar('_T0')
62 _T1 = TypeVar('_T1')
62 _T1 = TypeVar('_T1')
63 _S = TypeVar('_S')
63 _S = TypeVar('_S')
64 _Tbytestr = TypeVar('_Tbytestr', bound='bytestr')
64 _Tbytestr = TypeVar('_Tbytestr', bound='bytestr')
65
65
66
66
67 def future_set_exception_info(f, exc_info):
67 def future_set_exception_info(f, exc_info):
68 f.set_exception(exc_info[0])
68 f.set_exception(exc_info[0])
69
69
70
70
71 FileNotFoundError = builtins.FileNotFoundError
71 FileNotFoundError = builtins.FileNotFoundError
72
72
73
73
74 def identity(a: _T0) -> _T0:
74 def identity(a: _T0) -> _T0:
75 return a
75 return a
76
76
77
77
78 def _rapply(f, xs):
78 def _rapply(f, xs):
79 if xs is None:
79 if xs is None:
80 # assume None means non-value of optional data
80 # assume None means non-value of optional data
81 return xs
81 return xs
82 if isinstance(xs, (list, set, tuple)):
82 if isinstance(xs, (list, set, tuple)):
83 return type(xs)(_rapply(f, x) for x in xs)
83 return type(xs)(_rapply(f, x) for x in xs)
84 if isinstance(xs, dict):
84 if isinstance(xs, dict):
85 return type(xs)((_rapply(f, k), _rapply(f, v)) for k, v in xs.items())
85 return type(xs)((_rapply(f, k), _rapply(f, v)) for k, v in xs.items())
86 return f(xs)
86 return f(xs)
87
87
88
88
89 def rapply(f, xs):
89 def rapply(f, xs):
90 """Apply function recursively to every item preserving the data structure
90 """Apply function recursively to every item preserving the data structure
91
91
92 >>> def f(x):
92 >>> def f(x):
93 ... return 'f(%s)' % x
93 ... return 'f(%s)' % x
94 >>> rapply(f, None) is None
94 >>> rapply(f, None) is None
95 True
95 True
96 >>> rapply(f, 'a')
96 >>> rapply(f, 'a')
97 'f(a)'
97 'f(a)'
98 >>> rapply(f, {'a'}) == {'f(a)'}
98 >>> rapply(f, {'a'}) == {'f(a)'}
99 True
99 True
100 >>> rapply(f, ['a', 'b', None, {'c': 'd'}, []])
100 >>> rapply(f, ['a', 'b', None, {'c': 'd'}, []])
101 ['f(a)', 'f(b)', None, {'f(c)': 'f(d)'}, []]
101 ['f(a)', 'f(b)', None, {'f(c)': 'f(d)'}, []]
102
102
103 >>> xs = [object()]
103 >>> xs = [object()]
104 >>> rapply(identity, xs) is xs
104 >>> rapply(identity, xs) is xs
105 True
105 True
106 """
106 """
107 if f is identity:
107 if f is identity:
108 # fast path mainly for py2
108 # fast path mainly for py2
109 return xs
109 return xs
110 return _rapply(f, xs)
110 return _rapply(f, xs)
111
111
112
112
113 if os.name == r'nt':
113 if os.name == r'nt':
114 # MBCS (or ANSI) filesystem encoding must be used as before.
114 # MBCS (or ANSI) filesystem encoding must be used as before.
115 # Otherwise non-ASCII filenames in existing repositories would be
115 # Otherwise non-ASCII filenames in existing repositories would be
116 # corrupted.
116 # corrupted.
117 # This must be set once prior to any fsencode/fsdecode calls.
117 # This must be set once prior to any fsencode/fsdecode calls.
118 sys._enablelegacywindowsfsencoding() # pytype: disable=module-attr
118 sys._enablelegacywindowsfsencoding() # pytype: disable=module-attr
119
119
120 fsencode = os.fsencode
120 fsencode = os.fsencode
121 fsdecode = os.fsdecode
121 fsdecode = os.fsdecode
122 oscurdir: bytes = os.curdir.encode('ascii')
122 oscurdir: bytes = os.curdir.encode('ascii')
123 oslinesep: bytes = os.linesep.encode('ascii')
123 oslinesep: bytes = os.linesep.encode('ascii')
124 osname: bytes = os.name.encode('ascii')
124 osname: bytes = os.name.encode('ascii')
125 ospathsep: bytes = os.pathsep.encode('ascii')
125 ospathsep: bytes = os.pathsep.encode('ascii')
126 ospardir: bytes = os.pardir.encode('ascii')
126 ospardir: bytes = os.pardir.encode('ascii')
127 ossep: bytes = os.sep.encode('ascii')
127 ossep: bytes = os.sep.encode('ascii')
128 osaltsep: Optional[bytes] = os.altsep.encode('ascii') if os.altsep else None
128 osaltsep: Optional[bytes] = os.altsep.encode('ascii') if os.altsep else None
129 osdevnull: bytes = os.devnull.encode('ascii')
129 osdevnull: bytes = os.devnull.encode('ascii')
130
130
131 sysplatform: bytes = sys.platform.encode('ascii')
131 sysplatform: bytes = sys.platform.encode('ascii')
132 sysexecutable: bytes = os.fsencode(sys.executable) if sys.executable else b''
132 sysexecutable: bytes = os.fsencode(sys.executable) if sys.executable else b''
133
133
134
134
135 if TYPE_CHECKING:
135 if TYPE_CHECKING:
136
136
137 @overload
137 @overload
138 def maplist(f: Callable[[_T0], _S], arg: Iterable[_T0]) -> List[_S]:
138 def maplist(f: Callable[[_T0], _S], arg: Iterable[_T0]) -> List[_S]:
139 ...
139 ...
140
140
141 @overload
141 @overload
142 def maplist(
142 def maplist(
143 f: Callable[[_T0, _T1], _S], arg1: Iterable[_T0], arg2: Iterable[_T1]
143 f: Callable[[_T0, _T1], _S], arg1: Iterable[_T0], arg2: Iterable[_T1]
144 ) -> List[_S]:
144 ) -> List[_S]:
145 ...
145 ...
146
146
147
147
148 def maplist(f, *args):
148 def maplist(f, *args):
149 return list(map(f, *args))
149 return list(map(f, *args))
150
150
151
151
152 def rangelist(*args) -> List[int]:
152 def rangelist(*args) -> List[int]:
153 return list(range(*args))
153 return list(range(*args))
154
154
155
155
156 def ziplist(*args):
156 def ziplist(*args):
157 return list(zip(*args))
157 return list(zip(*args))
158
158
159
159
160 rawinput = input
160 rawinput = input
161 getargspec = inspect.getfullargspec
161 getargspec = inspect.getfullargspec
162
162
163 long = int
163 long = int
164
164
165 if builtins.getattr(sys, 'argv', None) is not None:
165 if builtins.getattr(sys, 'argv', None) is not None:
166 # On POSIX, the char** argv array is converted to Python str using
166 # On POSIX, the char** argv array is converted to Python str using
167 # Py_DecodeLocale(). The inverse of this is Py_EncodeLocale(), which
167 # Py_DecodeLocale(). The inverse of this is Py_EncodeLocale(), which
168 # isn't directly callable from Python code. In practice, os.fsencode()
168 # isn't directly callable from Python code. In practice, os.fsencode()
169 # can be used instead (this is recommended by Python's documentation
169 # can be used instead (this is recommended by Python's documentation
170 # for sys.argv).
170 # for sys.argv).
171 #
171 #
172 # On Windows, the wchar_t **argv is passed into the interpreter as-is.
172 # On Windows, the wchar_t **argv is passed into the interpreter as-is.
173 # Like POSIX, we need to emulate what Py_EncodeLocale() would do. But
173 # Like POSIX, we need to emulate what Py_EncodeLocale() would do. But
174 # there's an additional wrinkle. What we really want to access is the
174 # there's an additional wrinkle. What we really want to access is the
175 # ANSI codepage representation of the arguments, as this is what
175 # ANSI codepage representation of the arguments, as this is what
176 # `int main()` would receive if Python 3 didn't define `int wmain()`
176 # `int main()` would receive if Python 3 didn't define `int wmain()`
177 # (this is how Python 2 worked). To get that, we encode with the mbcs
177 # (this is how Python 2 worked). To get that, we encode with the mbcs
178 # encoding, which will pass CP_ACP to the underlying Windows API to
178 # encoding, which will pass CP_ACP to the underlying Windows API to
179 # produce bytes.
179 # produce bytes.
180 sysargv: List[bytes] = []
180 sysargv: List[bytes] = []
181 if os.name == r'nt':
181 if os.name == r'nt':
182 sysargv = [a.encode("mbcs", "ignore") for a in sys.argv]
182 sysargv = [a.encode("mbcs", "ignore") for a in sys.argv]
183 else:
183 else:
184 sysargv = [fsencode(a) for a in sys.argv]
184 sysargv = [fsencode(a) for a in sys.argv]
185
185
186 bytechr = struct.Struct('>B').pack
186 bytechr = struct.Struct('>B').pack
187 byterepr = b'%r'.__mod__
187 byterepr = b'%r'.__mod__
188
188
189
189
190 class bytestr(bytes):
190 class bytestr(bytes):
191 """A bytes which mostly acts as a Python 2 str
191 """A bytes which mostly acts as a Python 2 str
192
192
193 >>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1)
193 >>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1)
194 ('', 'foo', 'ascii', '1')
194 ('', 'foo', 'ascii', '1')
195 >>> s = bytestr(b'foo')
195 >>> s = bytestr(b'foo')
196 >>> assert s is bytestr(s)
196 >>> assert s is bytestr(s)
197
197
198 __bytes__() should be called if provided:
198 __bytes__() should be called if provided:
199
199
200 >>> class bytesable:
200 >>> class bytesable:
201 ... def __bytes__(self):
201 ... def __bytes__(self):
202 ... return b'bytes'
202 ... return b'bytes'
203 >>> bytestr(bytesable())
203 >>> bytestr(bytesable())
204 'bytes'
204 'bytes'
205
205
206 There's no implicit conversion from non-ascii str as its encoding is
206 There's no implicit conversion from non-ascii str as its encoding is
207 unknown:
207 unknown:
208
208
209 >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS
209 >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS
210 Traceback (most recent call last):
210 Traceback (most recent call last):
211 ...
211 ...
212 UnicodeEncodeError: ...
212 UnicodeEncodeError: ...
213
213
214 Comparison between bytestr and bytes should work:
214 Comparison between bytestr and bytes should work:
215
215
216 >>> assert bytestr(b'foo') == b'foo'
216 >>> assert bytestr(b'foo') == b'foo'
217 >>> assert b'foo' == bytestr(b'foo')
217 >>> assert b'foo' == bytestr(b'foo')
218 >>> assert b'f' in bytestr(b'foo')
218 >>> assert b'f' in bytestr(b'foo')
219 >>> assert bytestr(b'f') in b'foo'
219 >>> assert bytestr(b'f') in b'foo'
220
220
221 Sliced elements should be bytes, not integer:
221 Sliced elements should be bytes, not integer:
222
222
223 >>> s[1], s[:2]
223 >>> s[1], s[:2]
224 (b'o', b'fo')
224 (b'o', b'fo')
225 >>> list(s), list(reversed(s))
225 >>> list(s), list(reversed(s))
226 ([b'f', b'o', b'o'], [b'o', b'o', b'f'])
226 ([b'f', b'o', b'o'], [b'o', b'o', b'f'])
227
227
228 As bytestr type isn't propagated across operations, you need to cast
228 As bytestr type isn't propagated across operations, you need to cast
229 bytes to bytestr explicitly:
229 bytes to bytestr explicitly:
230
230
231 >>> s = bytestr(b'foo').upper()
231 >>> s = bytestr(b'foo').upper()
232 >>> t = bytestr(s)
232 >>> t = bytestr(s)
233 >>> s[0], t[0]
233 >>> s[0], t[0]
234 (70, b'F')
234 (70, b'F')
235
235
236 Be careful to not pass a bytestr object to a function which expects
236 Be careful to not pass a bytestr object to a function which expects
237 bytearray-like behavior.
237 bytearray-like behavior.
238
238
239 >>> t = bytes(t) # cast to bytes
239 >>> t = bytes(t) # cast to bytes
240 >>> assert type(t) is bytes
240 >>> assert type(t) is bytes
241 """
241 """
242
242
243 # Trick pytype into not demanding Iterable[int] be passed to __new__(),
243 # Trick pytype into not demanding Iterable[int] be passed to __new__(),
244 # since the appropriate bytes format is done internally.
244 # since the appropriate bytes format is done internally.
245 #
245 #
246 # https://github.com/google/pytype/issues/500
246 # https://github.com/google/pytype/issues/500
247 if TYPE_CHECKING:
247 if TYPE_CHECKING:
248
248
249 def __init__(self, s: object = b'') -> None:
249 def __init__(self, s: object = b'') -> None:
250 pass
250 pass
251
251
252 def __new__(cls: Type[_Tbytestr], s: object = b'') -> _Tbytestr:
252 def __new__(cls: Type[_Tbytestr], s: object = b'') -> _Tbytestr:
253 if isinstance(s, bytestr):
253 if isinstance(s, bytestr):
254 return s
254 return s
255 if not isinstance(
255 if not isinstance(
256 s, (bytes, bytearray)
256 s, (bytes, bytearray)
257 ) and not builtins.hasattr( # hasattr-py3-only
257 ) and not builtins.hasattr( # hasattr-py3-only
258 s, u'__bytes__'
258 s, u'__bytes__'
259 ):
259 ):
260 s = str(s).encode('ascii')
260 s = str(s).encode('ascii')
261 return bytes.__new__(cls, s)
261 return bytes.__new__(cls, s)
262
262
263 # The base class uses `int` return in py3, but the point of this class is to
263 # The base class uses `int` return in py3, but the point of this class is to
264 # behave like py2.
264 # behave like py2.
265 def __getitem__(self, key) -> bytes: # pytype: disable=signature-mismatch
265 def __getitem__(self, key) -> bytes: # pytype: disable=signature-mismatch
266 s = bytes.__getitem__(self, key)
266 s = bytes.__getitem__(self, key)
267 if not isinstance(s, bytes):
267 if not isinstance(s, bytes):
268 s = bytechr(s)
268 s = bytechr(s)
269 return s
269 return s
270
270
271 # The base class expects `Iterator[int]` return in py3, but the point of
271 # The base class expects `Iterator[int]` return in py3, but the point of
272 # this class is to behave like py2.
272 # this class is to behave like py2.
273 def __iter__(self) -> Iterator[bytes]: # pytype: disable=signature-mismatch
273 def __iter__(self) -> Iterator[bytes]: # pytype: disable=signature-mismatch
274 return iterbytestr(bytes.__iter__(self))
274 return iterbytestr(bytes.__iter__(self))
275
275
276 def __repr__(self) -> str:
276 def __repr__(self) -> str:
277 return bytes.__repr__(self)[1:] # drop b''
277 return bytes.__repr__(self)[1:] # drop b''
278
278
279
279
280 def iterbytestr(s: Iterable[int]) -> Iterator[bytes]:
280 def iterbytestr(s: Iterable[int]) -> Iterator[bytes]:
281 """Iterate bytes as if it were a str object of Python 2"""
281 """Iterate bytes as if it were a str object of Python 2"""
282 return map(bytechr, s)
282 return map(bytechr, s)
283
283
284
284
285 if TYPE_CHECKING:
285 if TYPE_CHECKING:
286
286
287 @overload
287 @overload
288 def maybebytestr(s: bytes) -> bytestr:
288 def maybebytestr(s: bytes) -> bytestr:
289 ...
289 ...
290
290
291 @overload
291 @overload
292 def maybebytestr(s: _T0) -> _T0:
292 def maybebytestr(s: _T0) -> _T0:
293 ...
293 ...
294
294
295
295
296 def maybebytestr(s):
296 def maybebytestr(s):
297 """Promote bytes to bytestr"""
297 """Promote bytes to bytestr"""
298 if isinstance(s, bytes):
298 if isinstance(s, bytes):
299 return bytestr(s)
299 return bytestr(s)
300 return s
300 return s
301
301
302
302
303 def sysbytes(s: AnyStr) -> bytes:
303 def sysbytes(s: AnyStr) -> bytes:
304 """Convert an internal str (e.g. keyword, __doc__) back to bytes
304 """Convert an internal str (e.g. keyword, __doc__) back to bytes
305
305
306 This never raises UnicodeEncodeError, but only ASCII characters
306 This never raises UnicodeEncodeError, but only ASCII characters
307 can be round-trip by sysstr(sysbytes(s)).
307 can be round-trip by sysstr(sysbytes(s)).
308 """
308 """
309 if isinstance(s, bytes):
309 if isinstance(s, bytes):
310 return s
310 return s
311 return s.encode('utf-8')
311 return s.encode('utf-8')
312
312
313
313
314 def sysstr(s: AnyStr) -> str:
314 def sysstr(s: AnyStr) -> str:
315 """Return a keyword str to be passed to Python functions such as
315 """Return a keyword str to be passed to Python functions such as
316 getattr() and str.encode()
316 getattr() and str.encode()
317
317
318 This never raises UnicodeDecodeError. Non-ascii characters are
318 This never raises UnicodeDecodeError. Non-ascii characters are
319 considered invalid and mapped to arbitrary but unique code points
319 considered invalid and mapped to arbitrary but unique code points
320 such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
320 such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
321 """
321 """
322 if isinstance(s, builtins.str):
322 if isinstance(s, builtins.str):
323 return s
323 return s
324 return s.decode('latin-1')
324 return s.decode('latin-1')
325
325
326
326
327 def strurl(url: AnyStr) -> str:
327 def strurl(url: AnyStr) -> str:
328 """Converts a bytes url back to str"""
328 """Converts a bytes url back to str"""
329 if isinstance(url, bytes):
329 if isinstance(url, bytes):
330 return url.decode('ascii')
330 return url.decode('ascii')
331 return url
331 return url
332
332
333
333
334 def bytesurl(url: AnyStr) -> bytes:
334 def bytesurl(url: AnyStr) -> bytes:
335 """Converts a str url to bytes by encoding in ascii"""
335 """Converts a str url to bytes by encoding in ascii"""
336 if isinstance(url, str):
336 if isinstance(url, str):
337 return url.encode('ascii')
337 return url.encode('ascii')
338 return url
338 return url
339
339
340
340
341 def raisewithtb(exc: BaseException, tb) -> NoReturn:
341 def raisewithtb(exc: BaseException, tb) -> NoReturn:
342 """Raise exception with the given traceback"""
342 """Raise exception with the given traceback"""
343 raise exc.with_traceback(tb)
343 raise exc.with_traceback(tb)
344
344
345
345
346 def getdoc(obj: object) -> Optional[bytes]:
346 def getdoc(obj: object) -> Optional[bytes]:
347 """Get docstring as bytes; may be None so gettext() won't confuse it
347 """Get docstring as bytes; may be None so gettext() won't confuse it
348 with _('')"""
348 with _('')"""
349 doc = builtins.getattr(obj, '__doc__', None)
349 doc = builtins.getattr(obj, '__doc__', None)
350 if doc is None:
350 if doc is None:
351 return doc
351 return doc
352 return sysbytes(doc)
352 return sysbytes(doc)
353
353
354
354
355 def _wrapattrfunc(f):
355 def _wrapattrfunc(f):
356 @functools.wraps(f)
356 @functools.wraps(f)
357 def w(object, name, *args):
357 def w(object, name, *args):
358 if isinstance(name, bytes):
359 from . import util
360
361 msg = b'function "%s" take `str` as argument, not `bytes`'
362 fname = f.__name__.encode('ascii')
363 msg %= fname
364 util.nouideprecwarn(msg, b"6.6", stacklevel=2)
358 return f(object, sysstr(name), *args)
365 return f(object, sysstr(name), *args)
359
366
360 return w
367 return w
361
368
362
369
363 # these wrappers are automagically imported by hgloader
370 # these wrappers are automagically imported by hgloader
364 delattr = _wrapattrfunc(builtins.delattr)
371 delattr = _wrapattrfunc(builtins.delattr)
365 getattr = _wrapattrfunc(builtins.getattr)
372 getattr = _wrapattrfunc(builtins.getattr)
366 hasattr = _wrapattrfunc(builtins.hasattr)
373 hasattr = _wrapattrfunc(builtins.hasattr)
367 setattr = _wrapattrfunc(builtins.setattr)
374 setattr = _wrapattrfunc(builtins.setattr)
368 xrange = builtins.range
375 xrange = builtins.range
369 unicode = str
376 unicode = str
370
377
371
378
372 def open(
379 def open(
373 name,
380 name,
374 mode: AnyStr = b'r',
381 mode: AnyStr = b'r',
375 buffering: int = -1,
382 buffering: int = -1,
376 encoding: Optional[str] = None,
383 encoding: Optional[str] = None,
377 ) -> Any:
384 ) -> Any:
378 # TODO: assert binary mode, and cast result to BinaryIO?
385 # TODO: assert binary mode, and cast result to BinaryIO?
379 return builtins.open(name, sysstr(mode), buffering, encoding)
386 return builtins.open(name, sysstr(mode), buffering, encoding)
380
387
381
388
382 safehasattr = _wrapattrfunc(builtins.hasattr)
389 safehasattr = _wrapattrfunc(builtins.hasattr)
383
390
384
391
385 def _getoptbwrapper(
392 def _getoptbwrapper(
386 orig, args: Sequence[bytes], shortlist: bytes, namelist: Sequence[bytes]
393 orig, args: Sequence[bytes], shortlist: bytes, namelist: Sequence[bytes]
387 ) -> _GetOptResult:
394 ) -> _GetOptResult:
388 """
395 """
389 Takes bytes arguments, converts them to unicode, pass them to
396 Takes bytes arguments, converts them to unicode, pass them to
390 getopt.getopt(), convert the returned values back to bytes and then
397 getopt.getopt(), convert the returned values back to bytes and then
391 return them for Python 3 compatibility as getopt.getopt() don't accepts
398 return them for Python 3 compatibility as getopt.getopt() don't accepts
392 bytes on Python 3.
399 bytes on Python 3.
393 """
400 """
394 args = [a.decode('latin-1') for a in args]
401 args = [a.decode('latin-1') for a in args]
395 shortlist = shortlist.decode('latin-1')
402 shortlist = shortlist.decode('latin-1')
396 namelist = [a.decode('latin-1') for a in namelist]
403 namelist = [a.decode('latin-1') for a in namelist]
397 opts, args = orig(args, shortlist, namelist)
404 opts, args = orig(args, shortlist, namelist)
398 opts = [(a[0].encode('latin-1'), a[1].encode('latin-1')) for a in opts]
405 opts = [(a[0].encode('latin-1'), a[1].encode('latin-1')) for a in opts]
399 args = [a.encode('latin-1') for a in args]
406 args = [a.encode('latin-1') for a in args]
400 return opts, args
407 return opts, args
401
408
402
409
403 def strkwargs(dic: Mapping[bytes, _T0]) -> Dict[str, _T0]:
410 def strkwargs(dic: Mapping[bytes, _T0]) -> Dict[str, _T0]:
404 """
411 """
405 Converts the keys of a python dictonary to str i.e. unicodes so that
412 Converts the keys of a python dictonary to str i.e. unicodes so that
406 they can be passed as keyword arguments as dictionaries with bytes keys
413 they can be passed as keyword arguments as dictionaries with bytes keys
407 can't be passed as keyword arguments to functions on Python 3.
414 can't be passed as keyword arguments to functions on Python 3.
408 """
415 """
409 dic = {k.decode('latin-1'): v for k, v in dic.items()}
416 dic = {k.decode('latin-1'): v for k, v in dic.items()}
410 return dic
417 return dic
411
418
412
419
413 def byteskwargs(dic: Mapping[str, _T0]) -> Dict[bytes, _T0]:
420 def byteskwargs(dic: Mapping[str, _T0]) -> Dict[bytes, _T0]:
414 """
421 """
415 Converts keys of python dictionaries to bytes as they were converted to
422 Converts keys of python dictionaries to bytes as they were converted to
416 str to pass that dictonary as a keyword argument on Python 3.
423 str to pass that dictonary as a keyword argument on Python 3.
417 """
424 """
418 dic = {k.encode('latin-1'): v for k, v in dic.items()}
425 dic = {k.encode('latin-1'): v for k, v in dic.items()}
419 return dic
426 return dic
420
427
421
428
422 # TODO: handle shlex.shlex().
429 # TODO: handle shlex.shlex().
423 def shlexsplit(
430 def shlexsplit(
424 s: bytes, comments: bool = False, posix: bool = True
431 s: bytes, comments: bool = False, posix: bool = True
425 ) -> List[bytes]:
432 ) -> List[bytes]:
426 """
433 """
427 Takes bytes argument, convert it to str i.e. unicodes, pass that into
434 Takes bytes argument, convert it to str i.e. unicodes, pass that into
428 shlex.split(), convert the returned value to bytes and return that for
435 shlex.split(), convert the returned value to bytes and return that for
429 Python 3 compatibility as shelx.split() don't accept bytes on Python 3.
436 Python 3 compatibility as shelx.split() don't accept bytes on Python 3.
430 """
437 """
431 ret = shlex.split(s.decode('latin-1'), comments, posix)
438 ret = shlex.split(s.decode('latin-1'), comments, posix)
432 return [a.encode('latin-1') for a in ret]
439 return [a.encode('latin-1') for a in ret]
433
440
434
441
435 iteritems = lambda x: x.items()
442 iteritems = lambda x: x.items()
436 itervalues = lambda x: x.values()
443 itervalues = lambda x: x.values()
437
444
438 json_loads = json.loads
445 json_loads = json.loads
439
446
440 isjython: bool = sysplatform.startswith(b'java')
447 isjython: bool = sysplatform.startswith(b'java')
441
448
442 isdarwin: bool = sysplatform.startswith(b'darwin')
449 isdarwin: bool = sysplatform.startswith(b'darwin')
443 islinux: bool = sysplatform.startswith(b'linux')
450 islinux: bool = sysplatform.startswith(b'linux')
444 isposix: bool = osname == b'posix'
451 isposix: bool = osname == b'posix'
445 iswindows: bool = osname == b'nt'
452 iswindows: bool = osname == b'nt'
446
453
447
454
448 def getoptb(
455 def getoptb(
449 args: Sequence[bytes], shortlist: bytes, namelist: Sequence[bytes]
456 args: Sequence[bytes], shortlist: bytes, namelist: Sequence[bytes]
450 ) -> _GetOptResult:
457 ) -> _GetOptResult:
451 return _getoptbwrapper(getopt.getopt, args, shortlist, namelist)
458 return _getoptbwrapper(getopt.getopt, args, shortlist, namelist)
452
459
453
460
454 def gnugetoptb(
461 def gnugetoptb(
455 args: Sequence[bytes], shortlist: bytes, namelist: Sequence[bytes]
462 args: Sequence[bytes], shortlist: bytes, namelist: Sequence[bytes]
456 ) -> _GetOptResult:
463 ) -> _GetOptResult:
457 return _getoptbwrapper(getopt.gnu_getopt, args, shortlist, namelist)
464 return _getoptbwrapper(getopt.gnu_getopt, args, shortlist, namelist)
458
465
459
466
460 def mkdtemp(
467 def mkdtemp(
461 suffix: bytes = b'', prefix: bytes = b'tmp', dir: Optional[bytes] = None
468 suffix: bytes = b'', prefix: bytes = b'tmp', dir: Optional[bytes] = None
462 ) -> bytes:
469 ) -> bytes:
463 return tempfile.mkdtemp(suffix, prefix, dir)
470 return tempfile.mkdtemp(suffix, prefix, dir)
464
471
465
472
466 # text=True is not supported; use util.from/tonativeeol() instead
473 # text=True is not supported; use util.from/tonativeeol() instead
467 def mkstemp(
474 def mkstemp(
468 suffix: bytes = b'', prefix: bytes = b'tmp', dir: Optional[bytes] = None
475 suffix: bytes = b'', prefix: bytes = b'tmp', dir: Optional[bytes] = None
469 ) -> Tuple[int, bytes]:
476 ) -> Tuple[int, bytes]:
470 return tempfile.mkstemp(suffix, prefix, dir)
477 return tempfile.mkstemp(suffix, prefix, dir)
471
478
472
479
473 # TemporaryFile does not support an "encoding=" argument on python2.
480 # TemporaryFile does not support an "encoding=" argument on python2.
474 # This wrapper file are always open in byte mode.
481 # This wrapper file are always open in byte mode.
475 def unnamedtempfile(mode: Optional[bytes] = None, *args, **kwargs) -> BinaryIO:
482 def unnamedtempfile(mode: Optional[bytes] = None, *args, **kwargs) -> BinaryIO:
476 if mode is None:
483 if mode is None:
477 mode = 'w+b'
484 mode = 'w+b'
478 else:
485 else:
479 mode = sysstr(mode)
486 mode = sysstr(mode)
480 assert 'b' in mode
487 assert 'b' in mode
481 return cast(BinaryIO, tempfile.TemporaryFile(mode, *args, **kwargs))
488 return cast(BinaryIO, tempfile.TemporaryFile(mode, *args, **kwargs))
482
489
483
490
484 # NamedTemporaryFile does not support an "encoding=" argument on python2.
491 # NamedTemporaryFile does not support an "encoding=" argument on python2.
485 # This wrapper file are always open in byte mode.
492 # This wrapper file are always open in byte mode.
486 def namedtempfile(
493 def namedtempfile(
487 mode: bytes = b'w+b',
494 mode: bytes = b'w+b',
488 bufsize: int = -1,
495 bufsize: int = -1,
489 suffix: bytes = b'',
496 suffix: bytes = b'',
490 prefix: bytes = b'tmp',
497 prefix: bytes = b'tmp',
491 dir: Optional[bytes] = None,
498 dir: Optional[bytes] = None,
492 delete: bool = True,
499 delete: bool = True,
493 ):
500 ):
494 mode = sysstr(mode)
501 mode = sysstr(mode)
495 assert 'b' in mode
502 assert 'b' in mode
496 return tempfile.NamedTemporaryFile(
503 return tempfile.NamedTemporaryFile(
497 mode, bufsize, suffix=suffix, prefix=prefix, dir=dir, delete=delete
504 mode, bufsize, suffix=suffix, prefix=prefix, dir=dir, delete=delete
498 )
505 )
General Comments 0
You need to be logged in to leave comments. Login now