##// END OF EJS Templates
dynamic-import: use sysstr for importing extension and others...
dynamic-import: use sysstr for importing extension and others This logic is used by extensions, and python hooks and merge-tools. All this logic eventually deals with native string (unicode in Python 3). This patch makes it handle `str` directly instead of relying on some pycompat low lever layer to do the conversion at the last minutes. We adjust the Python version filtering of a test as the output seems to be present with Python 3.7 too.

File last commit:

r51071:829aa604 default
r51816:c642c039 default
Show More
pycompat.py
498 lines | 13.5 KiB | text/x-python | PythonLexer
timeless
pycompat: add empty and queue to handle py3 divergence...
r28818 # pycompat.py - portability shim for python 3
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
"""Mercurial portability shim for python 3.
This contains aliases to hide python version-specific details from the core.
"""
Gregory Szorc
pycompat: remove first not ispy3 block...
r49724 import builtins
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 import codecs
Gregory Szorc
pycompat: remove first not ispy3 block...
r49724 import concurrent.futures as futures
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 import functools
Pulkit Goyal
py3: make a bytes version of getopt.getopt()...
r30578 import getopt
Gregory Szorc
pycompat: remove first not ispy3 block...
r49724 import http.client as httplib
import http.cookiejar as cookielib
Augie Fackler
py3: introduce and use pycompat.getargspec...
r36196 import inspect
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 import io
Gregory Szorc
py3: define and use json.loads polyfill...
r43697 import json
Pulkit Goyal
py3: add a bytes version of os.name...
r30302 import os
Gregory Szorc
pycompat: remove first not ispy3 block...
r49724 import queue
Pulkit Goyal
py3: have a bytes version of shlex.split()...
r30678 import shlex
Gregory Szorc
pycompat: remove first not ispy3 block...
r49724 import socketserver
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 import struct
Pulkit Goyal
pycompat: make pycompat demandimport friendly...
r29584 import sys
Yuya Nishihara
py3: wrap tempfile.mkstemp() to use bytes path...
r38182 import tempfile
Gregory Szorc
pycompat: remove first not ispy3 block...
r49724 import xmlrpc.client as xmlrpclib
Pulkit Goyal
pycompat: make pycompat demandimport friendly...
r29584
Matt Harbison
typing: add type hints to global variables in mercurial/pycompat.py...
r50696 from typing import (
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 Any,
AnyStr,
BinaryIO,
Matt Harbison
typing: add type hints to pycompat.maplist()...
r51070 Callable,
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 Dict,
Matt Harbison
typing: add type hints to pycompat.bytestr...
r50698 Iterable,
Iterator,
Matt Harbison
typing: add type hints to global variables in mercurial/pycompat.py...
r50696 List,
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 Mapping,
NoReturn,
Matt Harbison
typing: add type hints to global variables in mercurial/pycompat.py...
r50696 Optional,
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 Sequence,
Tuple,
Matt Harbison
typing: add type hints to pycompat.bytestr...
r50698 Type,
TypeVar,
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 cast,
overload,
Matt Harbison
typing: add type hints to global variables in mercurial/pycompat.py...
r50696 )
Gregory Szorc
pycompat: remove large Python 2 block...
r49726
Augie Fackler
formatting: blacken the codebase...
r43346 ispy3 = sys.version_info[0] >= 3
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 ispypy = '__pypy__' in sys.builtin_module_names
Yuya Nishihara
typing: consolidate "if not globals():" trick...
r44212 TYPE_CHECKING = False
if not globals(): # hide this from non-pytype users
import typing
TYPE_CHECKING = typing.TYPE_CHECKING
Yuya Nishihara
pycompat: provide 'ispy3' constant...
r30030
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 _GetOptResult = Tuple[List[Tuple[bytes, bytes]], List[bytes]]
_T0 = TypeVar('_T0')
Matt Harbison
typing: add type hints to pycompat.maplist()...
r51070 _T1 = TypeVar('_T1')
_S = TypeVar('_S')
Matt Harbison
typing: add type hints to pycompat.bytestr...
r50698 _Tbytestr = TypeVar('_Tbytestr', bound='bytestr')
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
pycompat: remove first not ispy3 block...
r49724 def future_set_exception_info(f, exc_info):
f.set_exception(exc_info[0])
Pulkit Goyal
py3: conditionalize the urlparse import...
r29431
Augie Fackler
py3: paper over differences in future exception handling...
r37687
Gregory Szorc
pycompat: remove first not ispy3 block...
r49724 FileNotFoundError = builtins.FileNotFoundError
template: FileNotFoundError is actually a built in exception...
r48665
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def identity(a: _T0) -> _T0:
Yuya Nishihara
pycompat: introduce identity function as a compat stub...
r31774 return a
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
pycompat: move rapply() from util...
r38594 def _rapply(f, xs):
if xs is None:
# assume None means non-value of optional data
return xs
if isinstance(xs, (list, set, tuple)):
return type(xs)(_rapply(f, x) for x in xs)
if isinstance(xs, dict):
return type(xs)((_rapply(f, k), _rapply(f, v)) for k, v in xs.items())
return f(xs)
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
pycompat: move rapply() from util...
r38594 def rapply(f, xs):
"""Apply function recursively to every item preserving the data structure
>>> def f(x):
... return 'f(%s)' % x
>>> rapply(f, None) is None
True
>>> rapply(f, 'a')
'f(a)'
>>> rapply(f, {'a'}) == {'f(a)'}
True
>>> rapply(f, ['a', 'b', None, {'c': 'd'}, []])
['f(a)', 'f(b)', None, {'f(c)': 'f(d)'}, []]
>>> xs = [object()]
>>> rapply(identity, xs) is xs
True
"""
if f is identity:
# fast path mainly for py2
return xs
return _rapply(f, xs)
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
pycompat: remove check for Python >= 3.6...
r49814 if os.name == r'nt':
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 # MBCS (or ANSI) filesystem encoding must be used as before.
# Otherwise non-ASCII filenames in existing repositories would be
# corrupted.
# This must be set once prior to any fsencode/fsdecode calls.
sys._enablelegacywindowsfsencoding() # pytype: disable=module-attr
Yuya Nishihara
py3: enable legacy fs encoding to fix filename compatibility on Windows...
r43613
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 fsencode = os.fsencode
fsdecode = os.fsdecode
Matt Harbison
typing: add type hints to global variables in mercurial/pycompat.py...
r50696 oscurdir: bytes = os.curdir.encode('ascii')
oslinesep: bytes = os.linesep.encode('ascii')
osname: bytes = os.name.encode('ascii')
ospathsep: bytes = os.pathsep.encode('ascii')
ospardir: bytes = os.pardir.encode('ascii')
ossep: bytes = os.sep.encode('ascii')
osaltsep: Optional[bytes] = os.altsep.encode('ascii') if os.altsep else None
osdevnull: bytes = os.devnull.encode('ascii')
Matt Harbison
py3: rename pycompat.getcwd() to encoding.getcwd() (API)...
r39843
Matt Harbison
typing: add type hints to global variables in mercurial/pycompat.py...
r50696 sysplatform: bytes = sys.platform.encode('ascii')
sysexecutable: bytes = os.fsencode(sys.executable) if sys.executable else b''
Yuya Nishihara
pycompat: name maplist() and ziplist() for better traceback message
r36952
Gregory Szorc
pycompat: remove large Python 2 block...
r49726
Matt Harbison
typing: add type hints to pycompat.maplist()...
r51070 if TYPE_CHECKING:
@overload
def maplist(f: Callable[[_T0], _S], arg: Iterable[_T0]) -> List[_S]:
...
@overload
def maplist(
f: Callable[[_T0, _T1], _S], arg1: Iterable[_T0], arg2: Iterable[_T1]
) -> List[_S]:
...
def maplist(f, *args):
return list(map(f, *args))
Yuya Nishihara
pycompat: name maplist() and ziplist() for better traceback message
r36952
Gregory Szorc
pycompat: remove large Python 2 block...
r49726
Matt Harbison
typing: add the return type hint to pycompat.rangelist()...
r51071 def rangelist(*args) -> List[int]:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 return list(range(*args))
Yuya Nishihara
annotate: do not construct attr.s object per line while computing history...
r37082
Gregory Szorc
pycompat: remove large Python 2 block...
r49726
def ziplist(*args):
return list(zip(*args))
Yuya Nishihara
pycompat: name maplist() and ziplist() for better traceback message
r36952
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 rawinput = input
getargspec = inspect.getfullargspec
Yuya Nishihara
py3: document why os.fsencode() can be used to get back bytes argv...
r30334
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 long = int
Matt Harbison
cbor: teach the encoder to handle python `long` type for Windows...
r39490
Matt Harbison
pycompat: explicitly prefix builtin attr usage with `builtins.`...
r50697 if builtins.getattr(sys, 'argv', None) is not None:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 # On POSIX, the char** argv array is converted to Python str using
# Py_DecodeLocale(). The inverse of this is Py_EncodeLocale(), which
# isn't directly callable from Python code. In practice, os.fsencode()
# can be used instead (this is recommended by Python's documentation
# for sys.argv).
#
# On Windows, the wchar_t **argv is passed into the interpreter as-is.
# Like POSIX, we need to emulate what Py_EncodeLocale() would do. But
# there's an additional wrinkle. What we really want to access is the
# ANSI codepage representation of the arguments, as this is what
# `int main()` would receive if Python 3 didn't define `int wmain()`
# (this is how Python 2 worked). To get that, we encode with the mbcs
# encoding, which will pass CP_ACP to the underlying Windows API to
# produce bytes.
Matt Harbison
typing: add type hints to global variables in mercurial/pycompat.py...
r50696 sysargv: List[bytes] = []
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 if os.name == r'nt':
sysargv = [a.encode("mbcs", "ignore") for a in sys.argv]
else:
sysargv = [fsencode(a) for a in sys.argv]
Yuya Nishihara
py3: move xrange alias next to import lines...
r29797
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 bytechr = struct.Struct('>B').pack
byterepr = b'%r'.__mod__
Yuya Nishihara
pycompat: add bytestr wrapper which mostly acts as a Python 2 str...
r31439
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 class bytestr(bytes):
"""A bytes which mostly acts as a Python 2 str
Yuya Nishihara
pycompat: try __bytes__() to convert object to bytestr...
r32450
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 >>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1)
('', 'foo', 'ascii', '1')
>>> s = bytestr(b'foo')
>>> assert s is bytestr(s)
__bytes__() should be called if provided:
Yuya Nishihara
pycompat: try __bytes__() to convert object to bytestr...
r32450
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 >>> class bytesable:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 ... def __bytes__(self):
... return b'bytes'
>>> bytestr(bytesable())
'bytes'
Yuya Nishihara
pycompat: add bytestr wrapper which mostly acts as a Python 2 str...
r31439
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 There's no implicit conversion from non-ascii str as its encoding is
unknown:
Yuya Nishihara
pycompat: add bytestr wrapper which mostly acts as a Python 2 str...
r31439
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS
Traceback (most recent call last):
...
UnicodeEncodeError: ...
Yuya Nishihara
pycompat: add bytestr wrapper which mostly acts as a Python 2 str...
r31439
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 Comparison between bytestr and bytes should work:
Yuya Nishihara
pycompat: add bytestr wrapper which mostly acts as a Python 2 str...
r31439
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 >>> assert bytestr(b'foo') == b'foo'
>>> assert b'foo' == bytestr(b'foo')
>>> assert b'f' in bytestr(b'foo')
>>> assert bytestr(b'f') in b'foo'
Yuya Nishihara
pycompat: add bytestr wrapper which mostly acts as a Python 2 str...
r31439
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 Sliced elements should be bytes, not integer:
Yuya Nishihara
pycompat: add bytestr wrapper which mostly acts as a Python 2 str...
r31439
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 >>> s[1], s[:2]
(b'o', b'fo')
>>> list(s), list(reversed(s))
([b'f', b'o', b'o'], [b'o', b'o', b'f'])
Yuya Nishihara
pycompat: add bytestr wrapper which mostly acts as a Python 2 str...
r31439
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 As bytestr type isn't propagated across operations, you need to cast
bytes to bytestr explicitly:
Yuya Nishihara
pycompat: add bytestr wrapper which mostly acts as a Python 2 str...
r31439
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 >>> s = bytestr(b'foo').upper()
>>> t = bytestr(s)
>>> s[0], t[0]
(70, b'F')
Matt Harbison
typing: add a fake `__init__()` to bytestr to distract pytype...
r48819
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 Be careful to not pass a bytestr object to a function which expects
bytearray-like behavior.
>>> t = bytes(t) # cast to bytes
>>> assert type(t) is bytes
"""
Matt Harbison
typing: add a fake `__init__()` to bytestr to distract pytype...
r48819
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 # Trick pytype into not demanding Iterable[int] be passed to __new__(),
# since the appropriate bytes format is done internally.
#
# https://github.com/google/pytype/issues/500
if TYPE_CHECKING:
Yuya Nishihara
pycompat: add bytestr wrapper which mostly acts as a Python 2 str...
r31439
Matt Harbison
typing: add type hints to pycompat.bytestr...
r50698 def __init__(self, s: object = b'') -> None:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 pass
Matt Harbison
typing: add type hints to pycompat.bytestr...
r50698 def __new__(cls: Type[_Tbytestr], s: object = b'') -> _Tbytestr:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 if isinstance(s, bytestr):
Yuya Nishihara
pycompat: add bytestr wrapper which mostly acts as a Python 2 str...
r31439 return s
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 if not isinstance(
s, (bytes, bytearray)
Matt Harbison
pycompat: explicitly prefix builtin attr usage with `builtins.`...
r50697 ) and not builtins.hasattr( # hasattr-py3-only
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 s, u'__bytes__'
):
s = str(s).encode('ascii')
return bytes.__new__(cls, s)
Yuya Nishihara
py3: always drop b'' prefix from repr() of bytestr...
r35921
Matt Harbison
typing: disable `signature-mismatch` warnings on a few bytestr functions...
r50996 # The base class uses `int` return in py3, but the point of this class is to
# behave like py2.
def __getitem__(self, key) -> bytes: # pytype: disable=signature-mismatch
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 s = bytes.__getitem__(self, key)
if not isinstance(s, bytes):
s = bytechr(s)
Yuya Nishihara
py3: drop b'' from repr() of smartset...
r35922 return s
Matt Harbison
typing: disable `signature-mismatch` warnings on a few bytestr functions...
r50996 # The base class expects `Iterator[int]` return in py3, but the point of
# this class is to behave like py2.
def __iter__(self) -> Iterator[bytes]: # pytype: disable=signature-mismatch
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 return iterbytestr(bytes.__iter__(self))
Matt Harbison
typing: add type hints to pycompat.bytestr...
r50698 def __repr__(self) -> str:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 return bytes.__repr__(self)[1:] # drop b''
Yuya Nishihara
py3: have registrar process docstrings in bytes...
r31820
Matt Harbison
typing: add type hints to pycompat.bytestr...
r50698 def iterbytestr(s: Iterable[int]) -> Iterator[bytes]:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 """Iterate bytes as if it were a str object of Python 2"""
return map(bytechr, s)
Yuya Nishihara
py3: have registrar process docstrings in bytes...
r31820
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 if TYPE_CHECKING:
@overload
def maybebytestr(s: bytes) -> bytestr:
...
@overload
def maybebytestr(s: _T0) -> _T0:
...
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 def maybebytestr(s):
"""Promote bytes to bytestr"""
if isinstance(s, bytes):
return bytestr(s)
return s
Yuya Nishihara
pycompat: extract function that converts attribute or encoding name to str...
r30032
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def sysbytes(s: AnyStr) -> bytes:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 """Convert an internal str (e.g. keyword, __doc__) back to bytes
This never raises UnicodeEncodeError, but only ASCII characters
can be round-trip by sysstr(sysbytes(s)).
"""
if isinstance(s, bytes):
return s
return s.encode('utf-8')
Yuya Nishihara
pycompat: extract function that converts attribute or encoding name to str...
r30032
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def sysstr(s: AnyStr) -> str:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 """Return a keyword str to be passed to Python functions such as
getattr() and str.encode()
This never raises UnicodeDecodeError. Non-ascii characters are
considered invalid and mapped to arbitrary but unique code points
such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
"""
if isinstance(s, builtins.str):
return s
return s.decode('latin-1')
Pulkit Goyal
py3: add a new strurl() which will convert a bytes url to str
r32859
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def strurl(url: AnyStr) -> str:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 """Converts a bytes url back to str"""
if isinstance(url, bytes):
return url.decode('ascii')
return url
Pulkit Goyal
py3: add a new bytesurl() to convert a str url into bytes
r32860
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def bytesurl(url: AnyStr) -> bytes:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 """Converts a str url to bytes by encoding in ascii"""
if isinstance(url, str):
return url.encode('ascii')
return url
Yuya Nishihara
pycompat: extract helper to raise exception with traceback...
r32186
Gregory Szorc
pycompat: remove large Python 2 block...
r49726
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def raisewithtb(exc: BaseException, tb) -> NoReturn:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 """Raise exception with the given traceback"""
raise exc.with_traceback(tb)
Yuya Nishihara
py3: convert __doc__ back to bytes in help.py...
r32615
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def getdoc(obj: object) -> Optional[bytes]:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 """Get docstring as bytes; may be None so gettext() won't confuse it
with _('')"""
Matt Harbison
pycompat: explicitly prefix builtin attr usage with `builtins.`...
r50697 doc = builtins.getattr(obj, '__doc__', None)
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 if doc is None:
return doc
return sysbytes(doc)
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
pycompat: remove large Python 2 block...
r49726
def _wrapattrfunc(f):
@functools.wraps(f)
def w(object, name, *args):
return f(object, sysstr(name), *args)
Yuya Nishihara
py3: provide (del|get|has|set)attr wrappers that accepts bytes...
r29799
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 return w
Yuya Nishihara
py3: provide (del|get|has|set)attr wrappers that accepts bytes...
r29799
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 # these wrappers are automagically imported by hgloader
delattr = _wrapattrfunc(builtins.delattr)
getattr = _wrapattrfunc(builtins.getattr)
hasattr = _wrapattrfunc(builtins.hasattr)
setattr = _wrapattrfunc(builtins.setattr)
xrange = builtins.range
unicode = str
Pulkit Goyal
py3: add pycompat.open and replace open() calls...
r31149
Gregory Szorc
pycompat: remove large Python 2 block...
r49726
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def open(
name,
mode: AnyStr = b'r',
buffering: int = -1,
encoding: Optional[str] = None,
) -> Any:
# TODO: assert binary mode, and cast result to BinaryIO?
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 return builtins.open(name, sysstr(mode), buffering, encoding)
Yuya Nishihara
util: make safehasattr() a pycompat function...
r37117
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 safehasattr = _wrapattrfunc(builtins.hasattr)
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def _getoptbwrapper(
orig, args: Sequence[bytes], shortlist: bytes, namelist: Sequence[bytes]
) -> _GetOptResult:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 """
Takes bytes arguments, converts them to unicode, pass them to
getopt.getopt(), convert the returned values back to bytes and then
return them for Python 3 compatibility as getopt.getopt() don't accepts
bytes on Python 3.
"""
args = [a.decode('latin-1') for a in args]
shortlist = shortlist.decode('latin-1')
namelist = [a.decode('latin-1') for a in namelist]
opts, args = orig(args, shortlist, namelist)
opts = [(a[0].encode('latin-1'), a[1].encode('latin-1')) for a in opts]
args = [a.encode('latin-1') for a in args]
return opts, args
Pulkit Goyal
py3: make a bytes version of getopt.getopt()...
r30578
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def strkwargs(dic: Mapping[bytes, _T0]) -> Dict[str, _T0]:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 """
Converts the keys of a python dictonary to str i.e. unicodes so that
they can be passed as keyword arguments as dictionaries with bytes keys
can't be passed as keyword arguments to functions on Python 3.
"""
dic = {k.decode('latin-1'): v for k, v in dic.items()}
return dic
Pulkit Goyal
py3: utility functions to convert keys of kwargs to bytes/unicodes...
r30579
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def byteskwargs(dic: Mapping[str, _T0]) -> Dict[bytes, _T0]:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 """
Converts keys of python dictionaries to bytes as they were converted to
str to pass that dictonary as a keyword argument on Python 3.
"""
dic = {k.encode('latin-1'): v for k, v in dic.items()}
return dic
Pulkit Goyal
py3: have a bytes version of shlex.split()...
r30678
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 # TODO: handle shlex.shlex().
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def shlexsplit(
s: bytes, comments: bool = False, posix: bool = True
) -> List[bytes]:
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 """
Takes bytes argument, convert it to str i.e. unicodes, pass that into
shlex.split(), convert the returned value to bytes and return that for
Python 3 compatibility as shelx.split() don't accept bytes on Python 3.
"""
ret = shlex.split(s.decode('latin-1'), comments, posix)
return [a.encode('latin-1') for a in ret]
Floris Bruynooghe
patchbomb: protect email addresses from shell...
r43289
Gregory Szorc
py3: define and use json.loads polyfill...
r43697
Gregory Szorc
pycompat: remove large Python 2 block...
r49726 iteritems = lambda x: x.items()
itervalues = lambda x: x.values()
Gregory Szorc
pycompat: remove json.loads polyfill for Python 3.5...
r49815 json_loads = json.loads
Jun Wu
selectors2: do not use platform.system()...
r34640
Matt Harbison
typing: add type hints to global variables in mercurial/pycompat.py...
r50696 isjython: bool = sysplatform.startswith(b'java')
Jun Wu
pycompat: define operating system constants...
r34645
Matt Harbison
typing: add type hints to global variables in mercurial/pycompat.py...
r50696 isdarwin: bool = sysplatform.startswith(b'darwin')
islinux: bool = sysplatform.startswith(b'linux')
isposix: bool = osname == b'posix'
iswindows: bool = osname == b'nt'
Yuya Nishihara
fancyopts: use getopt.gnu_getopt()...
r35226
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def getoptb(
args: Sequence[bytes], shortlist: bytes, namelist: Sequence[bytes]
) -> _GetOptResult:
Yuya Nishihara
fancyopts: use getopt.gnu_getopt()...
r35226 return _getoptbwrapper(getopt.getopt, args, shortlist, namelist)
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def gnugetoptb(
args: Sequence[bytes], shortlist: bytes, namelist: Sequence[bytes]
) -> _GetOptResult:
Yuya Nishihara
fancyopts: use getopt.gnu_getopt()...
r35226 return _getoptbwrapper(getopt.gnu_getopt, args, shortlist, namelist)
Yuya Nishihara
py3: wrap tempfile.mkstemp() to use bytes path...
r38182
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def mkdtemp(
suffix: bytes = b'', prefix: bytes = b'tmp', dir: Optional[bytes] = None
) -> bytes:
Yuya Nishihara
py3: wrap tempfile.mkdtemp() to use bytes path...
r38183 return tempfile.mkdtemp(suffix, prefix, dir)
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
py3: wrap tempfile.mkstemp() to use bytes path...
r38182 # text=True is not supported; use util.from/tonativeeol() instead
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def mkstemp(
suffix: bytes = b'', prefix: bytes = b'tmp', dir: Optional[bytes] = None
) -> Tuple[int, bytes]:
Yuya Nishihara
py3: wrap tempfile.mkstemp() to use bytes path...
r38182 return tempfile.mkstemp(suffix, prefix, dir)
Yuya Nishihara
py3: wrap tempfile.NamedTemporaryFile() to return bytes fp.name...
r38184
Augie Fackler
formatting: blacken the codebase...
r43346
pycompat: add an entry for unnamedtmpfile...
r46319 # TemporaryFile does not support an "encoding=" argument on python2.
# This wrapper file are always open in byte mode.
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 def unnamedtempfile(mode: Optional[bytes] = None, *args, **kwargs) -> BinaryIO:
pycompat: add an entry for unnamedtmpfile...
r46319 if mode is None:
Matt Harbison
pycompat: fix a bytes vs str issue in `unnamedtempfile()`...
r47385 mode = 'w+b'
pycompat: add an entry for unnamedtmpfile...
r46319 else:
mode = sysstr(mode)
assert 'b' in mode
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 return cast(BinaryIO, tempfile.TemporaryFile(mode, *args, **kwargs))
pycompat: add an entry for unnamedtmpfile...
r46319
pycompat: update comment about unnamedtempfile...
r46318 # NamedTemporaryFile does not support an "encoding=" argument on python2.
# This wrapper file are always open in byte mode.
Augie Fackler
formatting: blacken the codebase...
r43346 def namedtempfile(
Matt Harbison
typing: add type hints to most mercurial/pycompat.py functions...
r50702 mode: bytes = b'w+b',
bufsize: int = -1,
suffix: bytes = b'',
prefix: bytes = b'tmp',
dir: Optional[bytes] = None,
delete: bool = True,
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Yuya Nishihara
py3: wrap tempfile.NamedTemporaryFile() to return bytes fp.name...
r38184 mode = sysstr(mode)
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 assert 'b' in mode
Augie Fackler
formatting: blacken the codebase...
r43346 return tempfile.NamedTemporaryFile(
mode, bufsize, suffix=suffix, prefix=prefix, dir=dir, delete=delete
)