-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathautogen.py
213 lines (171 loc) · 6.62 KB
/
autogen.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
import ast
import os
import re
def delete_space(parts, start, end):
if start > end or end >= len(parts):
return None
count = 0
while count < len(parts[start]):
if parts[start][count] == ' ':
count += 1
else:
break
return '\n'.join(y for y in [x[count:] for x in parts[start:end + 1] if len(x) > count])
def change_args_to_dict(string):
if string is None:
return None
ans = []
strings = string.split('\n')
ind = 1
start = 0
while ind <= len(strings):
if ind < len(strings) and strings[ind].startswith(" "):
ind += 1
else:
if start < ind:
ans.append('\n'.join(strings[start:ind]))
start = ind
ind += 1
d = {}
for line in ans:
if ":" in line and len(line) > 0:
lines = line.split(":")
d[lines[0]] = lines[1].strip()
return d
def remove_next_line(comments):
for x in comments:
if comments[x] is not None and '\n' in comments[x]:
comments[x] = ' '.join(comments[x].split('\n'))
return comments
def skip_space_line(parts, ind):
while ind < len(parts):
if re.match(r'^\s*$', parts[ind]):
ind += 1
else:
break
return ind
# check if comment is None or len(comment) == 0 return {}
def parse_func_string(comment):
if comment is None or len(comment) == 0:
return {}
comments = {}
paras = ('Args', 'Attributes', 'Returns', 'Raises')
comment_parts = ['short_description', 'long_description', 'Args', 'Attributes', 'Returns', 'Raises']
for x in comment_parts:
comments[x] = None
parts = re.split(r'\n', comment)
ind = 1
while ind < len(parts):
if re.match(r'^\s*$', parts[ind]):
break
else:
ind += 1
comments['short_description'] = '\n'.join(['\n'.join(re.split('\n\s+', x.strip())) for x in parts[0:ind]]).strip(
':\n\t ')
ind = skip_space_line(parts, ind)
start = ind
while ind < len(parts):
if parts[ind].strip().startswith(paras):
break
else:
ind += 1
long_description = '\n'.join(['\n'.join(re.split('\n\s+', x.strip())) for x in parts[start:ind]]).strip(':\n\t ')
comments['long_description'] = long_description
ind = skip_space_line(paras, ind)
while ind < len(parts):
if parts[ind].strip().startswith(paras):
start = ind
start_with = parts[ind].strip()
ind += 1
while ind < len(parts):
if parts[ind].strip().startswith(paras):
break
else:
ind += 1
part = delete_space(parts, start + 1, ind - 1)
if start_with.startswith(paras[0]):
comments[paras[0]] = change_args_to_dict(part)
elif start_with.startswith(paras[1]):
comments[paras[1]] = change_args_to_dict(part)
elif start_with.startswith(paras[2]):
comments[paras[2]] = change_args_to_dict(part)
elif start_with.startswith(paras[3]):
comments[paras[3]] = part
ind = skip_space_line(parts, ind)
else:
ind += 1
remove_next_line(comments)
return comments
sample_comment = """Fetches rows from a Bigtable.
Hello world.
Retrieves rows pertaining to the given keys from the Table instance
represented by big_table. Silly things may happen if
other_silly_variable is not None.
Retrieves rows pertaining to the given keys from the Table instance
represented by big_table. Silly things may happen if
other_silly_variable is not None.
Args:
big_table: An open Bigtable Table instance.
keys: A sequence of strings representing the key of each table row
to fetch.
other_silly_variable: Another optional variable, that has a much
longer name than the other args, and which does nothing.
Raises:
IOError: An error occurred accessing the bigtable.Table object.
"""
def to_md(comment_dict):
doc = ''
if 'short_description' in comment_dict:
doc += comment_dict['short_description']
doc += '\n'
if 'long_description' in comment_dict:
doc += comment_dict['long_description']
doc += '\n'
if 'Args' in comment_dict and comment_dict['Args'] is not None:
doc += '#####Args\n'
for arg, des in comment_dict['Args'].items():
doc += '* **' + arg + '**: ' + des + '\n\n'
if 'Attributes' in comment_dict and comment_dict['Attributes'] is not None:
doc += '#####Attributes\n'
for arg, des in comment_dict['Attributes'].items():
doc += '* **' + arg + '**: ' + des + '\n\n'
if 'Returns' in comment_dict and comment_dict['Returns'] is not None:
doc += '#####Returns\n'
if isinstance(comment_dict['Returns'], str):
doc += comment_dict['Returns']
doc += '\n'
else:
for arg, des in comment_dict['Returns'].items():
doc += '* **' + arg + '**: ' + des + '\n\n'
return doc
def get_func_comments(function_definitions):
doc = ''
for f in function_definitions:
temp_str = to_md(parse_func_string(ast.get_docstring(f)))
if temp_str != '':
doc += '###' + f.name + '\n' + temp_str
return doc
def get_comments_str(file_name):
with open(file_name) as fd:
file_contents = fd.read()
module = ast.parse(file_contents)
function_definitions = [node for node in module.body if isinstance(node, ast.FunctionDef)]
doc = get_func_comments(function_definitions)
class_definitions = [node for node in module.body if isinstance(node, ast.ClassDef)]
for class_def in class_definitions:
temp_str = to_md(parse_func_string(ast.get_docstring(class_def)))
method_definitions = [node for node in class_def.body if isinstance(node, ast.FunctionDef)]
temp_str += get_func_comments(method_definitions)
if temp_str != '':
doc += '##' + class_def.name + '\n' + temp_str
return doc
def extract_comments(directory):
for parent, dir_names, file_names in os.walk(directory):
for file_name in file_names:
if os.path.splitext(file_name)[1] == '.py' and file_name != '__init__.py':
# with open
doc = get_comments_str(os.path.join(parent, file_name))
output_file = open(os.path.join('docs/temp/', file_name[:-3] + '.md'), 'w')
output_file.write(doc)
output_file.close()
extract_comments('../autokaggle')