Skip to content

Commit d79d89e

Browse files
hauntsaninjacdce8p
andauthored
Fix getargs argument passing (#18350)
Fixes mypyc/mypyc#1078 Introduced in #17930 See the first commit to see the bug (wrong condition) --------- Co-authored-by: Marc Mueller <[email protected]>
1 parent a07ccf7 commit d79d89e

File tree

2 files changed

+24
-12
lines changed

2 files changed

+24
-12
lines changed

mypyc/lib-rt/getargs.c

+9-12
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,12 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
250250
current_arg = Py_NewRef(PyTuple_GET_ITEM(args, i));
251251
}
252252
else if (nkwargs && i >= pos) {
253-
int res = PyDict_GetItemStringRef(kwargs, kwlist[i], &current_arg);
254-
if (res == 1) {
255-
--nkwargs;
256-
}
257-
else if (res == -1) {
253+
if (unlikely(PyDict_GetItemStringRef(kwargs, kwlist[i], &current_arg) < 0)) {
258254
return 0;
259255
}
256+
if (current_arg) {
257+
--nkwargs;
258+
}
260259
}
261260
else {
262261
current_arg = NULL;
@@ -371,11 +370,12 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
371370
Py_ssize_t j;
372371
/* make sure there are no arguments given by name and position */
373372
for (i = pos; i < bound_pos_args && i < len; i++) {
374-
int res = PyDict_GetItemStringRef(kwargs, kwlist[i], &current_arg);
375-
if (res == 1) {
376-
Py_DECREF(current_arg);
373+
PyObject *current_arg;
374+
if (unlikely(PyDict_GetItemStringRef(kwargs, kwlist[i], &current_arg) < 0)) {
375+
goto latefail;
377376
}
378-
else if (unlikely(res == 0)) {
377+
if (unlikely(current_arg != NULL)) {
378+
Py_DECREF(current_arg);
379379
/* arg present in tuple and in dict */
380380
PyErr_Format(PyExc_TypeError,
381381
"argument for %.200s%s given by name ('%s') "
@@ -385,9 +385,6 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
385385
kwlist[i], i+1);
386386
goto latefail;
387387
}
388-
else if (unlikely(res == -1)) {
389-
goto latefail;
390-
}
391388
}
392389
/* make sure there are no extraneous keyword arguments */
393390
j = 0;

mypyc/test-data/run-classes.test

+15
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,21 @@ a = A(10)
467467
assert a.foo() == 11
468468
assert foo() == 21
469469

470+
[case testClassKwargs]
471+
class X:
472+
def __init__(self, msg: str, **variables: int) -> None:
473+
pass
474+
[file driver.py]
475+
import traceback
476+
from native import X
477+
X('hello', a=0)
478+
try:
479+
X('hello', msg='hello')
480+
except TypeError as e:
481+
print(f"{type(e).__name__}: {e}")
482+
[out]
483+
TypeError: argument for __init__() given by name ('msg') and position (1)
484+
470485
[case testGenericClass]
471486
from typing import TypeVar, Generic, Sequence
472487
T = TypeVar('T')

0 commit comments

Comments
 (0)