From dd5d67d72901761fbfbac46d160dc0206625c88d Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Sat, 28 Dec 2024 00:47:30 -0800 Subject: [PATCH 1/5] Fix getargs argument passing Fixes https://github.com/mypyc/mypyc/issues/1078 See https://github.com/python/mypy/pull/17930 --- mypyc/lib-rt/getargs.c | 2 -- mypyc/test-data/run-classes.test | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/mypyc/lib-rt/getargs.c b/mypyc/lib-rt/getargs.c index 4f2f8aa0be83..9b6ab2f5a3f2 100644 --- a/mypyc/lib-rt/getargs.c +++ b/mypyc/lib-rt/getargs.c @@ -374,8 +374,6 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, int res = PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg); if (res == 1) { Py_DECREF(current_arg); - } - else if (unlikely(res == 0)) { /* arg present in tuple and in dict */ PyErr_Format(PyExc_TypeError, "argument for %.200s%s given by name ('%s') " diff --git a/mypyc/test-data/run-classes.test b/mypyc/test-data/run-classes.test index cf30bddbef64..f7aa72d0c6fd 100644 --- a/mypyc/test-data/run-classes.test +++ b/mypyc/test-data/run-classes.test @@ -467,6 +467,14 @@ a = A(10) assert a.foo() == 11 assert foo() == 21 +[case testClassKwargs] +class X: + def __init__(self, msg: str, **variables: int) -> None: + pass +[file driver.py] +from native import X +X('hello', a=0) + [case testGenericClass] from typing import TypeVar, Generic, Sequence T = TypeVar('T') From c00d9679593ccd87e70dad3f6b2a255a9464b076 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 28 Dec 2024 03:26:10 -0800 Subject: [PATCH 2/5] Update mypyc/test-data/run-classes.test Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com> --- mypyc/test-data/run-classes.test | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mypyc/test-data/run-classes.test b/mypyc/test-data/run-classes.test index f7aa72d0c6fd..be1cefad00eb 100644 --- a/mypyc/test-data/run-classes.test +++ b/mypyc/test-data/run-classes.test @@ -472,8 +472,19 @@ class X: def __init__(self, msg: str, **variables: int) -> None: pass [file driver.py] +import traceback from native import X X('hello', a=0) +try: + X('hello', msg='hello') +except TypeError: + traceback.print_exc() +[out] +Traceback (most recent call last): + File "driver.py", line 5, in + X('hello', msg='hello') + ~^^^^^^^^^^^^^^^^^^^^^^ +TypeError: argument for __init__() given by name ('msg') and position (1) [case testGenericClass] from typing import TypeVar, Generic, Sequence From 9856dce93acc4cc744493a9680d78968eee47912 Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Sat, 28 Dec 2024 00:51:57 -0800 Subject: [PATCH 3/5] vanity --- mypyc/lib-rt/getargs.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/mypyc/lib-rt/getargs.c b/mypyc/lib-rt/getargs.c index 9b6ab2f5a3f2..5eb4c649e206 100644 --- a/mypyc/lib-rt/getargs.c +++ b/mypyc/lib-rt/getargs.c @@ -250,13 +250,12 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, current_arg = Py_NewRef(PyTuple_GET_ITEM(args, i)); } else if (nkwargs && i >= pos) { - int res = PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg); - if (res == 1) { - --nkwargs; - } - else if (res == -1) { + if (PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0) { return 0; } + if (current_arg) { + --nkwargs; + } } else { current_arg = NULL; @@ -371,8 +370,11 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, Py_ssize_t j; /* make sure there are no arguments given by name and position */ for (i = pos; i < bound_pos_args && i < len; i++) { - int res = PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg); - if (res == 1) { + PyObject *current_arg; + if (PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0) { + goto latefail; + } + if (unlikely(current_arg != NULL)) { Py_DECREF(current_arg); /* arg present in tuple and in dict */ PyErr_Format(PyExc_TypeError, @@ -383,9 +385,6 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, kwlist[i], i+1); goto latefail; } - else if (unlikely(res == -1)) { - goto latefail; - } } /* make sure there are no extraneous keyword arguments */ j = 0; From df34517fa9a347af4ee93acdfc481e29b043f31f Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Sat, 28 Dec 2024 03:29:11 -0800 Subject: [PATCH 4/5] more unlikely --- mypyc/lib-rt/getargs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypyc/lib-rt/getargs.c b/mypyc/lib-rt/getargs.c index 5eb4c649e206..163b9ac2b163 100644 --- a/mypyc/lib-rt/getargs.c +++ b/mypyc/lib-rt/getargs.c @@ -250,7 +250,7 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, current_arg = Py_NewRef(PyTuple_GET_ITEM(args, i)); } else if (nkwargs && i >= pos) { - if (PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0) { + if (unlikely(PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0)) { return 0; } if (current_arg) { @@ -371,7 +371,7 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, /* make sure there are no arguments given by name and position */ for (i = pos; i < bound_pos_args && i < len; i++) { PyObject *current_arg; - if (PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0) { + if (unlikely(PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0)) { goto latefail; } if (unlikely(current_arg != NULL)) { From 9a46130c844b111b86d63f0d47b4d616489d94a5 Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Sat, 28 Dec 2024 03:37:54 -0800 Subject: [PATCH 5/5] remove tildes --- mypyc/test-data/run-classes.test | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/mypyc/test-data/run-classes.test b/mypyc/test-data/run-classes.test index be1cefad00eb..387f91e489ee 100644 --- a/mypyc/test-data/run-classes.test +++ b/mypyc/test-data/run-classes.test @@ -477,13 +477,9 @@ from native import X X('hello', a=0) try: X('hello', msg='hello') -except TypeError: - traceback.print_exc() +except TypeError as e: + print(f"{type(e).__name__}: {e}") [out] -Traceback (most recent call last): - File "driver.py", line 5, in - X('hello', msg='hello') - ~^^^^^^^^^^^^^^^^^^^^^^ TypeError: argument for __init__() given by name ('msg') and position (1) [case testGenericClass]