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 e8a2c03

Browse files
committed
Sequence methods, add repeat().
1 parent e774c9b commit e8a2c03

File tree

3 files changed

+198
-4
lines changed

3 files changed

+198
-4
lines changed

‎doc/sphinx/source/new_types.rst‎

Lines changed: 119 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ Tests are in ``tests/unit/test_c_seqobject.py``:
633633
- ``PyObject *(*binaryfunc)(PyObject*, PyObject*)``
634634
* - Description
635635
- Takes two sequences and returns a new third one with the first and second concatenated.
636-
This is used by the ``+`` operator.
636+
This is used by the ``+`` Python operator and the `PySequence_Concat()`_ C API.
637637

638638
Implementation
639639
--------------
@@ -690,7 +690,6 @@ In ``src/cpy/Object/cSeqObject.c``:
690690
return ret;
691691
}
692692
693-
694693
Tests
695694
--------------
696695

@@ -708,9 +707,126 @@ Tests are in ``tests/unit/test_c_seqobject.py``:
708707
assert len(obj) == 6
709708
assert list(obj) == [7, 4, 1, ] + [70, 40, 100, ]
710709
710+
---------------
711+
``sq_repeat``
712+
---------------
713+
714+
.. list-table:: Sequence Methods: ``sq_concat``
715+
:widths: 20 80
716+
:header-rows: 0
717+
718+
* - Member
719+
- `sq_repeat`_
720+
* - Function type
721+
- `ssizeargfunc`_
722+
* - Function signature
723+
- ``PyObject *(*ssizeargfunc)(PyObject*, Py_ssize_t)``
724+
* - Description
725+
- Returns a new sequence with the old one repeated the given number of times times.
726+
This is used by the ``*`` Python operator and the `PySequence_Repeat()`_ C API.
727+
728+
Implementation
729+
--------------
730+
731+
The implementation is fairly straightforward in ``src/cpy/Object/cSeqObject.c``.
732+
Note that ``count`` can be zero or negative:
733+
734+
.. code-block:: c
735+
736+
/** Return a new sequence which contains the old one repeated count times. */
737+
static PyObject *
738+
SequenceLongObject_sq_repeat(PyObject *self, Py_ssize_t count) {
739+
PyObject *ret = SequenceLongObject_new(&SequenceLongObjectType, NULL, NULL);
740+
if (!ret) {
741+
assert(PyErr_Occurred());
742+
return NULL;
743+
}
744+
assert(ret != self);
745+
if (((SequenceLongObject *) self)->size > 0 && count > 0) {
746+
/* For convenience. */
747+
SequenceLongObject *self_as_slo = (SequenceLongObject *) self;
748+
SequenceLongObject *ret_as_slo = (SequenceLongObject *) ret;
749+
ret_as_slo->size = self_as_slo->size * count;
750+
assert(ret_as_slo->size > 0);
751+
ret_as_slo->array_long = malloc(ret_as_slo->size * sizeof(long));
752+
if (!ret_as_slo->array_long) {
753+
PyErr_Format(PyExc_MemoryError, "%s(): Can not create new object.", __FUNCTION__);
754+
Py_DECREF(ret);
755+
return NULL;
756+
}
757+
Py_ssize_t ret_index = 0;
758+
for (Py_ssize_t i = 0; i < count; ++i) {
759+
for (Py_ssize_t j = 0; j < self_as_slo->size; ++j) {
760+
ret_as_slo->array_long[ret_index] = self_as_slo->array_long[j];
761+
++ret_index;
762+
}
763+
}
764+
} else {
765+
/* Empty sequence. */
766+
}
767+
return ret;
768+
}
769+
770+
Tests
771+
--------------
772+
773+
Tests are in ``tests/unit/test_c_seqobject.py``:
774+
775+
.. code-block:: python
776+
777+
@pytest.mark.parametrize(
778+
'initial_sequence, count, expected',
779+
(
780+
(
781+
[], 1, [],
782+
),
783+
(
784+
[7, 4, 1, ], 0, [],
785+
),
786+
(
787+
[7, 4, 1, ], -1, [],
788+
),
789+
(
790+
[7, 4, 1, ], 1, [7, 4, 1, ],
791+
),
792+
(
793+
[7, 4, 1, ], 2, [7, 4, 1, 7, 4, 1, ],
794+
),
795+
(
796+
[7, 4, 1, ], 3, [7, 4, 1, 7, 4, 1, 7, 4, 1, ],
797+
),
798+
)
799+
)
800+
def test_SequenceLongObject_repeat(initial_sequence, count, expected):
801+
obj_a = cSeqObject.SequenceLongObject(initial_sequence)
802+
obj = obj_a * count
803+
print()
804+
assert id(obj_a) != id(obj)
805+
assert list(obj) == expected
806+
assert list(obj) == (list(obj_a) * count)
807+
808+
809+
810+
811+
812+
813+
814+
815+
816+
817+
818+
819+
820+
821+
822+
823+
824+
825+
826+
711827
712828
713-
TOOD:
829+
TODO:
714830

715831
====================================
716832
TODOs:

‎src/cpy/Object/cSeqObject.c‎

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,50 @@ SequenceLongObject_sq_concat(PyObject *self, PyObject *other) {
145145
return ret;
146146
}
147147

148+
/**
149+
* Return a new sequence which contains the old one repeated count times.
150+
* @param self
151+
* @param count
152+
* @return
153+
*/
154+
static PyObject *
155+
SequenceLongObject_sq_repeat(PyObject *self, Py_ssize_t count) {
156+
PyObject *ret = SequenceLongObject_new(&SequenceLongObjectType, NULL, NULL);
157+
if (!ret) {
158+
assert(PyErr_Occurred());
159+
return NULL;
160+
}
161+
assert(ret != self);
162+
if (((SequenceLongObject *) self)->size > 0 && count > 0) {
163+
/* For convenience. */
164+
SequenceLongObject *self_as_slo = (SequenceLongObject *) self;
165+
SequenceLongObject *ret_as_slo = (SequenceLongObject *) ret;
166+
ret_as_slo->size = self_as_slo->size * count;
167+
assert(ret_as_slo->size > 0);
168+
ret_as_slo->array_long = malloc(ret_as_slo->size * sizeof(long));
169+
if (!ret_as_slo->array_long) {
170+
PyErr_Format(PyExc_MemoryError, "%s(): Can not create new object.", __FUNCTION__);
171+
Py_DECREF(ret);
172+
return NULL;
173+
}
174+
Py_ssize_t ret_index = 0;
175+
for (Py_ssize_t i = 0; i < count; ++i) {
176+
// fprintf(stdout, "%s(): Setting %p Count %zd\n", __FUNCTION__, (void *) ret, i);
177+
for (Py_ssize_t j = 0; j < self_as_slo->size; ++j) {
178+
// fprintf(
179+
// stdout, "%s(): Setting %p [%zd] to %zd\n",
180+
// __FUNCTION__, (void *) ret, ret_index, self_as_slo->array_long[j]
181+
// );
182+
ret_as_slo->array_long[ret_index] = self_as_slo->array_long[j];
183+
++ret_index;
184+
}
185+
}
186+
} else {
187+
/* Empty sequence. */
188+
}
189+
return ret;
190+
}
191+
148192
static PyObject *
149193
SequenceLongObject_sq_item(PyObject *self, Py_ssize_t index) {
150194
// fprintf(stdout, "%s(): index=%zd\n", __FUNCTION__, index);
@@ -168,7 +212,7 @@ SequenceLongObject_sq_item(PyObject *self, Py_ssize_t index) {
168212
PySequenceMethods SequenceLongObject_sequence_methods = {
169213
.sq_length = &SequenceLongObject_sq_length,
170214
.sq_concat = &SequenceLongObject_sq_concat,
171-
.sq_repeat = NULL,
215+
.sq_repeat = &SequenceLongObject_sq_repeat,
172216
.sq_item = &SequenceLongObject_sq_item,
173217
.sq_ass_item = NULL,
174218
.sq_contains = NULL,

‎tests/unit/test_c_seqobject.py‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ def test_SequenceLongObject_dir():
3131
'__le__',
3232
'__len__',
3333
'__lt__',
34+
'__mul__',
3435
'__ne__',
3536
'__new__',
3637
'__reduce__',
3738
'__reduce_ex__',
3839
'__repr__',
40+
'__rmul__',
3941
'__setattr__',
4042
'__sizeof__',
4143
'__str__',
@@ -61,6 +63,38 @@ def test_SequenceLongObject_concat():
6163
assert len(obj) == 6
6264
assert list(obj) == [7, 4, 1, ] + [70, 40, 100, ]
6365

66+
67+
@pytest.mark.parametrize(
68+
'initial_sequence, count, expected',
69+
(
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+
),
88+
)
89+
)
90+
def test_SequenceLongObject_repeat(initial_sequence, count, expected):
91+
obj_a = cSeqObject.SequenceLongObject(initial_sequence)
92+
obj = obj_a * count
93+
print()
94+
assert id(obj_a) != id(obj)
95+
assert list(obj) == expected
96+
assert list(obj) == (list(obj_a) * count)
97+
6498
# @pytest.mark.skipif(not (sys.version_info.minor < 7), reason='Python < 3.7')
6599
# def test_str_dir_pre_37():
66100
# s = cObject.Str()

0 commit comments

Comments
(0)

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