Skip to content

Commit d553110

Browse files
pythongh-107178: Add the C API tests for the Abstract Objects Layer
Cover all the Mapping Protocol, almost all the Sequence Protocol (except PySequence_Fast) and a part of the Object Protocol. Move existing tests to Lib/test/test_capi/test_abstract.py and Modules/_testcapi/abstract.c.
1 parent 1e50112 commit d553110

File tree

10 files changed

+1376
-296
lines changed

10 files changed

+1376
-296
lines changed

Lib/test/test_capi/test_abstract.py

Lines changed: 722 additions & 0 deletions
Large diffs are not rendered by default.

Lib/test/test_capi/test_misc.py

Lines changed: 0 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -299,137 +299,6 @@ def test_getitem_with_error(self):
299299
def test_buildvalue_N(self):
300300
_testcapi.test_buildvalue_N()
301301

302-
def test_mapping_keys_values_items(self):
303-
class Mapping1(dict):
304-
def keys(self):
305-
return list(super().keys())
306-
def values(self):
307-
return list(super().values())
308-
def items(self):
309-
return list(super().items())
310-
class Mapping2(dict):
311-
def keys(self):
312-
return tuple(super().keys())
313-
def values(self):
314-
return tuple(super().values())
315-
def items(self):
316-
return tuple(super().items())
317-
dict_obj = {'foo': 1, 'bar': 2, 'spam': 3}
318-
319-
for mapping in [{}, OrderedDict(), Mapping1(), Mapping2(),
320-
dict_obj, OrderedDict(dict_obj),
321-
Mapping1(dict_obj), Mapping2(dict_obj)]:
322-
self.assertListEqual(_testcapi.get_mapping_keys(mapping),
323-
list(mapping.keys()))
324-
self.assertListEqual(_testcapi.get_mapping_values(mapping),
325-
list(mapping.values()))
326-
self.assertListEqual(_testcapi.get_mapping_items(mapping),
327-
list(mapping.items()))
328-
329-
def test_mapping_keys_values_items_bad_arg(self):
330-
self.assertRaises(AttributeError, _testcapi.get_mapping_keys, None)
331-
self.assertRaises(AttributeError, _testcapi.get_mapping_values, None)
332-
self.assertRaises(AttributeError, _testcapi.get_mapping_items, None)
333-
334-
class BadMapping:
335-
def keys(self):
336-
return None
337-
def values(self):
338-
return None
339-
def items(self):
340-
return None
341-
bad_mapping = BadMapping()
342-
self.assertRaises(TypeError, _testcapi.get_mapping_keys, bad_mapping)
343-
self.assertRaises(TypeError, _testcapi.get_mapping_values, bad_mapping)
344-
self.assertRaises(TypeError, _testcapi.get_mapping_items, bad_mapping)
345-
346-
def test_mapping_has_key(self):
347-
dct = {'a': 1}
348-
self.assertTrue(_testcapi.mapping_has_key(dct, 'a'))
349-
self.assertFalse(_testcapi.mapping_has_key(dct, 'b'))
350-
351-
class SubDict(dict):
352-
pass
353-
354-
dct2 = SubDict({'a': 1})
355-
self.assertTrue(_testcapi.mapping_has_key(dct2, 'a'))
356-
self.assertFalse(_testcapi.mapping_has_key(dct2, 'b'))
357-
358-
def test_sequence_set_slice(self):
359-
# Correct case:
360-
data = [1, 2, 3, 4, 5]
361-
data_copy = data.copy()
362-
363-
_testcapi.sequence_set_slice(data, 1, 3, [8, 9])
364-
data_copy[1:3] = [8, 9]
365-
self.assertEqual(data, data_copy)
366-
self.assertEqual(data, [1, 8, 9, 4, 5])
367-
368-
# Custom class:
369-
class Custom:
370-
def __setitem__(self, index, value):
371-
self.index = index
372-
self.value = value
373-
374-
c = Custom()
375-
_testcapi.sequence_set_slice(c, 0, 5, 'abc')
376-
self.assertEqual(c.index, slice(0, 5))
377-
self.assertEqual(c.value, 'abc')
378-
379-
# Immutable sequences must raise:
380-
bad_seq1 = (1, 2, 3, 4)
381-
with self.assertRaises(TypeError):
382-
_testcapi.sequence_set_slice(bad_seq1, 1, 3, (8, 9))
383-
self.assertEqual(bad_seq1, (1, 2, 3, 4))
384-
385-
bad_seq2 = 'abcd'
386-
with self.assertRaises(TypeError):
387-
_testcapi.sequence_set_slice(bad_seq2, 1, 3, 'xy')
388-
self.assertEqual(bad_seq2, 'abcd')
389-
390-
# Not a sequence:
391-
with self.assertRaises(TypeError):
392-
_testcapi.sequence_set_slice(None, 1, 3, 'xy')
393-
394-
def test_sequence_del_slice(self):
395-
# Correct case:
396-
data = [1, 2, 3, 4, 5]
397-
data_copy = data.copy()
398-
399-
_testcapi.sequence_del_slice(data, 1, 3)
400-
del data_copy[1:3]
401-
self.assertEqual(data, data_copy)
402-
self.assertEqual(data, [1, 4, 5])
403-
404-
# Custom class:
405-
class Custom:
406-
def __delitem__(self, index):
407-
self.index = index
408-
409-
c = Custom()
410-
_testcapi.sequence_del_slice(c, 0, 5)
411-
self.assertEqual(c.index, slice(0, 5))
412-
413-
# Immutable sequences must raise:
414-
bad_seq1 = (1, 2, 3, 4)
415-
with self.assertRaises(TypeError):
416-
_testcapi.sequence_del_slice(bad_seq1, 1, 3)
417-
self.assertEqual(bad_seq1, (1, 2, 3, 4))
418-
419-
bad_seq2 = 'abcd'
420-
with self.assertRaises(TypeError):
421-
_testcapi.sequence_del_slice(bad_seq2, 1, 3)
422-
self.assertEqual(bad_seq2, 'abcd')
423-
424-
# Not a sequence:
425-
with self.assertRaises(TypeError):
426-
_testcapi.sequence_del_slice(None, 1, 3)
427-
428-
mapping = {1: 'a', 2: 'b', 3: 'c'}
429-
with self.assertRaises(KeyError):
430-
_testcapi.sequence_del_slice(mapping, 1, 3)
431-
self.assertEqual(mapping, {1: 'a', 2: 'b', 3: 'c'})
432-
433302
@unittest.skipUnless(hasattr(_testcapi, 'negative_refcount'),
434303
'need _testcapi.negative_refcount')
435304
def test_negative_refcount(self):

Lib/test/test_class.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,8 +455,8 @@ def __init__(self):
455455
self.attr = 1
456456

457457
a = A()
458-
self.assertEqual(_testcapi.hasattr_string(a, "attr"), True)
459-
self.assertEqual(_testcapi.hasattr_string(a, "noattr"), False)
458+
self.assertEqual(_testcapi.object_hasattrstring(a, b"attr"), 1)
459+
self.assertEqual(_testcapi.object_hasattrstring(a, b"noattr"), 0)
460460
self.assertIsNone(sys.exception())
461461

462462
def testDel(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add the C API test for functions in the Mapping Protocol, the Sequence
2+
Protocol and some functions in the Object Protocol.

Modules/Setup.stdlib.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@
159159
@MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
160160
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
161161
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c
162-
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/unicode.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyos.c _testcapi/immortal.c _testcapi/heaptype_relative.c _testcapi/gc.c
162+
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyos.c _testcapi/immortal.c _testcapi/heaptype_relative.c _testcapi/gc.c
163163
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
164164

165165
# Some testing modules MUST be built as shared libraries.

0 commit comments

Comments
 (0)