Commit ee7ae0b9 authored by Vladimir Matveev's avatar Vladimir Matveev Committed by GitHub

Preserve default arguments values on methods for introspection whenever possible (GH-4118)

Closes https://github.com/cython/cython/issues/4061
parent 73521046
......@@ -9371,21 +9371,22 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
# so their optional arguments must be static, too.
# TODO: change CyFunction implementation to pass both function object and owning object for method calls
must_use_constants = env.is_c_class_scope or (self.def_node.is_wrapper and env.is_module_scope)
for arg in self.def_node.args:
if arg.default and not must_use_constants:
if not arg.default.is_literal:
arg.is_dynamic = True
if arg.type.is_pyobject:
nonliteral_objects.append(arg)
if arg.default:
if not must_use_constants:
if not arg.default.is_literal:
arg.is_dynamic = True
if arg.type.is_pyobject:
nonliteral_objects.append(arg)
else:
nonliteral_other.append(arg)
else:
nonliteral_other.append(arg)
else:
arg.default = DefaultLiteralArgNode(arg.pos, arg.default)
if arg.kw_only:
default_kwargs.append(arg)
else:
default_args.append(arg)
arg.default = DefaultLiteralArgNode(arg.pos, arg.default)
if arg.default.type and arg.default.type.can_coerce_to_pyobject(env):
if arg.kw_only:
default_kwargs.append(arg)
else:
default_args.append(arg)
if arg.annotation:
arg.annotation = arg.annotation.analyse_types(env)
annotations.append((arg.pos, arg.name, arg.annotation.string))
......
......@@ -251,3 +251,51 @@ def test_func_default_scope_local():
return arg
print i # genexprs don't leak
return func
cdef class C:
def f1(self, a, b=1, c=[]):
pass
def f2(self, a, b=1,/, c=[1]):
pass
def f3(self, a, /, b=1, *, c=[1]):
pass
cpdef f4(self, a, char*c=NULL):
pass
cpdef f5(self, a, str s = "123"):
pass
cpdef f6(self, a, int s = 4):
pass
cpdef f7(self, a, dict s = {'a':22}):
pass
cpdef f8(self, a, list s = [15]):
pass
def check_defaults_on_methods_for_introspection():
"""
>>> C.f1.__defaults__
(1, [])
>>> C.f1.__kwdefaults__
>>> C.f2.__defaults__
(1, [1])
>>> C.f2.__kwdefaults__
>>> C.f3.__defaults__
(1,)
>>> C.f3.__kwdefaults__
{'c': [1]}
>>> C.f4.__defaults__
>>> C.f4.__kwdefaults__
>>> C.f5.__defaults__
('123',)
>>> C.f5.__kwdefaults__
>>> C.f6.__defaults__
(4,)
>>> C.f6.__kwdefaults__
>>> C.f7.__defaults__
({'a': 22},)
>>> C.f7.__kwdefaults__
>>> C.f8.__defaults__
([15],)
>>> C.f8.__kwdefaults__
"""
pass
......@@ -101,19 +101,17 @@ cpdef cp1(a, b):
"""
# Currently broken, see GH #1864
cpdef cp2(a, b=True):
"""
>>> def py_cp2(a, b=True): pass
#>>> signatures_match(cp2, py_cp2)
>>> signatures_match(cp2, py_cp2)
"""
# Currently broken, see GH #1864
cpdef cp3(a=1, b=True):
"""
>>> def py_cp3(a=1, b=True): pass
#>>> signatures_match(cp3, py_cp3)
>>> signatures_match(cp3, py_cp3)
"""
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment