Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8acaa67

Browse files
committed
Add sq_contains, test and documentation.
1 parent 1b25e8e commit 8acaa67

File tree

3 files changed

+138
-2
lines changed

3 files changed

+138
-2
lines changed

‎doc/sphinx/source/new_types.rst

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,8 @@ The Sequence Function Table
562562
- ``int (*objobjproc)(PyObject*, PyObject*)``
563563
- Returns non-zero if the sequence contains the given object.
564564
Used by `PySequence_Contains()`_.
565-
This slot may be left to NULL, in this case PySequence_Contains() simply traverses the sequence until it finds a match.
565+
This slot may be left to NULL, in this case PySequence_Contains() simply traverses the sequence until it
566+
finds a match.
566567
* - `sq_inplace_concat`_
567568
- `binaryfunc`_
568569
- ``PyObject *(*binaryfunc)(PyObject*, PyObject*)``
@@ -1157,6 +1158,91 @@ Deleting a value with an out of range index:
11571158
assert err.value.args[0] == expected
11581159
11591160
1161+
-------------------
1162+
``sq_ass_contains``
1163+
-------------------
1164+
1165+
.. list-table:: Sequence Methods: ``sq_ass_contains``
1166+
:widths: 20 80
1167+
:header-rows: 0
1168+
1169+
* - Member
1170+
- `sq_ass_contains`_
1171+
* - Function type
1172+
- `objobjproc`_
1173+
* - Function signature
1174+
- ``int (*objobjproc)(PyObject*, PyObject*)``
1175+
* - Description
1176+
- Returns non-zero if the sequence contains the given object.
1177+
If an item in o is equal to value, return 1, otherwise return 0. On error, return -1.
1178+
This is equivalent to the Python expression ``value in o``.
1179+
Used by `PySequence_Contains()`_.
1180+
This slot may be left to NULL, in this case `PySequence_Contains()`_ simply traverses the sequence until it
1181+
finds a match.
1182+
1183+
Implementation
1184+
--------------
1185+
1186+
In ``src/cpy/Object/cSeqObject.c``:
1187+
1188+
.. code-block:: c
1189+
1190+
/** If an item in self is equal to value, return 1, otherwise return 0.
1191+
* On error, return -1. */
1192+
static int
1193+
SequenceLongObject_sq_contains(PyObject *self, PyObject *value) {
1194+
fprintf(
1195+
stdout, "%s()#%d: self=%p value=%p\n",
1196+
__FUNCTION__, __LINE__, (void *) self, (void *) value
1197+
);
1198+
if (!PyLong_Check(value)) {
1199+
/* Alternates: Could raise TypeError or return -1.
1200+
* Here we act benignly! */
1201+
return 0;
1202+
}
1203+
long c_value = PyLong_AsLong(value);
1204+
/* For convenience. */
1205+
SequenceLongObject *self_as_slo = (SequenceLongObject *) self;
1206+
for (Py_ssize_t i = 0; i < SequenceLongObject_sq_length(self); ++i) {
1207+
if (self_as_slo->array_long[i] == c_value) {
1208+
return 1;
1209+
}
1210+
}
1211+
return 0;
1212+
}
1213+
1214+
.. note::
1215+
1216+
Whilst ``SequenceLongObject_sq_contains()`` returns 0 or 1 Python code such as ``value in obj`` converts this to
1217+
``False`` and ``True`` respectively
1218+
1219+
Tests
1220+
--------------
1221+
1222+
Tests are in ``tests/unit/test_c_seqobject.py``:
1223+
1224+
.. code-block:: python
1225+
1226+
from cPyExtPatt import cSeqObject
1227+
1228+
@pytest.mark.parametrize(
1229+
'initial_sequence, value, expected',
1230+
(
1231+
(
1232+
[7, ], 0, False,
1233+
),
1234+
(
1235+
[7, ], 7, True,
1236+
),
1237+
(
1238+
[1, 4, 7, ], 7, True,
1239+
),
1240+
)
1241+
)
1242+
def test_SequenceLongObject_contains(initial_sequence, value, expected):
1243+
obj = cSeqObject.SequenceLongObject(initial_sequence)
1244+
result = value in obj
1245+
assert result == expected
11601246
11611247
11621248

‎src/cpy/Object/cSeqObject.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,13 +305,41 @@ SequenceLongObject_sq_ass_item(PyObject *self, Py_ssize_t index, PyObject *value
305305
return 0;
306306
}
307307

308+
/**
309+
* If an item in self is equal to value, return 1, otherwise return 0. On error, return -1.
310+
* @param self
311+
* @param value
312+
* @return
313+
*/
314+
static int
315+
SequenceLongObject_sq_contains(PyObject *self, PyObject *value) {
316+
fprintf(
317+
stdout, "%s()#%d: self=%p value=%p\n",
318+
__FUNCTION__, __LINE__, (void *) self, (void *) value
319+
);
320+
if (!PyLong_Check(value)) {
321+
/* Alternates: Could raise TypeError or return -1.
322+
* Here we act benignly! */
323+
return 0;
324+
}
325+
long c_value = PyLong_AsLong(value);
326+
/* For convenience. */
327+
SequenceLongObject *self_as_slo = (SequenceLongObject *) self;
328+
for (Py_ssize_t i = 0; i < SequenceLongObject_sq_length(self); ++i) {
329+
if (self_as_slo->array_long[i] == c_value) {
330+
return 1;
331+
}
332+
}
333+
return 0;
334+
}
335+
308336
static PySequenceMethods SequenceLongObject_sequence_methods = {
309337
.sq_length = (lenfunc)SequenceLongObject_sq_length,
310338
.sq_concat = (binaryfunc)SequenceLongObject_sq_concat,
311339
.sq_repeat = (ssizeargfunc)SequenceLongObject_sq_repeat,
312340
.sq_item = (ssizeargfunc)SequenceLongObject_sq_item,
313341
.sq_ass_item = (ssizeobjargproc)SequenceLongObject_sq_ass_item,
314-
.sq_contains = (objobjproc)NULL,
342+
.sq_contains = (objobjproc)SequenceLongObject_sq_contains,
315343
.sq_inplace_concat = (binaryfunc)NULL,
316344
.sq_inplace_repeat = (ssizeargfunc)NULL,
317345
};

‎tests/unit/test_c_seqobject.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ def test_SequenceLongObject_dir_pre_311():
1616
assert result == [
1717
'__add__',
1818
'__class__',
19+
'__contains__',
1920
'__delattr__',
2021
'__delitem__',
2122
'__dir__',
@@ -53,6 +54,7 @@ def test_SequenceLongObject_dir_311_plus():
5354
assert result == [
5455
'__add__',
5556
'__class__',
57+
'__contains__',
5658
'__delattr__',
5759
'__delitem__',
5860
'__dir__',
@@ -287,6 +289,26 @@ def test_SequenceLongObject_delitem_raises(initial_sequence, index, expected):
287289
del obj[index]
288290
assert err.value.args[0] == expected
289291

292+
293+
@pytest.mark.parametrize(
294+
'initial_sequence, value, expected',
295+
(
296+
(
297+
[7, ], 0, False,
298+
),
299+
(
300+
[7, ], 7, True,
301+
),
302+
(
303+
[1, 4, 7, ], 7, True,
304+
),
305+
)
306+
)
307+
def test_SequenceLongObject_contains(initial_sequence, value, expected):
308+
obj = cSeqObject.SequenceLongObject(initial_sequence)
309+
result = value in obj
310+
assert result == expected
311+
290312
# @pytest.mark.parametrize(
291313
# 'initial_sequence, index, value, expected',
292314
# (

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /