We no longer support Python 2. So we can delete its compatibility
code and remove the conditional and dedent the Python 3 code.
In order to make the linter happy, we had to inline imports in the
stanza at the top of the file.
( )
Alphare |
hg-reviewers |
We no longer support Python 2. So we can delete its compatibility
code and remove the conditional and dedent the Python 3 code.
In order to make the linter happy, we had to inline imports in the
stanza at the top of the file.
No Linters Available |
No Unit Test Coverage |
Path | Packages | |||
---|---|---|---|---|
M | mercurial/pycompat.py (629 lines) |
Commit | Parents | Author | Summary | Date |
---|---|---|---|---|
4abe41a5f474 | c45ca45b04c9 | Gregory Szorc | Feb 20 2022, 4:48 PM |
# pycompat.py - portability shim for python 3 | # pycompat.py - portability shim for python 3 | ||||
# | # | ||||
# This software may be used and distributed according to the terms of the | # This software may be used and distributed according to the terms of the | ||||
# GNU General Public License version 2 or any later version. | # GNU General Public License version 2 or any later version. | ||||
"""Mercurial portability shim for python 3. | """Mercurial portability shim for python 3. | ||||
This contains aliases to hide python version-specific details from the core. | This contains aliases to hide python version-specific details from the core. | ||||
""" | """ | ||||
from __future__ import absolute_import | from __future__ import absolute_import | ||||
import builtins | import builtins | ||||
import codecs | |||||
import concurrent.futures as futures | import concurrent.futures as futures | ||||
import functools | |||||
import getopt | import getopt | ||||
import http.client as httplib | import http.client as httplib | ||||
import http.cookiejar as cookielib | import http.cookiejar as cookielib | ||||
import inspect | import inspect | ||||
import io | |||||
import json | import json | ||||
import os | import os | ||||
import queue | import queue | ||||
import shlex | import shlex | ||||
import socketserver | import socketserver | ||||
import struct | |||||
import sys | import sys | ||||
import tempfile | import tempfile | ||||
import xmlrpc.client as xmlrpclib | import xmlrpc.client as xmlrpclib | ||||
ispy3 = sys.version_info[0] >= 3 | ispy3 = sys.version_info[0] >= 3 | ||||
ispypy = '__pypy__' in sys.builtin_module_names | ispypy = '__pypy__' in sys.builtin_module_names | ||||
TYPE_CHECKING = False | TYPE_CHECKING = False | ||||
if not globals(): # hide this from non-pytype users | if not globals(): # hide this from non-pytype users | ||||
import typing | import typing | ||||
TYPE_CHECKING = typing.TYPE_CHECKING | TYPE_CHECKING = typing.TYPE_CHECKING | ||||
True | True | ||||
""" | """ | ||||
if f is identity: | if f is identity: | ||||
# fast path mainly for py2 | # fast path mainly for py2 | ||||
return xs | return xs | ||||
return _rapply(f, xs) | return _rapply(f, xs) | ||||
if ispy3: | |||||
import builtins | |||||
import codecs | |||||
import functools | |||||
import io | |||||
import struct | |||||
if os.name == r'nt' and sys.version_info >= (3, 6): | if os.name == r'nt' and sys.version_info >= (3, 6): | ||||
# MBCS (or ANSI) filesystem encoding must be used as before. | # MBCS (or ANSI) filesystem encoding must be used as before. | ||||
# Otherwise non-ASCII filenames in existing repositories would be | # Otherwise non-ASCII filenames in existing repositories would be | ||||
# corrupted. | # corrupted. | ||||
# This must be set once prior to any fsencode/fsdecode calls. | # This must be set once prior to any fsencode/fsdecode calls. | ||||
sys._enablelegacywindowsfsencoding() # pytype: disable=module-attr | sys._enablelegacywindowsfsencoding() # pytype: disable=module-attr | ||||
fsencode = os.fsencode | fsencode = os.fsencode | ||||
fsdecode = os.fsdecode | fsdecode = os.fsdecode | ||||
oscurdir = os.curdir.encode('ascii') | oscurdir = os.curdir.encode('ascii') | ||||
oslinesep = os.linesep.encode('ascii') | oslinesep = os.linesep.encode('ascii') | ||||
osname = os.name.encode('ascii') | osname = os.name.encode('ascii') | ||||
ospathsep = os.pathsep.encode('ascii') | ospathsep = os.pathsep.encode('ascii') | ||||
ospardir = os.pardir.encode('ascii') | ospardir = os.pardir.encode('ascii') | ||||
ossep = os.sep.encode('ascii') | ossep = os.sep.encode('ascii') | ||||
osaltsep = os.altsep | osaltsep = os.altsep | ||||
if osaltsep: | if osaltsep: | ||||
osaltsep = osaltsep.encode('ascii') | osaltsep = osaltsep.encode('ascii') | ||||
osdevnull = os.devnull.encode('ascii') | osdevnull = os.devnull.encode('ascii') | ||||
sysplatform = sys.platform.encode('ascii') | sysplatform = sys.platform.encode('ascii') | ||||
sysexecutable = sys.executable | sysexecutable = sys.executable | ||||
if sysexecutable: | if sysexecutable: | ||||
sysexecutable = os.fsencode(sysexecutable) | sysexecutable = os.fsencode(sysexecutable) | ||||
bytesio = io.BytesIO | bytesio = io.BytesIO | ||||
# TODO deprecate stringio name, as it is a lie on Python 3. | # TODO deprecate stringio name, as it is a lie on Python 3. | ||||
stringio = bytesio | stringio = bytesio | ||||
def maplist(*args): | def maplist(*args): | ||||
return list(map(*args)) | return list(map(*args)) | ||||
def rangelist(*args): | def rangelist(*args): | ||||
return list(range(*args)) | return list(range(*args)) | ||||
def ziplist(*args): | def ziplist(*args): | ||||
return list(zip(*args)) | return list(zip(*args)) | ||||
rawinput = input | rawinput = input | ||||
getargspec = inspect.getfullargspec | getargspec = inspect.getfullargspec | ||||
long = int | long = int | ||||
if getattr(sys, 'argv', None) is not None: | if getattr(sys, 'argv', None) is not None: | ||||
# On POSIX, the char** argv array is converted to Python str using | # On POSIX, the char** argv array is converted to Python str using | ||||
# Py_DecodeLocale(). The inverse of this is Py_EncodeLocale(), which | # Py_DecodeLocale(). The inverse of this is Py_EncodeLocale(), which | ||||
# isn't directly callable from Python code. In practice, os.fsencode() | # isn't directly callable from Python code. In practice, os.fsencode() | ||||
# can be used instead (this is recommended by Python's documentation | # can be used instead (this is recommended by Python's documentation | ||||
# for sys.argv). | # for sys.argv). | ||||
# | # | ||||
# On Windows, the wchar_t **argv is passed into the interpreter as-is. | # 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 | # 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 | # there's an additional wrinkle. What we really want to access is the | ||||
# ANSI codepage representation of the arguments, as this is what | # ANSI codepage representation of the arguments, as this is what | ||||
# `int main()` would receive if Python 3 didn't define `int wmain()` | # `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 | # (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 | # encoding, which will pass CP_ACP to the underlying Windows API to | ||||
# produce bytes. | # produce bytes. | ||||
if os.name == r'nt': | if os.name == r'nt': | ||||
sysargv = [a.encode("mbcs", "ignore") for a in sys.argv] | sysargv = [a.encode("mbcs", "ignore") for a in sys.argv] | ||||
else: | else: | ||||
sysargv = [fsencode(a) for a in sys.argv] | sysargv = [fsencode(a) for a in sys.argv] | ||||
bytechr = struct.Struct('>B').pack | bytechr = struct.Struct('>B').pack | ||||
byterepr = b'%r'.__mod__ | byterepr = b'%r'.__mod__ | ||||
class bytestr(bytes): | class bytestr(bytes): | ||||
"""A bytes which mostly acts as a Python 2 str | """A bytes which mostly acts as a Python 2 str | ||||
>>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1) | >>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), bytestr(1) | ||||
('', 'foo', 'ascii', '1') | ('', 'foo', 'ascii', '1') | ||||
>>> s = bytestr(b'foo') | >>> s = bytestr(b'foo') | ||||
>>> assert s is bytestr(s) | >>> assert s is bytestr(s) | ||||
__bytes__() should be called if provided: | __bytes__() should be called if provided: | ||||
>>> class bytesable(object): | >>> class bytesable(object): | ||||
... def __bytes__(self): | ... def __bytes__(self): | ||||
... return b'bytes' | ... return b'bytes' | ||||
>>> bytestr(bytesable()) | >>> bytestr(bytesable()) | ||||
'bytes' | 'bytes' | ||||
There's no implicit conversion from non-ascii str as its encoding is | There's no implicit conversion from non-ascii str as its encoding is | ||||
unknown: | unknown: | ||||
>>> bytestr(chr(0x80)) # doctest: +ELLIPSIS | >>> bytestr(chr(0x80)) # doctest: +ELLIPSIS | ||||
Traceback (most recent call last): | Traceback (most recent call last): | ||||
... | ... | ||||
UnicodeEncodeError: ... | UnicodeEncodeError: ... | ||||
Comparison between bytestr and bytes should work: | Comparison between bytestr and bytes should work: | ||||
>>> assert bytestr(b'foo') == b'foo' | >>> assert bytestr(b'foo') == b'foo' | ||||
>>> assert b'foo' == bytestr(b'foo') | >>> assert b'foo' == bytestr(b'foo') | ||||
>>> assert b'f' in bytestr(b'foo') | >>> assert b'f' in bytestr(b'foo') | ||||
>>> assert bytestr(b'f') in b'foo' | >>> assert bytestr(b'f') in b'foo' | ||||
Sliced elements should be bytes, not integer: | Sliced elements should be bytes, not integer: | ||||
>>> s[1], s[:2] | >>> s[1], s[:2] | ||||
(b'o', b'fo') | (b'o', b'fo') | ||||
>>> list(s), list(reversed(s)) | >>> list(s), list(reversed(s)) | ||||
([b'f', b'o', b'o'], [b'o', b'o', b'f']) | ([b'f', b'o', b'o'], [b'o', b'o', b'f']) | ||||
As bytestr type isn't propagated across operations, you need to cast | As bytestr type isn't propagated across operations, you need to cast | ||||
bytes to bytestr explicitly: | bytes to bytestr explicitly: | ||||
>>> s = bytestr(b'foo').upper() | >>> s = bytestr(b'foo').upper() | ||||
>>> t = bytestr(s) | >>> t = bytestr(s) | ||||
>>> s[0], t[0] | >>> s[0], t[0] | ||||
(70, b'F') | (70, b'F') | ||||
Be careful to not pass a bytestr object to a function which expects | Be careful to not pass a bytestr object to a function which expects | ||||
bytearray-like behavior. | bytearray-like behavior. | ||||
>>> t = bytes(t) # cast to bytes | >>> t = bytes(t) # cast to bytes | ||||
>>> assert type(t) is bytes | >>> assert type(t) is bytes | ||||
""" | """ | ||||
# Trick pytype into not demanding Iterable[int] be passed to __new__(), | # Trick pytype into not demanding Iterable[int] be passed to __new__(), | ||||
# since the appropriate bytes format is done internally. | # since the appropriate bytes format is done internally. | ||||
# | # | ||||
# https://github.com/google/pytype/issues/500 | # https://github.com/google/pytype/issues/500 | ||||
if TYPE_CHECKING: | if TYPE_CHECKING: | ||||
def __init__(self, s=b''): | def __init__(self, s=b''): | ||||
pass | pass | ||||
def __new__(cls, s=b''): | def __new__(cls, s=b''): | ||||
if isinstance(s, bytestr): | if isinstance(s, bytestr): | ||||
return s | return s | ||||
if not isinstance( | if not isinstance( | ||||
s, (bytes, bytearray) | s, (bytes, bytearray) | ||||
) and not hasattr( # hasattr-py3-only | ) and not hasattr( # hasattr-py3-only | ||||
s, u'__bytes__' | s, u'__bytes__' | ||||
): | ): | ||||
s = str(s).encode('ascii') | s = str(s).encode('ascii') | ||||
return bytes.__new__(cls, s) | return bytes.__new__(cls, s) | ||||
def __getitem__(self, key): | def __getitem__(self, key): | ||||
s = bytes.__getitem__(self, key) | s = bytes.__getitem__(self, key) | ||||
if not isinstance(s, bytes): | if not isinstance(s, bytes): | ||||
s = bytechr(s) | s = bytechr(s) | ||||
return s | return s | ||||
def __iter__(self): | def __iter__(self): | ||||
return iterbytestr(bytes.__iter__(self)) | return iterbytestr(bytes.__iter__(self)) | ||||
def __repr__(self): | def __repr__(self): | ||||
return bytes.__repr__(self)[1:] # drop b'' | return bytes.__repr__(self)[1:] # drop b'' | ||||
def iterbytestr(s): | def iterbytestr(s): | ||||
"""Iterate bytes as if it were a str object of Python 2""" | """Iterate bytes as if it were a str object of Python 2""" | ||||
return map(bytechr, s) | return map(bytechr, s) | ||||
def maybebytestr(s): | def maybebytestr(s): | ||||
"""Promote bytes to bytestr""" | """Promote bytes to bytestr""" | ||||
if isinstance(s, bytes): | if isinstance(s, bytes): | ||||
return bytestr(s) | return bytestr(s) | ||||
return s | return s | ||||
def sysbytes(s): | def sysbytes(s): | ||||
"""Convert an internal str (e.g. keyword, __doc__) back to bytes | """Convert an internal str (e.g. keyword, __doc__) back to bytes | ||||
This never raises UnicodeEncodeError, but only ASCII characters | This never raises UnicodeEncodeError, but only ASCII characters | ||||
can be round-trip by sysstr(sysbytes(s)). | can be round-trip by sysstr(sysbytes(s)). | ||||
""" | """ | ||||
if isinstance(s, bytes): | if isinstance(s, bytes): | ||||
return s | return s | ||||
return s.encode('utf-8') | return s.encode('utf-8') | ||||
def sysstr(s): | def sysstr(s): | ||||
"""Return a keyword str to be passed to Python functions such as | """Return a keyword str to be passed to Python functions such as | ||||
getattr() and str.encode() | getattr() and str.encode() | ||||
This never raises UnicodeDecodeError. Non-ascii characters are | This never raises UnicodeDecodeError. Non-ascii characters are | ||||
considered invalid and mapped to arbitrary but unique code points | considered invalid and mapped to arbitrary but unique code points | ||||
such that 'sysstr(a) != sysstr(b)' for all 'a != b'. | such that 'sysstr(a) != sysstr(b)' for all 'a != b'. | ||||
""" | """ | ||||
if isinstance(s, builtins.str): | if isinstance(s, builtins.str): | ||||
return s | return s | ||||
return s.decode('latin-1') | return s.decode('latin-1') | ||||
def strurl(url): | def strurl(url): | ||||
"""Converts a bytes url back to str""" | """Converts a bytes url back to str""" | ||||
if isinstance(url, bytes): | if isinstance(url, bytes): | ||||
return url.decode('ascii') | return url.decode('ascii') | ||||
return url | return url | ||||
def bytesurl(url): | def bytesurl(url): | ||||
"""Converts a str url to bytes by encoding in ascii""" | """Converts a str url to bytes by encoding in ascii""" | ||||
if isinstance(url, str): | if isinstance(url, str): | ||||
return url.encode('ascii') | return url.encode('ascii') | ||||
return url | return url | ||||
def raisewithtb(exc, tb): | def raisewithtb(exc, tb): | ||||
"""Raise exception with the given traceback""" | """Raise exception with the given traceback""" | ||||
raise exc.with_traceback(tb) | raise exc.with_traceback(tb) | ||||
def getdoc(obj): | def getdoc(obj): | ||||
"""Get docstring as bytes; may be None so gettext() won't confuse it | """Get docstring as bytes; may be None so gettext() won't confuse it | ||||
with _('')""" | with _('')""" | ||||
doc = getattr(obj, '__doc__', None) | doc = getattr(obj, '__doc__', None) | ||||
if doc is None: | if doc is None: | ||||
return doc | return doc | ||||
return sysbytes(doc) | return sysbytes(doc) | ||||
def _wrapattrfunc(f): | def _wrapattrfunc(f): | ||||
@functools.wraps(f) | @functools.wraps(f) | ||||
def w(object, name, *args): | def w(object, name, *args): | ||||
return f(object, sysstr(name), *args) | return f(object, sysstr(name), *args) | ||||
return w | return w | ||||
# these wrappers are automagically imported by hgloader | # these wrappers are automagically imported by hgloader | ||||
delattr = _wrapattrfunc(builtins.delattr) | delattr = _wrapattrfunc(builtins.delattr) | ||||
getattr = _wrapattrfunc(builtins.getattr) | getattr = _wrapattrfunc(builtins.getattr) | ||||
hasattr = _wrapattrfunc(builtins.hasattr) | hasattr = _wrapattrfunc(builtins.hasattr) | ||||
setattr = _wrapattrfunc(builtins.setattr) | setattr = _wrapattrfunc(builtins.setattr) | ||||
xrange = builtins.range | xrange = builtins.range | ||||
unicode = str | unicode = str | ||||
def open(name, mode=b'r', buffering=-1, encoding=None): | def open(name, mode=b'r', buffering=-1, encoding=None): | ||||
return builtins.open(name, sysstr(mode), buffering, encoding) | return builtins.open(name, sysstr(mode), buffering, encoding) | ||||
safehasattr = _wrapattrfunc(builtins.hasattr) | safehasattr = _wrapattrfunc(builtins.hasattr) | ||||
def _getoptbwrapper(orig, args, shortlist, namelist): | def _getoptbwrapper(orig, args, shortlist, namelist): | ||||
""" | """ | ||||
Takes bytes arguments, converts them to unicode, pass them to | Takes bytes arguments, converts them to unicode, pass them to | ||||
getopt.getopt(), convert the returned values back to bytes and then | getopt.getopt(), convert the returned values back to bytes and then | ||||
return them for Python 3 compatibility as getopt.getopt() don't accepts | return them for Python 3 compatibility as getopt.getopt() don't accepts | ||||
bytes on Python 3. | bytes on Python 3. | ||||
""" | """ | ||||
args = [a.decode('latin-1') for a in args] | args = [a.decode('latin-1') for a in args] | ||||
shortlist = shortlist.decode('latin-1') | shortlist = shortlist.decode('latin-1') | ||||
namelist = [a.decode('latin-1') for a in namelist] | namelist = [a.decode('latin-1') for a in namelist] | ||||
opts, args = orig(args, shortlist, namelist) | opts, args = orig(args, shortlist, namelist) | ||||
opts = [(a[0].encode('latin-1'), a[1].encode('latin-1')) for a in opts] | opts = [(a[0].encode('latin-1'), a[1].encode('latin-1')) for a in opts] | ||||
args = [a.encode('latin-1') for a in args] | args = [a.encode('latin-1') for a in args] | ||||
return opts, args | return opts, args | ||||
def strkwargs(dic): | def strkwargs(dic): | ||||
""" | """ | ||||
Converts the keys of a python dictonary to str i.e. unicodes so that | 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 | they can be passed as keyword arguments as dictionaries with bytes keys | ||||
can't be passed as keyword arguments to functions on Python 3. | can't be passed as keyword arguments to functions on Python 3. | ||||
""" | """ | ||||
dic = {k.decode('latin-1'): v for k, v in dic.items()} | dic = {k.decode('latin-1'): v for k, v in dic.items()} | ||||
return dic | return dic | ||||
def byteskwargs(dic): | def byteskwargs(dic): | ||||
""" | """ | ||||
Converts keys of python dictionaries to bytes as they were converted to | Converts keys of python dictionaries to bytes as they were converted to | ||||
str to pass that dictonary as a keyword argument on Python 3. | str to pass that dictonary as a keyword argument on Python 3. | ||||
""" | """ | ||||
dic = {k.encode('latin-1'): v for k, v in dic.items()} | dic = {k.encode('latin-1'): v for k, v in dic.items()} | ||||
return dic | return dic | ||||
# TODO: handle shlex.shlex(). | # TODO: handle shlex.shlex(). | ||||
def shlexsplit(s, comments=False, posix=True): | def shlexsplit(s, comments=False, posix=True): | ||||
""" | """ | ||||
Takes bytes argument, convert it to str i.e. unicodes, pass that into | 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 | 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. | Python 3 compatibility as shelx.split() don't accept bytes on Python 3. | ||||
""" | """ | ||||
ret = shlex.split(s.decode('latin-1'), comments, posix) | ret = shlex.split(s.decode('latin-1'), comments, posix) | ||||
return [a.encode('latin-1') for a in ret] | return [a.encode('latin-1') for a in ret] | ||||
iteritems = lambda x: x.items() | iteritems = lambda x: x.items() | ||||
itervalues = lambda x: x.values() | itervalues = lambda x: x.values() | ||||
# Python 3.5's json.load and json.loads require str. We polyfill its | # Python 3.5's json.load and json.loads require str. We polyfill its | ||||
# code for detecting encoding from bytes. | # code for detecting encoding from bytes. | ||||
if sys.version_info[0:2] < (3, 6): | if sys.version_info[0:2] < (3, 6): | ||||
def _detect_encoding(b): | def _detect_encoding(b): | ||||
bstartswith = b.startswith | bstartswith = b.startswith | ||||
if bstartswith((codecs.BOM_UTF32_BE, codecs.BOM_UTF32_LE)): | if bstartswith((codecs.BOM_UTF32_BE, codecs.BOM_UTF32_LE)): | ||||
return 'utf-32' | return 'utf-32' | ||||
if bstartswith((codecs.BOM_UTF16_BE, codecs.BOM_UTF16_LE)): | if bstartswith((codecs.BOM_UTF16_BE, codecs.BOM_UTF16_LE)): | ||||
return 'utf-16' | return 'utf-16' | ||||
if bstartswith(codecs.BOM_UTF8): | if bstartswith(codecs.BOM_UTF8): | ||||
return 'utf-8-sig' | return 'utf-8-sig' | ||||
if len(b) >= 4: | if len(b) >= 4: | ||||
if not b[0]: | if not b[0]: | ||||
# 00 00 -- -- - utf-32-be | # 00 00 -- -- - utf-32-be | ||||
# 00 XX -- -- - utf-16-be | # 00 XX -- -- - utf-16-be | ||||
return 'utf-16-be' if b[1] else 'utf-32-be' | return 'utf-16-be' if b[1] else 'utf-32-be' | ||||
if not b[1]: | if not b[1]: | ||||
# XX 00 00 00 - utf-32-le | # XX 00 00 00 - utf-32-le | ||||
# XX 00 00 XX - utf-16-le | # XX 00 00 XX - utf-16-le | ||||
# XX 00 XX -- - utf-16-le | # XX 00 XX -- - utf-16-le | ||||
return 'utf-16-le' if b[2] or b[3] else 'utf-32-le' | return 'utf-16-le' if b[2] or b[3] else 'utf-32-le' | ||||
elif len(b) == 2: | elif len(b) == 2: | ||||
if not b[0]: | if not b[0]: | ||||
# 00 XX - utf-16-be | # 00 XX - utf-16-be | ||||
return 'utf-16-be' | return 'utf-16-be' | ||||
if not b[1]: | if not b[1]: | ||||
# XX 00 - utf-16-le | # XX 00 - utf-16-le | ||||
return 'utf-16-le' | return 'utf-16-le' | ||||
# default | # default | ||||
return 'utf-8' | return 'utf-8' | ||||
def json_loads(s, *args, **kwargs): | def json_loads(s, *args, **kwargs): | ||||
if isinstance(s, (bytes, bytearray)): | if isinstance(s, (bytes, bytearray)): | ||||
s = s.decode(_detect_encoding(s), 'surrogatepass') | s = s.decode(_detect_encoding(s), 'surrogatepass') | ||||
return json.loads(s, *args, **kwargs) | return json.loads(s, *args, **kwargs) | ||||
else: | else: | ||||
json_loads = json.loads | json_loads = json.loads | ||||
else: | |||||
import cStringIO | |||||
xrange = xrange | |||||
unicode = unicode | |||||
bytechr = chr | |||||
byterepr = repr | |||||
bytestr = str | |||||
iterbytestr = iter | |||||
maybebytestr = identity | |||||
sysbytes = identity | |||||
sysstr = identity | |||||
strurl = identity | |||||
bytesurl = identity | |||||
open = open | |||||
delattr = delattr | |||||
getattr = getattr | |||||
hasattr = hasattr | |||||
setattr = setattr | |||||
# this can't be parsed on Python 3 | |||||
exec(b'def raisewithtb(exc, tb):\n raise exc, None, tb\n') | |||||
def fsencode(filename): | |||||
""" | |||||
Partial backport from os.py in Python 3, which only accepts bytes. | |||||
In Python 2, our paths should only ever be bytes, a unicode path | |||||
indicates a bug. | |||||
""" | |||||
if isinstance(filename, str): | |||||
return filename | |||||
else: | |||||
raise TypeError("expect str, not %s" % type(filename).__name__) | |||||
# In Python 2, fsdecode() has a very chance to receive bytes. So it's | |||||
# better not to touch Python 2 part as it's already working fine. | |||||
fsdecode = identity | |||||
def getdoc(obj): | |||||
return getattr(obj, '__doc__', None) | |||||
_notset = object() | |||||
def safehasattr(thing, attr): | |||||
return getattr(thing, attr, _notset) is not _notset | |||||
def _getoptbwrapper(orig, args, shortlist, namelist): | |||||
return orig(args, shortlist, namelist) | |||||
strkwargs = identity | |||||
byteskwargs = identity | |||||
oscurdir = os.curdir | |||||
oslinesep = os.linesep | |||||
osname = os.name | |||||
ospathsep = os.pathsep | |||||
ospardir = os.pardir | |||||
ossep = os.sep | |||||
osaltsep = os.altsep | |||||
osdevnull = os.devnull | |||||
long = long | |||||
if getattr(sys, 'argv', None) is not None: | |||||
sysargv = sys.argv | |||||
sysplatform = sys.platform | |||||
sysexecutable = sys.executable | |||||
shlexsplit = shlex.split | |||||
bytesio = cStringIO.StringIO | |||||
stringio = bytesio | |||||
maplist = map | |||||
rangelist = range | |||||
ziplist = zip | |||||
rawinput = raw_input | |||||
getargspec = inspect.getargspec | |||||
iteritems = lambda x: x.iteritems() | |||||
itervalues = lambda x: x.itervalues() | |||||
json_loads = json.loads | |||||
isjython = sysplatform.startswith(b'java') | isjython = sysplatform.startswith(b'java') | ||||
isdarwin = sysplatform.startswith(b'darwin') | isdarwin = sysplatform.startswith(b'darwin') | ||||
islinux = sysplatform.startswith(b'linux') | islinux = sysplatform.startswith(b'linux') | ||||
isposix = osname == b'posix' | isposix = osname == b'posix' | ||||
iswindows = osname == b'nt' | iswindows = osname == b'nt' | ||||