diff --git a/mercurial/profiling.py b/mercurial/profiling.py --- a/mercurial/profiling.py +++ b/mercurial/profiling.py @@ -272,7 +272,12 @@ exception_type, exception_value, traceback ) if self._output == b'blackbox': + # We always use io.BytesIO if self._output == b"blackbox". But + # pytype doesn't realize this and thinks we're attempting to + # access .getvalue() on an IO type. + # pytype: disable=attribute-error val = b'Profile:\n%s' % self._fp.getvalue() + # pytype: enable=attribute-error # ui.log treats the input as a format string, # so we need to escape any % signs. val = val.replace(b'%', b'%%') diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py --- a/mercurial/pycompat.py +++ b/mercurial/pycompat.py @@ -36,6 +36,16 @@ if not globals(): # hide this from non-pytype users import typing + from typing import ( + Any, + AnyStr, + Dict, + IO, + Iterator, + List, + NoReturn, + Tuple, + ) TYPE_CHECKING = typing.TYPE_CHECKING @@ -112,15 +122,15 @@ sysexecutable = os.fsencode(sysexecutable) -def maplist(*args): +def maplist(*args) -> 'List[Any]': return list(map(*args)) -def rangelist(*args): +def rangelist(*args) -> 'List[int]': return list(range(*args)) -def ziplist(*args): +def ziplist(*args) -> 'List[Any]': return list(zip(*args)) @@ -226,20 +236,20 @@ s = str(s).encode('ascii') return bytes.__new__(cls, s) - def __getitem__(self, key): + def __getitem__(self, key) -> bytes: s = bytes.__getitem__(self, key) if not isinstance(s, bytes): s = bytechr(s) return s - def __iter__(self): + def __iter__(self) -> 'Iterator[bytes]': return iterbytestr(bytes.__iter__(self)) - def __repr__(self): + def __repr__(self) -> str: return bytes.__repr__(self)[1:] # drop b'' -def iterbytestr(s): +def iterbytestr(s) -> 'Iterator[bytes]': """Iterate bytes as if it were a str object of Python 2""" return map(bytechr, s) @@ -251,7 +261,7 @@ return s -def sysbytes(s): +def sysbytes(s) -> bytes: """Convert an internal str (e.g. keyword, __doc__) back to bytes This never raises UnicodeEncodeError, but only ASCII characters @@ -262,7 +272,7 @@ return s.encode('utf-8') -def sysstr(s): +def sysstr(s) -> str: """Return a keyword str to be passed to Python functions such as getattr() and str.encode() @@ -275,26 +285,26 @@ return s.decode('latin-1') -def strurl(url): +def strurl(url) -> str: """Converts a bytes url back to str""" if isinstance(url, bytes): return url.decode('ascii') return url -def bytesurl(url): +def bytesurl(url) -> bytes: """Converts a str url to bytes by encoding in ascii""" if isinstance(url, str): return url.encode('ascii') return url -def raisewithtb(exc, tb): +def raisewithtb(exc, tb) -> 'NoReturn': """Raise exception with the given traceback""" raise exc.with_traceback(tb) -def getdoc(obj): +def getdoc(obj) -> bytes: """Get docstring as bytes; may be None so gettext() won't confuse it with _('')""" doc = getattr(obj, '__doc__', None) @@ -320,14 +330,16 @@ unicode = str -def open(name, mode=b'r', buffering=-1, encoding=None): +def open(name, mode=b'r', buffering=-1, encoding=None) -> 'IO[AnyStr]': return builtins.open(name, sysstr(mode), buffering, encoding) safehasattr = _wrapattrfunc(builtins.hasattr) -def _getoptbwrapper(orig, args, shortlist, namelist): +def _getoptbwrapper( + orig, args, shortlist, namelist +) -> 'Tuple[List[Tuple[bytes, bytes]], List[bytes]]': """ Takes bytes arguments, converts them to unicode, pass them to getopt.getopt(), convert the returned values back to bytes and then @@ -343,7 +355,7 @@ return opts, args -def strkwargs(dic): +def strkwargs(dic) -> 'Dict[str, Any]': """ 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 @@ -353,7 +365,7 @@ return dic -def byteskwargs(dic): +def byteskwargs(dic) -> 'Dict[bytes, Any]': """ Converts keys of python dictionaries to bytes as they were converted to str to pass that dictonary as a keyword argument on Python 3. @@ -363,7 +375,7 @@ # TODO: handle shlex.shlex(). -def shlexsplit(s, comments=False, posix=True): +def shlexsplit(s, comments=False, posix=True) -> 'List[bytes]': """ 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 @@ -394,18 +406,18 @@ return _getoptbwrapper(getopt.gnu_getopt, args, shortlist, namelist) -def mkdtemp(suffix=b'', prefix=b'tmp', dir=None): +def mkdtemp(suffix=b'', prefix=b'tmp', dir=None) -> 'AnyStr': return tempfile.mkdtemp(suffix, prefix, dir) # text=True is not supported; use util.from/tonativeeol() instead -def mkstemp(suffix=b'', prefix=b'tmp', dir=None): +def mkstemp(suffix=b'', prefix=b'tmp', dir=None) -> 'Tuple[int, AnyStr]': return tempfile.mkstemp(suffix, prefix, dir) # TemporaryFile does not support an "encoding=" argument on python2. # This wrapper file are always open in byte mode. -def unnamedtempfile(mode=None, *args, **kwargs): +def unnamedtempfile(mode=None, *args, **kwargs) -> 'IO[AnyStr]': if mode is None: mode = 'w+b' else: