mirror of
https://github.com/python/cpython.git
synced 2025-11-02 03:01:58 +00:00
gh-123465: Allow Py_RELATIVE_OFFSET for __*offset__ members (GH-123474)
This commit is contained in:
parent
ce9f84a47b
commit
16be8db6be
8 changed files with 422 additions and 74 deletions
|
|
@ -851,8 +851,13 @@ class TestPEP590(unittest.TestCase):
|
|||
@requires_limited_api
|
||||
def test_vectorcall_limited_incoming(self):
|
||||
from _testcapi import pyobject_vectorcall
|
||||
obj = _testlimitedcapi.LimitedVectorCallClass()
|
||||
self.assertEqual(pyobject_vectorcall(obj, (), ()), "vectorcall called")
|
||||
for cls in (_testlimitedcapi.LimitedVectorCallClass,
|
||||
_testlimitedcapi.LimitedRelativeVectorCallClass):
|
||||
with self.subTest(cls=cls):
|
||||
obj = cls()
|
||||
self.assertEqual(
|
||||
pyobject_vectorcall(obj, (), ()),
|
||||
"vectorcall called")
|
||||
|
||||
@requires_limited_api
|
||||
def test_vectorcall_limited_outgoing(self):
|
||||
|
|
|
|||
|
|
@ -541,14 +541,19 @@ class CAPITest(unittest.TestCase):
|
|||
self.assertEqual(new_type_refcnt, sys.getrefcount(A))
|
||||
|
||||
def test_heaptype_with_dict(self):
|
||||
inst = _testcapi.HeapCTypeWithDict()
|
||||
inst.foo = 42
|
||||
self.assertEqual(inst.foo, 42)
|
||||
self.assertEqual(inst.dictobj, inst.__dict__)
|
||||
self.assertEqual(inst.dictobj, {"foo": 42})
|
||||
for cls in (
|
||||
_testcapi.HeapCTypeWithDict,
|
||||
_testlimitedcapi.HeapCTypeWithRelativeDict,
|
||||
):
|
||||
with self.subTest(cls=cls):
|
||||
inst = cls()
|
||||
inst.foo = 42
|
||||
self.assertEqual(inst.foo, 42)
|
||||
self.assertEqual(inst.dictobj, inst.__dict__)
|
||||
self.assertEqual(inst.dictobj, {"foo": 42})
|
||||
|
||||
inst = _testcapi.HeapCTypeWithDict()
|
||||
self.assertEqual({}, inst.__dict__)
|
||||
inst = cls()
|
||||
self.assertEqual({}, inst.__dict__)
|
||||
|
||||
def test_heaptype_with_managed_dict(self):
|
||||
inst = _testcapi.HeapCTypeWithManagedDict()
|
||||
|
|
@ -585,10 +590,15 @@ class CAPITest(unittest.TestCase):
|
|||
self.assertEqual({}, inst.__dict__)
|
||||
|
||||
def test_heaptype_with_weakref(self):
|
||||
inst = _testcapi.HeapCTypeWithWeakref()
|
||||
ref = weakref.ref(inst)
|
||||
self.assertEqual(ref(), inst)
|
||||
self.assertEqual(inst.weakreflist, ref)
|
||||
for cls in (
|
||||
_testcapi.HeapCTypeWithWeakref,
|
||||
_testlimitedcapi.HeapCTypeWithRelativeWeakref,
|
||||
):
|
||||
with self.subTest(cls=cls):
|
||||
inst = cls()
|
||||
ref = weakref.ref(inst)
|
||||
self.assertEqual(ref(), inst)
|
||||
self.assertEqual(inst.weakreflist, ref)
|
||||
|
||||
def test_heaptype_with_managed_weakref(self):
|
||||
inst = _testcapi.HeapCTypeWithManagedWeakref()
|
||||
|
|
@ -730,45 +740,56 @@ class CAPITest(unittest.TestCase):
|
|||
self.assertIsInstance(sub, metaclass)
|
||||
|
||||
def test_multiple_inheritance_ctypes_with_weakref_or_dict(self):
|
||||
for weakref_cls in (_testcapi.HeapCTypeWithWeakref,
|
||||
_testlimitedcapi.HeapCTypeWithRelativeWeakref):
|
||||
for dict_cls in (_testcapi.HeapCTypeWithDict,
|
||||
_testlimitedcapi.HeapCTypeWithRelativeDict):
|
||||
with self.subTest(weakref_cls=weakref_cls, dict_cls=dict_cls):
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
class Both1(_testcapi.HeapCTypeWithWeakref, _testcapi.HeapCTypeWithDict):
|
||||
pass
|
||||
with self.assertRaises(TypeError):
|
||||
class Both2(_testcapi.HeapCTypeWithDict, _testcapi.HeapCTypeWithWeakref):
|
||||
pass
|
||||
with self.assertRaises(TypeError):
|
||||
class Both1(weakref_cls, dict_cls):
|
||||
pass
|
||||
with self.assertRaises(TypeError):
|
||||
class Both2(dict_cls, weakref_cls):
|
||||
pass
|
||||
|
||||
def test_multiple_inheritance_ctypes_with_weakref_or_dict_and_other_builtin(self):
|
||||
for dict_cls in (_testcapi.HeapCTypeWithDict,
|
||||
_testlimitedcapi.HeapCTypeWithRelativeDict):
|
||||
for weakref_cls in (_testcapi.HeapCTypeWithWeakref,
|
||||
_testlimitedcapi.HeapCTypeWithRelativeWeakref):
|
||||
with self.subTest(dict_cls=dict_cls, weakref_cls=weakref_cls):
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
class C1(_testcapi.HeapCTypeWithDict, list):
|
||||
pass
|
||||
with self.assertRaises(TypeError):
|
||||
class C1(dict_cls, list):
|
||||
pass
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
class C2(_testcapi.HeapCTypeWithWeakref, list):
|
||||
pass
|
||||
with self.assertRaises(TypeError):
|
||||
class C2(weakref_cls, list):
|
||||
pass
|
||||
|
||||
class C3(_testcapi.HeapCTypeWithManagedDict, list):
|
||||
pass
|
||||
class C4(_testcapi.HeapCTypeWithManagedWeakref, list):
|
||||
pass
|
||||
class C3(_testcapi.HeapCTypeWithManagedDict, list):
|
||||
pass
|
||||
class C4(_testcapi.HeapCTypeWithManagedWeakref, list):
|
||||
pass
|
||||
|
||||
inst = C3()
|
||||
inst.append(0)
|
||||
str(inst.__dict__)
|
||||
inst = C3()
|
||||
inst.append(0)
|
||||
str(inst.__dict__)
|
||||
|
||||
inst = C4()
|
||||
inst.append(0)
|
||||
str(inst.__weakref__)
|
||||
inst = C4()
|
||||
inst.append(0)
|
||||
str(inst.__weakref__)
|
||||
|
||||
for cls in (_testcapi.HeapCTypeWithManagedDict, _testcapi.HeapCTypeWithManagedWeakref):
|
||||
for cls2 in (_testcapi.HeapCTypeWithDict, _testcapi.HeapCTypeWithWeakref):
|
||||
class S(cls, cls2):
|
||||
pass
|
||||
class B1(C3, cls):
|
||||
pass
|
||||
class B2(C4, cls):
|
||||
pass
|
||||
for cls in (_testcapi.HeapCTypeWithManagedDict,
|
||||
_testcapi.HeapCTypeWithManagedWeakref):
|
||||
for cls2 in (dict_cls, weakref_cls):
|
||||
class S(cls, cls2):
|
||||
pass
|
||||
class B1(C3, cls):
|
||||
pass
|
||||
class B2(C4, cls):
|
||||
pass
|
||||
|
||||
def test_pytype_fromspec_with_repeated_slots(self):
|
||||
for variant in range(2):
|
||||
|
|
@ -1272,6 +1293,53 @@ class TestHeapTypeRelative(unittest.TestCase):
|
|||
SystemError, r"PyMember_SetOne used with Py_RELATIVE_OFFSET"):
|
||||
instance.set_memb_relative(0)
|
||||
|
||||
def test_heaptype_relative_special_members_errors(self):
|
||||
for member_name in "__vectorcalloffset__", "__dictoffset__", "__weaklistoffset__":
|
||||
with self.subTest(member_name=member_name):
|
||||
with self.assertRaisesRegex(
|
||||
SystemError,
|
||||
r"With Py_RELATIVE_OFFSET, basicsize must be negative."):
|
||||
_testlimitedcapi.make_heaptype_with_member(
|
||||
basicsize=sys.getsizeof(object()) + 100,
|
||||
add_relative_flag=True,
|
||||
member_name=member_name,
|
||||
member_offset=0,
|
||||
member_type=_testlimitedcapi.Py_T_PYSSIZET,
|
||||
member_flags=_testlimitedcapi.Py_READONLY,
|
||||
)
|
||||
with self.assertRaisesRegex(
|
||||
SystemError,
|
||||
r"Member offset out of range \(0\.\.-basicsize\)"):
|
||||
_testlimitedcapi.make_heaptype_with_member(
|
||||
basicsize=-8,
|
||||
add_relative_flag=True,
|
||||
member_name=member_name,
|
||||
member_offset=-1,
|
||||
member_type=_testlimitedcapi.Py_T_PYSSIZET,
|
||||
member_flags=_testlimitedcapi.Py_READONLY,
|
||||
)
|
||||
with self.assertRaisesRegex(
|
||||
SystemError,
|
||||
r"type of %s must be Py_T_PYSSIZET" % member_name):
|
||||
_testlimitedcapi.make_heaptype_with_member(
|
||||
basicsize=-100,
|
||||
add_relative_flag=True,
|
||||
member_name=member_name,
|
||||
member_offset=0,
|
||||
member_flags=_testlimitedcapi.Py_READONLY,
|
||||
)
|
||||
with self.assertRaisesRegex(
|
||||
SystemError,
|
||||
r"flags for %s must be " % member_name):
|
||||
_testlimitedcapi.make_heaptype_with_member(
|
||||
basicsize=-100,
|
||||
add_relative_flag=True,
|
||||
member_name=member_name,
|
||||
member_offset=0,
|
||||
member_type=_testlimitedcapi.Py_T_PYSSIZET,
|
||||
member_flags=0,
|
||||
)
|
||||
|
||||
def test_pyobject_getitemdata_error(self):
|
||||
"""Test PyObject_GetItemData fails on unsupported types"""
|
||||
with self.assertRaises(TypeError):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue