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