second commit
This commit is contained in:
51
env/lib/python3.11/site-packages/future/builtins/__init__.py
vendored
Normal file
51
env/lib/python3.11/site-packages/future/builtins/__init__.py
vendored
Normal 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__ = []
|
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/__init__.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/__init__.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/disabled.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/disabled.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/iterators.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/iterators.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/misc.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/misc.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/new_min_max.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/new_min_max.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/newnext.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/newnext.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/newround.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/newround.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/newsuper.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/future/builtins/__pycache__/newsuper.cpython-311.pyc
vendored
Normal file
Binary file not shown.
66
env/lib/python3.11/site-packages/future/builtins/disabled.py
vendored
Normal file
66
env/lib/python3.11/site-packages/future/builtins/disabled.py
vendored
Normal 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__ = []
|
52
env/lib/python3.11/site-packages/future/builtins/iterators.py
vendored
Normal file
52
env/lib/python3.11/site-packages/future/builtins/iterators.py
vendored
Normal 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__ = []
|
135
env/lib/python3.11/site-packages/future/builtins/misc.py
vendored
Normal file
135
env/lib/python3.11/site-packages/future/builtins/misc.py
vendored
Normal 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')
|
59
env/lib/python3.11/site-packages/future/builtins/new_min_max.py
vendored
Normal file
59
env/lib/python3.11/site-packages/future/builtins/new_min_max.py
vendored
Normal 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)
|
70
env/lib/python3.11/site-packages/future/builtins/newnext.py
vendored
Normal file
70
env/lib/python3.11/site-packages/future/builtins/newnext.py
vendored
Normal 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']
|
105
env/lib/python3.11/site-packages/future/builtins/newround.py
vendored
Normal file
105
env/lib/python3.11/site-packages/future/builtins/newround.py
vendored
Normal 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']
|
113
env/lib/python3.11/site-packages/future/builtins/newsuper.py
vendored
Normal file
113
env/lib/python3.11/site-packages/future/builtins/newsuper.py
vendored
Normal 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']
|
Reference in New Issue
Block a user