second commit

This commit is contained in:
2024-12-27 22:31:23 +09:00
parent 2353324570
commit 10a0f110ca
8819 changed files with 1307198 additions and 28 deletions

View File

@ -0,0 +1,51 @@
"""
A module that brings in equivalents of the new and modified Python 3
builtins into Py2. Has no effect on Py3.
See the docs `here <https://python-future.org/what-else.html>`_
(``docs/what-else.rst``) for more information.
"""
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, max, min)
from future.utils import PY3
if PY3:
import builtins
bytes = builtins.bytes
dict = builtins.dict
int = builtins.int
list = builtins.list
object = builtins.object
range = builtins.range
str = builtins.str
__all__ = []
else:
from future.types import (newbytes as bytes,
newdict as dict,
newint as int,
newlist as list,
newobject as object,
newrange as range,
newstr as str)
from future import utils
if not utils.PY3:
# We only import names that shadow the builtins on Py2. No other namespace
# pollution on Py2.
# Only shadow builtins on Py2; no new names
__all__ = ['filter', 'map', 'zip',
'ascii', 'chr', 'hex', 'input', 'next', 'oct', 'open', 'pow',
'round', 'super',
'bytes', 'dict', 'int', 'list', 'object', 'range', 'str', 'max', 'min'
]
else:
# No namespace pollution on Py3
__all__ = []

View File

@ -0,0 +1,66 @@
"""
This disables builtin functions (and one exception class) which are
removed from Python 3.3.
This module is designed to be used like this::
from future.builtins.disabled import *
This disables the following obsolete Py2 builtin functions::
apply, cmp, coerce, execfile, file, input, long,
raw_input, reduce, reload, unicode, xrange
We don't hack __builtin__, which is very fragile because it contaminates
imported modules too. Instead, we just create new functions with
the same names as the obsolete builtins from Python 2 which raise
NameError exceptions when called.
Note that both ``input()`` and ``raw_input()`` are among the disabled
functions (in this module). Although ``input()`` exists as a builtin in
Python 3, the Python 2 ``input()`` builtin is unsafe to use because it
can lead to shell injection. Therefore we shadow it by default upon ``from
future.builtins.disabled import *``, in case someone forgets to import our
replacement ``input()`` somehow and expects Python 3 semantics.
See the ``future.builtins.misc`` module for a working version of
``input`` with Python 3 semantics.
(Note that callable() is not among the functions disabled; this was
reintroduced into Python 3.2.)
This exception class is also disabled:
StandardError
"""
from __future__ import division, absolute_import, print_function
from future import utils
OBSOLETE_BUILTINS = ['apply', 'chr', 'cmp', 'coerce', 'execfile', 'file',
'input', 'long', 'raw_input', 'reduce', 'reload',
'unicode', 'xrange', 'StandardError']
def disabled_function(name):
'''
Returns a function that cannot be called
'''
def disabled(*args, **kwargs):
'''
A function disabled by the ``future`` module. This function is
no longer a builtin in Python 3.
'''
raise NameError('obsolete Python 2 builtin {0} is disabled'.format(name))
return disabled
if not utils.PY3:
for fname in OBSOLETE_BUILTINS:
locals()[fname] = disabled_function(fname)
__all__ = OBSOLETE_BUILTINS
else:
__all__ = []

View File

@ -0,0 +1,52 @@
"""
This module is designed to be used as follows::
from future.builtins.iterators import *
And then, for example::
for i in range(10**15):
pass
for (a, b) in zip(range(10**15), range(-10**15, 0)):
pass
Note that this is standard Python 3 code, plus some imports that do
nothing on Python 3.
The iterators this brings in are::
- ``range``
- ``filter``
- ``map``
- ``zip``
On Python 2, ``range`` is a pure-Python backport of Python 3's ``range``
iterator with slicing support. The other iterators (``filter``, ``map``,
``zip``) are from the ``itertools`` module on Python 2. On Python 3 these
are available in the module namespace but not exported for * imports via
__all__ (zero no namespace pollution).
Note that these are also available in the standard library
``future_builtins`` module on Python 2 -- but not Python 3, so using
the standard library version is not portable, nor anywhere near complete.
"""
from __future__ import division, absolute_import, print_function
import itertools
from future import utils
if not utils.PY3:
filter = itertools.ifilter
map = itertools.imap
from future.types import newrange as range
zip = itertools.izip
__all__ = ['filter', 'map', 'range', 'zip']
else:
import builtins
filter = builtins.filter
map = builtins.map
range = builtins.range
zip = builtins.zip
__all__ = []

View File

@ -0,0 +1,135 @@
"""
A module that brings in equivalents of various modified Python 3 builtins
into Py2. Has no effect on Py3.
The builtin functions are:
- ``ascii`` (from Py2's future_builtins module)
- ``hex`` (from Py2's future_builtins module)
- ``oct`` (from Py2's future_builtins module)
- ``chr`` (equivalent to ``unichr`` on Py2)
- ``input`` (equivalent to ``raw_input`` on Py2)
- ``next`` (calls ``__next__`` if it exists, else ``next`` method)
- ``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.
input()
-------
Like the new ``input()`` function from Python 3 (without eval()), except
that it returns bytes. Equivalent to Python 2's ``raw_input()``.
Warning: By default, importing this module *removes* the old Python 2
input() function entirely from ``__builtin__`` for safety. This is
because forgetting to import the new ``input`` from ``future`` might
otherwise lead to a security vulnerability (shell injection) on Python 2.
To restore it, you can retrieve it yourself from
``__builtin__._old_input``.
Fortunately, ``input()`` seems to be seldom used in the wild in Python
2...
"""
from future import utils
if utils.PY2:
from io import open
from future_builtins import ascii, oct, hex
from __builtin__ import unichr as chr, pow as _builtin_pow
import __builtin__
# Only for backward compatibility with future v0.8.2:
isinstance = __builtin__.isinstance
# Warning: Python 2's input() is unsafe and MUST not be able to be used
# accidentally by someone who expects Python 3 semantics but forgets
# to import it on Python 2. Versions of ``future`` prior to 0.11
# deleted it from __builtin__. Now we keep in __builtin__ but shadow
# the name like all others. Just be sure to import ``input``.
input = raw_input
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()
def pow(x, y, z=_SENTINEL):
"""
pow(x, y[, z]) -> number
With two arguments, equivalent to x**y. With three arguments,
equivalent to (x**y) % z, but may be more efficient (e.g. for ints).
"""
# Handle newints
if isinstance(x, newint):
x = long(x)
if isinstance(y, newint):
y = long(y)
if isinstance(z, newint):
z = long(z)
try:
if z == _SENTINEL:
return _builtin_pow(x, y)
else:
return _builtin_pow(x, y, z)
except ValueError:
if z == _SENTINEL:
return _builtin_pow(x+0j, y)
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', 'max', 'min']
else:
import builtins
ascii = builtins.ascii
chr = builtins.chr
hex = builtins.hex
input = builtins.input
next = builtins.next
# Only for backward compatibility with future v0.8.2:
isinstance = builtins.isinstance
oct = builtins.oct
open = builtins.open
pow = builtins.pow
round = builtins.round
super = builtins.super
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
# did, we'd add this:
# try:
# callable = builtins.callable
# except AttributeError:
# # Definition from Pandas
# def callable(obj):
# return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
# __all__.append('callable')

View File

@ -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)

View File

@ -0,0 +1,70 @@
'''
This module provides a newnext() function in Python 2 that mimics the
behaviour of ``next()`` in Python 3, falling back to Python 2's behaviour for
compatibility if this fails.
``newnext(iterator)`` calls the iterator's ``__next__()`` method if it exists. If this
doesn't exist, it falls back to calling a ``next()`` method.
For example:
>>> class Odds(object):
... def __init__(self, start=1):
... self.value = start - 2
... def __next__(self): # note the Py3 interface
... self.value += 2
... return self.value
... def __iter__(self):
... return self
...
>>> iterator = Odds()
>>> next(iterator)
1
>>> next(iterator)
3
If you are defining your own custom iterator class as above, it is preferable
to explicitly decorate the class with the @implements_iterator decorator from
``future.utils`` as follows:
>>> @implements_iterator
... class Odds(object):
... # etc
... pass
This next() function is primarily for consuming iterators defined in Python 3
code elsewhere that we would like to run on Python 2 or 3.
'''
_builtin_next = next
_SENTINEL = object()
def newnext(iterator, default=_SENTINEL):
"""
next(iterator[, default])
Return the next item from the iterator. If default is given and the iterator
is exhausted, it is returned instead of raising StopIteration.
"""
# args = []
# if default is not _SENTINEL:
# args.append(default)
try:
try:
return iterator.__next__()
except AttributeError:
try:
return iterator.next()
except AttributeError:
raise TypeError("'{0}' object is not an iterator".format(
iterator.__class__.__name__))
except StopIteration as e:
if default is _SENTINEL:
raise e
else:
return default
__all__ = ['newnext']

View File

@ -0,0 +1,105 @@
"""
``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
# hopefully correctness).
from decimal import Decimal, ROUND_HALF_EVEN
def newround(number, ndigits=None):
"""
See Python 3 documentation: uses Banker's Rounding.
Delegates to the __round__ method if for some reason this exists.
If not, rounds a number to a given precision in decimal digits (default
0 digits). This returns an int when called with one argument,
otherwise the same type as the number. ndigits may be negative.
See the test_round method in future/tests/test_builtins.py for
examples.
"""
return_int = False
if ndigits is None:
return_int = True
ndigits = 0
if hasattr(number, '__round__'):
return number.__round__(ndigits)
exponent = Decimal('10') ** (-ndigits)
# 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)
else:
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(result)
else:
return float(result)
### From Python 2.7's decimal.py. Only needed to support Py2.6:
def from_float_26(f):
"""Converts a float to a decimal number, exactly.
Note that Decimal.from_float(0.1) is not the same as Decimal('0.1').
Since 0.1 is not exactly representable in binary floating point, the
value is stored as the nearest representable value which is
0x1.999999999999ap-4. The exact equivalent of the value in decimal
is 0.1000000000000000055511151231257827021181583404541015625.
>>> Decimal.from_float(0.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')
>>> Decimal.from_float(float('nan'))
Decimal('NaN')
>>> Decimal.from_float(float('inf'))
Decimal('Infinity')
>>> Decimal.from_float(-float('inf'))
Decimal('-Infinity')
>>> Decimal.from_float(-0.0)
Decimal('-0')
"""
import math as _math
from decimal import _dec_from_triple # only available on Py2.6 and Py2.7 (not 3.3)
if isinstance(f, (int, long)): # handle integer inputs
return Decimal(f)
if _math.isinf(f) or _math.isnan(f): # raises TypeError if not a float
return Decimal(repr(f))
if _math.copysign(1.0, f) == 1.0:
sign = 0
else:
sign = 1
n, d = abs(f).as_integer_ratio()
# int.bit_length() method doesn't exist on Py2.6:
def bit_length(d):
if d != 0:
return len(bin(abs(d))) - 2
else:
return 0
k = bit_length(d) - 1
result = _dec_from_triple(sign, str(n*5**k), -k)
return result
__all__ = ['newround']

View File

@ -0,0 +1,113 @@
'''
This module provides a newsuper() function in Python 2 that mimics the
behaviour of super() in Python 3. It is designed to be used as follows:
from __future__ import division, absolute_import, print_function
from future.builtins import super
And then, for example:
class VerboseList(list):
def append(self, item):
print('Adding an item')
super().append(item) # new simpler super() function
Importing this module on Python 3 has no effect.
This is based on (i.e. almost identical to) Ryan Kelly's magicsuper
module here:
https://github.com/rfk/magicsuper.git
Excerpts from Ryan's docstring:
"Of course, you can still explicitly pass in the arguments if you want
to do something strange. Sometimes you really do want that, e.g. to
skip over some classes in the method resolution order.
"How does it work? By inspecting the calling frame to determine the
function object being executed and the object on which it's being
called, and then walking the object's __mro__ chain to find out where
that function was defined. Yuck, but it seems to work..."
'''
from __future__ import absolute_import
import sys
from types import FunctionType
from future.utils import PY3, PY26
_builtin_super = super
_SENTINEL = object()
def newsuper(typ=_SENTINEL, type_or_obj=_SENTINEL, framedepth=1):
'''Like builtin super(), but capable of magic.
This acts just like the builtin super() function, but if called
without any arguments it attempts to infer them at runtime.
'''
# Infer the correct call if used without arguments.
if typ is _SENTINEL:
# We'll need to do some frame hacking.
f = sys._getframe(framedepth)
try:
# Get the function's first positional argument.
type_or_obj = f.f_locals[f.f_code.co_varnames[0]]
except (IndexError, KeyError,):
raise RuntimeError('super() used in a function with no args')
try:
typ = find_owner(type_or_obj, f.f_code)
except (AttributeError, RuntimeError, TypeError):
# see issues #160, #267
try:
typ = find_owner(type_or_obj.__class__, f.f_code)
except AttributeError:
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:
return _builtin_super(typ, type_or_obj)
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
return getattr(newsuper(framedepth=2),nm)(*args, **kwds)
__all__ = ['newsuper']