mercurial/pycompat.py
author Julien Cristau <jcristau@debian.org>
Mon, 14 Oct 2024 16:46:25 +0200
branchstable
changeset 51696 cd788962c6d9
parent 51325 7e6aae033d8d
permissions -rw-r--r--
tests: use shlex.quote instead of pipes.quote The pipes module got removed in python 3.13. https://bugs.debian.org/1084553
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
28818
6041fb8f2da8 pycompat: add empty and queue to handle py3 divergence
timeless <timeless@mozdev.org>
parents:
diff changeset
     1
# pycompat.py - portability shim for python 3
6041fb8f2da8 pycompat: add empty and queue to handle py3 divergence
timeless <timeless@mozdev.org>
parents:
diff changeset
     2
#
6041fb8f2da8 pycompat: add empty and queue to handle py3 divergence
timeless <timeless@mozdev.org>
parents:
diff changeset
     3
# This software may be used and distributed according to the terms of the
6041fb8f2da8 pycompat: add empty and queue to handle py3 divergence
timeless <timeless@mozdev.org>
parents:
diff changeset
     4
# GNU General Public License version 2 or any later version.
6041fb8f2da8 pycompat: add empty and queue to handle py3 divergence
timeless <timeless@mozdev.org>
parents:
diff changeset
     5
6041fb8f2da8 pycompat: add empty and queue to handle py3 divergence
timeless <timeless@mozdev.org>
parents:
diff changeset
     6
"""Mercurial portability shim for python 3.
6041fb8f2da8 pycompat: add empty and queue to handle py3 divergence
timeless <timeless@mozdev.org>
parents:
diff changeset
     7
6041fb8f2da8 pycompat: add empty and queue to handle py3 divergence
timeless <timeless@mozdev.org>
parents:
diff changeset
     8
This contains aliases to hide python version-specific details from the core.
6041fb8f2da8 pycompat: add empty and queue to handle py3 divergence
timeless <timeless@mozdev.org>
parents:
diff changeset
     9
"""
6041fb8f2da8 pycompat: add empty and queue to handle py3 divergence
timeless <timeless@mozdev.org>
parents:
diff changeset
    10
6041fb8f2da8 pycompat: add empty and queue to handle py3 divergence
timeless <timeless@mozdev.org>
parents:
diff changeset
    11
48960
57b58413dad1 pycompat: remove first not ispy3 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48926
diff changeset
    12
import builtins
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
    13
import codecs
48960
57b58413dad1 pycompat: remove first not ispy3 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48926
diff changeset
    14
import concurrent.futures as futures
30583
c6ce11f2ee50 py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30509
diff changeset
    15
import getopt
48960
57b58413dad1 pycompat: remove first not ispy3 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48926
diff changeset
    16
import http.client as httplib
57b58413dad1 pycompat: remove first not ispy3 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48926
diff changeset
    17
import http.cookiejar as cookielib
36216
646002338365 py3: introduce and use pycompat.getargspec
Augie Fackler <augie@google.com>
parents: 36083
diff changeset
    18
import inspect
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
    19
import io
43380
579672b347d2 py3: define and use json.loads polyfill
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43117
diff changeset
    20
import json
30315
3874ddba1ab4 py3: add a bytes version of os.name
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30313
diff changeset
    21
import os
48960
57b58413dad1 pycompat: remove first not ispy3 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48926
diff changeset
    22
import queue
30681
caf7e1c5efe4 py3: have a bytes version of shlex.split()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30671
diff changeset
    23
import shlex
48960
57b58413dad1 pycompat: remove first not ispy3 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48926
diff changeset
    24
import socketserver
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
    25
import struct
29584
06587edd1233 pycompat: make pycompat demandimport friendly
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29566
diff changeset
    26
import sys
38197
aac4be30e250 py3: wrap tempfile.mkstemp() to use bytes path
Yuya Nishihara <yuya@tcha.org>
parents: 37890
diff changeset
    27
import tempfile
48960
57b58413dad1 pycompat: remove first not ispy3 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48926
diff changeset
    28
import xmlrpc.client as xmlrpclib
29584
06587edd1233 pycompat: make pycompat demandimport friendly
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29566
diff changeset
    29
49896
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
    30
from typing import (
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
    31
    Any,
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
    32
    AnyStr,
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
    33
    BinaryIO,
50218
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
    34
    Callable,
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
    35
    Dict,
49898
55d45d0de4e7 typing: add type hints to pycompat.bytestr
Matt Harbison <matt_harbison@yahoo.com>
parents: 49897
diff changeset
    36
    Iterable,
55d45d0de4e7 typing: add type hints to pycompat.bytestr
Matt Harbison <matt_harbison@yahoo.com>
parents: 49897
diff changeset
    37
    Iterator,
49896
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
    38
    List,
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
    39
    Mapping,
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
    40
    NoReturn,
49896
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
    41
    Optional,
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
    42
    Sequence,
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
    43
    Tuple,
49898
55d45d0de4e7 typing: add type hints to pycompat.bytestr
Matt Harbison <matt_harbison@yahoo.com>
parents: 49897
diff changeset
    44
    Type,
55d45d0de4e7 typing: add type hints to pycompat.bytestr
Matt Harbison <matt_harbison@yahoo.com>
parents: 49897
diff changeset
    45
    TypeVar,
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
    46
    cast,
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
    47
    overload,
49896
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
    48
)
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
    49
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
    50
ispy3 = sys.version_info[0] >= 3
43554
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43551
diff changeset
    51
ispypy = '__pypy__' in sys.builtin_module_names
43793
7b14d649af1b typing: consolidate "if not globals():" trick
Yuya Nishihara <yuya@tcha.org>
parents: 43788
diff changeset
    52
TYPE_CHECKING = False
7b14d649af1b typing: consolidate "if not globals():" trick
Yuya Nishihara <yuya@tcha.org>
parents: 43788
diff changeset
    53
7b14d649af1b typing: consolidate "if not globals():" trick
Yuya Nishihara <yuya@tcha.org>
parents: 43788
diff changeset
    54
if not globals():  # hide this from non-pytype users
7b14d649af1b typing: consolidate "if not globals():" trick
Yuya Nishihara <yuya@tcha.org>
parents: 43788
diff changeset
    55
    import typing
7b14d649af1b typing: consolidate "if not globals():" trick
Yuya Nishihara <yuya@tcha.org>
parents: 43788
diff changeset
    56
7b14d649af1b typing: consolidate "if not globals():" trick
Yuya Nishihara <yuya@tcha.org>
parents: 43788
diff changeset
    57
    TYPE_CHECKING = typing.TYPE_CHECKING
30031
0f6d6fdd3c2a pycompat: provide 'ispy3' constant
Yuya Nishihara <yuya@tcha.org>
parents: 29812
diff changeset
    58
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
    59
_GetOptResult = Tuple[List[Tuple[bytes, bytes]], List[bytes]]
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
    60
_T0 = TypeVar('_T0')
50218
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
    61
_T1 = TypeVar('_T1')
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
    62
_S = TypeVar('_S')
49898
55d45d0de4e7 typing: add type hints to pycompat.bytestr
Matt Harbison <matt_harbison@yahoo.com>
parents: 49897
diff changeset
    63
_Tbytestr = TypeVar('_Tbytestr', bound='bytestr')
55d45d0de4e7 typing: add type hints to pycompat.bytestr
Matt Harbison <matt_harbison@yahoo.com>
parents: 49897
diff changeset
    64
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
    65
48960
57b58413dad1 pycompat: remove first not ispy3 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48926
diff changeset
    66
def future_set_exception_info(f, exc_info):
57b58413dad1 pycompat: remove first not ispy3 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48926
diff changeset
    67
    f.set_exception(exc_info[0])
29431
80880ad3fccd py3: conditionalize the urlparse import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29414
diff changeset
    68
37669
1cb54e6193a6 py3: paper over differences in future exception handling
Augie Fackler <augie@google.com>
parents: 37628
diff changeset
    69
48960
57b58413dad1 pycompat: remove first not ispy3 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48926
diff changeset
    70
FileNotFoundError = builtins.FileNotFoundError
47852
2b76255a4f74 template: FileNotFoundError is actually a built in exception
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46380
diff changeset
    71
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
    72
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
    73
def identity(a: _T0) -> _T0:
31777
7d2cbe11ae48 pycompat: introduce identity function as a compat stub
Yuya Nishihara <yuya@tcha.org>
parents: 31579
diff changeset
    74
    return a
7d2cbe11ae48 pycompat: introduce identity function as a compat stub
Yuya Nishihara <yuya@tcha.org>
parents: 31579
diff changeset
    75
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
    76
38576
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    77
def _rapply(f, xs):
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    78
    if xs is None:
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    79
        # assume None means non-value of optional data
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    80
        return xs
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    81
    if isinstance(xs, (list, set, tuple)):
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    82
        return type(xs)(_rapply(f, x) for x in xs)
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    83
    if isinstance(xs, dict):
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    84
        return type(xs)((_rapply(f, k), _rapply(f, v)) for k, v in xs.items())
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    85
    return f(xs)
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    86
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
    87
38576
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    88
def rapply(f, xs):
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    89
    """Apply function recursively to every item preserving the data structure
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    90
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    91
    >>> def f(x):
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    92
    ...     return 'f(%s)' % x
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    93
    >>> rapply(f, None) is None
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    94
    True
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    95
    >>> rapply(f, 'a')
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    96
    'f(a)'
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    97
    >>> rapply(f, {'a'}) == {'f(a)'}
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    98
    True
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
    99
    >>> rapply(f, ['a', 'b', None, {'c': 'd'}, []])
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
   100
    ['f(a)', 'f(b)', None, {'f(c)': 'f(d)'}, []]
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
   101
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
   102
    >>> xs = [object()]
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
   103
    >>> rapply(identity, xs) is xs
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
   104
    True
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
   105
    """
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
   106
    if f is identity:
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
   107
        # fast path mainly for py2
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
   108
        return xs
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
   109
    return _rapply(f, xs)
152f4822d210 pycompat: move rapply() from util
Yuya Nishihara <yuya@tcha.org>
parents: 38341
diff changeset
   110
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
   111
49050
9ac1a4507bb3 pycompat: remove check for Python >= 3.6
Gregory Szorc <gregory.szorc@gmail.com>
parents: 49037
diff changeset
   112
if os.name == r'nt':
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   113
    # MBCS (or ANSI) filesystem encoding must be used as before.
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   114
    # Otherwise non-ASCII filenames in existing repositories would be
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   115
    # corrupted.
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   116
    # This must be set once prior to any fsencode/fsdecode calls.
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   117
    sys._enablelegacywindowsfsencoding()  # pytype: disable=module-attr
43484
8d5489b048b7 py3: enable legacy fs encoding to fix filename compatibility on Windows
Yuya Nishihara <yuya@tcha.org>
parents: 43117
diff changeset
   118
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   119
fsencode = os.fsencode
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   120
fsdecode = os.fsdecode
49896
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   121
oscurdir: bytes = os.curdir.encode('ascii')
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   122
oslinesep: bytes = os.linesep.encode('ascii')
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   123
osname: bytes = os.name.encode('ascii')
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   124
ospathsep: bytes = os.pathsep.encode('ascii')
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   125
ospardir: bytes = os.pardir.encode('ascii')
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   126
ossep: bytes = os.sep.encode('ascii')
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   127
osaltsep: Optional[bytes] = os.altsep.encode('ascii') if os.altsep else None
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   128
osdevnull: bytes = os.devnull.encode('ascii')
39823
24e493ec2229 py3: rename pycompat.getcwd() to encoding.getcwd() (API)
Matt Harbison <matt_harbison@yahoo.com>
parents: 39658
diff changeset
   129
49896
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   130
sysplatform: bytes = sys.platform.encode('ascii')
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   131
sysexecutable: bytes = os.fsencode(sys.executable) if sys.executable else b''
36940
dbae581010ea pycompat: name maplist() and ziplist() for better traceback message
Yuya Nishihara <yuya@tcha.org>
parents: 36677
diff changeset
   132
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   133
50218
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
   134
if TYPE_CHECKING:
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
   135
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
   136
    @overload
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
   137
    def maplist(f: Callable[[_T0], _S], arg: Iterable[_T0]) -> List[_S]:
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
   138
        ...
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
   139
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
   140
    @overload
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
   141
    def maplist(
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
   142
        f: Callable[[_T0, _T1], _S], arg1: Iterable[_T0], arg2: Iterable[_T1]
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
   143
    ) -> List[_S]:
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
   144
        ...
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
   145
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
   146
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
   147
def maplist(f, *args):
0ab92dabea6e typing: add type hints to pycompat.maplist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50150
diff changeset
   148
    return list(map(f, *args))
36940
dbae581010ea pycompat: name maplist() and ziplist() for better traceback message
Yuya Nishihara <yuya@tcha.org>
parents: 36677
diff changeset
   149
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   150
50219
829aa604d71a typing: add the return type hint to pycompat.rangelist()
Matt Harbison <matt_harbison@yahoo.com>
parents: 50218
diff changeset
   151
def rangelist(*args) -> List[int]:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   152
    return list(range(*args))
37067
434e520adb8c annotate: do not construct attr.s object per line while computing history
Yuya Nishihara <yuya@tcha.org>
parents: 36964
diff changeset
   153
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   154
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   155
def ziplist(*args):
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   156
    return list(zip(*args))
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   157
36940
dbae581010ea pycompat: name maplist() and ziplist() for better traceback message
Yuya Nishihara <yuya@tcha.org>
parents: 36677
diff changeset
   158
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   159
rawinput = input
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   160
getargspec = inspect.getfullargspec
30344
19d8e19fde5b py3: document why os.fsencode() can be used to get back bytes argv
Yuya Nishihara <yuya@tcha.org>
parents: 30340
diff changeset
   161
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   162
long = int
39473
8d858fbf2759 cbor: teach the encoder to handle python `long` type for Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 39329
diff changeset
   163
49897
f3f33980f19b pycompat: explicitly prefix builtin attr usage with `builtins.`
Matt Harbison <matt_harbison@yahoo.com>
parents: 49896
diff changeset
   164
if builtins.getattr(sys, 'argv', None) is not None:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   165
    # On POSIX, the char** argv array is converted to Python str using
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   166
    # Py_DecodeLocale(). The inverse of this is Py_EncodeLocale(), which
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   167
    # isn't directly callable from Python code. In practice, os.fsencode()
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   168
    # can be used instead (this is recommended by Python's documentation
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   169
    # for sys.argv).
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   170
    #
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   171
    # On Windows, the wchar_t **argv is passed into the interpreter as-is.
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   172
    # Like POSIX, we need to emulate what Py_EncodeLocale() would do. But
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   173
    # there's an additional wrinkle. What we really want to access is the
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   174
    # ANSI codepage representation of the arguments, as this is what
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   175
    # `int main()` would receive if Python 3 didn't define `int wmain()`
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   176
    # (this is how Python 2 worked). To get that, we encode with the mbcs
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   177
    # encoding, which will pass CP_ACP to the underlying Windows API to
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   178
    # produce bytes.
49896
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   179
    sysargv: List[bytes] = []
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   180
    if os.name == r'nt':
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   181
        sysargv = [a.encode("mbcs", "ignore") for a in sys.argv]
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   182
    else:
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   183
        sysargv = [fsencode(a) for a in sys.argv]
29808
965c91bad9e3 py3: move xrange alias next to import lines
Yuya Nishihara <yuya@tcha.org>
parents: 29790
diff changeset
   184
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   185
bytechr = struct.Struct('>B').pack
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   186
byterepr = b'%r'.__mod__
31448
b70407bd84d5 pycompat: add bytestr wrapper which mostly acts as a Python 2 str
Yuya Nishihara <yuya@tcha.org>
parents: 31434
diff changeset
   187
b70407bd84d5 pycompat: add bytestr wrapper which mostly acts as a Python 2 str
Yuya Nishihara <yuya@tcha.org>
parents: 31434
diff changeset
   188
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   189
class bytestr(bytes):
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   190
    """A bytes which mostly acts as a Python 2 str
32488
548478efc46c pycompat: try __bytes__() to convert object to bytestr
Yuya Nishihara <yuya@tcha.org>
parents: 32232
diff changeset
   191
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   192
    >>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1)
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   193
    ('', 'foo', 'ascii', '1')
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   194
    >>> s = bytestr(b'foo')
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   195
    >>> assert s is bytestr(s)
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   196
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   197
    __bytes__() should be called if provided:
32488
548478efc46c pycompat: try __bytes__() to convert object to bytestr
Yuya Nishihara <yuya@tcha.org>
parents: 32232
diff changeset
   198
49037
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
   199
    >>> class bytesable:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   200
    ...     def __bytes__(self):
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   201
    ...         return b'bytes'
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   202
    >>> bytestr(bytesable())
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   203
    'bytes'
31448
b70407bd84d5 pycompat: add bytestr wrapper which mostly acts as a Python 2 str
Yuya Nishihara <yuya@tcha.org>
parents: 31434
diff changeset
   204
51157
f0e7d51bb454 pycompat: fix bytestr(bytes) in Python 3.11
Georges Racinet <georges.racinet@octobus.net>
parents: 50947
diff changeset
   205
    ...unless the argument is the bytes *type* itself: it gets a
f0e7d51bb454 pycompat: fix bytestr(bytes) in Python 3.11
Georges Racinet <georges.racinet@octobus.net>
parents: 50947
diff changeset
   206
    __bytes__() method in Python 3.11, which cannot be used as in an instance
f0e7d51bb454 pycompat: fix bytestr(bytes) in Python 3.11
Georges Racinet <georges.racinet@octobus.net>
parents: 50947
diff changeset
   207
    of bytes:
f0e7d51bb454 pycompat: fix bytestr(bytes) in Python 3.11
Georges Racinet <georges.racinet@octobus.net>
parents: 50947
diff changeset
   208
f0e7d51bb454 pycompat: fix bytestr(bytes) in Python 3.11
Georges Racinet <georges.racinet@octobus.net>
parents: 50947
diff changeset
   209
    >>> bytestr(bytes)
f0e7d51bb454 pycompat: fix bytestr(bytes) in Python 3.11
Georges Racinet <georges.racinet@octobus.net>
parents: 50947
diff changeset
   210
    "<class 'bytes'>"
f0e7d51bb454 pycompat: fix bytestr(bytes) in Python 3.11
Georges Racinet <georges.racinet@octobus.net>
parents: 50947
diff changeset
   211
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   212
    There's no implicit conversion from non-ascii str as its encoding is
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   213
    unknown:
31448
b70407bd84d5 pycompat: add bytestr wrapper which mostly acts as a Python 2 str
Yuya Nishihara <yuya@tcha.org>
parents: 31434
diff changeset
   214
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   215
    >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   216
    Traceback (most recent call last):
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   217
      ...
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   218
    UnicodeEncodeError: ...
31448
b70407bd84d5 pycompat: add bytestr wrapper which mostly acts as a Python 2 str
Yuya Nishihara <yuya@tcha.org>
parents: 31434
diff changeset
   219
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   220
    Comparison between bytestr and bytes should work:
31448
b70407bd84d5 pycompat: add bytestr wrapper which mostly acts as a Python 2 str
Yuya Nishihara <yuya@tcha.org>
parents: 31434
diff changeset
   221
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   222
    >>> assert bytestr(b'foo') == b'foo'
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   223
    >>> assert b'foo' == bytestr(b'foo')
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   224
    >>> assert b'f' in bytestr(b'foo')
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   225
    >>> assert bytestr(b'f') in b'foo'
31448
b70407bd84d5 pycompat: add bytestr wrapper which mostly acts as a Python 2 str
Yuya Nishihara <yuya@tcha.org>
parents: 31434
diff changeset
   226
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   227
    Sliced elements should be bytes, not integer:
31448
b70407bd84d5 pycompat: add bytestr wrapper which mostly acts as a Python 2 str
Yuya Nishihara <yuya@tcha.org>
parents: 31434
diff changeset
   228
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   229
    >>> s[1], s[:2]
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   230
    (b'o', b'fo')
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   231
    >>> list(s), list(reversed(s))
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   232
    ([b'f', b'o', b'o'], [b'o', b'o', b'f'])
31448
b70407bd84d5 pycompat: add bytestr wrapper which mostly acts as a Python 2 str
Yuya Nishihara <yuya@tcha.org>
parents: 31434
diff changeset
   233
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   234
    As bytestr type isn't propagated across operations, you need to cast
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   235
    bytes to bytestr explicitly:
31448
b70407bd84d5 pycompat: add bytestr wrapper which mostly acts as a Python 2 str
Yuya Nishihara <yuya@tcha.org>
parents: 31434
diff changeset
   236
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   237
    >>> s = bytestr(b'foo').upper()
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   238
    >>> t = bytestr(s)
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   239
    >>> s[0], t[0]
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   240
    (70, b'F')
48029
1fda8c9358ce typing: add a fake `__init__()` to bytestr to distract pytype
Matt Harbison <matt_harbison@yahoo.com>
parents: 47852
diff changeset
   241
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   242
    Be careful to not pass a bytestr object to a function which expects
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   243
    bytearray-like behavior.
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   244
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   245
    >>> t = bytes(t)  # cast to bytes
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   246
    >>> assert type(t) is bytes
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   247
    """
48029
1fda8c9358ce typing: add a fake `__init__()` to bytestr to distract pytype
Matt Harbison <matt_harbison@yahoo.com>
parents: 47852
diff changeset
   248
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   249
    # Trick pytype into not demanding Iterable[int] be passed to __new__(),
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   250
    # since the appropriate bytes format is done internally.
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   251
    #
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   252
    # https://github.com/google/pytype/issues/500
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   253
    if TYPE_CHECKING:
31448
b70407bd84d5 pycompat: add bytestr wrapper which mostly acts as a Python 2 str
Yuya Nishihara <yuya@tcha.org>
parents: 31434
diff changeset
   254
49898
55d45d0de4e7 typing: add type hints to pycompat.bytestr
Matt Harbison <matt_harbison@yahoo.com>
parents: 49897
diff changeset
   255
        def __init__(self, s: object = b'') -> None:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   256
            pass
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   257
49898
55d45d0de4e7 typing: add type hints to pycompat.bytestr
Matt Harbison <matt_harbison@yahoo.com>
parents: 49897
diff changeset
   258
    def __new__(cls: Type[_Tbytestr], s: object = b'') -> _Tbytestr:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   259
        if isinstance(s, bytestr):
31448
b70407bd84d5 pycompat: add bytestr wrapper which mostly acts as a Python 2 str
Yuya Nishihara <yuya@tcha.org>
parents: 31434
diff changeset
   260
            return s
51157
f0e7d51bb454 pycompat: fix bytestr(bytes) in Python 3.11
Georges Racinet <georges.racinet@octobus.net>
parents: 50947
diff changeset
   261
        if not isinstance(s, (bytes, bytearray)) and (
f0e7d51bb454 pycompat: fix bytestr(bytes) in Python 3.11
Georges Racinet <georges.racinet@octobus.net>
parents: 50947
diff changeset
   262
            isinstance(s, type)
f0e7d51bb454 pycompat: fix bytestr(bytes) in Python 3.11
Georges Racinet <georges.racinet@octobus.net>
parents: 50947
diff changeset
   263
            or not builtins.hasattr(s, u'__bytes__')  # hasattr-py3-only
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   264
        ):
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   265
            s = str(s).encode('ascii')
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   266
        return bytes.__new__(cls, s)
35943
1a31111e6239 py3: always drop b'' prefix from repr() of bytestr
Yuya Nishihara <yuya@tcha.org>
parents: 35412
diff changeset
   267
50150
b900f40c343e typing: disable `signature-mismatch` warnings on a few bytestr functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49902
diff changeset
   268
    # The base class uses `int` return in py3, but the point of this class is to
b900f40c343e typing: disable `signature-mismatch` warnings on a few bytestr functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49902
diff changeset
   269
    # behave like py2.
b900f40c343e typing: disable `signature-mismatch` warnings on a few bytestr functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49902
diff changeset
   270
    def __getitem__(self, key) -> bytes:  # pytype: disable=signature-mismatch
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   271
        s = bytes.__getitem__(self, key)
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   272
        if not isinstance(s, bytes):
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   273
            s = bytechr(s)
35944
fc44c2657dc5 py3: drop b'' from repr() of smartset
Yuya Nishihara <yuya@tcha.org>
parents: 35943
diff changeset
   274
        return s
fc44c2657dc5 py3: drop b'' from repr() of smartset
Yuya Nishihara <yuya@tcha.org>
parents: 35943
diff changeset
   275
50150
b900f40c343e typing: disable `signature-mismatch` warnings on a few bytestr functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49902
diff changeset
   276
    # The base class expects `Iterator[int]` return in py3, but the point of
b900f40c343e typing: disable `signature-mismatch` warnings on a few bytestr functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49902
diff changeset
   277
    # this class is to behave like py2.
b900f40c343e typing: disable `signature-mismatch` warnings on a few bytestr functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49902
diff changeset
   278
    def __iter__(self) -> Iterator[bytes]:  # pytype: disable=signature-mismatch
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   279
        return iterbytestr(bytes.__iter__(self))
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   280
49898
55d45d0de4e7 typing: add type hints to pycompat.bytestr
Matt Harbison <matt_harbison@yahoo.com>
parents: 49897
diff changeset
   281
    def __repr__(self) -> str:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   282
        return bytes.__repr__(self)[1:]  # drop b''
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   283
31820
45761ef1bc93 py3: have registrar process docstrings in bytes
Yuya Nishihara <yuya@tcha.org>
parents: 31778
diff changeset
   284
49898
55d45d0de4e7 typing: add type hints to pycompat.bytestr
Matt Harbison <matt_harbison@yahoo.com>
parents: 49897
diff changeset
   285
def iterbytestr(s: Iterable[int]) -> Iterator[bytes]:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   286
    """Iterate bytes as if it were a str object of Python 2"""
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   287
    return map(bytechr, s)
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   288
31820
45761ef1bc93 py3: have registrar process docstrings in bytes
Yuya Nishihara <yuya@tcha.org>
parents: 31778
diff changeset
   289
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   290
if TYPE_CHECKING:
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   291
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   292
    @overload
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   293
    def maybebytestr(s: bytes) -> bytestr:
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   294
        ...
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   295
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   296
    @overload
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   297
    def maybebytestr(s: _T0) -> _T0:
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   298
        ...
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   299
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   300
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   301
def maybebytestr(s):
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   302
    """Promote bytes to bytestr"""
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   303
    if isinstance(s, bytes):
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   304
        return bytestr(s)
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   305
    return s
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   306
30032
2219f4f82ede pycompat: extract function that converts attribute or encoding name to str
Yuya Nishihara <yuya@tcha.org>
parents: 30031
diff changeset
   307
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   308
def sysbytes(s: AnyStr) -> bytes:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   309
    """Convert an internal str (e.g. keyword, __doc__) back to bytes
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   310
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   311
    This never raises UnicodeEncodeError, but only ASCII characters
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   312
    can be round-trip by sysstr(sysbytes(s)).
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   313
    """
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   314
    if isinstance(s, bytes):
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   315
        return s
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   316
    return s.encode('utf-8')
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   317
30032
2219f4f82ede pycompat: extract function that converts attribute or encoding name to str
Yuya Nishihara <yuya@tcha.org>
parents: 30031
diff changeset
   318
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   319
def sysstr(s: AnyStr) -> str:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   320
    """Return a keyword str to be passed to Python functions such as
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   321
    getattr() and str.encode()
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   322
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   323
    This never raises UnicodeDecodeError. Non-ascii characters are
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   324
    considered invalid and mapped to arbitrary but unique code points
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   325
    such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   326
    """
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   327
    if isinstance(s, builtins.str):
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   328
        return s
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   329
    return s.decode('latin-1')
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   330
32877
a05f3675c46a py3: add a new strurl() which will convert a bytes url to str
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32638
diff changeset
   331
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   332
def strurl(url: AnyStr) -> str:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   333
    """Converts a bytes url back to str"""
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   334
    if isinstance(url, bytes):
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   335
        return url.decode('ascii')
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   336
    return url
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   337
32878
f22f39d56bb5 py3: add a new bytesurl() to convert a str url into bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32877
diff changeset
   338
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   339
def bytesurl(url: AnyStr) -> bytes:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   340
    """Converts a str url to bytes by encoding in ascii"""
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   341
    if isinstance(url, str):
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   342
        return url.encode('ascii')
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   343
    return url
32232
76f9a0009b4b pycompat: extract helper to raise exception with traceback
Yuya Nishihara <yuya@tcha.org>
parents: 31942
diff changeset
   344
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   345
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   346
def raisewithtb(exc: BaseException, tb) -> NoReturn:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   347
    """Raise exception with the given traceback"""
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   348
    raise exc.with_traceback(tb)
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   349
32638
c9318beb7c1a py3: convert __doc__ back to bytes in help.py
Yuya Nishihara <yuya@tcha.org>
parents: 32488
diff changeset
   350
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   351
def getdoc(obj: object) -> Optional[bytes]:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   352
    """Get docstring as bytes; may be None so gettext() won't confuse it
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   353
    with _('')"""
49897
f3f33980f19b pycompat: explicitly prefix builtin attr usage with `builtins.`
Matt Harbison <matt_harbison@yahoo.com>
parents: 49896
diff changeset
   354
    doc = builtins.getattr(obj, '__doc__', None)
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   355
    if doc is None:
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   356
        return doc
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   357
    return sysbytes(doc)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
   358
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   359
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   360
# these wrappers are automagically imported by hgloader
51183
c845479fc64d cleanup: drop the `bytes` compatibility for attribute related function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50947
diff changeset
   361
delattr = builtins.delattr
c845479fc64d cleanup: drop the `bytes` compatibility for attribute related function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50947
diff changeset
   362
getattr = builtins.getattr
c845479fc64d cleanup: drop the `bytes` compatibility for attribute related function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50947
diff changeset
   363
hasattr = builtins.hasattr
c845479fc64d cleanup: drop the `bytes` compatibility for attribute related function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50947
diff changeset
   364
setattr = builtins.setattr
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   365
xrange = builtins.range
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   366
unicode = str
31159
76a64c1e5439 py3: add pycompat.open and replace open() calls
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30820
diff changeset
   367
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   368
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   369
def open(
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   370
    name,
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   371
    mode: AnyStr = b'r',
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   372
    buffering: int = -1,
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   373
    encoding: Optional[str] = None,
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   374
) -> Any:
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   375
    # TODO: assert binary mode, and cast result to BinaryIO?
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   376
    return builtins.open(name, sysstr(mode), buffering, encoding)
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   377
37102
6ca5f825a0ca util: make safehasattr() a pycompat function
Yuya Nishihara <yuya@tcha.org>
parents: 37067
diff changeset
   378
51183
c845479fc64d cleanup: drop the `bytes` compatibility for attribute related function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50947
diff changeset
   379
safehasattr = builtins.hasattr
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   380
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   381
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   382
def _getoptbwrapper(
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   383
    orig, args: Sequence[bytes], shortlist: bytes, namelist: Sequence[bytes]
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   384
) -> _GetOptResult:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   385
    """
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   386
    Takes bytes arguments, converts them to unicode, pass them to
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   387
    getopt.getopt(), convert the returned values back to bytes and then
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   388
    return them for Python 3 compatibility as getopt.getopt() don't accepts
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   389
    bytes on Python 3.
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   390
    """
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   391
    args = [a.decode('latin-1') for a in args]
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   392
    shortlist = shortlist.decode('latin-1')
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   393
    namelist = [a.decode('latin-1') for a in namelist]
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   394
    opts, args = orig(args, shortlist, namelist)
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   395
    opts = [(a[0].encode('latin-1'), a[1].encode('latin-1')) for a in opts]
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   396
    args = [a.encode('latin-1') for a in args]
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   397
    return opts, args
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   398
30583
c6ce11f2ee50 py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30509
diff changeset
   399
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   400
def strkwargs(dic: Mapping[bytes, _T0]) -> Dict[str, _T0]:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   401
    """
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   402
    Converts the keys of a python dictonary to str i.e. unicodes so that
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   403
    they can be passed as keyword arguments as dictionaries with bytes keys
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   404
    can't be passed as keyword arguments to functions on Python 3.
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   405
    """
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   406
    dic = {k.decode('latin-1'): v for k, v in dic.items()}
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   407
    return dic
30584
fbc3f73dc802 py3: utility functions to convert keys of kwargs to bytes/unicodes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30583
diff changeset
   408
fbc3f73dc802 py3: utility functions to convert keys of kwargs to bytes/unicodes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30583
diff changeset
   409
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   410
def byteskwargs(dic: Mapping[str, _T0]) -> Dict[bytes, _T0]:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   411
    """
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   412
    Converts keys of python dictionaries to bytes as they were converted to
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   413
    str to pass that dictonary as a keyword argument on Python 3.
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   414
    """
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   415
    dic = {k.encode('latin-1'): v for k, v in dic.items()}
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   416
    return dic
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   417
30681
caf7e1c5efe4 py3: have a bytes version of shlex.split()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30671
diff changeset
   418
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   419
# TODO: handle shlex.shlex().
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   420
def shlexsplit(
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   421
    s: bytes, comments: bool = False, posix: bool = True
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   422
) -> List[bytes]:
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   423
    """
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   424
    Takes bytes argument, convert it to str i.e. unicodes, pass that into
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   425
    shlex.split(), convert the returned value to bytes and return that for
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   426
    Python 3 compatibility as shelx.split() don't accept bytes on Python 3.
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   427
    """
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   428
    ret = shlex.split(s.decode('latin-1'), comments, posix)
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   429
    return [a.encode('latin-1') for a in ret]
43021
2cc453284d5c patchbomb: protect email addresses from shell
Floris Bruynooghe <flub@google.com>
parents: 40577
diff changeset
   430
43380
579672b347d2 py3: define and use json.loads polyfill
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43117
diff changeset
   431
48962
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   432
iteritems = lambda x: x.items()
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   433
itervalues = lambda x: x.values()
79009cca491e pycompat: remove large Python 2 block
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48960
diff changeset
   434
49051
c3a48dd506da pycompat: remove json.loads polyfill for Python 3.5
Gregory Szorc <gregory.szorc@gmail.com>
parents: 49050
diff changeset
   435
json_loads = json.loads
34639
a568a46751b6 selectors2: do not use platform.system()
Jun Wu <quark@fb.com>
parents: 34468
diff changeset
   436
49896
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   437
isjython: bool = sysplatform.startswith(b'java')
34644
c0a6c19690ff pycompat: define operating system constants
Jun Wu <quark@fb.com>
parents: 34639
diff changeset
   438
49896
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   439
isdarwin: bool = sysplatform.startswith(b'darwin')
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   440
islinux: bool = sysplatform.startswith(b'linux')
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   441
isposix: bool = osname == b'posix'
9cd327509cd4 typing: add type hints to global variables in mercurial/pycompat.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 49069
diff changeset
   442
iswindows: bool = osname == b'nt'
35235
5b569d512fbd fancyopts: use getopt.gnu_getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 34644
diff changeset
   443
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
   444
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   445
def getoptb(
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   446
    args: Sequence[bytes], shortlist: bytes, namelist: Sequence[bytes]
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   447
) -> _GetOptResult:
35235
5b569d512fbd fancyopts: use getopt.gnu_getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 34644
diff changeset
   448
    return _getoptbwrapper(getopt.getopt, args, shortlist, namelist)
5b569d512fbd fancyopts: use getopt.gnu_getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 34644
diff changeset
   449
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
   450
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   451
def gnugetoptb(
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   452
    args: Sequence[bytes], shortlist: bytes, namelist: Sequence[bytes]
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   453
) -> _GetOptResult:
35235
5b569d512fbd fancyopts: use getopt.gnu_getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 34644
diff changeset
   454
    return _getoptbwrapper(getopt.gnu_getopt, args, shortlist, namelist)
38197
aac4be30e250 py3: wrap tempfile.mkstemp() to use bytes path
Yuya Nishihara <yuya@tcha.org>
parents: 37890
diff changeset
   455
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
   456
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   457
def mkdtemp(
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   458
    suffix: bytes = b'', prefix: bytes = b'tmp', dir: Optional[bytes] = None
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   459
) -> bytes:
38198
2ce60954b1b7 py3: wrap tempfile.mkdtemp() to use bytes path
Yuya Nishihara <yuya@tcha.org>
parents: 38197
diff changeset
   460
    return tempfile.mkdtemp(suffix, prefix, dir)
2ce60954b1b7 py3: wrap tempfile.mkdtemp() to use bytes path
Yuya Nishihara <yuya@tcha.org>
parents: 38197
diff changeset
   461
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
   462
38197
aac4be30e250 py3: wrap tempfile.mkstemp() to use bytes path
Yuya Nishihara <yuya@tcha.org>
parents: 37890
diff changeset
   463
# text=True is not supported; use util.from/tonativeeol() instead
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   464
def mkstemp(
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   465
    suffix: bytes = b'', prefix: bytes = b'tmp', dir: Optional[bytes] = None
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   466
) -> Tuple[int, bytes]:
38197
aac4be30e250 py3: wrap tempfile.mkstemp() to use bytes path
Yuya Nishihara <yuya@tcha.org>
parents: 37890
diff changeset
   467
    return tempfile.mkstemp(suffix, prefix, dir)
38199
cc9aa88792fe py3: wrap tempfile.NamedTemporaryFile() to return bytes fp.name
Yuya Nishihara <yuya@tcha.org>
parents: 38198
diff changeset
   468
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
   469
45727
d4c4391aa7f2 pycompat: add an entry for unnamedtmpfile
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45726
diff changeset
   470
# TemporaryFile does not support an "encoding=" argument on python2.
d4c4391aa7f2 pycompat: add an entry for unnamedtmpfile
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45726
diff changeset
   471
# This wrapper file are always open in byte mode.
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   472
def unnamedtempfile(mode: Optional[bytes] = None, *args, **kwargs) -> BinaryIO:
45727
d4c4391aa7f2 pycompat: add an entry for unnamedtmpfile
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45726
diff changeset
   473
    if mode is None:
46380
7a29d9002250 pycompat: fix a bytes vs str issue in `unnamedtempfile()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 46178
diff changeset
   474
        mode = 'w+b'
45727
d4c4391aa7f2 pycompat: add an entry for unnamedtmpfile
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45726
diff changeset
   475
    else:
d4c4391aa7f2 pycompat: add an entry for unnamedtmpfile
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45726
diff changeset
   476
        mode = sysstr(mode)
d4c4391aa7f2 pycompat: add an entry for unnamedtmpfile
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45726
diff changeset
   477
    assert 'b' in mode
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   478
    return cast(BinaryIO, tempfile.TemporaryFile(mode, *args, **kwargs))
45727
d4c4391aa7f2 pycompat: add an entry for unnamedtmpfile
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45726
diff changeset
   479
d4c4391aa7f2 pycompat: add an entry for unnamedtmpfile
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45726
diff changeset
   480
45726
d1072cba8aff pycompat: update comment about unnamedtempfile
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45057
diff changeset
   481
# NamedTemporaryFile does not support an "encoding=" argument on python2.
d1072cba8aff pycompat: update comment about unnamedtempfile
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45057
diff changeset
   482
# This wrapper file are always open in byte mode.
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
   483
def namedtempfile(
49902
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   484
    mode: bytes = b'w+b',
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   485
    bufsize: int = -1,
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   486
    suffix: bytes = b'',
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   487
    prefix: bytes = b'tmp',
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   488
    dir: Optional[bytes] = None,
c5a06cc37401 typing: add type hints to most mercurial/pycompat.py functions
Matt Harbison <matt_harbison@yahoo.com>
parents: 49898
diff changeset
   489
    delete: bool = True,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
   490
):
38199
cc9aa88792fe py3: wrap tempfile.NamedTemporaryFile() to return bytes fp.name
Yuya Nishihara <yuya@tcha.org>
parents: 38198
diff changeset
   491
    mode = sysstr(mode)
43554
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43551
diff changeset
   492
    assert 'b' in mode
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
   493
    return tempfile.NamedTemporaryFile(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
   494
        mode, bufsize, suffix=suffix, prefix=prefix, dir=dir, delete=delete
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
   495
    )