From 330b3643d65ed26e6f1f80726cfe0854be1b89b2 Mon Sep 17 00:00:00 2001 From: algorithm1832 <737634857@qq.com> Date: Sat, 25 Oct 2025 00:20:28 +0800 Subject: [PATCH 1/7] add parsing for posonlyargs --- docs/api/gen_doc.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/api/gen_doc.py b/docs/api/gen_doc.py index d0ffb25fa0e..b8a766e0689 100755 --- a/docs/api/gen_doc.py +++ b/docs/api/gen_doc.py @@ -365,12 +365,25 @@ def gen_functions_args_str(node): str_args_list = [] if isinstance(node, ast.FunctionDef): # 'args', 'defaults', 'kw_defaults', 'kwarg', 'kwonlyargs', 'posonlyargs', 'vararg' + if node.args.posonlyargs is not None: + for arg in node.args.posonlyargs: + if not arg.arg == "self": + str_args_list.append(arg.arg) + str_args_list.append("/") + for arg in node.args.args: if not arg.arg == "self": str_args_list.append(arg.arg) defarg_ind_start = len(str_args_list) - len(node.args.defaults) + if node.args.posonlyargs is not None and len(node.args.defaults) > len( + node.args.args + ): + defarg_ind_start -= 1 + for defarg_ind in range(len(node.args.defaults)): + if str_args_list[defarg_ind_start + defarg_ind] == "/": + defarg_ind_start += 1 if isinstance(node.args.defaults[defarg_ind], ast.Name): str_args_list[defarg_ind_start + defarg_ind] += "=" + str( node.args.defaults[defarg_ind].id From fabf85a71b1ee32823760017dbe2702ab5f90fd0 Mon Sep 17 00:00:00 2001 From: algorithm1832 <737634857@qq.com> Date: Mon, 27 Oct 2025 15:46:34 +0800 Subject: [PATCH 2/7] refactor code --- docs/api/gen_doc.py | 104 ++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 46 deletions(-) diff --git a/docs/api/gen_doc.py b/docs/api/gen_doc.py index b8a766e0689..07e1290a4fb 100755 --- a/docs/api/gen_doc.py +++ b/docs/api/gen_doc.py @@ -319,7 +319,7 @@ def parse_module_file(mod): ) if isinstance(node, ast.FunctionDef): api_info_dict[obj_id]["args"] = ( - gen_functions_args_str(node) + gen_function_args_string(node) ) elif isinstance(node, ast.ClassDef): for n in node.body: @@ -328,7 +328,7 @@ def parse_module_file(mod): and n.name == "__init__" ): api_info_dict[obj_id]["args"] = ( - gen_functions_args_str(n) + gen_function_args_string(n) ) break else: @@ -361,52 +361,64 @@ def parse_module_file(mod): logger.debug("%s omitted", obj_full_name) -def gen_functions_args_str(node): - str_args_list = [] - if isinstance(node, ast.FunctionDef): - # 'args', 'defaults', 'kw_defaults', 'kwarg', 'kwonlyargs', 'posonlyargs', 'vararg' - if node.args.posonlyargs is not None: - for arg in node.args.posonlyargs: - if not arg.arg == "self": - str_args_list.append(arg.arg) - str_args_list.append("/") +def gen_function_args_string(fn_node: ast.FunctionDef) -> str: + def _gen_default_value_string(default_node: ast.expr) -> str: + if isinstance(default_node, ast.Constant): + default_value = default_node.value + if isinstance(default_value, str): + return f"'{default_value}'" + return str(default_value) + elif isinstance(default_node, ast.Name): + return default_node.id + return "..." - for arg in node.args.args: - if not arg.arg == "self": - str_args_list.append(arg.arg) + def _is_self_arg(arg: ast.arg) -> bool: + return arg.arg == "self" - defarg_ind_start = len(str_args_list) - len(node.args.defaults) - if node.args.posonlyargs is not None and len(node.args.defaults) > len( - node.args.args - ): - defarg_ind_start -= 1 - - for defarg_ind in range(len(node.args.defaults)): - if str_args_list[defarg_ind_start + defarg_ind] == "/": - defarg_ind_start += 1 - if isinstance(node.args.defaults[defarg_ind], ast.Name): - str_args_list[defarg_ind_start + defarg_ind] += "=" + str( - node.args.defaults[defarg_ind].id - ) - elif isinstance(node.args.defaults[defarg_ind], ast.Constant): - defarg_val = str(node.args.defaults[defarg_ind].value) - if isinstance(node.args.defaults[defarg_ind].value, str): - defarg_val = f"'{defarg_val}'" - str_args_list[defarg_ind_start + defarg_ind] += "=" + defarg_val - if node.args.vararg is not None: - str_args_list.append("*" + node.args.vararg.arg) - if len(node.args.kwonlyargs) > 0: - if node.args.vararg is None: - str_args_list.append("*") - for kwoarg, d in zip(node.args.kwonlyargs, node.args.kw_defaults): - if isinstance(d, ast.Constant): - str_args_list.append(f"{kwoarg.arg}={d.value}") - elif isinstance(d, ast.Name): - str_args_list.append(f"{kwoarg.arg}={d.id}") - if node.args.kwarg is not None: - str_args_list.append("**" + node.args.kwarg.arg) - - return ", ".join(str_args_list) + if not isinstance(fn_node, ast.FunctionDef): + logger.warning( + "The provided node %s is not a FunctionDef.", ast.unparse(fn_node) + ) + return "" + arg_list = [] + posonlyargs_count = len(fn_node.args.posonlyargs) + # posonlyargs + for i, arg in enumerate(fn_node.args.posonlyargs): + if _is_self_arg(arg): + continue + arg_list.append(arg.arg) + if posonlyargs_count > 0: + arg_list.append("/") + # args + for i, arg in enumerate(fn_node.args.args): + if _is_self_arg(arg): + continue + arg_list.append(arg.arg) + # assign default values + defaults_start_index = len(arg_list) - len(fn_node.args.defaults) + jump = 0 if defaults_start_index > posonlyargs_count else -1 + for i, default in enumerate(fn_node.args.defaults): + if jump == -1 and defaults_start_index + i > posonlyargs_count: + jump = 0 + arg_index = defaults_start_index + i + jump + arg_name = fn_node.args.args[arg_index].arg + default_value_str = _gen_default_value_string(default) + arg_list[arg_index] = f"{arg_name}={default_value_str}" + # vararg + if fn_node.args.vararg: + arg_list.append(f"*{fn_node.args.vararg.arg}") + # kwonlyargs + if fn_node.args.kwonlyargs: + arg_list.append("*") + for i, kwonlyarg in enumerate(fn_node.args.kwonlyargs): + kwdefault = fn_node.args.kw_defaults[i] + assert kwdefault is not None + default_value_str = _gen_default_value_string(kwdefault) + arg_list.append(f"{kwonlyarg.arg}={default_value_str}") + # kwarg + if fn_node.args.kwarg: + arg_list.append(f"**{fn_node.args.kwarg.arg}") + return ", ".join(arg_list) # step 2 fill field : `display` From b154e084cd1511457f15763505ba966f991a7328 Mon Sep 17 00:00:00 2001 From: algorithm1832 <737634857@qq.com> Date: Mon, 27 Oct 2025 16:23:18 +0800 Subject: [PATCH 3/7] remove assert --- docs/api/gen_doc.py | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/api/gen_doc.py b/docs/api/gen_doc.py index 07e1290a4fb..31018fca0a8 100755 --- a/docs/api/gen_doc.py +++ b/docs/api/gen_doc.py @@ -412,7 +412,6 @@ def _is_self_arg(arg: ast.arg) -> bool: arg_list.append("*") for i, kwonlyarg in enumerate(fn_node.args.kwonlyargs): kwdefault = fn_node.args.kw_defaults[i] - assert kwdefault is not None default_value_str = _gen_default_value_string(kwdefault) arg_list.append(f"{kwonlyarg.arg}={default_value_str}") # kwarg From db898fd7bfe53e609574849249adfb27bbedd47c Mon Sep 17 00:00:00 2001 From: algorithm1832 <737634857@qq.com> Date: Mon, 27 Oct 2025 16:26:50 +0800 Subject: [PATCH 4/7] add None default value processing --- docs/api/gen_doc.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/api/gen_doc.py b/docs/api/gen_doc.py index 31018fca0a8..4212b61e7b7 100755 --- a/docs/api/gen_doc.py +++ b/docs/api/gen_doc.py @@ -412,8 +412,9 @@ def _is_self_arg(arg: ast.arg) -> bool: arg_list.append("*") for i, kwonlyarg in enumerate(fn_node.args.kwonlyargs): kwdefault = fn_node.args.kw_defaults[i] - default_value_str = _gen_default_value_string(kwdefault) - arg_list.append(f"{kwonlyarg.arg}={default_value_str}") + if kwdefault is not None: + default_value_str = _gen_default_value_string(kwdefault) + arg_list.append(f"{kwonlyarg.arg}={default_value_str}") # kwarg if fn_node.args.kwarg: arg_list.append(f"**{fn_node.args.kwarg.arg}") From fbb6fd905366e4ce2c449460d767c3c52fb3eb15 Mon Sep 17 00:00:00 2001 From: algorithm1832 <737634857@qq.com> Date: Mon, 27 Oct 2025 16:33:28 +0800 Subject: [PATCH 5/7] fix argument name processing --- docs/api/gen_doc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/gen_doc.py b/docs/api/gen_doc.py index 4212b61e7b7..526a4e9b787 100755 --- a/docs/api/gen_doc.py +++ b/docs/api/gen_doc.py @@ -401,7 +401,7 @@ def _is_self_arg(arg: ast.arg) -> bool: if jump == -1 and defaults_start_index + i > posonlyargs_count: jump = 0 arg_index = defaults_start_index + i + jump - arg_name = fn_node.args.args[arg_index].arg + arg_name = arg_list[arg_index] default_value_str = _gen_default_value_string(default) arg_list[arg_index] = f"{arg_name}={default_value_str}" # vararg From 9ca407fec1576052bbfc53d6cddee0c69b3b77a3 Mon Sep 17 00:00:00 2001 From: algorithm1832 <737634857@qq.com> Date: Mon, 27 Oct 2025 16:47:31 +0800 Subject: [PATCH 6/7] add None default value processing --- docs/api/gen_doc.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/api/gen_doc.py b/docs/api/gen_doc.py index 526a4e9b787..340f7ffb91d 100755 --- a/docs/api/gen_doc.py +++ b/docs/api/gen_doc.py @@ -412,7 +412,9 @@ def _is_self_arg(arg: ast.arg) -> bool: arg_list.append("*") for i, kwonlyarg in enumerate(fn_node.args.kwonlyargs): kwdefault = fn_node.args.kw_defaults[i] - if kwdefault is not None: + if kwdefault is None: + arg_list.append(kwonlyarg.arg) + else: default_value_str = _gen_default_value_string(kwdefault) arg_list.append(f"{kwonlyarg.arg}={default_value_str}") # kwarg From 76f7408e93d9fe8a05cedaf5a34bafae58452777 Mon Sep 17 00:00:00 2001 From: algorithm1832 <737634857@qq.com> Date: Mon, 27 Oct 2025 16:57:26 +0800 Subject: [PATCH 7/7] refactor code --- docs/api/gen_doc.py | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/docs/api/gen_doc.py b/docs/api/gen_doc.py index 340f7ffb91d..6be58f6be89 100755 --- a/docs/api/gen_doc.py +++ b/docs/api/gen_doc.py @@ -382,28 +382,24 @@ def _is_self_arg(arg: ast.arg) -> bool: return "" arg_list = [] posonlyargs_count = len(fn_node.args.posonlyargs) - # posonlyargs - for i, arg in enumerate(fn_node.args.posonlyargs): - if _is_self_arg(arg): - continue - arg_list.append(arg.arg) - if posonlyargs_count > 0: - arg_list.append("/") - # args - for i, arg in enumerate(fn_node.args.args): - if _is_self_arg(arg): + # posonlyargs and args + defaults_start_index = ( + len(fn_node.args.args) + + len(fn_node.args.posonlyargs) + - len(fn_node.args.defaults) + ) + for i, arg in enumerate(fn_node.args.posonlyargs + fn_node.args.args): + if _is_self_arg(arg) and i == 0: continue - arg_list.append(arg.arg) - # assign default values - defaults_start_index = len(arg_list) - len(fn_node.args.defaults) - jump = 0 if defaults_start_index > posonlyargs_count else -1 - for i, default in enumerate(fn_node.args.defaults): - if jump == -1 and defaults_start_index + i > posonlyargs_count: - jump = 0 - arg_index = defaults_start_index + i + jump - arg_name = arg_list[arg_index] - default_value_str = _gen_default_value_string(default) - arg_list[arg_index] = f"{arg_name}={default_value_str}" + if i == posonlyargs_count and posonlyargs_count > 0: + arg_list.append("/") + if i >= defaults_start_index: + default_value_str = _gen_default_value_string( + fn_node.args.defaults[i - defaults_start_index] + ) + arg_list.append(f"{arg.arg}={default_value_str}") + else: + arg_list.append(arg.arg) # vararg if fn_node.args.vararg: arg_list.append(f"*{fn_node.args.vararg.arg}")