Skip to content

Commit 377659b

Browse files
committed
Finish edit for new_types.rst
1 parent f95b45e commit 377659b

File tree

1 file changed

+68
-139
lines changed

1 file changed

+68
-139
lines changed

doc/sphinx/source/new_types.rst

+68-139
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,8 @@ Emulating Sequence Types
434434

435435
This section describes how to make an object act like a sequence using
436436
`tp_as_sequence <https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_as_sequence>`_.
437-
See also `Sequence Object Structures <https://docs.python.org/3/c-api/typeobj.html#sequence-structs>`_
437+
See also `Sequence Object Structures <https://docs.python.org/3/c-api/typeobj.html#sequence-structs>`_.
438+
This allows your objects to have set and get methods like a list.
438439

439440
As an example here is an extension that can represent a sequence of longs in C with a CPython sequence interface.
440441
The code is in ``src/cpy/Object/cSeqObject.c``.
@@ -674,10 +675,13 @@ In ``src/cpy/Object/cSeqObject.c``:
674675
}
675676
/* For convenience. */
676677
SequenceLongObject *ret_as_slo = (SequenceLongObject *) ret;
677-
ret_as_slo->size = ((SequenceLongObject *) self)->size + ((SequenceLongObject *) other)->size;
678+
ret_as_slo->size = ((SequenceLongObject *) self)->size \
679+
+ ((SequenceLongObject *) other)->size;
678680
ret_as_slo->array_long = malloc(ret_as_slo->size * sizeof(long));
679681
if (!ret_as_slo->array_long) {
680-
PyErr_Format(PyExc_MemoryError, "%s(): Can not create new object.", __FUNCTION__);
682+
PyErr_Format(
683+
PyExc_MemoryError, "%s(): Can not create new object.", __FUNCTION__
684+
);
681685
Py_DECREF(ret);
682686
return NULL;
683687
}
@@ -763,7 +767,9 @@ Note that ``count`` can be zero or negative:
763767
assert(ret_as_slo->size > 0);
764768
ret_as_slo->array_long = malloc(ret_as_slo->size * sizeof(long));
765769
if (!ret_as_slo->array_long) {
766-
PyErr_Format(PyExc_MemoryError, "%s(): Can not create new object.", __FUNCTION__);
770+
PyErr_Format(
771+
PyExc_MemoryError, "%s(): Can not create new object.", __FUNCTION__
772+
);
767773
Py_DECREF(ret);
768774
return NULL;
769775
}
@@ -790,24 +796,12 @@ Tests are in ``tests/unit/test_c_seqobject.py``:
790796
@pytest.mark.parametrize(
791797
'initial_sequence, count, expected',
792798
(
793-
(
794-
[], 1, [],
795-
),
796-
(
797-
[7, 4, 1, ], 0, [],
798-
),
799-
(
800-
[7, 4, 1, ], -1, [],
801-
),
802-
(
803-
[7, 4, 1, ], 1, [7, 4, 1, ],
804-
),
805-
(
806-
[7, 4, 1, ], 2, [7, 4, 1, 7, 4, 1, ],
807-
),
808-
(
809-
[7, 4, 1, ], 3, [7, 4, 1, 7, 4, 1, 7, 4, 1, ],
810-
),
799+
([], 1, [],),
800+
([7, 4, 1, ], 0, [],),
801+
([7, 4, 1, ], -1, [],),
802+
([7, 4, 1, ], 1, [7, 4, 1, ],),
803+
([7, 4, 1, ], 2, [7, 4, 1, 7, 4, 1, ],),
804+
([7, 4, 1, ], 3, [7, 4, 1, 7, 4, 1, 7, 4, 1, ],),
811805
)
812806
)
813807
def test_SequenceLongObject_repeat(initial_sequence, count, expected):
@@ -877,7 +871,7 @@ In ``src/cpy/Object/cSeqObject.c``:
877871
Tests
878872
--------------
879873

880-
Tests are in ``tests/unit/test_c_seqobject.py`` which includes failure modes:
874+
Tests are in ``tests/unit/test_c_seqobject.py``:
881875

882876
.. code-block:: python
883877
@@ -886,42 +880,30 @@ Tests are in ``tests/unit/test_c_seqobject.py`` which includes failure modes:
886880
@pytest.mark.parametrize(
887881
'initial_sequence, index, expected',
888882
(
889-
(
890-
[7, 4, 1, ], 0, 7,
891-
),
892-
(
893-
[7, 4, 1, ], 1, 4,
894-
),
895-
(
896-
[7, 4, 1, ], 2, 1,
897-
),
898-
(
899-
[7, 4, 1, ], -1, 1,
900-
),
901-
(
902-
[7, 4, 1, ], -2, 4,
903-
),
904-
(
905-
[7, 4, 1, ], -3, 7,
906-
),
883+
([7, 4, 1, ], 0, 7,),
884+
([7, 4, 1, ], 1, 4,),
885+
([7, 4, 1, ], 2, 1,),
886+
([7, 4, 1, ], -1, 1,),
887+
([7, 4, 1, ], -2, 4,),
888+
([7, 4, 1, ], -3, 7,),
907889
)
908890
)
909891
def test_SequenceLongObject_item(initial_sequence, index, expected):
910892
obj = cSeqObject.SequenceLongObject(initial_sequence)
911893
assert obj[index] == expected
912894
895+
And failure modes:
896+
897+
.. code-block:: python
898+
899+
from cPyExtPatt import cSeqObject
900+
913901
@pytest.mark.parametrize(
914902
'initial_sequence, index, expected',
915903
(
916-
(
917-
[], 0, 'Index 0 is out of range for length 0',
918-
),
919-
(
920-
[], -1, 'Index -1 is out of range for length 0',
921-
),
922-
(
923-
[1, ], 2, 'Index 2 is out of range for length 1',
924-
),
904+
([], 0, 'Index 0 is out of range for length 0',),
905+
([], -1, 'Index -1 is out of range for length 0',),
906+
([1, ], 2, 'Index 2 is out of range for length 1',),
925907
)
926908
)
927909
def test_SequenceLongObject_item_raises(initial_sequence, index, expected):
@@ -954,6 +936,7 @@ Tests are in ``tests/unit/test_c_seqobject.py`` which includes failure modes:
954936
- ``int (*ssizeobjargproc)(PyObject*, Py_ssize_t, PyObject*)``
955937
* - Description
956938
- Sets the the n'th item in the sequence.
939+
Returns 0 on success, -1 on failure.
957940
If the value is NULL the item is deleted and the sequence concatenated (thus called by `PyObject_DelItem()`_).
958941
Negative indexes are handled appropriately.
959942
Used by `PyObject_SetItem()`_.
@@ -964,7 +947,7 @@ Implementation
964947
.. warning::
965948

966949
There is an undocumented feature when using `sq_ass_item`_ from `PyObject_SetItem()`_ and `PyObject_DelItem()`_
967-
when using negative indexes when the negative index is *out of range*.
950+
when using negative indexes and when the index is *out of range*.
968951

969952
In that case, before the `sq_ass_item`_ function is called the index will have had the sequence length added to it.
970953

@@ -973,7 +956,8 @@ Implementation
973956
If the given index is -5 then the index that the `sq_ass_item`_ function receives is -2.
974957

975958
Thus the slightly odd code below to fix this problem.
976-
Failing to do this will mean out of range errors will not be detected by the `sq_ass_item`_ function.
959+
Failing to do this will mean out of range errors will not be detected by the `sq_ass_item`_ function and any
960+
error message will be wrong.
977961

978962

979963
In ``src/cpy/Object/cSeqObject.c``:
@@ -1038,7 +1022,10 @@ In ``src/cpy/Object/cSeqObject.c``:
10381022
new_array[index_new_array] = self_as_slo->array_long[i];
10391023
}
10401024
/* Copy past the index. */
1041-
for (Py_ssize_t i = my_index + 1; i < self_as_slo->size; ++i, ++index_new_array) {
1025+
for (
1026+
Py_ssize_t i = my_index + 1;
1027+
i < self_as_slo->size;
1028+
++i, ++index_new_array) {
10421029
new_array[index_new_array] = self_as_slo->array_long[i];
10431030
}
10441031
@@ -1063,18 +1050,10 @@ First setting a value:
10631050
@pytest.mark.parametrize(
10641051
'initial_sequence, index, value, expected',
10651052
(
1066-
(
1067-
[7, 4, 1, ], 0, 14, [14, 4, 1, ],
1068-
),
1069-
(
1070-
[7, 4, 1, ], -1, 14, [7, 4, 14, ],
1071-
),
1072-
(
1073-
[7, 4, 1, ], -2, 14, [7, 14, 1, ],
1074-
),
1075-
(
1076-
[7, 4, 1, ], -3, 14, [14, 4, 1, ],
1077-
),
1053+
([7, 4, 1, ], 0, 14, [14, 4, 1, ],),
1054+
([7, 4, 1, ], -1, 14, [7, 4, 14, ],),
1055+
([7, 4, 1, ], -2, 14, [7, 14, 1, ],),
1056+
([7, 4, 1, ], -3, 14, [14, 4, 1, ],),
10781057
)
10791058
)
10801059
def test_SequenceLongObject_setitem(initial_sequence, index, value, expected):
@@ -1092,21 +1071,14 @@ Setting a value with an out of range index:
10921071
@pytest.mark.parametrize(
10931072
'initial_sequence, index, expected',
10941073
(
1095-
(
1096-
[7, 4, 1, ], 3, 'Index 3 is out of range for length 3',
1097-
),
1098-
(
1099-
[7, 4, 1, ], -4, 'Index -4 is out of range for length 3',
1100-
),
1074+
([7, 4, 1, ], 3, 'Index 3 is out of range for length 3',),
1075+
([7, 4, 1, ], -4, 'Index -4 is out of range for length 3',),
11011076
)
11021077
)
11031078
def test_SequenceLongObject_setitem_raises(initial_sequence, index, expected):
1104-
print()
1105-
print(initial_sequence, index, expected)
11061079
obj = cSeqObject.SequenceLongObject(initial_sequence)
11071080
with pytest.raises(IndexError) as err:
11081081
obj[index] = 100
1109-
print(list(obj))
11101082
assert err.value.args[0] == expected
11111083
11121084
@@ -1119,27 +1091,13 @@ Deleting a value:
11191091
@pytest.mark.parametrize(
11201092
'initial_sequence, index, expected',
11211093
(
1122-
(
1123-
[7, ], 0, [],
1124-
),
1125-
(
1126-
[7, ], -1, [],
1127-
),
1128-
(
1129-
[7, 4, 1, ], 1, [7, 1, ],
1130-
),
1131-
(
1132-
[7, 4, ], 0, [4, ],
1133-
),
1134-
(
1135-
[7, 4, 1, ], -1, [7, 4, ],
1136-
),
1137-
(
1138-
[7, 4, 1, ], -2, [7, 1, ],
1139-
),
1140-
(
1141-
[7, 4, 1, ], -3, [4, 1, ],
1142-
),
1094+
([7, ], 0, [],),
1095+
([7, ], -1, [],),
1096+
([7, 4, 1, ], 1, [7, 1, ],),
1097+
([7, 4, ], 0, [4, ],),
1098+
([7, 4, 1, ], -1, [7, 4, ],),
1099+
([7, 4, 1, ], -2, [7, 1, ],),
1100+
([7, 4, 1, ], -3, [4, 1, ],),
11431101
)
11441102
)
11451103
def test_SequenceLongObject_delitem(initial_sequence, index, expected):
@@ -1157,25 +1115,14 @@ Deleting a value with an out of range index:
11571115
@pytest.mark.parametrize(
11581116
'initial_sequence, index, expected',
11591117
(
1160-
(
1161-
[], 0, 'Index 0 is out of range for length 0',
1162-
),
1163-
(
1164-
[], -1, 'Index -1 is out of range for length 0',
1165-
),
1166-
(
1167-
[7, ], 1, 'Index 1 is out of range for length 1',
1168-
),
1169-
(
1170-
[7, ], -3, 'Index -3 is out of range for length 1',
1171-
),
1118+
([], 0, 'Index 0 is out of range for length 0',),
1119+
([], -1, 'Index -1 is out of range for length 0',),
1120+
([7, ], 1, 'Index 1 is out of range for length 1',),
1121+
([7, ], -3, 'Index -3 is out of range for length 1',),
11721122
)
11731123
)
11741124
def test_SequenceLongObject_delitem_raises(initial_sequence, index, expected):
1175-
print()
1176-
print(initial_sequence, index, expected)
11771125
obj = cSeqObject.SequenceLongObject(initial_sequence)
1178-
print(list(obj))
11791126
with pytest.raises(IndexError) as err:
11801127
del obj[index]
11811128
assert err.value.args[0] == expected
@@ -1256,15 +1203,9 @@ Tests are in ``tests/unit/test_c_seqobject.py``:
12561203
@pytest.mark.parametrize(
12571204
'initial_sequence, value, expected',
12581205
(
1259-
(
1260-
[7, ], 0, False,
1261-
),
1262-
(
1263-
[7, ], 7, True,
1264-
),
1265-
(
1266-
[1, 4, 7, ], 7, True,
1267-
),
1206+
([7, ], 0, False,),
1207+
([7, ], 7, True,),
1208+
([1, 4, 7, ], 7, True,),
12681209
)
12691210
)
12701211
def test_SequenceLongObject_contains(initial_sequence, value, expected):
@@ -1361,24 +1302,12 @@ Tests are in ``tests/unit/test_c_seqobject.py``:
13611302
@pytest.mark.parametrize(
13621303
'initial_sequence, count, expected',
13631304
(
1364-
(
1365-
[], 1, [],
1366-
),
1367-
(
1368-
[7, 4, 1, ], 0, [],
1369-
),
1370-
(
1371-
[7, 4, 1, ], -1, [],
1372-
),
1373-
(
1374-
[7, 4, 1, ], 1, [7, 4, 1, ],
1375-
),
1376-
(
1377-
[7, 4, 1, ], 2, [7, 4, 1, 7, 4, 1, ],
1378-
),
1379-
(
1380-
[7, 4, 1, ], 3, [7, 4, 1, 7, 4, 1, 7, 4, 1, ],
1381-
),
1305+
([], 1, [],),
1306+
([7, 4, 1, ], 0, [],),
1307+
([7, 4, 1, ], -1, [],),
1308+
([7, 4, 1, ], 1, [7, 4, 1, ],),
1309+
([7, 4, 1, ], 2, [7, 4, 1, 7, 4, 1, ],),
1310+
([7, 4, 1, ], 3, [7, 4, 1, 7, 4, 1, 7, 4, 1, ],),
13821311
)
13831312
)
13841313
def test_SequenceLongObject_repeat_inplace(initial_sequence, count, expected):
@@ -1407,8 +1336,8 @@ All these functions are gathered together in a `PySequenceMethods`_ table:
14071336
.sq_item = (ssizeargfunc)SequenceLongObject_sq_item,
14081337
.sq_ass_item = (ssizeobjargproc)SequenceLongObject_sq_ass_item,
14091338
.sq_contains = (objobjproc)SequenceLongObject_sq_contains,
1410-
.sq_inplace_concat = (binaryfunc)NULL,
1411-
.sq_inplace_repeat = (ssizeargfunc)NULL,
1339+
.sq_inplace_concat = (binaryfunc)NULL, // Not implemented. See above.
1340+
.sq_inplace_repeat = (ssizeargfunc)NULL, // Not implemented. See above.
14121341
};
14131342
14141343
And the ``SequenceLongObjectType`` type is declared with the ``tp_as_sequence`` field referring to this table:

0 commit comments

Comments
 (0)