-
-
Notifications
You must be signed in to change notification settings - Fork 3k
stubgen: Preserve simple defaults in function signatures #15355
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
4692138
8401f8e
c55605f
8624298
69ba241
73d5ddd
e432e5c
d8e7460
4011c16
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -99,6 +99,7 @@ | |
NameExpr, | ||
OpExpr, | ||
OverloadedFuncDef, | ||
SetExpr, | ||
Statement, | ||
StrExpr, | ||
TempNode, | ||
|
@@ -491,15 +492,21 @@ def _get_func_args(self, o: FuncDef, ctx: FunctionContext) -> list[ArgSig]: | |
if kind.is_named() and not any(arg.name.startswith("*") for arg in args): | ||
args.append(ArgSig("*")) | ||
|
||
default = "..." | ||
if arg_.initializer: | ||
if not typename: | ||
typename = self.get_str_type_of_node(arg_.initializer, True, False) | ||
potential_default, valid = self.get_str_default_of_node(arg_.initializer) | ||
if valid and len(potential_default) <= 200: | ||
default = potential_default | ||
elif kind == ARG_STAR: | ||
name = f"*{name}" | ||
elif kind == ARG_STAR2: | ||
name = f"**{name}" | ||
|
||
args.append(ArgSig(name, typename, default=bool(arg_.initializer))) | ||
args.append( | ||
ArgSig(name, typename, default=bool(arg_.initializer), default_value=default) | ||
) | ||
|
||
if ctx.class_info is not None and all( | ||
arg.type is None and arg.default is False for arg in args | ||
|
@@ -1234,6 +1241,70 @@ def maybe_unwrap_unary_expr(self, expr: Expression) -> Expression: | |
# This is some other unary expr, we cannot do anything with it (yet?). | ||
return expr | ||
|
||
def get_str_default_of_node(self, rvalue: Expression) -> tuple[str, bool]: | ||
"""Get a string representation of the default value of a node. | ||
|
||
Returns a 2-tuple of the default and whether or not it is valid. | ||
""" | ||
if isinstance(rvalue, NameExpr): | ||
if rvalue.name in ("None", "True", "False"): | ||
return rvalue.name, True | ||
elif isinstance(rvalue, (IntExpr, FloatExpr)): | ||
return f"{rvalue.value}", True | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this work correctly for NaN and infinity? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Do these have a literal syntax? |
||
elif isinstance(rvalue, UnaryExpr): | ||
if isinstance(rvalue.expr, (IntExpr, FloatExpr)): | ||
return f"{rvalue.op}{rvalue.expr.value}", True | ||
elif isinstance(rvalue, StrExpr): | ||
return repr(rvalue.value), True | ||
elif isinstance(rvalue, BytesExpr): | ||
return "b" + repr(rvalue.value).replace("\\\\", "\\"), True | ||
elif isinstance(rvalue, TupleExpr): | ||
items_defaults = [] | ||
for e in rvalue.items: | ||
e_default, valid = self.get_str_default_of_node(e) | ||
if not valid: | ||
break | ||
items_defaults.append(e_default) | ||
else: | ||
closing = ",)" if len(items_defaults) == 1 else ")" | ||
default = "(" + ", ".join(items_defaults) + closing | ||
return default, True | ||
elif isinstance(rvalue, ListExpr): | ||
items_defaults = [] | ||
for e in rvalue.items: | ||
e_default, valid = self.get_str_default_of_node(e) | ||
if not valid: | ||
break | ||
items_defaults.append(e_default) | ||
else: | ||
default = "[" + ", ".join(items_defaults) + "]" | ||
return default, True | ||
elif isinstance(rvalue, SetExpr): | ||
items_defaults = [] | ||
for e in rvalue.items: | ||
e_default, valid = self.get_str_default_of_node(e) | ||
if not valid: | ||
break | ||
items_defaults.append(e_default) | ||
else: | ||
if items_defaults: | ||
default = "{" + ", ".join(items_defaults) + "}" | ||
return default, True | ||
elif isinstance(rvalue, DictExpr): | ||
items_defaults = [] | ||
for k, v in rvalue.items: | ||
if k is None: | ||
break | ||
k_default, k_valid = self.get_str_default_of_node(k) | ||
v_default, v_valid = self.get_str_default_of_node(v) | ||
if not (k_valid and v_valid): | ||
break | ||
items_defaults.append(f"{k_default}: {v_default}") | ||
else: | ||
default = "{" + ", ".join(items_defaults) + "}" | ||
return default, True | ||
return "...", False | ||
|
||
def should_reexport(self, name: str, full_module: str, name_is_alias: bool) -> bool: | ||
is_private = self.is_private_name(name, full_module + "." + name) | ||
if ( | ||
|
Uh oh!
There was an error while loading. Please reload this page.