Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
947e149
gh-87613: Argument Cliic @vectorcall decorator
cmaloney Feb 22, 2026
a9d0d6f
add blurb
cmaloney Mar 1, 2026
15f74e8
Move enumerate, reversed in enum.c to AC vectorcall
cmaloney Mar 1, 2026
a243517
Move tuple to AC vectorcall
cmaloney Mar 1, 2026
3698a32
Add _testclinic vectorcall sample + testing
cmaloney Mar 18, 2026
115a524
Merge upstream/main into ac_add_vectorcall
cmaloney May 18, 2026
04a148c
Simplify some test cases
cmaloney May 18, 2026
61746eb
Merge remote-tracking branch 'upstream/main' into ac_add_vectorcall
cmaloney May 18, 2026
b5d2e40
Ignore very large _testclinic
cmaloney May 19, 2026
71b0d8e
Up limit a bit more
cmaloney May 19, 2026
b96c326
Exclude more _testclinic from globals
cmaloney May 19, 2026
379fd85
Remove zero_arg case
cmaloney May 19, 2026
e9aff2f
Fix lint
cmaloney May 19, 2026
446bce5
Move to dataclass for vc args
cmaloney May 19, 2026
420d705
Fix test failures, refactor to dedup
cmaloney May 20, 2026
e4d18aa
Simplify now there's only exact_only
cmaloney May 20, 2026
1dcc72b
Merge branch 'main' into ac_add_vectorcall
cmaloney May 21, 2026
7e089b0
Remove removed class from globals-to-fix.tsv
cmaloney May 21, 2026
7f56bb0
Refactor kwarg parsing to be a helper function when emitting two pars…
cmaloney May 22, 2026
61ada45
Add a test class where all args are keyword allowed to increase cover…
cmaloney May 22, 2026
b1cd7b6
remove unnecessary branch in keyword parsing helper
cmaloney May 22, 2026
2a7c068
de-duplicate prototypes
cmaloney May 22, 2026
a19e9a8
Exercise critical section generation in testclinic
cmaloney May 22, 2026
d897215
Simplify comment wording
cmaloney Jun 5, 2026
bc744b2
Refactor parse_args codegeneration
cmaloney Jun 21, 2026
63c1dc5
Fix mypy error
cmaloney Jul 19, 2026
9357436
Fix some grammar in NEWS
cmaloney Jul 19, 2026
5e8e2a3
Merge remote-tracking branch 'upstream/main' into ac_add_vectorcall
cmaloney Aug 21, 2026
011e5c3
Apply suggetions from @eendebakpt, drop exact_only
cmaloney Aug 21, 2026
e4b4f0b
Update comments for recent implementation
cmaloney Aug 21, 2026
3bc0054
Remove PyType_GenericNew assert to fix windows builds
cmaloney Aug 21, 2026
70a6a68
Add a test that error messages should match between vectorcall and non
cmaloney Aug 22, 2026
67e9a37
Update out of range to use helper so error messages match
cmaloney Aug 22, 2026
9135933
Merge remote-tracking branch 'upstream/main' into ac_add_vectorcall
cmaloney Aug 22, 2026
6d8f207
Combine kwnames != NULL and positional out of range check to remove r…
cmaloney Aug 22, 2026
c2b8174
Fix tuple: condition was simplified wrong, varpos needs a check if mi…
cmaloney Aug 22, 2026
88d5928
Simplify _check_positional callsites
cmaloney Aug 22, 2026
5488010
Merge remote-tracking branch 'upstream/main' into ac_add_vectorcall
cmaloney Aug 27, 2026
52db6f7
Disable combining vectorcall and option groups
cmaloney Aug 27, 2026
afee565
Apply batched suggestions from code review
cmaloney Sep 4, 2026
64b3211
Apply batched suggestions from code review
cmaloney Sep 4, 2026
bdb5591
Back to building. Remove helper_call complexity
cmaloney Sep 4, 2026
48a70ab
_parse_args to _helper
cmaloney Sep 4, 2026
31cffb5
Remove no arguments case
cmaloney Sep 4, 2026
0c39c87
Switch to tp_new instead of tp_alloc. Enables bytearray.
cmaloney Sep 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Remove zero_arg case
  • Loading branch information
cmaloney committed May 19, 2026
commit 379fd85db6a2a196f6d19e31e060452b16b986d4
47 changes: 0 additions & 47 deletions Lib/test/test_clinic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2751,38 +2751,6 @@ class Foo "FooObject *" "Foo_Type"
self.assertTrue(func.vectorcall)
self.assertTrue(func.vectorcall_exact_only)

def test_vectorcall_zero_arg(self):
block = """
module m
class Foo "FooObject *" "Foo_Type"
@classmethod
@vectorcall zero_arg=_PyFoo_GetEmpty()
Foo.__new__
x: object = NULL
/
"""
func = self.parse_function(block, signatures_in_block=3,
function_index=2)
self.assertTrue(func.vectorcall)
self.assertFalse(func.vectorcall_exact_only)
self.assertEqual(func.vectorcall_zero_arg, '_PyFoo_GetEmpty()')

def test_vectorcall_zero_arg_with_exact(self):
block = """
module m
class Foo "FooObject *" "Foo_Type"
@classmethod
@vectorcall exact_only zero_arg=get_cached()
Foo.__new__
x: object = NULL
/
"""
func = self.parse_function(block, signatures_in_block=3,
function_index=2)
self.assertTrue(func.vectorcall)
self.assertTrue(func.vectorcall_exact_only)
self.assertEqual(func.vectorcall_zero_arg, 'get_cached()')

def test_vectorcall_invalid_kwarg(self):
err = "unknown argument"
block = """
Expand Down Expand Up @@ -4475,21 +4443,6 @@ def test_vc_new_exact_subclass(self):
self.assertIsInstance(obj, Sub)
self.assertIsInstance(obj, ac_tester.VcNewExact)

def test_vc_new_zeroarg_no_args(self):
# zero_arg returns Py_None when called with no arguments
result = ac_tester.VcNewZeroArg()
self.assertIs(result, None)

def test_vc_new_zeroarg_with_args(self):
self.assertIsInstance(ac_tester.VcNewZeroArg(1), ac_tester.VcNewZeroArg)
self.assertIsInstance(ac_tester.VcNewZeroArg(b=2), ac_tester.VcNewZeroArg)
self.assertIsInstance(ac_tester.VcNewZeroArg(1, b=2), ac_tester.VcNewZeroArg)

def test_vc_new_zeroarg_rejects_a_as_keyword(self):
# 'a' is positional-only
with self.assertRaises(TypeError):
ac_tester.VcNewZeroArg(a=1)


class LimitedCAPIOutputTests(unittest.TestCase):

Expand Down
34 changes: 0 additions & 34 deletions Modules/_testclinic.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ custom_converter(PyObject *obj, custom_t *val)
static PyTypeObject VcNew_Type;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created gh-150097 to track that we shouldn't need to do this

static PyTypeObject VcInit_Type;
static PyTypeObject VcNewExact_Type;
static PyTypeObject VcNewZeroArg_Type;

#include "clinic/_testclinic.c.h"


Expand Down Expand Up @@ -2409,35 +2407,6 @@ static PyTypeObject VcNewExact_Type = {
};


/* VcNewZeroArg: __new__ with zero_arg; returns Py_None when called with no args */

/*[clinic input]
class _testclinic.VcNewZeroArg "PyObject *" "&VcNewZeroArg_Type"
@classmethod
@vectorcall zero_arg=Py_NewRef(Py_None)
_testclinic.VcNewZeroArg.__new__ as vc_zeroarg_new
a: object = None
/
*
b: object = None
[clinic start generated code]*/

static PyObject *
vc_zeroarg_new_impl(PyTypeObject *type, PyObject *a, PyObject *b)
/*[clinic end generated code: output=6425b64d61c6317a input=f3d3ba860fc40034]*/
{
return type->tp_alloc(type, 0);
}

static PyTypeObject VcNewZeroArg_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "_testclinic.VcNewZeroArg",
.tp_basicsize = sizeof(PyObject),
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_new = vc_zeroarg_new,
.tp_vectorcall = vc_zeroarg_vectorcall,
};


/*[clinic input]
output push
Expand Down Expand Up @@ -2667,9 +2636,6 @@ PyInit__testclinic(void)
if (PyModule_AddType(m, &VcNewExact_Type) < 0) {
goto error;
}
if (PyModule_AddType(m, &VcNewZeroArg_Type) < 0) {
goto error;
}
return m;

error:
Expand Down
131 changes: 1 addition & 130 deletions Modules/clinic/_testclinic.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 1 addition & 4 deletions Objects/clinic/tupleobject.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Objects/tupleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -778,7 +778,7 @@ static PyObject *
tuple_subtype_new(PyTypeObject *type, PyObject *iterable);

/*[clinic input]
@vectorcall zero_arg=(PyObject*)&_Py_SINGLETON(tuple_empty)
@vectorcall
@classmethod
tuple.__new__ as tuple_new
iterable: object(c_default="NULL") = ()
Expand All @@ -794,7 +794,7 @@ If the argument is a tuple, the return value is the same object.

static PyObject *
tuple_new_impl(PyTypeObject *type, PyObject *iterable)
/*[clinic end generated code: output=4546d9f0d469bce7 input=fff66d7a13734d92]*/
/*[clinic end generated code: output=4546d9f0d469bce7 input=8fdda913493ebe48]*/
{
if (type != &PyTuple_Type)
return tuple_subtype_new(type, iterable);
Expand Down
6 changes: 0 additions & 6 deletions Tools/clinic/libclinic/dsl_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,6 @@
self.disable_fastcall = False
self.vectorcall = False
self.vectorcall_exact_only = False
self.vectorcall_zero_arg = ''
self.permit_long_summary = False
self.permit_long_docstring_body = False

Expand Down Expand Up @@ -477,13 +476,9 @@
if '=' in arg:
key, value = arg.split('=', 1)
else:
key, value = arg, ''

Check failure on line 479 in Tools/clinic/libclinic/dsl_parser.py

View workflow job for this annotation

GitHub Actions / lint

ruff (F841)

Tools/clinic/libclinic/dsl_parser.py:479:22: F841 Local variable `value` is assigned to but never used help: Remove assignment to unused variable `value`
if key == 'exact_only':
self.vectorcall_exact_only = True
elif key == 'zero_arg':
if not value:
fail("@vectorcall zero_arg requires a value")
self.vectorcall_zero_arg = value
else:
fail(f"@vectorcall: unknown argument {key!r}")

Expand Down Expand Up @@ -751,7 +746,6 @@
forced_text_signature=self.forced_text_signature,
vectorcall=self.vectorcall,
vectorcall_exact_only=self.vectorcall_exact_only,
vectorcall_zero_arg=self.vectorcall_zero_arg,
)
self.add_function(func)

Expand Down
1 change: 0 additions & 1 deletion Tools/clinic/libclinic/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ class Function:
target_critical_section: list[str] = dc.field(default_factory=list)
vectorcall: bool = False
vectorcall_exact_only: bool = False
vectorcall_zero_arg: str = ''

def __post_init__(self) -> None:
self.parent = self.cls or self.module
Expand Down
11 changes: 0 additions & 11 deletions Tools/clinic/libclinic/parse_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -1283,22 +1283,11 @@ def generate_vectorcall(self) -> str:
}}
""")

# Zero-arg shortcut: return a cached value when called with no args
zero_arg_shortcut = ""
if func.vectorcall_zero_arg:
zero_arg_shortcut = libclinic.normalize_snippet(f"""
if (nargs == 0 && kwnames == NULL) {{{{
return {func.vectorcall_zero_arg};
}}}}
""", indent=4)

# Assemble the full function
lines = [prototype]
lines.append(preamble)
if exact_check:
lines.append(exact_check)
if zero_arg_shortcut:
lines.append(zero_arg_shortcut)
lines.extend(parsing_code)
lines.append(finale)

Expand Down
Loading