Skip to content

Commit 01755d8

Browse files
authored
Merge pull request #1855 from PurityLake/error-key-get-pressed
pgScancodeWrapper now raises exception when trying to use __iter__
2 parents 9c0f4b9 + b51a546 commit 01755d8

File tree

3 files changed

+62
-0
lines changed

3 files changed

+62
-0
lines changed

docs/reST/ref/key.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,11 @@ for ``KMOD_NONE``, which should be compared using equals ``==``). For example:
266266
translate these pushed keys into a fully translated character value. See
267267
the ``pygame.KEYDOWN`` events on the :mod:`pygame.event` queue for this
268268
functionality.
269+
270+
.. versionchanged:: 2.1.4
271+
The collection of bools returned by ``get_pressed`` can not be iterated
272+
over because the indexes of the internal tuple does not correspond to the
273+
keycodes.
269274

270275
.. ## pygame.key.get_pressed ##
271276

src_c/key.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,50 @@ pg_scancodewrapper_subscript(pgScancodeWrapper *self, PyObject *item)
8888
return ret;
8989
}
9090

91+
static PyObject *
92+
pg_iter_raise(PyObject *self)
93+
{
94+
PyErr_SetString(PyExc_TypeError,
95+
"Iterating over key states is not supported");
96+
return NULL;
97+
}
98+
99+
/**
100+
* There is an issue in PyPy that causes __iter__ to be called
101+
* on creation of a ScancodeWrapper. This stops this from
102+
* happening.
103+
*/
104+
#ifdef PYPY_VERSION
105+
static PyObject *
106+
pg_scancodewrapper_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
107+
{
108+
PyObject *tuple = NULL;
109+
Py_ssize_t size = PyTuple_Size(args);
110+
if (size == 1) {
111+
tuple = PyTuple_GET_ITEM(args, 0);
112+
if (PyTuple_Check(tuple)) {
113+
size = PyTuple_Size(tuple);
114+
}
115+
else {
116+
tuple = NULL;
117+
}
118+
}
119+
120+
pgScancodeWrapper *obj =
121+
(pgScancodeWrapper *)(subtype->tp_alloc(subtype, size));
122+
123+
if (obj && tuple) {
124+
for (Py_ssize_t i = 0; i < size; ++i) {
125+
PyObject *item = PyTuple_GET_ITEM((PyObject *)tuple, i);
126+
PyTuple_SET_ITEM((PyObject *)obj, i, item);
127+
}
128+
Py_DECREF(tuple);
129+
}
130+
131+
return (PyObject *)obj;
132+
}
133+
#endif /* PYPY_VERSION */
134+
91135
static PyMappingMethods pg_scancodewrapper_mapping = {
92136
.mp_subscript = (binaryfunc)pg_scancodewrapper_subscript,
93137
};
@@ -106,6 +150,11 @@ static PyTypeObject pgScancodeWrapper_Type = {
106150
PyVarObject_HEAD_INIT(NULL, 0).tp_name = "pygame.key.ScancodeWrapper",
107151
.tp_repr = (reprfunc)pg_scancodewrapper_repr,
108152
.tp_as_mapping = &pg_scancodewrapper_mapping,
153+
.tp_iter = (getiterfunc)pg_iter_raise,
154+
.tp_iternext = (iternextfunc)pg_iter_raise,
155+
#ifdef PYPY_VERSION
156+
.tp_new = pg_scancodewrapper_new,
157+
#endif
109158
.tp_flags =
110159
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_TUPLE_SUBCLASS | Py_TPFLAGS_BASETYPE,
111160
};

test/key_test.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,14 @@ def test_get_pressed(self):
234234
states = pygame.key.get_pressed()
235235
self.assertEqual(states[pygame.K_RIGHT], 0)
236236

237+
def test_get_pressed_not_iter(self):
238+
states = pygame.key.get_pressed()
239+
with self.assertRaises(TypeError):
240+
next(states)
241+
with self.assertRaises(TypeError):
242+
for k in states:
243+
pass
244+
237245
def test_name_and_key_code(self):
238246
for const_name in dir(pygame):
239247
if not const_name.startswith("K_") or const_name in SKIPPED_KEYS:

0 commit comments

Comments
 (0)