initiated venv, installed FreeSimpleGUI and PySerial
This commit is contained in:
@ -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__ = []
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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__ = []
|
||||
@ -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
.venv/lib/python3.12/site-packages/future/builtins/misc.py
Normal file
135
.venv/lib/python3.12/site-packages/future/builtins/misc.py
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')
|
||||
@ -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)
|
||||
@ -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
.venv/lib/python3.12/site-packages/future/builtins/newround.py
Normal file
105
.venv/lib/python3.12/site-packages/future/builtins/newround.py
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
.venv/lib/python3.12/site-packages/future/builtins/newsuper.py
Normal file
113
.venv/lib/python3.12/site-packages/future/builtins/newsuper.py
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