-
Notifications
You must be signed in to change notification settings - Fork 1
/
yolo.py
executable file
·174 lines (118 loc) · 4.52 KB
/
yolo.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
#! /usr/bin/env python
import re
import os
import json
import configargparse
import simplejson as json
from git import Repo, InvalidGitRepositoryError
YOLO_TAG_REGEX = re.compile(
'[ \t]*(#|(/\*)|(//)|(\<\!\-\-)) yolo, (?P<reason>[^\n]*)')
SORRY_TAG_REGEX = re.compile('[ \t]*(#|(/\*)|(//)|(\<\!\-\-)) sorry')
def main():
options = get_options()
yolo_results = [yolo_file(sourcefile)
for sourcefile in options.sourcefiles]
if len(yolo_results) is 1:
print json.dumps(yolo_results[0], cls=GitObjectEncoder)
else:
print json.dumps(yolo_results, cls=GitObjectEncoder)
# yolo, these options are just mocked up
def get_options():
options_parser = configargparse.ArgParser(
default_config_files=['./.yolorc'])
options_parser.add('-c', '--config', required=False, is_config_file=True,
env_var='YOLO_CONFIG', help='config file path')
options_parser.add('sourcefiles', nargs='+',
help='the sourcefile(s) to run yolo on')
return options_parser.parse_args()
# sorry
# yolo, we can decide field names later
def yolo(source_lines):
if isinstance(source_lines, (basestring,)):
source_lines = source_lines.split('\n')
yolo_blocks = find_yolo_blocks(source_lines)
yolo_data = {
'yolo_blocks': yolo_blocks,
'yolo_count': len(yolo_blocks)
}
return yolo_data
# sorry
def yolo_file(filename):
# yolo, this means we assume the file is checked in... hahaha
repo = find_git_repo(filename)
# sorry
with open(filename, 'rb') as sourcefile:
yolo_data = yolo(sourcefile)
yolo_blocks = yolo_data['yolo_blocks']
if repo:
blame_data = get_blame_data(repo, 'HEAD', filename)
line_number = 1
for yolo_block in yolo_blocks:
for line_info in yolo_block['lines']:
line_info['blame'] = blame_data[line_info['line_number']]
yolo_data['authors'] = list(set(commit.author
for commit in blame_data.values()))
return yolo_data
# yolo, wip implementation
def find_yolo_blocks(source_lines):
yolo_blocks = []
source_lines = enumerate(source_lines, 1)
for line_number, source_line in source_lines:
if is_yolo_tag(source_line):
reason = YOLO_TAG_REGEX.match(source_line).groupdict()['reason']
start_line_number = line_number + 1
# start grabbing the yoloed lines, look for a sorry tag
yoloed_lines = []
for yoloed_line_number, yoloed_line in source_lines:
if is_sorry_tag(yoloed_line):
end_line_number = yoloed_line_number - 1
yolo_blocks.append({
'reason': reason,
'start_line_number': start_line_number,
'end_line_number': end_line_number,
'lines': yoloed_lines
})
break # back to looking for yolo tags
else:
yoloed_lines.append({
'line': yoloed_line,
'line_number': yoloed_line_number
})
return yolo_blocks
# sorry
def find_git_repo(filename):
path = os.path.abspath(filename)
while path is not '/':
path = os.path.dirname(path)
try:
return Repo(path)
except InvalidGitRepositoryError:
continue
def get_blame_data(repo, rev, sourcefile):
lines_by_commit = repo.blame(rev, sourcefile)
line_number = 1
blame_data = {}
for commit, lines in lines_by_commit:
for line in lines:
blame_data[line_number] = commit
line_number += 1
return blame_data
def is_yolo_tag(source_line):
return YOLO_TAG_REGEX.match(source_line) is not None
def is_sorry_tag(source_line):
return SORRY_TAG_REGEX.match(source_line) is not None
# yolo, this encoder is so verbose... its mostly proof of concept
class GitObjectEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, (set,)):
return [self.default(o) for o in obj]
if hasattr(obj, '__slots__'):
data = {key: getattr(obj, key)
for key in obj.__slots__ if hasattr(obj, key) and
key not in ('parents',)}
return data
else:
return super(GitObjectEncoder, self).default(obj)
# sorry
if __name__ == '__main__':
main()