7
7
8
8
import abc
9
9
import ast
10
+ import inspect
10
11
from dataclasses import dataclass
11
- from typing import Dict , List , Optional , Tuple , cast
12
+ from typing import Dict , List , Optional , Tuple , cast , Callable
12
13
13
14
from docstring_parser import parse
14
15
from pyre_extensions import none_throws
18
19
# pyre-ignore-all-errors[16]
19
20
20
21
21
- def get_arg_names (app_specs_func_def : ast .FunctionDef ) -> List [str ]:
22
- arg_names = []
23
- fn_args = app_specs_func_def .args
24
- for arg_def in fn_args .args :
25
- arg_names .append (arg_def .arg )
26
- if fn_args .vararg :
27
- arg_names .append (fn_args .vararg .arg )
28
- for arg in fn_args .kwonlyargs :
29
- arg_names .append (arg .arg )
30
- return arg_names
22
+ def _get_default_arguments_descriptions (fn : Callable [..., object ]) -> Dict [str , str ]:
23
+ parameters = inspect .signature (fn ).parameters
24
+ args_decs = {}
25
+ for parameter_name in parameters .keys ():
26
+ args_decs [parameter_name ] = parameter_name
27
+ return args_decs
31
28
32
29
33
- def parse_fn_docstring ( func_description : str ) -> Tuple [str , Dict [str , str ]]:
30
+ def get_fn_docstring ( fn : Callable [..., object ] ) -> Tuple [str , Dict [str , str ]]:
34
31
"""
35
- Given a docstring in a google-style format, returns the function description and
36
- description of all arguments.
37
- See: https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html
32
+ Parses the function and arguments description from the provided function. Docstring should be in
33
+ gogle-style format: https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html
34
+
35
+ If function has no docstring, the function descriptoin will be the name of the function, and
36
+ the arguments descriptions will be names of the arguments.
37
+
38
+ The arguments that are not present in the docstring will contain their names as description
39
+
40
+ Args:
41
+ fn: Function with or without docstring
42
+
43
+ Returns:
44
+ function description, arguments description where key is the name of the argument and value
45
+ if the description
38
46
"""
39
- args_description = {}
47
+ args_description = _get_default_arguments_descriptions (fn )
48
+ func_description = inspect .getdoc (fn )
49
+ if not func_description :
50
+ return fn .__name__ , args_description
40
51
docstring = parse (func_description )
41
52
for param in docstring .params :
42
53
args_description [param .arg_name ] = param .description
43
54
short_func_description = docstring .short_description
44
- return (short_func_description or "" , args_description )
45
-
46
-
47
- def _get_fn_docstring (
48
- source : str , function_name : str
49
- ) -> Optional [Tuple [str , Dict [str , str ]]]:
50
- module = ast .parse (source )
51
- for expr in module .body :
52
- if type (expr ) == ast .FunctionDef :
53
- func_def = cast (ast .FunctionDef , expr )
54
- if func_def .name == function_name :
55
- docstring = ast .get_docstring (func_def )
56
- if not docstring :
57
- return None
58
- return parse_fn_docstring (docstring )
59
- return None
60
-
61
-
62
- def get_short_fn_description (path : str , function_name : str ) -> Optional [str ]:
63
- source = read_conf_file (path )
64
- docstring = _get_fn_docstring (source , function_name )
65
- if not docstring :
66
- return None
67
- return docstring [0 ]
55
+ return (short_func_description or fn .__name__ , args_description )
68
56
69
57
70
58
@dataclass
@@ -91,38 +79,6 @@ def _gen_linter_message(self, description: str, lineno: int) -> LinterMessage:
91
79
)
92
80
93
81
94
- class TorchxDocstringValidator (TorchxFunctionValidator ):
95
- def validate (self , app_specs_func_def : ast .FunctionDef ) -> List [LinterMessage ]:
96
- """
97
- Validates the docstring of the `get_app_spec` function. Criteria:
98
- * There mast be google-style docstring
99
- * If there are more than zero arguments, there mast be a `Args:` section defined
100
- with all arguments included.
101
- """
102
- docsting = ast .get_docstring (app_specs_func_def )
103
- lineno = app_specs_func_def .lineno
104
- if not docsting :
105
- desc = (
106
- f"`{ app_specs_func_def .name } ` is missing a Google Style docstring, please add one. "
107
- "For more information on the docstring format see: "
108
- "https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html"
109
- )
110
- return [self ._gen_linter_message (desc , lineno )]
111
-
112
- arg_names = get_arg_names (app_specs_func_def )
113
- _ , docstring_arg_defs = parse_fn_docstring (docsting )
114
- missing_args = [
115
- arg_name for arg_name in arg_names if arg_name not in docstring_arg_defs
116
- ]
117
- if len (missing_args ) > 0 :
118
- desc = (
119
- f"`{ app_specs_func_def .name } ` not all function arguments are present"
120
- f" in the docstring. Missing args: { missing_args } "
121
- )
122
- return [self ._gen_linter_message (desc , lineno )]
123
- return []
124
-
125
-
126
82
class TorchxFunctionArgsValidator (TorchxFunctionValidator ):
127
83
def validate (self , app_specs_func_def : ast .FunctionDef ) -> List [LinterMessage ]:
128
84
linter_errors = []
@@ -149,7 +105,6 @@ def _validate_arg_def(
149
105
)
150
106
]
151
107
if isinstance (arg_def .annotation , ast .Name ):
152
- # TODO(aivanou): add support for primitive type check
153
108
return []
154
109
complex_type_def = cast (ast .Subscript , none_throws (arg_def .annotation ))
155
110
if complex_type_def .value .id == "Optional" :
@@ -239,12 +194,6 @@ class TorchFunctionVisitor(ast.NodeVisitor):
239
194
Visitor that finds the component_function and runs registered validators on it.
240
195
Current registered validators:
241
196
242
- * TorchxDocstringValidator - validates the docstring of the function.
243
- Criteria:
244
- * There format should be google-python
245
- * If there are more than zero arguments defined, there
246
- should be obligatory `Args:` section that describes each argument on a new line.
247
-
248
197
* TorchxFunctionArgsValidator - validates arguments of the function.
249
198
Criteria:
250
199
* Each argument should be annotated with the type
@@ -260,7 +209,6 @@ class TorchFunctionVisitor(ast.NodeVisitor):
260
209
261
210
def __init__ (self , component_function_name : str ) -> None :
262
211
self .validators = [
263
- TorchxDocstringValidator (),
264
212
TorchxFunctionArgsValidator (),
265
213
TorchxReturnValidator (),
266
214
]
0 commit comments