Skip to content

Commit 5ba72a9

Browse files
authored
Merge pull request python-pillow#8800 from radarhere/path_lists
Allow coords to be sequence of lists
1 parent 5e9eea1 commit 5ba72a9

File tree

3 files changed

+57
-42
lines changed

3 files changed

+57
-42
lines changed

Tests/test_imagedraw.py

+4
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,17 @@
3939
POINTS = (
4040
((10, 10), (20, 40), (30, 30)),
4141
[(10, 10), (20, 40), (30, 30)],
42+
([10, 10], [20, 40], [30, 30]),
43+
[[10, 10], [20, 40], [30, 30]],
4244
(10, 10, 20, 40, 30, 30),
4345
[10, 10, 20, 40, 30, 30],
4446
)
4547

4648
KITE_POINTS = (
4749
((10, 50), (70, 10), (90, 50), (70, 90), (10, 50)),
4850
[(10, 50), (70, 10), (90, 50), (70, 90), (10, 50)],
51+
([10, 50], [70, 10], [90, 50], [70, 90], [10, 50]),
52+
[[10, 50], [70, 10], [90, 50], [70, 90], [10, 50]],
4953
)
5054

5155

Tests/test_imagepath.py

+3-14
Original file line numberDiff line numberDiff line change
@@ -68,21 +68,10 @@ def test_path_constructors(
6868
assert list(p) == [(0.0, 1.0)]
6969

7070

71-
@pytest.mark.parametrize(
72-
"coords",
73-
(
74-
("a", "b"),
75-
([0, 1],),
76-
[[0, 1]],
77-
([0.0, 1.0],),
78-
[[0.0, 1.0]],
79-
),
80-
)
81-
def test_invalid_path_constructors(
82-
coords: tuple[str, str] | Sequence[Sequence[int]],
83-
) -> None:
71+
def test_invalid_path_constructors() -> None:
72+
# Arrange / Act
8473
with pytest.raises(ValueError, match="incorrect coordinate type"):
85-
ImagePath.Path(coords)
74+
ImagePath.Path(("a", "b"))
8675

8776

8877
@pytest.mark.parametrize(

src/path.c

+50-28
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,39 @@ path_dealloc(PyPathObject *path) {
109109

110110
#define PyPath_Check(op) (Py_TYPE(op) == &PyPathType)
111111

112+
static int
113+
assign_item_to_array(double *xy, Py_ssize_t j, PyObject *op) {
114+
if (PyFloat_Check(op)) {
115+
xy[j++] = PyFloat_AS_DOUBLE(op);
116+
} else if (PyLong_Check(op)) {
117+
xy[j++] = (float)PyLong_AS_LONG(op);
118+
} else if (PyNumber_Check(op)) {
119+
xy[j++] = PyFloat_AsDouble(op);
120+
} else if (PyList_Check(op)) {
121+
for (int k = 0; k < 2; k++) {
122+
PyObject *op1 = PyList_GetItemRef(op, k);
123+
if (op1 == NULL) {
124+
return -1;
125+
}
126+
j = assign_item_to_array(xy, j, op1);
127+
Py_DECREF(op1);
128+
if (j == -1) {
129+
return -1;
130+
}
131+
}
132+
} else {
133+
double x, y;
134+
if (PyArg_ParseTuple(op, "dd", &x, &y)) {
135+
xy[j++] = x;
136+
xy[j++] = y;
137+
} else {
138+
PyErr_SetString(PyExc_ValueError, "incorrect coordinate type");
139+
return -1;
140+
}
141+
}
142+
return j;
143+
}
144+
112145
Py_ssize_t
113146
PyPath_Flatten(PyObject *data, double **pxy) {
114147
Py_ssize_t i, j, n;
@@ -164,48 +197,32 @@ PyPath_Flatten(PyObject *data, double **pxy) {
164197
return -1;
165198
}
166199

167-
#define assign_item_to_array(op, decref) \
168-
if (PyFloat_Check(op)) { \
169-
xy[j++] = PyFloat_AS_DOUBLE(op); \
170-
} else if (PyLong_Check(op)) { \
171-
xy[j++] = (float)PyLong_AS_LONG(op); \
172-
} else if (PyNumber_Check(op)) { \
173-
xy[j++] = PyFloat_AsDouble(op); \
174-
} else if (PyArg_ParseTuple(op, "dd", &x, &y)) { \
175-
xy[j++] = x; \
176-
xy[j++] = y; \
177-
} else { \
178-
PyErr_SetString(PyExc_ValueError, "incorrect coordinate type"); \
179-
if (decref) { \
180-
Py_DECREF(op); \
181-
} \
182-
free(xy); \
183-
return -1; \
184-
} \
185-
if (decref) { \
186-
Py_DECREF(op); \
187-
}
188-
189200
/* Copy table to path array */
190201
if (PyList_Check(data)) {
191202
for (i = 0; i < n; i++) {
192-
double x, y;
193203
PyObject *op = PyList_GetItemRef(data, i);
194204
if (op == NULL) {
195205
free(xy);
196206
return -1;
197207
}
198-
assign_item_to_array(op, 1);
208+
j = assign_item_to_array(xy, j, op);
209+
Py_DECREF(op);
210+
if (j == -1) {
211+
free(xy);
212+
return -1;
213+
}
199214
}
200215
} else if (PyTuple_Check(data)) {
201216
for (i = 0; i < n; i++) {
202-
double x, y;
203217
PyObject *op = PyTuple_GET_ITEM(data, i);
204-
assign_item_to_array(op, 0);
218+
j = assign_item_to_array(xy, j, op);
219+
if (j == -1) {
220+
free(xy);
221+
return -1;
222+
}
205223
}
206224
} else {
207225
for (i = 0; i < n; i++) {
208-
double x, y;
209226
PyObject *op = PySequence_GetItem(data, i);
210227
if (!op) {
211228
/* treat IndexError as end of sequence */
@@ -217,7 +234,12 @@ PyPath_Flatten(PyObject *data, double **pxy) {
217234
return -1;
218235
}
219236
}
220-
assign_item_to_array(op, 1);
237+
j = assign_item_to_array(xy, j, op);
238+
Py_DECREF(op);
239+
if (j == -1) {
240+
free(xy);
241+
return -1;
242+
}
221243
}
222244
}
223245

0 commit comments

Comments
 (0)