44 if not globals(): # hide this from non-pytype users |
54 if not globals(): # hide this from non-pytype users |
45 import typing |
55 import typing |
46 |
56 |
47 TYPE_CHECKING = typing.TYPE_CHECKING |
57 TYPE_CHECKING = typing.TYPE_CHECKING |
48 |
58 |
|
59 _GetOptResult = Tuple[List[Tuple[bytes, bytes]], List[bytes]] |
|
60 _T0 = TypeVar('_T0') |
49 _Tbytestr = TypeVar('_Tbytestr', bound='bytestr') |
61 _Tbytestr = TypeVar('_Tbytestr', bound='bytestr') |
50 |
62 |
51 |
63 |
52 def future_set_exception_info(f, exc_info): |
64 def future_set_exception_info(f, exc_info): |
53 f.set_exception(exc_info[0]) |
65 f.set_exception(exc_info[0]) |
54 |
66 |
55 |
67 |
56 FileNotFoundError = builtins.FileNotFoundError |
68 FileNotFoundError = builtins.FileNotFoundError |
57 |
69 |
58 |
70 |
59 def identity(a): |
71 def identity(a: _T0) -> _T0: |
60 return a |
72 return a |
61 |
73 |
62 |
74 |
63 def _rapply(f, xs): |
75 def _rapply(f, xs): |
64 if xs is None: |
76 if xs is None: |
248 def iterbytestr(s: Iterable[int]) -> Iterator[bytes]: |
260 def iterbytestr(s: Iterable[int]) -> Iterator[bytes]: |
249 """Iterate bytes as if it were a str object of Python 2""" |
261 """Iterate bytes as if it were a str object of Python 2""" |
250 return map(bytechr, s) |
262 return map(bytechr, s) |
251 |
263 |
252 |
264 |
|
265 if TYPE_CHECKING: |
|
266 |
|
267 @overload |
|
268 def maybebytestr(s: bytes) -> bytestr: |
|
269 ... |
|
270 |
|
271 @overload |
|
272 def maybebytestr(s: _T0) -> _T0: |
|
273 ... |
|
274 |
|
275 |
253 def maybebytestr(s): |
276 def maybebytestr(s): |
254 """Promote bytes to bytestr""" |
277 """Promote bytes to bytestr""" |
255 if isinstance(s, bytes): |
278 if isinstance(s, bytes): |
256 return bytestr(s) |
279 return bytestr(s) |
257 return s |
280 return s |
258 |
281 |
259 |
282 |
260 def sysbytes(s): |
283 def sysbytes(s: AnyStr) -> bytes: |
261 """Convert an internal str (e.g. keyword, __doc__) back to bytes |
284 """Convert an internal str (e.g. keyword, __doc__) back to bytes |
262 |
285 |
263 This never raises UnicodeEncodeError, but only ASCII characters |
286 This never raises UnicodeEncodeError, but only ASCII characters |
264 can be round-trip by sysstr(sysbytes(s)). |
287 can be round-trip by sysstr(sysbytes(s)). |
265 """ |
288 """ |
266 if isinstance(s, bytes): |
289 if isinstance(s, bytes): |
267 return s |
290 return s |
268 return s.encode('utf-8') |
291 return s.encode('utf-8') |
269 |
292 |
270 |
293 |
271 def sysstr(s): |
294 def sysstr(s: AnyStr) -> str: |
272 """Return a keyword str to be passed to Python functions such as |
295 """Return a keyword str to be passed to Python functions such as |
273 getattr() and str.encode() |
296 getattr() and str.encode() |
274 |
297 |
275 This never raises UnicodeDecodeError. Non-ascii characters are |
298 This never raises UnicodeDecodeError. Non-ascii characters are |
276 considered invalid and mapped to arbitrary but unique code points |
299 considered invalid and mapped to arbitrary but unique code points |
279 if isinstance(s, builtins.str): |
302 if isinstance(s, builtins.str): |
280 return s |
303 return s |
281 return s.decode('latin-1') |
304 return s.decode('latin-1') |
282 |
305 |
283 |
306 |
284 def strurl(url): |
307 def strurl(url: AnyStr) -> str: |
285 """Converts a bytes url back to str""" |
308 """Converts a bytes url back to str""" |
286 if isinstance(url, bytes): |
309 if isinstance(url, bytes): |
287 return url.decode('ascii') |
310 return url.decode('ascii') |
288 return url |
311 return url |
289 |
312 |
290 |
313 |
291 def bytesurl(url): |
314 def bytesurl(url: AnyStr) -> bytes: |
292 """Converts a str url to bytes by encoding in ascii""" |
315 """Converts a str url to bytes by encoding in ascii""" |
293 if isinstance(url, str): |
316 if isinstance(url, str): |
294 return url.encode('ascii') |
317 return url.encode('ascii') |
295 return url |
318 return url |
296 |
319 |
297 |
320 |
298 def raisewithtb(exc, tb): |
321 def raisewithtb(exc: BaseException, tb) -> NoReturn: |
299 """Raise exception with the given traceback""" |
322 """Raise exception with the given traceback""" |
300 raise exc.with_traceback(tb) |
323 raise exc.with_traceback(tb) |
301 |
324 |
302 |
325 |
303 def getdoc(obj): |
326 def getdoc(obj: object) -> Optional[bytes]: |
304 """Get docstring as bytes; may be None so gettext() won't confuse it |
327 """Get docstring as bytes; may be None so gettext() won't confuse it |
305 with _('')""" |
328 with _('')""" |
306 doc = builtins.getattr(obj, '__doc__', None) |
329 doc = builtins.getattr(obj, '__doc__', None) |
307 if doc is None: |
330 if doc is None: |
308 return doc |
331 return doc |
324 setattr = _wrapattrfunc(builtins.setattr) |
347 setattr = _wrapattrfunc(builtins.setattr) |
325 xrange = builtins.range |
348 xrange = builtins.range |
326 unicode = str |
349 unicode = str |
327 |
350 |
328 |
351 |
329 def open(name, mode=b'r', buffering=-1, encoding=None): |
352 def open( |
|
353 name, |
|
354 mode: AnyStr = b'r', |
|
355 buffering: int = -1, |
|
356 encoding: Optional[str] = None, |
|
357 ) -> Any: |
|
358 # TODO: assert binary mode, and cast result to BinaryIO? |
330 return builtins.open(name, sysstr(mode), buffering, encoding) |
359 return builtins.open(name, sysstr(mode), buffering, encoding) |
331 |
360 |
332 |
361 |
333 safehasattr = _wrapattrfunc(builtins.hasattr) |
362 safehasattr = _wrapattrfunc(builtins.hasattr) |
334 |
363 |
335 |
364 |
336 def _getoptbwrapper(orig, args, shortlist, namelist): |
365 def _getoptbwrapper( |
|
366 orig, args: Sequence[bytes], shortlist: bytes, namelist: Sequence[bytes] |
|
367 ) -> _GetOptResult: |
337 """ |
368 """ |
338 Takes bytes arguments, converts them to unicode, pass them to |
369 Takes bytes arguments, converts them to unicode, pass them to |
339 getopt.getopt(), convert the returned values back to bytes and then |
370 getopt.getopt(), convert the returned values back to bytes and then |
340 return them for Python 3 compatibility as getopt.getopt() don't accepts |
371 return them for Python 3 compatibility as getopt.getopt() don't accepts |
341 bytes on Python 3. |
372 bytes on Python 3. |
347 opts = [(a[0].encode('latin-1'), a[1].encode('latin-1')) for a in opts] |
378 opts = [(a[0].encode('latin-1'), a[1].encode('latin-1')) for a in opts] |
348 args = [a.encode('latin-1') for a in args] |
379 args = [a.encode('latin-1') for a in args] |
349 return opts, args |
380 return opts, args |
350 |
381 |
351 |
382 |
352 def strkwargs(dic): |
383 def strkwargs(dic: Mapping[bytes, _T0]) -> Dict[str, _T0]: |
353 """ |
384 """ |
354 Converts the keys of a python dictonary to str i.e. unicodes so that |
385 Converts the keys of a python dictonary to str i.e. unicodes so that |
355 they can be passed as keyword arguments as dictionaries with bytes keys |
386 they can be passed as keyword arguments as dictionaries with bytes keys |
356 can't be passed as keyword arguments to functions on Python 3. |
387 can't be passed as keyword arguments to functions on Python 3. |
357 """ |
388 """ |
358 dic = {k.decode('latin-1'): v for k, v in dic.items()} |
389 dic = {k.decode('latin-1'): v for k, v in dic.items()} |
359 return dic |
390 return dic |
360 |
391 |
361 |
392 |
362 def byteskwargs(dic): |
393 def byteskwargs(dic: Mapping[str, _T0]) -> Dict[bytes, _T0]: |
363 """ |
394 """ |
364 Converts keys of python dictionaries to bytes as they were converted to |
395 Converts keys of python dictionaries to bytes as they were converted to |
365 str to pass that dictonary as a keyword argument on Python 3. |
396 str to pass that dictonary as a keyword argument on Python 3. |
366 """ |
397 """ |
367 dic = {k.encode('latin-1'): v for k, v in dic.items()} |
398 dic = {k.encode('latin-1'): v for k, v in dic.items()} |
368 return dic |
399 return dic |
369 |
400 |
370 |
401 |
371 # TODO: handle shlex.shlex(). |
402 # TODO: handle shlex.shlex(). |
372 def shlexsplit(s, comments=False, posix=True): |
403 def shlexsplit( |
|
404 s: bytes, comments: bool = False, posix: bool = True |
|
405 ) -> List[bytes]: |
373 """ |
406 """ |
374 Takes bytes argument, convert it to str i.e. unicodes, pass that into |
407 Takes bytes argument, convert it to str i.e. unicodes, pass that into |
375 shlex.split(), convert the returned value to bytes and return that for |
408 shlex.split(), convert the returned value to bytes and return that for |
376 Python 3 compatibility as shelx.split() don't accept bytes on Python 3. |
409 Python 3 compatibility as shelx.split() don't accept bytes on Python 3. |
377 """ |
410 """ |
390 islinux: bool = sysplatform.startswith(b'linux') |
423 islinux: bool = sysplatform.startswith(b'linux') |
391 isposix: bool = osname == b'posix' |
424 isposix: bool = osname == b'posix' |
392 iswindows: bool = osname == b'nt' |
425 iswindows: bool = osname == b'nt' |
393 |
426 |
394 |
427 |
395 def getoptb(args, shortlist, namelist): |
428 def getoptb( |
|
429 args: Sequence[bytes], shortlist: bytes, namelist: Sequence[bytes] |
|
430 ) -> _GetOptResult: |
396 return _getoptbwrapper(getopt.getopt, args, shortlist, namelist) |
431 return _getoptbwrapper(getopt.getopt, args, shortlist, namelist) |
397 |
432 |
398 |
433 |
399 def gnugetoptb(args, shortlist, namelist): |
434 def gnugetoptb( |
|
435 args: Sequence[bytes], shortlist: bytes, namelist: Sequence[bytes] |
|
436 ) -> _GetOptResult: |
400 return _getoptbwrapper(getopt.gnu_getopt, args, shortlist, namelist) |
437 return _getoptbwrapper(getopt.gnu_getopt, args, shortlist, namelist) |
401 |
438 |
402 |
439 |
403 def mkdtemp(suffix=b'', prefix=b'tmp', dir=None): |
440 def mkdtemp( |
|
441 suffix: bytes = b'', prefix: bytes = b'tmp', dir: Optional[bytes] = None |
|
442 ) -> bytes: |
404 return tempfile.mkdtemp(suffix, prefix, dir) |
443 return tempfile.mkdtemp(suffix, prefix, dir) |
405 |
444 |
406 |
445 |
407 # text=True is not supported; use util.from/tonativeeol() instead |
446 # text=True is not supported; use util.from/tonativeeol() instead |
408 def mkstemp(suffix=b'', prefix=b'tmp', dir=None): |
447 def mkstemp( |
|
448 suffix: bytes = b'', prefix: bytes = b'tmp', dir: Optional[bytes] = None |
|
449 ) -> Tuple[int, bytes]: |
409 return tempfile.mkstemp(suffix, prefix, dir) |
450 return tempfile.mkstemp(suffix, prefix, dir) |
410 |
451 |
411 |
452 |
412 # TemporaryFile does not support an "encoding=" argument on python2. |
453 # TemporaryFile does not support an "encoding=" argument on python2. |
413 # This wrapper file are always open in byte mode. |
454 # This wrapper file are always open in byte mode. |
414 def unnamedtempfile(mode=None, *args, **kwargs): |
455 def unnamedtempfile(mode: Optional[bytes] = None, *args, **kwargs) -> BinaryIO: |
415 if mode is None: |
456 if mode is None: |
416 mode = 'w+b' |
457 mode = 'w+b' |
417 else: |
458 else: |
418 mode = sysstr(mode) |
459 mode = sysstr(mode) |
419 assert 'b' in mode |
460 assert 'b' in mode |
420 return tempfile.TemporaryFile(mode, *args, **kwargs) |
461 return cast(BinaryIO, tempfile.TemporaryFile(mode, *args, **kwargs)) |
421 |
462 |
422 |
463 |
423 # NamedTemporaryFile does not support an "encoding=" argument on python2. |
464 # NamedTemporaryFile does not support an "encoding=" argument on python2. |
424 # This wrapper file are always open in byte mode. |
465 # This wrapper file are always open in byte mode. |
425 def namedtempfile( |
466 def namedtempfile( |
426 mode=b'w+b', bufsize=-1, suffix=b'', prefix=b'tmp', dir=None, delete=True |
467 mode: bytes = b'w+b', |
|
468 bufsize: int = -1, |
|
469 suffix: bytes = b'', |
|
470 prefix: bytes = b'tmp', |
|
471 dir: Optional[bytes] = None, |
|
472 delete: bool = True, |
427 ): |
473 ): |
428 mode = sysstr(mode) |
474 mode = sysstr(mode) |
429 assert 'b' in mode |
475 assert 'b' in mode |
430 return tempfile.NamedTemporaryFile( |
476 return tempfile.NamedTemporaryFile( |
431 mode, bufsize, suffix=suffix, prefix=prefix, dir=dir, delete=delete |
477 mode, bufsize, suffix=suffix, prefix=prefix, dir=dir, delete=delete |