90 @param toktext the text of the token (string) |
92 @param toktext the text of the token (string) |
91 @param srow starting row of the token (int) |
93 @param srow starting row of the token (int) |
92 @param scol starting column of the token (int) |
94 @param scol starting column of the token (int) |
93 @param line logical line the token was found (string) |
95 @param line logical line the token was found (string) |
94 """ |
96 """ |
95 self.tokenlist.append(Token(type=toktype, text=toktext, row=srow, |
97 self.tokenlist.append(Token(type=toktype, text=toktext, row=srow, |
96 col=scol, line=line)) |
98 col=scol, line=line)) |
97 |
99 |
98 spacer = ' ' |
100 spacer = ' ' |
99 |
101 |
|
102 |
100 class SourceStat(object): |
103 class SourceStat(object): |
101 """ |
104 """ |
102 Class used to calculate and store the source code statistics. |
105 Class used to calculate and store the source code statistics. |
103 """ |
106 """ |
104 def __init__(self): |
107 def __init__(self): |
105 """ |
108 """ |
106 Constructor |
109 Constructor |
107 """ |
110 """ |
108 self.identifiers = [] # list of identifiers in order of appearance |
111 self.identifiers = [] # list of identifiers in order of appearance |
109 self.active = [('TOTAL ',-1,0)] # stack of active identifiers and indent levels |
112 self.active = [('TOTAL ', -1, 0)] # stack of active identifiers and indent levels |
110 self.counters = {} # counters per identifier |
113 self.counters = {} # counters per identifier |
111 self.indent_level = 0 |
114 self.indent_level = 0 |
112 |
115 |
113 def indent(self, tok): |
116 def indent(self, tok): |
114 """ |
117 """ |
115 Public method used to increment the indentation level. |
118 Public method used to increment the indentation level. |
189 @param key key of the value to be retrieved (string) |
192 @param key key of the value to be retrieved (string) |
190 @return the value of the requested counter (int) |
193 @return the value of the requested counter (int) |
191 """ |
194 """ |
192 return self.counters.get(id, {}).get(key, 0) |
195 return self.counters.get(id, {}).get(key, 0) |
193 |
196 |
|
197 |
194 def summarize(total, key, value): |
198 def summarize(total, key, value): |
195 """ |
199 """ |
196 Module function used to collect overall statistics. |
200 Module function used to collect overall statistics. |
197 |
201 |
198 @param total the dictionary for the overall statistics |
202 @param total the dictionary for the overall statistics |
201 @return the value added to the overall statistics |
205 @return the value added to the overall statistics |
202 """ |
206 """ |
203 total[key] = total.setdefault(key, 0) + value |
207 total[key] = total.setdefault(key, 0) + value |
204 return value |
208 return value |
205 |
209 |
|
210 |
206 def analyze(filename, total): |
211 def analyze(filename, total): |
207 """ |
212 """ |
208 Module function used analyze the source of a Python file. |
213 Module function used analyze the source of a Python file. |
209 |
214 |
210 @param filename name of the Python file to be analyzed (string) |
215 @param filename name of the Python file to be analyzed (string) |
211 @param total dictionary receiving the overall code statistics |
216 @param total dictionary receiving the overall code statistics |
212 @return a statistics object with the collected code statistics (SourceStat) |
217 @return a statistics object with the collected code statistics (SourceStat) |
228 if tok.type == NEWLINE: |
233 if tok.type == NEWLINE: |
229 stats.inc('nloc') |
234 stats.inc('nloc') |
230 elif tok.type == COMMENT: |
235 elif tok.type == COMMENT: |
231 stats.inc('comments') |
236 stats.inc('comments') |
232 elif tok.type == EMPTY: |
237 elif tok.type == EMPTY: |
233 if parser.tokenlist[idx-1].type == token.OP: |
238 if parser.tokenlist[idx - 1].type == token.OP: |
234 stats.inc('nloc') |
239 stats.inc('nloc') |
235 else: |
240 else: |
236 stats.inc('empty') |
241 stats.inc('empty') |
237 elif tok.type == INDENT: |
242 elif tok.type == INDENT: |
238 stats.indent(tok) |
243 stats.indent(tok) |
239 elif tok.type == DEDENT: |
244 elif tok.type == DEDENT: |
240 stats.dedent(tok) |
245 stats.dedent(tok) |
241 elif tok.type == KEYWORD: |
246 elif tok.type == KEYWORD: |
242 if tok.text in ("class", "def"): |
247 if tok.text in ("class", "def"): |
243 stats.push(parser.tokenlist[idx+1].text, tok.row) |
248 stats.push(parser.tokenlist[idx + 1].text, tok.row) |
244 |
249 |
245 # collect overall statistics |
250 # collect overall statistics |
246 summarize(total, 'lines', parser.lines) |
251 summarize(total, 'lines', parser.lines) |
247 summarize(total, 'bytes', len(text)) |
252 summarize(total, 'bytes', len(text)) |
248 summarize(total, 'comments', stats.getCounter('TOTAL ', 'comments')) |
253 summarize(total, 'comments', stats.getCounter('TOTAL ', 'comments')) |
249 summarize(total, 'empty lines', stats.getCounter('TOTAL ', 'empty')) |
254 summarize(total, 'empty lines', stats.getCounter('TOTAL ', 'empty')) |
250 summarize(total, 'non-commentary lines', stats.getCounter('TOTAL ', 'nloc')) |
255 summarize(total, 'non-commentary lines', stats.getCounter('TOTAL ', 'nloc')) |
251 |
256 |
252 return stats |
257 return stats |
253 |
258 |
|
259 |
254 def main(): |
260 def main(): |
255 """ |
261 """ |
256 Modules main function used when called as a script. |
262 Modules main function used when called as a script. |
257 |
263 |
258 This function simply loops over all files given on the commandline |
264 This function simply loops over all files given on the commandline |