mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-22 21:32:31 +00:00
python-3.6.zip added from Github
README.cosmo contains the necessary links.
This commit is contained in:
parent
75fc601ff5
commit
0c4c56ff39
4219 changed files with 1968626 additions and 0 deletions
347
third_party/python/Lib/test/test_super.py
vendored
Normal file
347
third_party/python/Lib/test/test_super.py
vendored
Normal file
|
@ -0,0 +1,347 @@
|
|||
"""Unit tests for zero-argument super() & related machinery."""
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
import warnings
|
||||
from test.support import check_warnings
|
||||
|
||||
|
||||
class A:
|
||||
def f(self):
|
||||
return 'A'
|
||||
@classmethod
|
||||
def cm(cls):
|
||||
return (cls, 'A')
|
||||
|
||||
class B(A):
|
||||
def f(self):
|
||||
return super().f() + 'B'
|
||||
@classmethod
|
||||
def cm(cls):
|
||||
return (cls, super().cm(), 'B')
|
||||
|
||||
class C(A):
|
||||
def f(self):
|
||||
return super().f() + 'C'
|
||||
@classmethod
|
||||
def cm(cls):
|
||||
return (cls, super().cm(), 'C')
|
||||
|
||||
class D(C, B):
|
||||
def f(self):
|
||||
return super().f() + 'D'
|
||||
def cm(cls):
|
||||
return (cls, super().cm(), 'D')
|
||||
|
||||
class E(D):
|
||||
pass
|
||||
|
||||
class F(E):
|
||||
f = E.f
|
||||
|
||||
class G(A):
|
||||
pass
|
||||
|
||||
|
||||
class TestSuper(unittest.TestCase):
|
||||
|
||||
def tearDown(self):
|
||||
# This fixes the damage that test_various___class___pathologies does.
|
||||
nonlocal __class__
|
||||
__class__ = TestSuper
|
||||
|
||||
def test_basics_working(self):
|
||||
self.assertEqual(D().f(), 'ABCD')
|
||||
|
||||
def test_class_getattr_working(self):
|
||||
self.assertEqual(D.f(D()), 'ABCD')
|
||||
|
||||
def test_subclass_no_override_working(self):
|
||||
self.assertEqual(E().f(), 'ABCD')
|
||||
self.assertEqual(E.f(E()), 'ABCD')
|
||||
|
||||
def test_unbound_method_transfer_working(self):
|
||||
self.assertEqual(F().f(), 'ABCD')
|
||||
self.assertEqual(F.f(F()), 'ABCD')
|
||||
|
||||
def test_class_methods_still_working(self):
|
||||
self.assertEqual(A.cm(), (A, 'A'))
|
||||
self.assertEqual(A().cm(), (A, 'A'))
|
||||
self.assertEqual(G.cm(), (G, 'A'))
|
||||
self.assertEqual(G().cm(), (G, 'A'))
|
||||
|
||||
def test_super_in_class_methods_working(self):
|
||||
d = D()
|
||||
self.assertEqual(d.cm(), (d, (D, (D, (D, 'A'), 'B'), 'C'), 'D'))
|
||||
e = E()
|
||||
self.assertEqual(e.cm(), (e, (E, (E, (E, 'A'), 'B'), 'C'), 'D'))
|
||||
|
||||
def test_super_with_closure(self):
|
||||
# Issue4360: super() did not work in a function that
|
||||
# contains a closure
|
||||
class E(A):
|
||||
def f(self):
|
||||
def nested():
|
||||
self
|
||||
return super().f() + 'E'
|
||||
|
||||
self.assertEqual(E().f(), 'AE')
|
||||
|
||||
def test_various___class___pathologies(self):
|
||||
# See issue #12370
|
||||
class X(A):
|
||||
def f(self):
|
||||
return super().f()
|
||||
__class__ = 413
|
||||
x = X()
|
||||
self.assertEqual(x.f(), 'A')
|
||||
self.assertEqual(x.__class__, 413)
|
||||
class X:
|
||||
x = __class__
|
||||
def f():
|
||||
__class__
|
||||
self.assertIs(X.x, type(self))
|
||||
with self.assertRaises(NameError) as e:
|
||||
exec("""class X:
|
||||
__class__
|
||||
def f():
|
||||
__class__""", globals(), {})
|
||||
self.assertIs(type(e.exception), NameError) # Not UnboundLocalError
|
||||
class X:
|
||||
global __class__
|
||||
__class__ = 42
|
||||
def f():
|
||||
__class__
|
||||
self.assertEqual(globals()["__class__"], 42)
|
||||
del globals()["__class__"]
|
||||
self.assertNotIn("__class__", X.__dict__)
|
||||
class X:
|
||||
nonlocal __class__
|
||||
__class__ = 42
|
||||
def f():
|
||||
__class__
|
||||
self.assertEqual(__class__, 42)
|
||||
|
||||
def test___class___instancemethod(self):
|
||||
# See issue #14857
|
||||
class X:
|
||||
def f(self):
|
||||
return __class__
|
||||
self.assertIs(X().f(), X)
|
||||
|
||||
def test___class___classmethod(self):
|
||||
# See issue #14857
|
||||
class X:
|
||||
@classmethod
|
||||
def f(cls):
|
||||
return __class__
|
||||
self.assertIs(X.f(), X)
|
||||
|
||||
def test___class___staticmethod(self):
|
||||
# See issue #14857
|
||||
class X:
|
||||
@staticmethod
|
||||
def f():
|
||||
return __class__
|
||||
self.assertIs(X.f(), X)
|
||||
|
||||
def test___class___new(self):
|
||||
# See issue #23722
|
||||
# Ensure zero-arg super() works as soon as type.__new__() is completed
|
||||
test_class = None
|
||||
|
||||
class Meta(type):
|
||||
def __new__(cls, name, bases, namespace):
|
||||
nonlocal test_class
|
||||
self = super().__new__(cls, name, bases, namespace)
|
||||
test_class = self.f()
|
||||
return self
|
||||
|
||||
class A(metaclass=Meta):
|
||||
@staticmethod
|
||||
def f():
|
||||
return __class__
|
||||
|
||||
self.assertIs(test_class, A)
|
||||
|
||||
def test___class___delayed(self):
|
||||
# See issue #23722
|
||||
test_namespace = None
|
||||
|
||||
class Meta(type):
|
||||
def __new__(cls, name, bases, namespace):
|
||||
nonlocal test_namespace
|
||||
test_namespace = namespace
|
||||
return None
|
||||
|
||||
# This case shouldn't trigger the __classcell__ deprecation warning
|
||||
with check_warnings() as w:
|
||||
warnings.simplefilter("always", DeprecationWarning)
|
||||
class A(metaclass=Meta):
|
||||
@staticmethod
|
||||
def f():
|
||||
return __class__
|
||||
self.assertEqual(w.warnings, [])
|
||||
|
||||
self.assertIs(A, None)
|
||||
|
||||
B = type("B", (), test_namespace)
|
||||
self.assertIs(B.f(), B)
|
||||
|
||||
def test___class___mro(self):
|
||||
# See issue #23722
|
||||
test_class = None
|
||||
|
||||
class Meta(type):
|
||||
def mro(self):
|
||||
# self.f() doesn't work yet...
|
||||
self.__dict__["f"]()
|
||||
return super().mro()
|
||||
|
||||
class A(metaclass=Meta):
|
||||
def f():
|
||||
nonlocal test_class
|
||||
test_class = __class__
|
||||
|
||||
self.assertIs(test_class, A)
|
||||
|
||||
def test___classcell___expected_behaviour(self):
|
||||
# See issue #23722
|
||||
class Meta(type):
|
||||
def __new__(cls, name, bases, namespace):
|
||||
nonlocal namespace_snapshot
|
||||
namespace_snapshot = namespace.copy()
|
||||
return super().__new__(cls, name, bases, namespace)
|
||||
|
||||
# __classcell__ is injected into the class namespace by the compiler
|
||||
# when at least one method needs it, and should be omitted otherwise
|
||||
namespace_snapshot = None
|
||||
class WithoutClassRef(metaclass=Meta):
|
||||
pass
|
||||
self.assertNotIn("__classcell__", namespace_snapshot)
|
||||
|
||||
# With zero-arg super() or an explicit __class__ reference,
|
||||
# __classcell__ is the exact cell reference to be populated by
|
||||
# type.__new__
|
||||
namespace_snapshot = None
|
||||
class WithClassRef(metaclass=Meta):
|
||||
def f(self):
|
||||
return __class__
|
||||
|
||||
class_cell = namespace_snapshot["__classcell__"]
|
||||
method_closure = WithClassRef.f.__closure__
|
||||
self.assertEqual(len(method_closure), 1)
|
||||
self.assertIs(class_cell, method_closure[0])
|
||||
# Ensure the cell reference *doesn't* get turned into an attribute
|
||||
with self.assertRaises(AttributeError):
|
||||
WithClassRef.__classcell__
|
||||
|
||||
def test___classcell___missing(self):
|
||||
# See issue #23722
|
||||
# Some metaclasses may not pass the original namespace to type.__new__
|
||||
# We test that case here by forcibly deleting __classcell__
|
||||
class Meta(type):
|
||||
def __new__(cls, name, bases, namespace):
|
||||
namespace.pop('__classcell__', None)
|
||||
return super().__new__(cls, name, bases, namespace)
|
||||
|
||||
# The default case should continue to work without any warnings
|
||||
with check_warnings() as w:
|
||||
warnings.simplefilter("always", DeprecationWarning)
|
||||
class WithoutClassRef(metaclass=Meta):
|
||||
pass
|
||||
self.assertEqual(w.warnings, [])
|
||||
|
||||
# With zero-arg super() or an explicit __class__ reference, we expect
|
||||
# __build_class__ to emit a DeprecationWarning complaining that
|
||||
# __class__ was not set, and asking if __classcell__ was propagated
|
||||
# to type.__new__.
|
||||
# In Python 3.7, that warning will become a RuntimeError.
|
||||
expected_warning = (
|
||||
'__class__ not set.*__classcell__ propagated',
|
||||
DeprecationWarning
|
||||
)
|
||||
with check_warnings(expected_warning):
|
||||
warnings.simplefilter("always", DeprecationWarning)
|
||||
class WithClassRef(metaclass=Meta):
|
||||
def f(self):
|
||||
return __class__
|
||||
# Check __class__ still gets set despite the warning
|
||||
self.assertIs(WithClassRef().f(), WithClassRef)
|
||||
|
||||
# Check the warning is turned into an error as expected
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error", DeprecationWarning)
|
||||
with self.assertRaises(DeprecationWarning):
|
||||
class WithClassRef(metaclass=Meta):
|
||||
def f(self):
|
||||
return __class__
|
||||
|
||||
def test___classcell___overwrite(self):
|
||||
# See issue #23722
|
||||
# Overwriting __classcell__ with nonsense is explicitly prohibited
|
||||
class Meta(type):
|
||||
def __new__(cls, name, bases, namespace, cell):
|
||||
namespace['__classcell__'] = cell
|
||||
return super().__new__(cls, name, bases, namespace)
|
||||
|
||||
for bad_cell in (None, 0, "", object()):
|
||||
with self.subTest(bad_cell=bad_cell):
|
||||
with self.assertRaises(TypeError):
|
||||
class A(metaclass=Meta, cell=bad_cell):
|
||||
pass
|
||||
|
||||
def test___classcell___wrong_cell(self):
|
||||
# See issue #23722
|
||||
# Pointing the cell reference at the wrong class is also prohibited
|
||||
class Meta(type):
|
||||
def __new__(cls, name, bases, namespace):
|
||||
cls = super().__new__(cls, name, bases, namespace)
|
||||
B = type("B", (), namespace)
|
||||
return cls
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
class A(metaclass=Meta):
|
||||
def f(self):
|
||||
return __class__
|
||||
|
||||
def test_obscure_super_errors(self):
|
||||
def f():
|
||||
super()
|
||||
self.assertRaises(RuntimeError, f)
|
||||
def f(x):
|
||||
del x
|
||||
super()
|
||||
self.assertRaises(RuntimeError, f, None)
|
||||
class X:
|
||||
def f(x):
|
||||
nonlocal __class__
|
||||
del __class__
|
||||
super()
|
||||
self.assertRaises(RuntimeError, X().f)
|
||||
|
||||
def test_cell_as_self(self):
|
||||
class X:
|
||||
def meth(self):
|
||||
super()
|
||||
|
||||
def f():
|
||||
k = X()
|
||||
def g():
|
||||
return k
|
||||
return g
|
||||
c = f().__closure__[0]
|
||||
self.assertRaises(TypeError, X.meth, c)
|
||||
|
||||
def test_super_init_leaks(self):
|
||||
# Issue #26718: super.__init__ leaked memory if called multiple times.
|
||||
# This will be caught by regrtest.py -R if this leak.
|
||||
# NOTE: Despite the use in the test a direct call of super.__init__
|
||||
# is not endorsed.
|
||||
sp = super(float, 1.0)
|
||||
for i in range(1000):
|
||||
super.__init__(sp, int, i)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
Loading…
Add table
Add a link
Reference in a new issue