Skip to content

Commit c1c4c18

Browse files
authored
gh-114258: Use Argument Clinic for __getitem__ (gh-160068)
1 parent 03864a2 commit c1c4c18

15 files changed

Lines changed: 250 additions & 136 deletions

File tree

‎Lib/test/test_clinic.py‎

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from libclinic.return_converters import return_converters, int_return_converter
3535
from libclinic.block_parser import Block, BlockParser
3636
from libclinic.codegen import BlockPrinter, Destination
37-
from libclinic.dsl_parser import DSLParser, unsupported_special_methods
37+
from libclinic.dsl_parser import DSLParser
3838
from libclinic.slots import SlotSpec, SLOTS
3939
from libclinic.cli import parse_file, Clinic
4040

@@ -3368,8 +3368,8 @@ class Foo "FooObject *" ""
33683368
self.assertIn("METH_COEXIST", function.methoddef_flags)
33693369

33703370
def test_slot_parameters(self):
3371-
# __getitem__ is not supported yet; its parameter gives the slot
3372-
# (Py_ssize_t for sq_item, object for mp_subscript) and is not parsed.
3371+
# The parameter of __getitem__ gives the slot (Py_ssize_t for
3372+
# sq_item, object for mp_subscript) and is not parsed.
33733373
block = """
33743374
module foo
33753375
class Foo "FooObject *" ""
@@ -3383,21 +3383,17 @@ class Foo "FooObject *" ""
33833383
("Foo.__getitem__\n key: object = None\n /",
33843384
"The parameters of '__getitem__' cannot have a default value"),
33853385
]
3386-
supported = unsupported_special_methods - {'__getitem__'}
3387-
with (mock.patch.dict(SLOTS, {'__getitem__': SlotSpec(return_converter='object')}),
3388-
mock.patch.object(libclinic.dsl_parser,
3389-
'unsupported_special_methods', supported)):
3390-
for converter in "Py_ssize_t", "object":
3391-
with self.subTest(converter=converter):
3392-
function = self.parse_function(
3393-
block.format(converter=converter),
3394-
signatures_in_block=3, function_index=2)
3395-
self.assertIs(function.kind, FunctionKind.SLOT)
3396-
self.assertEqual(list(function.parameters), ["self", "key"])
3397-
for body, err in errors:
3398-
with self.subTest(block=body):
3399-
body = 'class Foo "FooObject *" "&Foo_Type"\n' + body
3400-
self.expect_failure(body, err)
3386+
for converter in ["Py_ssize_t", "object"]:
3387+
with self.subTest(converter=converter):
3388+
function = self.parse_function(
3389+
block.format(converter=converter),
3390+
signatures_in_block=3, function_index=2)
3391+
self.assertIs(function.kind, FunctionKind.SLOT)
3392+
self.assertEqual(list(function.parameters), ["self", "key"])
3393+
for body, err in errors:
3394+
with self.subTest(block=body):
3395+
body = 'class Foo "FooObject *" "&Foo_Type"\n' + body
3396+
self.expect_failure(body, err)
34013397

34023398
def test_slot_errors(self):
34033399
cases = [

‎Modules/_collectionsmodule.c‎

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,8 +1376,17 @@ valid_index(Py_ssize_t i, Py_ssize_t limit)
13761376
return (size_t) i < (size_t) limit;
13771377
}
13781378

1379+
/*[clinic input]
1380+
@critical_section
1381+
_collections.deque.__getitem__ as deque_item
1382+
deque: dequeobject
1383+
i: Py_ssize_t
1384+
/
1385+
[clinic start generated code]*/
1386+
13791387
static PyObject *
1380-
deque_item_lock_held(dequeobject *deque, Py_ssize_t i)
1388+
deque_item_impl(dequeobject *deque, Py_ssize_t i)
1389+
/*[clinic end generated code: output=52e62af1427d61ef input=89f14f06b29122a1]*/
13811390
{
13821391
block *b;
13831392
PyObject *item;
@@ -1415,17 +1424,6 @@ deque_item_lock_held(dequeobject *deque, Py_ssize_t i)
14151424
return Py_NewRef(item);
14161425
}
14171426

1418-
static PyObject *
1419-
deque_item(PyObject *self, Py_ssize_t i)
1420-
{
1421-
dequeobject *deque = dequeobject_CAST(self);
1422-
PyObject *result;
1423-
Py_BEGIN_CRITICAL_SECTION(deque);
1424-
result = deque_item_lock_held(deque, i);
1425-
Py_END_CRITICAL_SECTION();
1426-
return result;
1427-
}
1428-
14291427
static int
14301428
deque_del_item(dequeobject *deque, Py_ssize_t i)
14311429
{

‎Modules/_ctypes/_ctypes.c‎

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5026,8 +5026,17 @@ Array_init(PyObject *self, PyObject *args, PyObject *kw)
50265026
return 0;
50275027
}
50285028

5029+
/*[clinic input]
5030+
@critical_section
5031+
_ctypes.Array.__getitem__ as Array_item
5032+
myself: self
5033+
index: Py_ssize_t
5034+
/
5035+
[clinic start generated code]*/
5036+
50295037
static PyObject *
5030-
Array_item_lock_held(PyObject *myself, Py_ssize_t index)
5038+
Array_item_impl(PyObject *myself, Py_ssize_t index)
5039+
/*[clinic end generated code: output=d038162d727d7d9b input=68fa9889c77bb8c9]*/
50315040
{
50325041
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(myself);
50335042

@@ -5056,18 +5065,17 @@ Array_item_lock_held(PyObject *myself, Py_ssize_t index)
50565065
index, size, self->b_ptr + offset);
50575066
}
50585067

5059-
static PyObject *
5060-
Array_item(PyObject *myself, Py_ssize_t index)
5061-
{
5062-
PyObject *result;
5063-
Py_BEGIN_CRITICAL_SECTION(myself);
5064-
result = Array_item_lock_held(myself, index);
5065-
Py_END_CRITICAL_SECTION();
5066-
return result;
5067-
}
5068+
/*[clinic input]
5069+
@critical_section
5070+
_ctypes.Array.__getitem__ as Array_subscript
5071+
myself: self
5072+
item: object
5073+
/
5074+
[clinic start generated code]*/
50685075

50695076
static PyObject *
5070-
Array_subscript_lock_held(PyObject *myself, PyObject *item)
5077+
Array_subscript_impl(PyObject *myself, PyObject *item)
5078+
/*[clinic end generated code: output=5c88d612ad5c8a1a input=510935495a857cac]*/
50715079
{
50725080
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(myself);
50735081

@@ -5080,7 +5088,7 @@ Array_subscript_lock_held(PyObject *myself, PyObject *item)
50805088
return NULL;
50815089
if (i < 0)
50825090
i += self->b_length;
5083-
return Array_item_lock_held(myself, i);
5091+
return Array_item_impl(myself, i);
50845092
}
50855093
else if (PySlice_Check(item)) {
50865094
PyObject *proto;
@@ -5168,7 +5176,7 @@ Array_subscript_lock_held(PyObject *myself, PyObject *item)
51685176

51695177
for (cur = start, i = 0; i < slicelen;
51705178
cur += step, i++) {
5171-
PyObject *v = Array_item_lock_held(myself, cur);
5179+
PyObject *v = Array_item_impl(myself, cur);
51725180
if (v == NULL) {
51735181
Py_DECREF(np);
51745182
return NULL;
@@ -5185,16 +5193,6 @@ Array_subscript_lock_held(PyObject *myself, PyObject *item)
51855193
}
51865194

51875195

5188-
static PyObject *
5189-
Array_subscript(PyObject *myself, PyObject *item)
5190-
{
5191-
PyObject *result;
5192-
Py_BEGIN_CRITICAL_SECTION(myself);
5193-
result = Array_subscript_lock_held(myself, item);
5194-
Py_END_CRITICAL_SECTION();
5195-
return result;
5196-
}
5197-
51985196
/*[clinic input]
51995197
@critical_section
52005198
_ctypes.Array.__setitem__ as Array_ass_item
@@ -5577,8 +5575,22 @@ static PyType_Spec pycsimple_spec = {
55775575
/*
55785576
PyCPointer_Type
55795577
*/
5578+
/*[clinic input]
5579+
class _ctypes._Pointer "PyObject *" "clinic_state()->PyCPointer_Type"
5580+
[clinic start generated code]*/
5581+
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=452695db70aa7c3e]*/
5582+
5583+
/*[clinic input]
5584+
@critical_section
5585+
_ctypes._Pointer.__getitem__ as Pointer_item
5586+
myself: self
5587+
index: Py_ssize_t
5588+
/
5589+
[clinic start generated code]*/
5590+
55805591
static PyObject *
5581-
Pointer_item_lock_held(PyObject *myself, Py_ssize_t index)
5592+
Pointer_item_impl(PyObject *myself, Py_ssize_t index)
5593+
/*[clinic end generated code: output=4ae9d566e8038853 input=17943427cd04ed08]*/
55825594
{
55835595
CDataObject *self = _CDataObject_CAST(myself);
55845596
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
@@ -5617,21 +5629,6 @@ Pointer_item_lock_held(PyObject *myself, Py_ssize_t index)
56175629
index, size, (char *)((char *)deref + offset));
56185630
}
56195631

5620-
static PyObject *
5621-
Pointer_item(PyObject *self, Py_ssize_t index)
5622-
{
5623-
PyObject *res;
5624-
Py_BEGIN_CRITICAL_SECTION(self);
5625-
res = Pointer_item_lock_held(self, index);
5626-
Py_END_CRITICAL_SECTION();
5627-
return res;
5628-
}
5629-
5630-
/*[clinic input]
5631-
class _ctypes._Pointer "PyObject *" "clinic_state()->PyCPointer_Type"
5632-
[clinic start generated code]*/
5633-
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=452695db70aa7c3e]*/
5634-
56355632
/*[clinic input]
56365633
@critical_section
56375634
_ctypes._Pointer.__setitem__ as Pointer_ass_item
@@ -5824,7 +5821,7 @@ copy_pointer_to_list_lock_held(PyObject *myself, PyObject *np, Py_ssize_t len,
58245821
Py_ssize_t i;
58255822
size_t cur;
58265823
for (cur = start, i = 0; i < len; cur += step, i++) {
5827-
PyObject *v = Pointer_item_lock_held(myself, cur);
5824+
PyObject *v = Pointer_item_impl(myself, cur);
58285825
if (!v) {
58295826
return -1;
58305827
}

‎Modules/_ctypes/clinic/_ctypes.c.h‎

Lines changed: 46 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Modules/_dbmmodule.c‎

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,20 @@ dbm_bool(PyObject *self)
187187
return result;
188188
}
189189

190+
/*[clinic input]
191+
@critical_section
192+
_dbm.dbm.__getitem__ as dbm_subscript
193+
key: object
194+
/
195+
[clinic start generated code]*/
196+
190197
static PyObject *
191-
dbm_subscript_lock_held(PyObject *self, PyObject *key)
198+
dbm_subscript_impl(dbmobject *self, PyObject *key)
199+
/*[clinic end generated code: output=6278465f3ff37eaa input=e748b684a0870527]*/
192200
{
193201
datum drec, krec;
194202
Py_ssize_t tmp_size;
195-
dbmobject *dp = dbmobject_CAST(self);
203+
dbmobject *dp = self;
196204
_dbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
197205
assert(state != NULL);
198206
if (!PyArg_Parse(key, "s#", &krec.dptr, &tmp_size)) {
@@ -214,16 +222,6 @@ dbm_subscript_lock_held(PyObject *self, PyObject *key)
214222
return PyBytes_FromStringAndSize(drec.dptr, drec.dsize);
215223
}
216224

217-
static PyObject *
218-
dbm_subscript(PyObject *self, PyObject *key)
219-
{
220-
PyObject *result;
221-
Py_BEGIN_CRITICAL_SECTION(self);
222-
result = dbm_subscript_lock_held(self, key);
223-
Py_END_CRITICAL_SECTION();
224-
return result;
225-
}
226-
227225
/*[clinic input]
228226
@critical_section
229227
_dbm.dbm.__setitem__ as dbm_ass_sub

‎Modules/_gdbmmodule.c‎

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,20 @@ parse_datum(PyObject *o, datum *d, const char *failmsg)
250250
return 1;
251251
}
252252

253+
/*[clinic input]
254+
@critical_section
255+
_gdbm.gdbm.__getitem__ as gdbm_subscript
256+
key: object
257+
/
258+
[clinic start generated code]*/
259+
253260
static PyObject *
254-
gdbm_subscript_lock_held(PyObject *op, PyObject *key)
261+
gdbm_subscript_impl(gdbmobject *self, PyObject *key)
262+
/*[clinic end generated code: output=e96388d53678e967 input=8324d90d97ae98f0]*/
255263
{
256264
PyObject *v;
257265
datum drec, krec;
258-
gdbmobject *dp = _gdbmobject_CAST(op);
266+
gdbmobject *dp = self;
259267
_gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
260268

261269
if (!parse_datum(key, &krec, NULL)) {
@@ -276,16 +284,6 @@ gdbm_subscript_lock_held(PyObject *op, PyObject *key)
276284
return v;
277285
}
278286

279-
static PyObject *
280-
gdbm_subscript(PyObject *op, PyObject *key)
281-
{
282-
PyObject *result;
283-
Py_BEGIN_CRITICAL_SECTION(op);
284-
result = gdbm_subscript_lock_held(op, key);
285-
Py_END_CRITICAL_SECTION();
286-
return result;
287-
}
288-
289287
/*[clinic input]
290288
_gdbm.gdbm.get
291289

‎Modules/clinic/_collectionsmodule.c.h‎

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)