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

Commit 0c91f60

Browse files
authored
fix: refactor type hint retrieval (#312)
* fix: refactor type hint retrieval * fix: update spacing * test: update goldens * fix: update prefix start/end removal * fix: update docstring for Annotations
1 parent 313a1a5 commit 0c91f60

6 files changed

Lines changed: 113 additions & 15 deletions

docfx_yaml/extension.py

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
from pathlib import Path
3333
from functools import partial
3434
from itertools import zip_longest
35-
from typing import Dict, Iterable, List, Optional
35+
from typing import Any, Dict, Iterable, List, Optional
3636
from black import InvalidInput
3737

3838
try:
@@ -732,6 +732,54 @@ def extract_product_name(name):
732732
return product_name
733733

734734

735+
def _extract_type_name(annotation: Any) -> str:
736+
"""Extracts the type name for the given inspected object.
737+
738+
Used to identify and extract the type hints given through inspecting the
739+
source code. Carefully extracts only the relevant part for the given
740+
annotation.
741+
742+
Args:
743+
annotation: the inspected object in its type format. The type hint used
744+
is `Any`, because it's the type of the object inspected itself,
745+
which can come as any type available.
746+
747+
Returns:
748+
The extracted type hint in human-readable string format.
749+
"""
750+
type_name = ""
751+
# Extract names for simple types.
752+
try:
753+
return annotation.__name__
754+
except AttributeError:
755+
pass
756+
757+
# Try to extract names for more complicated types.
758+
type_name = str(annotation)
759+
if not annotation.__args__:
760+
return type_name
761+
762+
# If ForwardRef references are found, recursively remove them.
763+
prefix_to_remove_start = "ForwardRef('"
764+
if prefix_to_remove_start not in type_name:
765+
return type_name
766+
767+
prefix_to_remove_end = "')"
768+
prefix_start_len = len(prefix_to_remove_start)
769+
prefix_end_len = len(prefix_to_remove_end)
770+
771+
while prefix_to_remove_start in type_name:
772+
start_index = type_name.find(prefix_to_remove_start)
773+
end_index = type_name.find(prefix_to_remove_end, start_index)
774+
type_name = ''.join([
775+
type_name[:start_index],
776+
type_name[start_index+prefix_start_len:end_index],
777+
type_name[end_index+prefix_end_len:],
778+
])
779+
780+
return type_name
781+
782+
735783
def _create_datam(app, cls, module, name, _type, obj, lines=None):
736784
"""
737785
Build the data structure for an autodoc class
@@ -767,19 +815,12 @@ def _update_friendly_package_name(path):
767815
for annotation in argspec.annotations:
768816
if annotation == "return":
769817
continue
770-
# Extract names for simple types.
771818
try:
772-
type_map[annotation] = (argspec.annotations[annotation]).__name__
773-
# Try to extract names for more complicated types.
819+
type_map[annotation] = _extract_type_name(
820+
argspec.annotations[annotation])
774821
except AttributeError:
775-
vartype = argspec.annotations[annotation]
776-
try:
777-
type_map[annotation] = str(vartype._name)
778-
if vartype.__args__:
779-
type_map[annotation] += str(vartype.__args__)[:-2] + ")"
780-
except AttributeError:
781-
print(f"Could not parse argument information for {annotation}.")
782-
continue
822+
print(f"Could not parse argument information for {annotation}.")
823+
continue
783824

784825
# Add up the number of arguments. `argspec.args` contains a list of
785826
# all the arguments from the function.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
### YamlMime:UniversalReference
2+
api_name: []
3+
items:
4+
- children: []
5+
class: google.cloud.pubsub_v1.types.FeatureSet
6+
fullName: google.cloud.pubsub_v1.types.FeatureSet
7+
langs:
8+
- python
9+
module: google.cloud.pubsub_v1.types
10+
name: FeatureSet
11+
source:
12+
id: FeatureSet
13+
path: null
14+
startLine: null
15+
summary: API documentation for `pubsub_v1.types.FeatureSet` class.
16+
syntax: {}
17+
type: class
18+
uid: google.cloud.pubsub_v1.types.FeatureSet
19+
references: []
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
### YamlMime:UniversalReference
2+
api_name: []
3+
items:
4+
- children: []
5+
class: google.cloud.pubsub_v1.types.FieldOptions.EditionDefault
6+
fullName: google.cloud.pubsub_v1.types.FieldOptions.EditionDefault
7+
langs:
8+
- python
9+
module: google.cloud.pubsub_v1.types.FieldOptions
10+
name: EditionDefault
11+
source:
12+
id: EditionDefault
13+
path: null
14+
startLine: null
15+
summary: API documentation for `pubsub_v1.types.FieldOptions.EditionDefault` class.
16+
syntax: {}
17+
type: class
18+
uid: google.cloud.pubsub_v1.types.FieldOptions.EditionDefault
19+
references: []

tests/testdata/goldens/gapic-combo/google.cloud.pubsub_v1.types.FieldOptions.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
### YamlMime:UniversalReference
22
api_name: []
33
items:
4-
- children: []
4+
- children:
5+
- google.cloud.pubsub_v1.types.FieldOptions.EditionDefault
56
class: google.cloud.pubsub_v1.types.FieldOptions
67
fullName: google.cloud.pubsub_v1.types.FieldOptions
78
langs:
@@ -16,4 +17,9 @@ items:
1617
syntax: {}
1718
type: class
1819
uid: google.cloud.pubsub_v1.types.FieldOptions
19-
references: []
20+
references:
21+
- fullName: google.cloud.pubsub_v1.types.FieldOptions.EditionDefault
22+
isExternal: false
23+
name: EditionDefault
24+
parent: google.cloud.pubsub_v1.types.FieldOptions
25+
uid: google.cloud.pubsub_v1.types.FieldOptions.EditionDefault

tests/testdata/goldens/gapic-combo/google.cloud.pubsub_v1.types.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ items:
2828
- google.cloud.pubsub_v1.types.EnumValueOptions
2929
- google.cloud.pubsub_v1.types.ExpirationPolicy
3030
- google.cloud.pubsub_v1.types.ExtensionRangeOptions
31+
- google.cloud.pubsub_v1.types.FeatureSet
3132
- google.cloud.pubsub_v1.types.FieldDescriptorProto
3233
- google.cloud.pubsub_v1.types.FieldMask
3334
- google.cloud.pubsub_v1.types.FieldOptions
@@ -236,6 +237,11 @@ references:
236237
name: ExtensionRangeOptions
237238
parent: google.cloud.pubsub_v1.types
238239
uid: google.cloud.pubsub_v1.types.ExtensionRangeOptions
240+
- fullName: google.cloud.pubsub_v1.types.FeatureSet
241+
isExternal: false
242+
name: FeatureSet
243+
parent: google.cloud.pubsub_v1.types
244+
uid: google.cloud.pubsub_v1.types.FeatureSet
239245
- fullName: google.cloud.pubsub_v1.types.FieldDescriptorProto
240246
isExternal: false
241247
name: FieldDescriptorProto

tests/testdata/goldens/gapic-combo/toc.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,18 @@
129129
uid: google.cloud.pubsub_v1.types.ExtensionRangeOptions.Declaration
130130
name: ExtensionRangeOptions
131131
uid: google.cloud.pubsub_v1.types.ExtensionRangeOptions
132+
- name: FeatureSet
133+
uid: google.cloud.pubsub_v1.types.FeatureSet
132134
- name: FieldDescriptorProto
133135
uid: google.cloud.pubsub_v1.types.FieldDescriptorProto
134136
- name: FieldMask
135137
uid: google.cloud.pubsub_v1.types.FieldMask
136-
- name: FieldOptions
138+
- items:
139+
- name: Overview
140+
uid: google.cloud.pubsub_v1.types.FieldOptions
141+
- name: EditionDefault
142+
uid: google.cloud.pubsub_v1.types.FieldOptions.EditionDefault
143+
name: FieldOptions
137144
uid: google.cloud.pubsub_v1.types.FieldOptions
138145
- name: FileDescriptorProto
139146
uid: google.cloud.pubsub_v1.types.FileDescriptorProto

0 commit comments

Comments
 (0)