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 4a8742a

Browse files
committed
Sequence methods, add sq_item.
1 parent e8a2c03 commit 4a8742a

File tree

3 files changed

+167
-21
lines changed

3 files changed

+167
-21
lines changed

‎doc/sphinx/source/new_types.rst‎

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -806,21 +806,111 @@ Tests are in ``tests/unit/test_c_seqobject.py``:
806806
assert list(obj) == (list(obj_a) * count)
807807
808808
809+
---------------
810+
``sq_item``
811+
---------------
809812

813+
`sq_item`_ gives read access to an indexed member.
810814

815+
.. list-table:: Sequence Methods: ``sq_item``
816+
:widths: 20 80
817+
:header-rows: 0
811818

819+
* - Member
820+
- `sq_item`_
821+
* - Function type
822+
- `ssizeargfunc`_
823+
* - Function signature
824+
- ``PyObject *(*ssizeargfunc)(PyObject*, Py_ssize_t)``
825+
* - Description
826+
- Returns a *new* reference to the n'th item in the sequence.
827+
Negative indexes are handled appropriately.
828+
Used by `PySequence_GetItem()`_.
829+
This is a fairly crucial implementation for a sequence as `PySequence_Check()`_ detects this to decide if the
830+
object is a sequence.
812831

832+
Implementation
833+
--------------
813834

835+
In ``src/cpy/Object/cSeqObject.c``:
814836

837+
.. code-block:: c
815838
839+
/** Returns a new reference to an indexed item in a sequence. */
840+
static PyObject *
841+
SequenceLongObject_sq_item(PyObject *self, Py_ssize_t index) {
842+
Py_ssize_t my_index = index;
843+
if (my_index < 0) {
844+
my_index += SequenceLongObject_sq_length(self);
845+
}
846+
// Corner case example: len(self) == 0 and index < 0
847+
if (my_index < 0 || my_index >= SequenceLongObject_sq_length(self)) {
848+
PyErr_Format(
849+
PyExc_IndexError,
850+
"Index %ld is out of range for length %ld",
851+
index,
852+
SequenceLongObject_sq_length(self)
853+
);
854+
return NULL;
855+
}
856+
return PyLong_FromLong(((SequenceLongObject *) self)->array_long[my_index]);
857+
}
816858
859+
Tests
860+
--------------
817861

862+
Tests are in ``tests/unit/test_c_seqobject.py`` which includes failure modes:
818863

864+
.. code-block:: python
819865
866+
from cPyExtPatt import cSeqObject
820867
868+
@pytest.mark.parametrize(
869+
'initial_sequence, index, expected',
870+
(
871+
(
872+
[7, 4, 1, ], 0, 7,
873+
),
874+
(
875+
[7, 4, 1, ], 1, 4,
876+
),
877+
(
878+
[7, 4, 1, ], 2, 1,
879+
),
880+
(
881+
[7, 4, 1, ], -1, 1,
882+
),
883+
(
884+
[7, 4, 1, ], -2, 4,
885+
),
886+
(
887+
[7, 4, 1, ], -3, 7,
888+
),
889+
)
890+
)
891+
def test_SequenceLongObject_item(initial_sequence, index, expected):
892+
obj = cSeqObject.SequenceLongObject(initial_sequence)
893+
assert obj[index] == expected
821894
822-
823-
895+
@pytest.mark.parametrize(
896+
'initial_sequence, index, expected',
897+
(
898+
(
899+
[], 0, 'Index 0 is out of range for length 0',
900+
),
901+
(
902+
[], -1, 'Index -1 is out of range for length 0',
903+
),
904+
(
905+
[1, ], 2, 'Index 2 is out of range for length 1',
906+
),
907+
)
908+
)
909+
def test_SequenceLongObject_item_raises(initial_sequence, index, expected):
910+
obj = cSeqObject.SequenceLongObject(initial_sequence)
911+
with pytest.raises(IndexError) as err:
912+
obj[index]
913+
assert err.value.args[0] == expected
824914
825915
826916

‎src/cpy/Object/cSeqObject.c‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,14 +189,21 @@ SequenceLongObject_sq_repeat(PyObject *self, Py_ssize_t count) {
189189
return ret;
190190
}
191191

192+
/**
193+
* Returns a new reference to an indexed item in a sequence.
194+
* @param self
195+
* @param index
196+
* @return
197+
*/
192198
static PyObject *
193199
SequenceLongObject_sq_item(PyObject *self, Py_ssize_t index) {
194200
// fprintf(stdout, "%s(): index=%zd\n", __FUNCTION__, index);
195201
Py_ssize_t my_index = index;
196202
if (my_index < 0) {
197203
my_index += SequenceLongObject_sq_length(self);
198204
}
199-
if (my_index >= SequenceLongObject_sq_length(self)) {
205+
// Corner case example: len(self) == 0 and index < 0
206+
if (my_index < 0 || my_index >= SequenceLongObject_sq_length(self)) {
200207
// fprintf(stdout, "%s(): index=%zd\n", __FUNCTION__, index);
201208
PyErr_Format(
202209
PyExc_IndexError,

‎tests/unit/test_c_seqobject.py‎

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,24 +67,24 @@ def test_SequenceLongObject_concat():
6767
@pytest.mark.parametrize(
6868
'initial_sequence, count, expected',
6969
(
70-
(
71-
[], 1, [],
72-
),
73-
(
74-
[7, 4, 1, ], 0, [],
75-
),
76-
(
77-
[7, 4, 1, ], -1, [],
78-
),
79-
(
80-
[7, 4, 1, ], 1, [7, 4, 1, ],
81-
),
82-
(
83-
[7, 4, 1, ], 2, [7, 4, 1, 7, 4, 1, ],
84-
),
85-
(
86-
[7, 4, 1, ], 3, [7, 4, 1, 7, 4, 1, 7, 4, 1, ],
87-
),
70+
(
71+
[], 1, [],
72+
),
73+
(
74+
[7, 4, 1, ], 0, [],
75+
),
76+
(
77+
[7, 4, 1, ], -1, [],
78+
),
79+
(
80+
[7, 4, 1, ], 1, [7, 4, 1, ],
81+
),
82+
(
83+
[7, 4, 1, ], 2, [7, 4, 1, 7, 4, 1, ],
84+
),
85+
(
86+
[7, 4, 1, ], 3, [7, 4, 1, 7, 4, 1, 7, 4, 1, ],
87+
),
8888
)
8989
)
9090
def test_SequenceLongObject_repeat(initial_sequence, count, expected):
@@ -95,6 +95,55 @@ def test_SequenceLongObject_repeat(initial_sequence, count, expected):
9595
assert list(obj) == expected
9696
assert list(obj) == (list(obj_a) * count)
9797

98+
99+
@pytest.mark.parametrize(
100+
'initial_sequence, index, expected',
101+
(
102+
(
103+
[7, 4, 1, ], 0, 7,
104+
),
105+
(
106+
[7, 4, 1, ], 1, 4,
107+
),
108+
(
109+
[7, 4, 1, ], 2, 1,
110+
),
111+
(
112+
[7, 4, 1, ], -1, 1,
113+
),
114+
(
115+
[7, 4, 1, ], -2, 4,
116+
),
117+
(
118+
[7, 4, 1, ], -3, 7,
119+
),
120+
)
121+
)
122+
def test_SequenceLongObject_item(initial_sequence, index, expected):
123+
obj = cSeqObject.SequenceLongObject(initial_sequence)
124+
assert obj[index] == expected
125+
126+
127+
@pytest.mark.parametrize(
128+
'initial_sequence, index, expected',
129+
(
130+
(
131+
[], 0, 'Index 0 is out of range for length 0',
132+
),
133+
(
134+
[], -1, 'Index -1 is out of range for length 0',
135+
),
136+
(
137+
[1, ], 2, 'Index 2 is out of range for length 1',
138+
),
139+
)
140+
)
141+
def test_SequenceLongObject_item_raises(initial_sequence, index, expected):
142+
obj = cSeqObject.SequenceLongObject(initial_sequence)
143+
with pytest.raises(IndexError) as err:
144+
obj[index]
145+
assert err.value.args[0] == expected
146+
98147
# @pytest.mark.skipif(not (sys.version_info.minor < 7), reason='Python < 3.7')
99148
# def test_str_dir_pre_37():
100149
# s = cObject.Str()

0 commit comments

Comments
(0)

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