Skip to content
This repository was archived by the owner on Mar 26, 2026. It is now read-only.

Commit bb6898e

Browse files
dandhleetbpg
andauthored
fix: retrieve keyword arguments for docstrings (#389)
* fix: retrieve keyword arguments for docstrings * fix: update offset with kwonlydefaults included * Update docfx_yaml/extension.py Co-authored-by: Tyler Bui-Palsulich <26876514+tbpg@users.noreply.github.com> * fix: update to use original_args * fix: address default index skip issue * fix: update offset constraint --------- Co-authored-by: Tyler Bui-Palsulich <26876514+tbpg@users.noreply.github.com>
1 parent 28ddb34 commit bb6898e

1 file changed

Lines changed: 62 additions & 41 deletions

File tree

docfx_yaml/extension.py

Lines changed: 62 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -943,56 +943,77 @@ def _update_friendly_package_name(path):
943943
if _type in [METHOD, FUNCTION, CLASS]:
944944
argspec = inspect.getfullargspec(obj) # noqa
945945
type_map = {}
946-
if argspec.annotations:
947-
for annotation in argspec.annotations:
948-
if annotation == "return":
946+
947+
annotations = getattr(argspec, 'annotations', [])
948+
for annotation in argspec.annotations:
949+
if annotation == "return":
950+
continue
951+
try:
952+
type_map[annotation] = _extract_type_name(
953+
argspec.annotations[annotation])
954+
except AttributeError:
955+
print(f"Could not parse argument information for {annotation}.")
956+
continue
957+
958+
# Retrieve arguments from various sources like `argspec.args` and
959+
# `argspec.kwonlyargs` for positional/keyword arguments.
960+
original_args = argspec.args
961+
# Stores default information for kwonly arguments. Unlike
962+
# inspect.defaults, which is a tuple of default values, kw defaults
963+
# is a dict[name, defaultvalue].
964+
kw_defaults = {}
965+
if argspec.kwonlyargs:
966+
original_args.extend(argspec.kwonlyargs)
967+
if argspec.kwonlydefaults:
968+
kw_defaults.update(argspec.kwonlydefaults)
969+
arg_count += len(original_args)
970+
971+
# Retrieve the default values and convert to a list.
972+
defaults = list(getattr(argspec, 'defaults', []))
973+
# Counter used to extract default values.
974+
default_index = -len(argspec.args) + len(defaults)
975+
for arg in original_args:
976+
# Ignore adding in entry for "self" or if docstring cannot be
977+
# formed for current arg, such as docstring is missing or type
978+
# annotation is not given.
979+
if arg == 'cls' or arg not in type_map:
980+
default_index += 1
981+
continue
982+
983+
arg_map = {
984+
'id': arg,
985+
'var_type': type_map[arg],
986+
}
987+
988+
if arg in argspec.args:
989+
# default index will be between 0 and len(defaults) if we
990+
# processed args without defaults, and now only have
991+
# args with default values to assign.
992+
if default_index < 0 or default_index >= len(defaults):
949993
continue
950-
try:
951-
type_map[annotation] = _extract_type_name(
952-
argspec.annotations[annotation])
953-
except AttributeError:
954-
print(f"Could not parse argument information for {annotation}.")
994+
# Only add defaultValue when str(default) doesn't
995+
# contain object address string, for example:
996+
# (object at 0x) or <lambda> at 0x7fed4d57b5e0,
997+
# otherwise inspect.getargspec method will return wrong
998+
# defaults which contain object address for some,
999+
# like sys.stdout.
1000+
default_string = str(defaults[default_index])
1001+
if 'at 0x' in default_string:
9551002
continue
1003+
arg_map['defaultValue'] = default_string
1004+
if arg in kw_defaults:
1005+
# Cast to string, otherwise different types may be stored as
1006+
# value instead.
1007+
arg_map['defaultValue'] = str(kw_defaults[arg])
9561008

957-
# Add up the number of arguments. `argspec.args` contains a list of
958-
# all the arguments from the function.
959-
arg_count += len(argspec.args)
960-
for arg in argspec.args:
961-
arg_map = {}
962-
# Ignore adding in entry for "self"
963-
if arg != 'cls':
964-
arg_map['id'] = arg
965-
if arg in type_map:
966-
arg_map['var_type'] = type_map[arg]
967-
args.append(arg_map)
1009+
default_index += 1
1010+
args.append(arg_map)
9681011

9691012
if argspec.varargs:
9701013
args.append({'id': argspec.varargs})
9711014
if argspec.varkw:
9721015
args.append({'id': argspec.varkw})
9731016

974-
if argspec.defaults:
975-
# Attempt to add default values to arguments.
976-
try:
977-
for count, default in enumerate(argspec.defaults):
978-
# Find the first index which default arguments start at.
979-
# Every argument after this offset_count all have default values.
980-
offset_count = len(argspec.defaults)
981-
# Find the index of the current default value argument
982-
index = len(args) + count - offset_count
983-
984-
# Only add defaultValue when str(default) doesn't
985-
# contain object address string, for example:
986-
# (object at 0x) or <lambda> at 0x7fed4d57b5e0,
987-
# otherwise inspect.getargspec method will return wrong
988-
# defaults which contain object address for some,
989-
# like sys.stdout.
990-
default_string = str(default)
991-
if 'at 0x' not in default_string:
992-
args[index]['defaultValue'] = default_string
993-
# If we cannot find the argument, it is missing a type and was taken out intentionally.
994-
except IndexError:
995-
pass
9961017
try:
9971018
if len(lines) == 0:
9981019
lines = inspect.getdoc(obj)

0 commit comments

Comments
 (0)