aboutsummaryrefslogtreecommitdiffhomepage
path: root/libs/future
diff options
context:
space:
mode:
authormorpheus65535 <[email protected]>2021-12-01 15:47:00 -0500
committermorpheus65535 <[email protected]>2021-12-01 15:47:00 -0500
commit402c82d84f7bd51353348bea7d1a876ad9ecc5b1 (patch)
treec0635920594b9220ed31a20948b684c3b5a8a001 /libs/future
parent2d214bfbd5f9d1598c01b2e2dd35efa67ccb43af (diff)
downloadbazarr-402c82d84f7bd51353348bea7d1a876ad9ecc5b1.tar.gz
bazarr-402c82d84f7bd51353348bea7d1a876ad9ecc5b1.zip
Upgraded some embedded dependencies to be ready for Python 3.10. This doesn't mean that it's fully supported right now.
Diffstat (limited to 'libs/future')
-rw-r--r--libs/future/__init__.py10
-rw-r--r--libs/future/backports/__init__.py2
-rw-r--r--libs/future/backports/email/message.py6
-rw-r--r--libs/future/backports/http/client.py22
-rw-r--r--libs/future/backports/http/cookiejar.py5
-rw-r--r--libs/future/backports/http/cookies.py3
-rw-r--r--libs/future/backports/misc.py8
-rwxr-xr-x[-rw-r--r--]libs/future/backports/test/pystone.py0
-rw-r--r--libs/future/backports/urllib/request.py10
-rw-r--r--libs/future/builtins/__init__.py4
-rw-r--r--libs/future/builtins/misc.py17
-rw-r--r--libs/future/builtins/new_min_max.py59
-rw-r--r--libs/future/builtins/newround.py11
-rw-r--r--libs/future/moves/__init__.py2
-rw-r--r--libs/future/moves/copyreg.py6
-rw-r--r--libs/future/moves/urllib/request.py23
-rw-r--r--libs/future/tests/base.py10
-rw-r--r--libs/future/types/newbytes.py8
-rw-r--r--libs/future/types/newint.py6
-rw-r--r--libs/future/types/newmemoryview.py8
-rw-r--r--libs/future/types/newobject.py1
-rw-r--r--libs/future/types/newrange.py7
-rw-r--r--libs/future/types/newstr.py14
-rw-r--r--libs/future/utils/__init__.py76
24 files changed, 240 insertions, 78 deletions
diff --git a/libs/future/__init__.py b/libs/future/__init__.py
index 211fb43bc..ad419d67e 100644
--- a/libs/future/__init__.py
+++ b/libs/future/__init__.py
@@ -68,7 +68,7 @@ See: http://python-future.org
Credits
-------
-:Author: Ed Schofield
+:Author: Ed Schofield, Jordan M. Adler, et al
:Sponsor: Python Charmers Pty Ltd, Australia, and Python Charmers Pte
Ltd, Singapore. http://pythoncharmers.com
:Others: See docs/credits.rst or http://python-future.org/credits.html
@@ -76,7 +76,7 @@ Credits
Licensing
---------
-Copyright 2013-2018 Python Charmers Pty Ltd, Australia.
+Copyright 2013-2019 Python Charmers Pty Ltd, Australia.
The software is distributed under an MIT licence. See LICENSE.txt.
"""
@@ -84,10 +84,10 @@ The software is distributed under an MIT licence. See LICENSE.txt.
__title__ = 'future'
__author__ = 'Ed Schofield'
__license__ = 'MIT'
-__copyright__ = 'Copyright 2013-2018 Python Charmers Pty Ltd'
+__copyright__ = 'Copyright 2013-2019 Python Charmers Pty Ltd'
__ver_major__ = 0
-__ver_minor__ = 17
-__ver_patch__ = 0
+__ver_minor__ = 18
+__ver_patch__ = 2
__ver_sub__ = ''
__version__ = "%d.%d.%d%s" % (__ver_major__, __ver_minor__,
__ver_patch__, __ver_sub__)
diff --git a/libs/future/backports/__init__.py b/libs/future/backports/__init__.py
index 68291141c..c71e06535 100644
--- a/libs/future/backports/__init__.py
+++ b/libs/future/backports/__init__.py
@@ -10,7 +10,7 @@ __future_module__ = True
from future.standard_library import import_top_level_modules
-if sys.version_info[0] == 3:
+if sys.version_info[0] >= 3:
import_top_level_modules()
diff --git a/libs/future/backports/email/message.py b/libs/future/backports/email/message.py
index 99715fcc6..d8d9615d7 100644
--- a/libs/future/backports/email/message.py
+++ b/libs/future/backports/email/message.py
@@ -800,7 +800,7 @@ class Message(object):
# There was no Content-Type header, and we don't know what type
# to set it to, so raise an exception.
raise errors.HeaderParseError('No Content-Type header found')
- newparams = []
+ newparams = list()
foundp = False
for pk, pv in params:
if pk.lower() == 'boundary':
@@ -814,10 +814,10 @@ class Message(object):
# instead???
newparams.append(('boundary', '"%s"' % boundary))
# Replace the existing Content-Type header with the new value
- newheaders = []
+ newheaders = list()
for h, v in self._headers:
if h.lower() == 'content-type':
- parts = []
+ parts = list()
for k, v in newparams:
if v == '':
parts.append(k)
diff --git a/libs/future/backports/http/client.py b/libs/future/backports/http/client.py
index 5dd983d80..e663d125c 100644
--- a/libs/future/backports/http/client.py
+++ b/libs/future/backports/http/client.py
@@ -79,11 +79,15 @@ from future.backports.misc import create_connection as socket_create_connection
import io
import os
import socket
-import collections
from future.backports.urllib.parse import urlsplit
import warnings
from array import array
+if PY2:
+ from collections import Iterable
+else:
+ from collections.abc import Iterable
+
__all__ = ["HTTPResponse", "HTTPConnection",
"HTTPException", "NotConnected", "UnknownProtocol",
"UnknownTransferEncoding", "UnimplementedFileMode",
@@ -696,9 +700,19 @@ class HTTPResponse(io.RawIOBase):
while total_bytes < len(b):
if MAXAMOUNT < len(mvb):
temp_mvb = mvb[0:MAXAMOUNT]
- n = self.fp.readinto(temp_mvb)
+ if PY2:
+ data = self.fp.read(len(temp_mvb))
+ n = len(data)
+ temp_mvb[:n] = data
+ else:
+ n = self.fp.readinto(temp_mvb)
else:
- n = self.fp.readinto(mvb)
+ if PY2:
+ data = self.fp.read(len(mvb))
+ n = len(data)
+ mvb[:n] = data
+ else:
+ n = self.fp.readinto(mvb)
if not n:
raise IncompleteRead(bytes(mvb[0:total_bytes]), len(b))
mvb = mvb[n:]
@@ -892,7 +906,7 @@ class HTTPConnection(object):
try:
self.sock.sendall(data)
except TypeError:
- if isinstance(data, collections.Iterable):
+ if isinstance(data, Iterable):
for d in data:
self.sock.sendall(d)
else:
diff --git a/libs/future/backports/http/cookiejar.py b/libs/future/backports/http/cookiejar.py
index cad72f9b4..af3ef4151 100644
--- a/libs/future/backports/http/cookiejar.py
+++ b/libs/future/backports/http/cookiejar.py
@@ -33,7 +33,7 @@ from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from future.builtins import filter, int, map, open, str
-from future.utils import as_native_str
+from future.utils import as_native_str, PY2
__all__ = ['Cookie', 'CookieJar', 'CookiePolicy', 'DefaultCookiePolicy',
'FileCookieJar', 'LWPCookieJar', 'LoadError', 'MozillaCookieJar']
@@ -41,7 +41,8 @@ __all__ = ['Cookie', 'CookieJar', 'CookiePolicy', 'DefaultCookiePolicy',
import copy
import datetime
import re
-re.ASCII = 0
+if PY2:
+ re.ASCII = 0
import time
from future.backports.urllib.parse import urlparse, urlsplit, quote
from future.backports.http.client import HTTP_PORT
diff --git a/libs/future/backports/http/cookies.py b/libs/future/backports/http/cookies.py
index ae32ed7e7..8bb61e22c 100644
--- a/libs/future/backports/http/cookies.py
+++ b/libs/future/backports/http/cookies.py
@@ -138,7 +138,8 @@ from future.utils import PY2, as_native_str
# Import our required modules
#
import re
-re.ASCII = 0 # for py2 compatibility
+if PY2:
+ re.ASCII = 0 # for py2 compatibility
import string
__all__ = ["CookieError", "BaseCookie", "SimpleCookie"]
diff --git a/libs/future/backports/misc.py b/libs/future/backports/misc.py
index ef7520788..098a0667e 100644
--- a/libs/future/backports/misc.py
+++ b/libs/future/backports/misc.py
@@ -16,7 +16,6 @@ from __future__ import absolute_import
import subprocess
from math import ceil as oldceil
-from collections import Mapping, MutableMapping
from operator import itemgetter as _itemgetter, eq as _eq
import sys
@@ -25,7 +24,12 @@ from _weakref import proxy as _proxy
from itertools import repeat as _repeat, chain as _chain, starmap as _starmap
from socket import getaddrinfo, SOCK_STREAM, error, socket
-from future.utils import iteritems, itervalues, PY26, PY3
+from future.utils import iteritems, itervalues, PY2, PY26, PY3
+
+if PY2:
+ from collections import Mapping, MutableMapping
+else:
+ from collections.abc import Mapping, MutableMapping
def ceil(x):
diff --git a/libs/future/backports/test/pystone.py b/libs/future/backports/test/pystone.py
index 7652027b4..7652027b4 100644..100755
--- a/libs/future/backports/test/pystone.py
+++ b/libs/future/backports/test/pystone.py
diff --git a/libs/future/backports/urllib/request.py b/libs/future/backports/urllib/request.py
index b1545ca0f..baee5401a 100644
--- a/libs/future/backports/urllib/request.py
+++ b/libs/future/backports/urllib/request.py
@@ -109,11 +109,17 @@ import re
import socket
import sys
import time
-import collections
import tempfile
import contextlib
import warnings
+from future.utils import PY2
+
+if PY2:
+ from collections import Iterable
+else:
+ from collections.abc import Iterable
+
# check for SSL
try:
import ssl
@@ -1221,7 +1227,7 @@ class AbstractHTTPHandler(BaseHandler):
mv = memoryview(data)
size = len(mv) * mv.itemsize
except TypeError:
- if isinstance(data, collections.Iterable):
+ if isinstance(data, Iterable):
raise ValueError("Content-Length should be specified "
"for iterable data of type %r %r" % (type(data),
data))
diff --git a/libs/future/builtins/__init__.py b/libs/future/builtins/__init__.py
index 216465a15..8bc1649d2 100644
--- a/libs/future/builtins/__init__.py
+++ b/libs/future/builtins/__init__.py
@@ -11,7 +11,7 @@ from future.builtins.iterators import (filter, map, zip)
# The isinstance import is no longer needed. We provide it only for
# backward-compatibility with future v0.8.2. It will be removed in future v1.0.
from future.builtins.misc import (ascii, chr, hex, input, isinstance, next,
- oct, open, pow, round, super)
+ oct, open, pow, round, super, max, min)
from future.utils import PY3
if PY3:
@@ -43,7 +43,7 @@ if not utils.PY3:
__all__ = ['filter', 'map', 'zip',
'ascii', 'chr', 'hex', 'input', 'next', 'oct', 'open', 'pow',
'round', 'super',
- 'bytes', 'dict', 'int', 'list', 'object', 'range', 'str',
+ 'bytes', 'dict', 'int', 'list', 'object', 'range', 'str', 'max', 'min'
]
else:
diff --git a/libs/future/builtins/misc.py b/libs/future/builtins/misc.py
index 90dc384ad..f86ce5f34 100644
--- a/libs/future/builtins/misc.py
+++ b/libs/future/builtins/misc.py
@@ -13,6 +13,8 @@ The builtin functions are:
- ``open`` (equivalent to io.open on Py2)
- ``super`` (backport of Py3's magic zero-argument super() function
- ``round`` (new "Banker's Rounding" behaviour from Py3)
+- ``max`` (new default option from Py3.4)
+- ``min`` (new default option from Py3.4)
``isinstance`` is also currently exported for backwards compatibility
with v0.8.2, although this has been deprecated since v0.9.
@@ -59,6 +61,8 @@ if utils.PY2:
from future.builtins.newnext import newnext as next
from future.builtins.newround import newround as round
from future.builtins.newsuper import newsuper as super
+ from future.builtins.new_min_max import newmax as max
+ from future.builtins.new_min_max import newmin as min
from future.types.newint import newint
_SENTINEL = object()
@@ -89,11 +93,12 @@ if utils.PY2:
else:
return _builtin_pow(x+0j, y, z)
+
# ``future`` doesn't support Py3.0/3.1. If we ever did, we'd add this:
# callable = __builtin__.callable
__all__ = ['ascii', 'chr', 'hex', 'input', 'isinstance', 'next', 'oct',
- 'open', 'pow', 'round', 'super']
+ 'open', 'pow', 'round', 'super', 'max', 'min']
else:
import builtins
@@ -109,8 +114,14 @@ else:
pow = builtins.pow
round = builtins.round
super = builtins.super
-
- __all__ = []
+ if utils.PY34_PLUS:
+ max = builtins.max
+ min = builtins.min
+ __all__ = []
+ else:
+ from future.builtins.new_min_max import newmax as max
+ from future.builtins.new_min_max import newmin as min
+ __all__ = ['min', 'max']
# The callable() function was removed from Py3.0 and 3.1 and
# reintroduced into Py3.2+. ``future`` doesn't support Py3.0/3.1. If we ever
diff --git a/libs/future/builtins/new_min_max.py b/libs/future/builtins/new_min_max.py
new file mode 100644
index 000000000..6f0c2a86f
--- /dev/null
+++ b/libs/future/builtins/new_min_max.py
@@ -0,0 +1,59 @@
+import itertools
+
+from future import utils
+if utils.PY2:
+ from __builtin__ import max as _builtin_max, min as _builtin_min
+else:
+ from builtins import max as _builtin_max, min as _builtin_min
+
+_SENTINEL = object()
+
+
+def newmin(*args, **kwargs):
+ return new_min_max(_builtin_min, *args, **kwargs)
+
+
+def newmax(*args, **kwargs):
+ return new_min_max(_builtin_max, *args, **kwargs)
+
+
+def new_min_max(_builtin_func, *args, **kwargs):
+ """
+ To support the argument "default" introduced in python 3.4 for min and max
+ :param _builtin_func: builtin min or builtin max
+ :param args:
+ :param kwargs:
+ :return: returns the min or max based on the arguments passed
+ """
+
+ for key, _ in kwargs.items():
+ if key not in set(['key', 'default']):
+ raise TypeError('Illegal argument %s', key)
+
+ if len(args) == 0:
+ raise TypeError
+
+ if len(args) != 1 and kwargs.get('default', _SENTINEL) is not _SENTINEL:
+ raise TypeError
+
+ if len(args) == 1:
+ iterator = iter(args[0])
+ try:
+ first = next(iterator)
+ except StopIteration:
+ if kwargs.get('default', _SENTINEL) is not _SENTINEL:
+ return kwargs.get('default')
+ else:
+ raise ValueError('{}() arg is an empty sequence'.format(_builtin_func.__name__))
+ else:
+ iterator = itertools.chain([first], iterator)
+ if kwargs.get('key') is not None:
+ return _builtin_func(iterator, key=kwargs.get('key'))
+ else:
+ return _builtin_func(iterator)
+
+ if len(args) > 1:
+ if kwargs.get('key') is not None:
+ return _builtin_func(args, key=kwargs.get('key'))
+ else:
+ return _builtin_func(args)
diff --git a/libs/future/builtins/newround.py b/libs/future/builtins/newround.py
index 3943ebb6e..394a2c63c 100644
--- a/libs/future/builtins/newround.py
+++ b/libs/future/builtins/newround.py
@@ -38,11 +38,14 @@ def newround(number, ndigits=None):
if 'numpy' in repr(type(number)):
number = float(number)
- if not PY26:
- d = Decimal.from_float(number).quantize(exponent,
- rounding=ROUND_HALF_EVEN)
+ if isinstance(number, Decimal):
+ d = number
else:
- d = from_float_26(number).quantize(exponent, rounding=ROUND_HALF_EVEN)
+ if not PY26:
+ d = Decimal.from_float(number).quantize(exponent,
+ rounding=ROUND_HALF_EVEN)
+ else:
+ d = from_float_26(number).quantize(exponent, rounding=ROUND_HALF_EVEN)
if return_int:
return int(d)
diff --git a/libs/future/moves/__init__.py b/libs/future/moves/__init__.py
index 040fdcf01..0cd60d3d5 100644
--- a/libs/future/moves/__init__.py
+++ b/libs/future/moves/__init__.py
@@ -4,5 +4,5 @@ import sys
__future_module__ = True
from future.standard_library import import_top_level_modules
-if sys.version_info[0] == 3:
+if sys.version_info[0] >= 3:
import_top_level_modules()
diff --git a/libs/future/moves/copyreg.py b/libs/future/moves/copyreg.py
index 21c7a42f2..9d08cdc5e 100644
--- a/libs/future/moves/copyreg.py
+++ b/libs/future/moves/copyreg.py
@@ -2,7 +2,11 @@ from __future__ import absolute_import
from future.utils import PY3
if PY3:
- from copyreg import *
+ import copyreg, sys
+ # A "*" import uses Python 3's copyreg.__all__ which does not include
+ # all public names in the API surface for copyreg, this avoids that
+ # problem by just making our module _be_ a reference to the actual module.
+ sys.modules['future.moves.copyreg'] = copyreg
else:
__future_module__ = True
from copy_reg import *
diff --git a/libs/future/moves/urllib/request.py b/libs/future/moves/urllib/request.py
index 60e440a77..972aa4ab5 100644
--- a/libs/future/moves/urllib/request.py
+++ b/libs/future/moves/urllib/request.py
@@ -11,19 +11,8 @@ if PY3:
proxy_bypass,
quote,
request_host,
- splitattr,
- splithost,
- splitpasswd,
- splitport,
- splitquery,
- splittag,
- splittype,
- splituser,
- splitvalue,
thishost,
- to_bytes,
unquote,
- unwrap,
url2pathname,
urlcleanup,
urljoin,
@@ -32,6 +21,18 @@ if PY3:
urlretrieve,
urlsplit,
urlunparse)
+
+ from urllib.parse import (splitattr,
+ splithost,
+ splitpasswd,
+ splitport,
+ splitquery,
+ splittag,
+ splittype,
+ splituser,
+ splitvalue,
+ to_bytes,
+ unwrap)
else:
__future_module__ = True
with suspend_hooks():
diff --git a/libs/future/tests/base.py b/libs/future/tests/base.py
index 9f4607b69..4ef437baa 100644
--- a/libs/future/tests/base.py
+++ b/libs/future/tests/base.py
@@ -272,7 +272,11 @@ class CodeHandler(unittest.TestCase):
else:
headers = ''
- self.compare(output, headers + reformat_code(expected),
+ reformatted = reformat_code(expected)
+ if headers in reformatted:
+ headers = ''
+
+ self.compare(output, headers + reformatted,
ignore_imports=ignore_imports)
def unchanged(self, code, **kwargs):
@@ -338,6 +342,10 @@ class CodeHandler(unittest.TestCase):
'----\n%s\n----' % f.read(),
)
ErrorClass = (FuturizeError if 'futurize' in script else PasteurizeError)
+
+ if not hasattr(e, 'output'):
+ # The attribute CalledProcessError.output doesn't exist on Py2.6
+ e.output = None
raise ErrorClass(msg, e.returncode, e.cmd, output=e.output)
return output
diff --git a/libs/future/types/newbytes.py b/libs/future/types/newbytes.py
index 2a337c864..c9d584a7c 100644
--- a/libs/future/types/newbytes.py
+++ b/libs/future/types/newbytes.py
@@ -5,15 +5,19 @@ Why do this? Without it, the Python 2 bytes object is a very, very
different beast to the Python 3 bytes object.
"""
-from collections import Iterable
from numbers import Integral
import string
import copy
-from future.utils import istext, isbytes, PY3, with_metaclass
+from future.utils import istext, isbytes, PY2, PY3, with_metaclass
from future.types import no, issubset
from future.types.newobject import newobject
+if PY2:
+ from collections import Iterable
+else:
+ from collections.abc import Iterable
+
_builtin_bytes = bytes
diff --git a/libs/future/types/newint.py b/libs/future/types/newint.py
index 705b8fa95..748dba9d2 100644
--- a/libs/future/types/newint.py
+++ b/libs/future/types/newint.py
@@ -8,7 +8,6 @@ They are very similar. The most notable difference is:
from __future__ import division
import struct
-import collections
from future.types.newbytes import newbytes
from future.types.newobject import newobject
@@ -17,6 +16,9 @@ from future.utils import PY3, isint, istext, isbytes, with_metaclass, native
if PY3:
long = int
+ from collections.abc import Iterable
+else:
+ from collections import Iterable
class BaseNewInt(type):
@@ -356,7 +358,7 @@ class newint(with_metaclass(BaseNewInt, long)):
raise TypeError("cannot convert unicode objects to bytes")
# mybytes can also be passed as a sequence of integers on Py3.
# Test for this:
- elif isinstance(mybytes, collections.Iterable):
+ elif isinstance(mybytes, Iterable):
mybytes = newbytes(mybytes)
b = mybytes if byteorder == 'big' else mybytes[::-1]
if len(b) == 0:
diff --git a/libs/future/types/newmemoryview.py b/libs/future/types/newmemoryview.py
index 72c6990a7..09f804dcf 100644
--- a/libs/future/types/newmemoryview.py
+++ b/libs/future/types/newmemoryview.py
@@ -1,14 +1,16 @@
"""
A pretty lame implementation of a memoryview object for Python 2.6.
"""
-
-from collections import Iterable
from numbers import Integral
import string
-from future.utils import istext, isbytes, PY3, with_metaclass
+from future.utils import istext, isbytes, PY2, with_metaclass
from future.types import no, issubset
+if PY2:
+ from collections import Iterable
+else:
+ from collections.abc import Iterable
# class BaseNewBytes(type):
# def __instancecheck__(cls, instance):
diff --git a/libs/future/types/newobject.py b/libs/future/types/newobject.py
index 776d47664..31b84fc12 100644
--- a/libs/future/types/newobject.py
+++ b/libs/future/types/newobject.py
@@ -112,5 +112,6 @@ class newobject(object):
"""
return object(self)
+ __slots__ = []
__all__ = ['newobject']
diff --git a/libs/future/types/newrange.py b/libs/future/types/newrange.py
index 9173b0509..eda01a5a5 100644
--- a/libs/future/types/newrange.py
+++ b/libs/future/types/newrange.py
@@ -19,7 +19,12 @@ From Dan Crosta's README:
"""
from __future__ import absolute_import
-from collections import Sequence, Iterator
+from future.utils import PY2
+
+if PY2:
+ from collections import Sequence, Iterator
+else:
+ from collections.abc import Sequence, Iterator
from itertools import islice
from future.backports.misc import count # with step parameter on Py2.6
diff --git a/libs/future/types/newstr.py b/libs/future/types/newstr.py
index e6272fb90..8ca191f97 100644
--- a/libs/future/types/newstr.py
+++ b/libs/future/types/newstr.py
@@ -40,7 +40,6 @@ representations of your objects portably across Py3 and Py2, use the
"""
-from collections import Iterable
from numbers import Number
from future.utils import PY3, istext, with_metaclass, isnewbytes
@@ -51,6 +50,9 @@ from future.types.newobject import newobject
if PY3:
# We'll probably never use newstr on Py3 anyway...
unicode = str
+ from collections.abc import Iterable
+else:
+ from collections import Iterable
class BaseNewStr(type):
@@ -105,6 +107,7 @@ class newstr(with_metaclass(BaseNewStr, unicode)):
"""
Without the u prefix
"""
+
value = super(newstr, self).__repr__()
# assert value[0] == u'u'
return value[1:]
@@ -290,7 +293,14 @@ class newstr(with_metaclass(BaseNewStr, unicode)):
isinstance(other, bytes) and not isnewbytes(other)):
return super(newstr, self).__eq__(other)
else:
- return False
+ return NotImplemented
+
+ def __hash__(self):
+ if (isinstance(self, unicode) or
+ isinstance(self, bytes) and not isnewbytes(self)):
+ return super(newstr, self).__hash__()
+ else:
+ raise NotImplementedError()
def __ne__(self, other):
if (isinstance(other, unicode) or
diff --git a/libs/future/utils/__init__.py b/libs/future/utils/__init__.py
index 906f1e464..46bd96def 100644
--- a/libs/future/utils/__init__.py
+++ b/libs/future/utils/__init__.py
@@ -18,8 +18,10 @@ This module exports useful functions for 2/3 compatible code:
* types:
* text_type: unicode in Python 2, str in Python 3
- * binary_type: str in Python 2, bytes in Python 3
* string_types: basestring in Python 2, str in Python 3
+ * binary_type: str in Python 2, bytes in Python 3
+ * integer_types: (int, long) in Python 2, int in Python 3
+ * class_types: (type, types.ClassType) in Python 2, type in Python 3
* bchr(c):
Take an integer and make a 1-character byte string
@@ -55,7 +57,8 @@ import copy
import inspect
-PY3 = sys.version_info[0] == 3
+PY3 = sys.version_info[0] >= 3
+PY34_PLUS = sys.version_info[0:2] >= (3, 4)
PY35_PLUS = sys.version_info[0:2] >= (3, 5)
PY36_PLUS = sys.version_info[0:2] >= (3, 6)
PY2 = sys.version_info[0] == 2
@@ -405,12 +408,34 @@ if PY3:
allows re-raising exceptions with the cls value and traceback on
Python 2 and 3.
"""
- if value is not None and isinstance(tp, Exception):
- raise TypeError("instance exception may not have a separate value")
- if value is not None:
- exc = tp(value)
- else:
+ if isinstance(tp, BaseException):
+ # If the first object is an instance, the type of the exception
+ # is the class of the instance, the instance itself is the value,
+ # and the second object must be None.
+ if value is not None:
+ raise TypeError("instance exception may not have a separate value")
exc = tp
+ elif isinstance(tp, type) and not issubclass(tp, BaseException):
+ # If the first object is a class, it becomes the type of the
+ # exception.
+ raise TypeError("class must derive from BaseException, not %s" % tp.__name__)
+ else:
+ # The second object is used to determine the exception value: If it
+ # is an instance of the class, the instance becomes the exception
+ # value. If the second object is a tuple, it is used as the argument
+ # list for the class constructor; if it is None, an empty argument
+ # list is used, and any other object is treated as a single argument
+ # to the constructor. The instance so created by calling the
+ # constructor is used as the exception value.
+ if isinstance(value, tp):
+ exc = value
+ elif isinstance(value, tuple):
+ exc = tp(*value)
+ elif value is None:
+ exc = tp()
+ else:
+ exc = tp(value)
+
if exc.__traceback__ is not tb:
raise exc.with_traceback(tb)
raise exc
@@ -443,12 +468,14 @@ else:
e.__suppress_context__ = False
if isinstance(cause, type) and issubclass(cause, Exception):
e.__cause__ = cause()
+ e.__cause__.__traceback__ = sys.exc_info()[2]
e.__suppress_context__ = True
elif cause is None:
e.__cause__ = None
e.__suppress_context__ = True
elif isinstance(cause, BaseException):
e.__cause__ = cause
+ object.__setattr__(e.__cause__, '__traceback__', sys.exc_info()[2])
e.__suppress_context__ = True
else:
raise TypeError("exception causes must derive from BaseException")
@@ -552,15 +579,14 @@ def isbytes(obj):
def isnewbytes(obj):
"""
- Equivalent to the result of ``isinstance(obj, newbytes)`` were
- ``__instancecheck__`` not overridden on the newbytes subclass. In
- other words, it is REALLY a newbytes instance, not a Py2 native str
+ Equivalent to the result of ``type(obj) == type(newbytes)``
+ in other words, it is REALLY a newbytes instance, not a Py2 native str
object?
+
+ Note that this does not cover subclasses of newbytes, and it is not
+ equivalent to ininstance(obj, newbytes)
"""
- # TODO: generalize this so that it works with subclasses of newbytes
- # Import is here to avoid circular imports:
- from future.types.newbytes import newbytes
- return type(obj) == newbytes
+ return type(obj).__name__ == 'newbytes'
def isint(obj):
@@ -726,16 +752,16 @@ else:
__all__ = ['PY2', 'PY26', 'PY3', 'PYPY',
- 'as_native_str', 'bind_method', 'bord', 'bstr',
- 'bytes_to_native_str', 'encode_filename', 'ensure_new_type',
- 'exec_', 'get_next', 'getexception', 'implements_iterator',
- 'is_new_style', 'isbytes', 'isidentifier', 'isint',
- 'isnewbytes', 'istext', 'iteritems', 'iterkeys', 'itervalues',
- 'lfilter', 'listitems', 'listvalues', 'lmap', 'lrange',
- 'lzip', 'native', 'native_bytes', 'native_str',
+ 'as_native_str', 'binary_type', 'bind_method', 'bord', 'bstr',
+ 'bytes_to_native_str', 'class_types', 'encode_filename',
+ 'ensure_new_type', 'exec_', 'get_next', 'getexception',
+ 'implements_iterator', 'integer_types', 'is_new_style', 'isbytes',
+ 'isidentifier', 'isint', 'isnewbytes', 'istext', 'iteritems',
+ 'iterkeys', 'itervalues', 'lfilter', 'listitems', 'listvalues',
+ 'lmap', 'lrange', 'lzip', 'native', 'native_bytes', 'native_str',
'native_str_to_bytes', 'old_div',
'python_2_unicode_compatible', 'raise_',
- 'raise_with_traceback', 'reraise', 'text_to_native_str',
- 'tobytes', 'viewitems', 'viewkeys', 'viewvalues',
- 'with_metaclass'
- ]
+ 'raise_with_traceback', 'reraise', 'string_types',
+ 'text_to_native_str', 'text_type', 'tobytes', 'viewitems',
+ 'viewkeys', 'viewvalues', 'with_metaclass'
+ ]