diff --git a/script.module.future/addon.xml b/script.module.future/addon.xml index 29cd13cc2f..c52104fd1e 100644 --- a/script.module.future/addon.xml +++ b/script.module.future/addon.xml @@ -1,8 +1,5 @@ - + @@ -10,12 +7,12 @@ Clean single-source support for Python 3 and 2 future is the missing compatibility layer between Python 2 and Python 3. It allows you to use a single, clean Python 3.x-compatible codebase to support both Python 2 and Python 3 with minimal overhead. - all MIT + all + https://python-future.org https://github.com/PythonCharmers/python-future - http://python-future.org - icon.png + resources/icon.png diff --git a/script.module.future/icon.png b/script.module.future/icon.png deleted file mode 100644 index 5fe4707e08..0000000000 Binary files a/script.module.future/icon.png and /dev/null differ diff --git a/script.module.future/lib/future/__init__.py b/script.module.future/lib/future/__init__.py index ad419d67e2..b609299a7a 100644 --- a/script.module.future/lib/future/__init__.py +++ b/script.module.future/lib/future/__init__.py @@ -87,7 +87,7 @@ __copyright__ = 'Copyright 2013-2019 Python Charmers Pty Ltd' __ver_major__ = 0 __ver_minor__ = 18 -__ver_patch__ = 2 +__ver_patch__ = 3 __ver_sub__ = '' __version__ = "%d.%d.%d%s" % (__ver_major__, __ver_minor__, __ver_patch__, __ver_sub__) diff --git a/script.module.future/lib/future/backports/email/base64mime.py b/script.module.future/lib/future/backports/email/base64mime.py index 416d612e01..296392a6e1 100644 --- a/script.module.future/lib/future/backports/email/base64mime.py +++ b/script.module.future/lib/future/backports/email/base64mime.py @@ -28,6 +28,7 @@ from __future__ import absolute_import from future.builtins import range from future.builtins import bytes +from future.builtins import str __all__ = [ 'body_decode', diff --git a/script.module.future/lib/future/backports/http/cookiejar.py b/script.module.future/lib/future/backports/http/cookiejar.py index af3ef4151a..0ad80a0258 100644 --- a/script.module.future/lib/future/backports/http/cookiejar.py +++ b/script.module.future/lib/future/backports/http/cookiejar.py @@ -225,10 +225,14 @@ def _str2time(day, mon, yr, hr, min, sec, tz): (?::(\d\d))? # optional seconds )? # optional clock \s* - ([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+)? # timezone + (?: + ([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+) # timezone + \s* + )? + (?: + \(\w+\) # ASCII representation of timezone in parens. \s* - (?:\(\w+\))? # ASCII representation of timezone in parens. - \s*$""", re.X | re.ASCII) + )?$""", re.X | re.ASCII) def http2time(text): """Returns time in seconds since epoch of time represented by a string. @@ -298,9 +302,11 @@ def http2time(text): (?::?(\d\d(?:\.\d*)?))? # optional seconds (and fractional) )? # optional clock \s* - ([-+]?\d\d?:?(:?\d\d)? - |Z|z)? # timezone (Z is "zero meridian", i.e. GMT) - \s*$""", re.X | re. ASCII) + (?: + ([-+]?\d\d?:?(:?\d\d)? + |Z|z) # timezone (Z is "zero meridian", i.e. GMT) + \s* + )?$""", re.X | re. ASCII) def iso2time(text): """ As for http2time, but parses the ISO 8601 formats: diff --git a/script.module.future/lib/future/backports/misc.py b/script.module.future/lib/future/backports/misc.py index 098a0667e8..992b978f1f 100644 --- a/script.module.future/lib/future/backports/misc.py +++ b/script.module.future/lib/future/backports/misc.py @@ -46,6 +46,16 @@ def ceil(x): from itertools import islice +if PY26: + # itertools.count in Py 2.6 doesn't accept a step parameter + def count(start=0, step=1): + while True: + yield start + start += step +else: + from itertools import count + + if PY3: try: from _thread import get_ident @@ -85,6 +95,10 @@ def wrapper(self): return decorating_function +# OrderedDict Shim from Raymond Hettinger, python core dev +# http://code.activestate.com/recipes/576693-ordered-dictionary-for-py24/ +# here to support version 2.6. + ################################################################################ ### OrderedDict ################################################################################ diff --git a/script.module.future/lib/future/builtins/newround.py b/script.module.future/lib/future/builtins/newround.py index 394a2c63c4..b06c1169a5 100644 --- a/script.module.future/lib/future/builtins/newround.py +++ b/script.module.future/lib/future/builtins/newround.py @@ -2,6 +2,7 @@ ``python-future``: pure Python implementation of Python 3 round(). """ +from __future__ import division from future.utils import PYPY, PY26, bind_method # Use the decimal module for simplicity of implementation (and @@ -29,28 +30,30 @@ def newround(number, ndigits=None): if hasattr(number, '__round__'): return number.__round__(ndigits) - if ndigits < 0: - raise NotImplementedError('negative ndigits not supported yet') exponent = Decimal('10') ** (-ndigits) - if PYPY: - # Work around issue #24: round() breaks on PyPy with NumPy's types - if 'numpy' in repr(type(number)): - number = float(number) + # Work around issue #24: round() breaks on PyPy with NumPy's types + # Also breaks on CPython with NumPy's specialized int types like uint64 + if 'numpy' in repr(type(number)): + number = float(number) if isinstance(number, Decimal): d = number else: if not PY26: - d = Decimal.from_float(number).quantize(exponent, - rounding=ROUND_HALF_EVEN) + d = Decimal.from_float(number) else: - d = from_float_26(number).quantize(exponent, rounding=ROUND_HALF_EVEN) + d = from_float_26(number) + + if ndigits < 0: + result = newround(d / exponent) * exponent + else: + result = d.quantize(exponent, rounding=ROUND_HALF_EVEN) if return_int: - return int(d) + return int(result) else: - return float(d) + return float(result) ### From Python 2.7's decimal.py. Only needed to support Py2.6: diff --git a/script.module.future/lib/future/builtins/newsuper.py b/script.module.future/lib/future/builtins/newsuper.py index 5d3402bd2f..3e8cc80f04 100644 --- a/script.module.future/lib/future/builtins/newsuper.py +++ b/script.module.future/lib/future/builtins/newsuper.py @@ -60,44 +60,15 @@ def newsuper(typ=_SENTINEL, type_or_obj=_SENTINEL, framedepth=1): raise RuntimeError('super() used in a function with no args') try: - # Get the MRO so we can crawl it. - mro = type_or_obj.__mro__ - except (AttributeError, RuntimeError): # see issue #160 + typ = find_owner(type_or_obj, f.f_code) + except (AttributeError, RuntimeError, TypeError): + # see issues #160, #267 try: - mro = type_or_obj.__class__.__mro__ + typ = find_owner(type_or_obj.__class__, f.f_code) except AttributeError: - raise RuntimeError('super() used with a non-newstyle class') - - # A ``for...else`` block? Yes! It's odd, but useful. - # If unfamiliar with for...else, see: - # - # http://psung.blogspot.com/2007/12/for-else-in-python.html - for typ in mro: - # Find the class that owns the currently-executing method. - for meth in typ.__dict__.values(): - # Drill down through any wrappers to the underlying func. - # This handles e.g. classmethod() and staticmethod(). - try: - while not isinstance(meth,FunctionType): - if isinstance(meth, property): - # Calling __get__ on the property will invoke - # user code which might throw exceptions or have - # side effects - meth = meth.fget - else: - try: - meth = meth.__func__ - except AttributeError: - meth = meth.__get__(type_or_obj, typ) - except (AttributeError, TypeError): - continue - if meth.func_code is f.f_code: - break # Aha! Found you. - else: - continue # Not found! Move onto the next class in MRO. - break # Found! Break out of the search loop. - else: - raise RuntimeError('super() called outside a method') + raise RuntimeError('super() used with an old-style class') + except TypeError: + raise RuntimeError('super() called outside a method') # Dispatch to builtin super(). if type_or_obj is not _SENTINEL: @@ -105,6 +76,34 @@ def newsuper(typ=_SENTINEL, type_or_obj=_SENTINEL, framedepth=1): return _builtin_super(typ) +def find_owner(cls, code): + '''Find the class that owns the currently-executing method. + ''' + for typ in cls.__mro__: + for meth in typ.__dict__.values(): + # Drill down through any wrappers to the underlying func. + # This handles e.g. classmethod() and staticmethod(). + try: + while not isinstance(meth,FunctionType): + if isinstance(meth, property): + # Calling __get__ on the property will invoke + # user code which might throw exceptions or have + # side effects + meth = meth.fget + else: + try: + meth = meth.__func__ + except AttributeError: + meth = meth.__get__(cls, typ) + except (AttributeError, TypeError): + continue + if meth.func_code is code: + return typ # Aha! Found you. + # Not found! Move onto the next class in MRO. + + raise TypeError + + def superm(*args, **kwds): f = sys._getframe(1) nm = f.f_code.co_name diff --git a/script.module.future/lib/future/moves/tkinter/filedialog.py b/script.module.future/lib/future/moves/tkinter/filedialog.py index 973923e2c8..6a6f03ca2c 100644 --- a/script.module.future/lib/future/moves/tkinter/filedialog.py +++ b/script.module.future/lib/future/moves/tkinter/filedialog.py @@ -10,3 +10,9 @@ except ImportError: raise ImportError('The FileDialog module is missing. Does your Py2 ' 'installation include tkinter?') + + try: + from tkFileDialog import * + except ImportError: + raise ImportError('The tkFileDialog module is missing. Does your Py2 ' + 'installation include tkinter?') diff --git a/script.module.future/lib/future/types/newdict.py b/script.module.future/lib/future/types/newdict.py index 3f3a559dd5..d90316cb67 100644 --- a/script.module.future/lib/future/types/newdict.py +++ b/script.module.future/lib/future/types/newdict.py @@ -23,7 +23,7 @@ _builtin_dict = dict -ver = sys.version_info[:2] +ver = sys.version_info class BaseNewDict(type): @@ -38,47 +38,18 @@ class newdict(with_metaclass(BaseNewDict, _builtin_dict)): """ A backport of the Python 3 dict object to Py2 """ - def items(self): - """ - On Python 2.7+: - D.items() -> a set-like object providing a view on D's items - On Python 2.6: - D.items() -> an iterator over D's items - """ - if ver == (2, 7): - return self.viewitems() - elif ver == (2, 6): - return self.iteritems() - elif ver >= (3, 0): - return self.items() - - def keys(self): - """ - On Python 2.7+: - D.keys() -> a set-like object providing a view on D's keys - On Python 2.6: - D.keys() -> an iterator over D's keys - """ - if ver == (2, 7): - return self.viewkeys() - elif ver == (2, 6): - return self.iterkeys() - elif ver >= (3, 0): - return self.keys() - - def values(self): - """ - On Python 2.7+: - D.values() -> a set-like object providing a view on D's values - On Python 2.6: - D.values() -> an iterator over D's values - """ - if ver == (2, 7): - return self.viewvalues() - elif ver == (2, 6): - return self.itervalues() - elif ver >= (3, 0): - return self.values() + + if ver >= (3,): + # Inherit items, keys and values from `dict` in 3.x + pass + elif ver >= (2, 7): + items = dict.viewitems + keys = dict.viewkeys + values = dict.viewvalues + else: + items = dict.iteritems + keys = dict.iterkeys + values = dict.itervalues def __new__(cls, *args, **kwargs): """ @@ -93,13 +64,7 @@ def __new__(cls, *args, **kwargs): in the keyword argument list. For example: dict(one=1, two=2) """ - if len(args) == 0: - return super(newdict, cls).__new__(cls) - elif type(args[0]) == newdict: - value = args[0] - else: - value = args[0] - return super(newdict, cls).__new__(cls, value) + return super(newdict, cls).__new__(cls, *args) def __native__(self): """ diff --git a/script.module.future/lib/future/types/newint.py b/script.module.future/lib/future/types/newint.py index 748dba9d23..04a411e933 100644 --- a/script.module.future/lib/future/types/newint.py +++ b/script.module.future/lib/future/types/newint.py @@ -284,6 +284,9 @@ def __bool__(self): """ So subclasses can override this, Py3-style """ + if PY3: + return super(newint, self).__bool__() + return super(newint, self).__nonzero__() def __native__(self): diff --git a/script.module.future/lib/future/types/newrange.py b/script.module.future/lib/future/types/newrange.py index eda01a5a50..6d4ebe2f8f 100644 --- a/script.module.future/lib/future/types/newrange.py +++ b/script.module.future/lib/future/types/newrange.py @@ -87,7 +87,7 @@ def __eq__(self, other): return (isinstance(other, newrange) and (self._len == 0 == other._len or (self._start, self._step, self._len) == - (other._start, other._step, self._len))) + (other._start, other._step, other._len))) def __len__(self): return self._len diff --git a/script.module.future/lib/future/utils/__init__.py b/script.module.future/lib/future/utils/__init__.py index 46bd96def3..ec1b102746 100644 --- a/script.module.future/lib/future/utils/__init__.py +++ b/script.module.future/lib/future/utils/__init__.py @@ -61,6 +61,9 @@ 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) +PY37_PLUS = sys.version_info[0:2] >= (3, 7) +PY38_PLUS = sys.version_info[0:2] >= (3, 8) +PY39_PLUS = sys.version_info[0:2] >= (3, 9) PY2 = sys.version_info[0] == 2 PY26 = sys.version_info[0:2] == (2, 6) PY27 = sys.version_info[0:2] == (2, 7) @@ -527,9 +530,9 @@ def __next__(self): return cls if PY3: - get_next = lambda x: x.next -else: get_next = lambda x: x.__next__ +else: + get_next = lambda x: x.next def encode_filename(filename): diff --git a/script.module.future/lib/libfuturize/fixes/fix_division_safe.py b/script.module.future/lib/libfuturize/fixes/fix_division_safe.py index 3d5909cc19..65c8c1dac7 100644 --- a/script.module.future/lib/libfuturize/fixes/fix_division_safe.py +++ b/script.module.future/lib/libfuturize/fixes/fix_division_safe.py @@ -92,7 +92,12 @@ def match(self, node): else: children.append(child.clone()) if matched: - return Node(node.type, children, fixers_applied=node.fixers_applied) + # In Python 2.6, `Node` does not have the fixers_applied attribute + # https://github.com/python/cpython/blob/8493c0cd66cfc181ac1517268a74f077e9998701/Lib/lib2to3/pytree.py#L235 + if hasattr(Node, "fixers_applied"): + return Node(node.type, children, fixers_applied=node.fixers_applied) + else: + return Node(node.type, children) return False diff --git a/script.module.future/lib/libfuturize/fixes/fix_print.py b/script.module.future/lib/libfuturize/fixes/fix_print.py index 247b91b849..2554717cc2 100644 --- a/script.module.future/lib/libfuturize/fixes/fix_print.py +++ b/script.module.future/lib/libfuturize/fixes/fix_print.py @@ -57,6 +57,16 @@ def transform(self, node, results): if args and args[-1] == Comma(): args = args[:-1] end = " " + + # try to determine if the string ends in a non-space whitespace character, in which + # case there should be no space at the end of the conversion + string_leaves = [leaf for leaf in args[-1].leaves() if leaf.type == token.STRING] + if ( + string_leaves + and string_leaves[-1].value[0] != "r" # "raw" string + and string_leaves[-1].value[-3:-1] in (r"\t", r"\n", r"\r") + ): + end = "" if args and args[0] == pytree.Leaf(token.RIGHTSHIFT, u">>"): assert len(args) >= 2 file = args[1].clone() diff --git a/script.module.future/lib/libfuturize/fixes/fix_raise.py b/script.module.future/lib/libfuturize/fixes/fix_raise.py index f7518416fb..d113401c7d 100644 --- a/script.module.future/lib/libfuturize/fixes/fix_raise.py +++ b/script.module.future/lib/libfuturize/fixes/fix_raise.py @@ -94,7 +94,7 @@ def transform(self, node, results): args = [exc, Comma(), val] if tb is not None: args += [Comma(), tb] - return Call(Name(u"raise_"), args) + return Call(Name(u"raise_"), args, prefix=node.prefix) if tb is not None: tb.prefix = "" diff --git a/script.module.future/lib/past/builtins/misc.py b/script.module.future/lib/past/builtins/misc.py index ba50aa9ecc..3600695c0a 100644 --- a/script.module.future/lib/past/builtins/misc.py +++ b/script.module.future/lib/past/builtins/misc.py @@ -1,6 +1,8 @@ from __future__ import unicode_literals import inspect +import math +import numbers from future.utils import PY2, PY3, exec_ @@ -29,8 +31,67 @@ def cmp(x, y): cmp(x, y) -> integer Return negative if xy. + Python2 had looser comparison allowing cmp None and non Numerical types and collections. + Try to match the old behavior """ - return (x > y) - (x < y) + if isinstance(x, set) and isinstance(y, set): + raise TypeError('cannot compare sets using cmp()',) + try: + if isinstance(x, numbers.Number) and math.isnan(x): + if not isinstance(y, numbers.Number): + raise TypeError('cannot compare float("nan"), {type_y} with cmp'.format(type_y=type(y))) + if isinstance(y, int): + return 1 + else: + return -1 + if isinstance(y, numbers.Number) and math.isnan(y): + if not isinstance(x, numbers.Number): + raise TypeError('cannot compare {type_x}, float("nan") with cmp'.format(type_x=type(x))) + if isinstance(x, int): + return -1 + else: + return 1 + return (x > y) - (x < y) + except TypeError: + if x == y: + return 0 + type_order = [ + type(None), + numbers.Number, + dict, list, + set, + (str, bytes), + ] + x_type_index = y_type_index = None + for i, type_match in enumerate(type_order): + if isinstance(x, type_match): + x_type_index = i + if isinstance(y, type_match): + y_type_index = i + if cmp(x_type_index, y_type_index) == 0: + if isinstance(x, bytes) and isinstance(y, str): + return cmp(x.decode('ascii'), y) + if isinstance(y, bytes) and isinstance(x, str): + return cmp(x, y.decode('ascii')) + elif isinstance(x, list): + # if both arguments are lists take the comparison of the first non equal value + for x_elem, y_elem in zip(x, y): + elem_cmp_val = cmp(x_elem, y_elem) + if elem_cmp_val != 0: + return elem_cmp_val + # if all elements are equal, return equal/0 + return 0 + elif isinstance(x, dict): + if len(x) != len(y): + return cmp(len(x), len(y)) + else: + x_key = min(a for a in x if a not in y or x[a] != y[a]) + y_key = min(b for b in y if b not in x or x[b] != y[b]) + if x_key != y_key: + return cmp(x_key, y_key) + else: + return cmp(x[x_key], y[y_key]) + return cmp(x_type_index, y_type_index) from sys import intern @@ -42,7 +103,13 @@ def oct(number): return '0' + builtins.oct(number)[2:] raw_input = input - from imp import reload + + try: + from importlib import reload + except ImportError: + # for python2, python3 <= 3.4 + from imp import reload + unicode = str unichr = chr xrange = range @@ -82,7 +149,7 @@ def execfile(filename, myglobals=None, mylocals=None): if not isinstance(mylocals, Mapping): raise TypeError('locals must be a mapping') with open(filename, "rb") as fin: - source = fin.read() + source = fin.read() code = compile(source, filename, "exec") exec_(code, myglobals, mylocals) diff --git a/script.module.future/lib/past/types/basestring.py b/script.module.future/lib/past/types/basestring.py index 1cab22f6ca..9c21715a9f 100644 --- a/script.module.future/lib/past/types/basestring.py +++ b/script.module.future/lib/past/types/basestring.py @@ -25,9 +25,8 @@ class BaseBaseString(type): def __instancecheck__(cls, instance): return isinstance(instance, (bytes, str)) - def __subclasshook__(cls, thing): - # TODO: What should go here? - raise NotImplemented + def __subclasscheck__(cls, subclass): + return super(BaseBaseString, cls).__subclasscheck__(subclass) or issubclass(subclass, (bytes, str)) class basestring(with_metaclass(BaseBaseString)): diff --git a/script.module.future/lib/past/types/oldstr.py b/script.module.future/lib/past/types/oldstr.py index a477d8844e..5a0e378937 100644 --- a/script.module.future/lib/past/types/oldstr.py +++ b/script.module.future/lib/past/types/oldstr.py @@ -20,7 +20,7 @@ def __instancecheck__(cls, instance): def unescape(s): - """ + r""" Interprets strings with escape sequences Example: diff --git a/script.module.future/resources/icon.png b/script.module.future/resources/icon.png new file mode 100644 index 0000000000..ca4c53adbf Binary files /dev/null and b/script.module.future/resources/icon.png differ