Skip to content

Commit ca2714c

Browse files
committed
♻️ ⚡ 🎨 ✨ refactor CodeCounter
1 parent d0b9526 commit ca2714c

File tree

1 file changed

+34
-115
lines changed

1 file changed

+34
-115
lines changed

code_counter/core/counter.py

Lines changed: 34 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
# -*- coding: utf-8 -*-
33

44
import os
5-
import re
65
from collections import defaultdict
76
from code_counter.conf.config import Config
7+
from code_counter.core.countable.iterator import CountableFileIterator
88

99

1010
class CodeCounter:
@@ -20,7 +20,6 @@ def __init__(self):
2020

2121
self.search_args = None
2222
self.lines_of_language = {}
23-
self.pattern = None
2423

2524
self.result = {
2625
'total': {
@@ -43,35 +42,50 @@ def setSearchArgs(self, args):
4342

4443
self.lines_of_language = {suffix: 0 for suffix in self.config.suffix}
4544

46-
regex = r'.*\.({})$'.format('|'.join(self.config.suffix))
47-
self.pattern = re.compile(regex)
48-
4945
def search(self):
50-
if not self.search_args:
51-
raise Exception('search_args is None, please invoke setSearchArgs first.')
46+
if self.search_args is None:
47+
raise Exception('search_args is None, please invoke the `setSearchArgs` function first.')
5248

5349
input_path = self.search_args.input_path
54-
output_path = self.search_args.output_path
50+
if not input_path:
51+
print('{} is not a validate path.'.format(input_path))
52+
return
5553

54+
output_path = self.search_args.output_path
5655
output_file = open(output_path, 'w') if output_path else None
5756

5857
if self.search_args.verbose:
59-
print('\n\t{}'.format("SEARCHING"), file=output_file)
60-
print("\t{}".format('=' * 20), file=output_file)
61-
print('\t{:>10} |{:>10} |{:>10} |{:>10} |{:>10} | {}'
62-
.format("File Type", "Lines", "Code", "Blank", "Comment", "File Path"), file=output_file)
63-
print("\t{}".format('-' * 90), file=output_file)
64-
65-
if not input_path:
66-
print('{} is not a validate path.'.format(input_path))
67-
return
58+
self.print_searching_verbose_info(output_file)
6859

6960
for path in input_path:
7061
if os.path.exists(path):
71-
self.__search(path, output_file)
62+
for cf in CountableFileIterator(path):
63+
cf.count()
64+
if self.search_args.verbose:
65+
print(cf, file=output_file)
66+
self.files_of_language[cf.file_type] += 1
67+
self.total_file_lines += cf.file_lines
68+
self.total_code_lines += cf.code_lines
69+
self.total_blank_lines += cf.blank_lines
70+
self.total_comment_lines += cf.comment_lines
71+
self.lines_of_language[cf.file_type] += cf.code_lines
7272
else:
7373
print('{} is not a validate path.'.format(path))
74+
exit(1)
75+
76+
self.print_result_info(output_file)
77+
78+
if output_file:
79+
output_file.close()
80+
81+
def print_searching_verbose_info(self, output_file=None):
82+
print('\n\t{}'.format("SEARCHING"), file=output_file)
83+
print("\t{}".format('=' * 20), file=output_file)
84+
print('\t{:>10} |{:>10} |{:>10} |{:>10} |{:>10} | {}'
85+
.format("File Type", "Lines", "Code", "Blank", "Comment", "File Path"), file=output_file)
86+
print("\t{}".format('-' * 90), file=output_file)
7487

88+
def print_result_info(self, output_file=None):
7589
print('\n\t{}'.format("RESULT"), file=output_file)
7690
print("\t{}".format('=' * 20), file=output_file)
7791
print("\t{:<20}:{:>8} ({:>7})"
@@ -109,106 +123,11 @@ def search(self):
109123

110124
for tp, cnt in self.files_of_language.items():
111125
code_line = self.lines_of_language[tp]
126+
self.result['code'][tp] = code_line
127+
self.result['file'][tp] = cnt
112128
print("\t{:>10} |{:>10} |{:>10} |{:>10} |{:>10}".format(
113129
tp, cnt, '%.2f%%' % (cnt / total_files * 100),
114130
code_line, '%.2f%%' % (code_line / self.total_code_lines * 100)), file=output_file)
115-
self.result['code'][tp] = code_line
116-
self.result['file'][tp] = cnt
117-
118-
if output_file:
119-
output_file.close()
120-
121-
def __search(self, input_path, output_file=None):
122-
"""
123-
:param input_path: input file path
124-
:param output_file: output file path
125-
:return:
126-
"""
127-
if os.path.isdir(input_path):
128-
files = os.listdir(input_path)
129-
for file in files:
130-
file_path = os.path.join(input_path, file)
131-
if os.path.isdir(file_path):
132-
if os.path.split(file_path)[-1] in self.config.ignore:
133-
continue
134-
self.__search(file_path, output_file)
135-
elif os.path:
136-
file_path = os.path.join(input_path, file)
137-
self.__format_output(file_path, output_file)
138-
elif os.path.isfile(input_path):
139-
self.__format_output(input_path, output_file)
140-
141-
def __format_output(self, file_path, output_file=None):
142-
"""
143-
:param file_path: input file path
144-
:param output_file: output file path
145-
:return:
146-
"""
147-
try:
148-
res = re.match(self.pattern, file_path)
149-
if res:
150-
single = self.count_single(file_path, output_file)
151-
file_lines = single['file_lines']
152-
code_lines = single['code_lines']
153-
blank_lines = single['blank_lines']
154-
comment_lines = single['comment_lines']
155-
156-
file_type = os.path.splitext(file_path)[1][1:]
157-
self.files_of_language[file_type] += 1
158-
159-
if self.search_args.verbose:
160-
print('\t{:>10} |{:>10} |{:>10} |{:>10} |{:>10} | {}'
161-
.format(file_type, file_lines, code_lines, blank_lines, comment_lines, file_path),
162-
file=output_file)
163-
164-
self.total_file_lines += file_lines
165-
self.total_code_lines += code_lines
166-
self.total_blank_lines += blank_lines
167-
self.total_comment_lines += comment_lines
168-
self.lines_of_language[file_type] += code_lines
169-
except AttributeError as e:
170-
print(e)
171-
172-
def count_single(self, file_path, output_file=None):
173-
"""
174-
:param file_path: the file you want to count
175-
:param output_file: output file path
176-
:return: single { file_lines, code_lines, blank_lines, comment_lines }
177-
"""
178-
assert os.path.isfile(file_path), "Function: 'code_counter' need a file path, but {} is not.".format(file_path)
179-
180-
single = {
181-
'file_lines': 0,
182-
'code_lines': 0,
183-
'blank_lines': 0,
184-
'comment_lines': 0,
185-
}
186-
187-
with open(file_path, 'rb') as handle:
188-
for line_number, raw_line in enumerate(handle):
189-
try:
190-
line = raw_line.strip().decode('utf8')
191-
except UnicodeDecodeError:
192-
try:
193-
# If the code line contain Chinese string, decode it as gbk
194-
line = raw_line.strip().decode('gbk')
195-
except UnicodeDecodeError:
196-
if self.search_args.verbose:
197-
print('\n\t{:>10} | decode line occurs a problem, non-count it, at File "{}", line {}:'
198-
.format('WARN', file_path, line_number),
199-
file=output_file)
200-
print('\t{:>10} | {}\n'
201-
.format(' ', raw_line))
202-
continue
203-
204-
single['file_lines'] += 1
205-
if not line:
206-
single['blank_lines'] += 1
207-
elif line.startswith(tuple(self.config.comment)):
208-
single['comment_lines'] += 1
209-
else:
210-
single['code_lines'] += 1
211-
return single
212131

213132
def visualize(self):
214133
from matplotlib import pyplot as plt

0 commit comments

Comments
 (0)