Repository navigation
Description
Feature
property(None, None, None, None, None) constructs a property object in RustPython, but CPython raises TypeError because property() takes at most four arguments.
Reproduction
print(type(property(None, None, None, None, None)))RustPython:
<class 'property'>
CPython:
TypeError: property() takes at most 4 arguments (5 given)
Root cause
PropertyArgs declares a fifth #[pyarg(any, default)] field, name, and compute_arity_bounds counts every positional-or-keyword field toward the maximum arity, so PropertyArgs::arity() is 0..=5 and the leftover-positional check in FuncArgs::bind passes for five arguments; Initializer::init then stores the fifth one in the __name__ slot. CPython's property.__init__ is Argument Clinic generated with maxpos = 4 and the keyword list {fget, fset, fdel, doc}, so _PyArg_UnpackKeywords rejects the fifth argument before property_init_impl runs. The same field also makes RustPython accept property(name='x'), which is not in CPython's keyword list either.
Fix
Remove the name field from PropertyArgs and the assignment that consumes it in Initializer::init, which drops the derived arity back to 0..=4. No caller passes it: clone_property_with already passes name: None and copies the name separately, and the PyProperty name slot stays filled by __set_name__ and the __name__ setter.
Environment
- RustPython d248a04 (Python 3.14.0), also reproduced on 0.5.0
- CPython v3.14.3
- OS: Debian 12
Python Documentation or reference to CPython source code
-
CPython
property_init:Objects/clinic/descrobject.c.h#L133-L150— the Argument Clinic generated parser fixes the keyword list at four entries and passesmaxpos = 4:static const char * const _keywords[] = {"fget", "fset", "fdel", "doc", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "property", .kwtuple = KWTUPLE, }; ... fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, /*minpos*/ 0, /*maxpos*/ 4, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
-
CPython
_PyArg_UnpackKeywords:Python/getargs.c#L2429-L2441— raises theTypeErroronce the argument count exceedsmaxargs, before the implementation function is reached:if (!varpos && nargs + nkwargs > maxargs) { /* Adding "keyword" (when nargs == 0) prevents producing wrong error messages in some special cases (see bpo-31229). */ PyErr_Format(PyExc_TypeError, "%.200s%s takes at most %d %sargument%s (%zd given)", (parser->fname == NULL) ? "function" : parser->fname, (parser->fname == NULL) ? "" : "()", maxargs, (nargs == 0) ? "keyword " : "", (maxargs == 1) ? "" : "s", nargs + nkwargs); return NULL; }
-
Documentation:
property, whose signature isproperty(fget=None, fset=None, fdel=None, doc=None).
Related arity-validation gaps in other builtin constructors: #8461, #8462.
AI disclosure: this report was drafted with Claude Code (claude-opus-5) and reviewed by me before submission. The divergence comes from a differential-testing run against CPython 3.14.3, and every source reference above was checked against the linked revisions.
Activity