RFC: `py_call!` macro
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 16.2k
- Forks
- 1k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 66
Description
At the moment, to call a Python function we have .call(args, kwargs), .call1(args) and .call0() methods.
I have two main concerns with these:
- I think to a user the names are not immediately intuitive. That said, I can't suggest a combination I love much better.
- These calls all use the tuple-and-dict calling convention. We now have the "vectorcall" calling convention which supports a list of arguments as a C array, (and optionally keyword argument names as a tuple), which is meaningfully more efficient.
I have been wondering for a while if we should have a py_call! macro which mirrors Python syntax and does its best to be efficient.
In all of these examples below, I assume obj to be Bound<'_, T>:
py_call!{ obj() } // call obj without arguments, equivalent to current `obj.call0()`
py_call!{ obj(a, b) } // call obj with positional arguments a and b. Use "vectorcall" convention for efficiency
py_call!{ obj(a, b, *args) } // call obj with positional arguments a, b, and the unpacked `*args` iterable.
py_call!{ obj(a, b, *args, x=1, y=2) } // same as above with keyword arguments x and y
py_call!{ obj(a, b, *args, x=1, y=2, **kwargs) } // and even with `kwargs` iterable
Some special cases might still use the tuple-and-dict convention:
py_call!{ obj(*args) } // call obj with args
py_call!{ obj(**kwargs) } // call obj with kwargs
py_call!{ obj(*args, **kwargs) } // call obj with args and kwargs
I wonder if we would extend this to method calls:
py_call!{ obj.method(*args) } // call obj.method with args
// etc
I suspect that this macro would prefer to be a proc-macro for better error messages etc. The implementation... would probably be a jumble of interesting traits.
I honestly have no idea how easy / hard the implementation would be, but I'm excited that this might create a nice user experience and also be a win for performance!
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing the existing .call(args, kwargs), .call1(args), and .call0() APIs and the issue's vectorcall examples. Compare the proposed syntax and method-call extension with the current calling conventions and assess the proc-macro and trait design. Done would require an agreed scope and an implemented, efficient macro API with coverage for the listed call forms.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, rust
- Domain
- api, backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100