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