69
69
ModuleDescriptionDict ,
70
70
Options ,
71
71
)
72
- from pylint .utils import ASTWalker , FileState , LinterStats , utils
72
+ from pylint .utils import ASTWalker , FileState , LinterStats , merge_stats , utils
73
73
74
74
MANAGER = astroid .MANAGER
75
75
@@ -320,6 +320,7 @@ def __init__(
320
320
321
321
# Attributes related to stats
322
322
self .stats = LinterStats ()
323
+ self .all_stats : list [LinterStats ] = []
323
324
324
325
# Attributes related to (command-line) options and their parsing
325
326
self .options : Options = options + _make_linter_options (self )
@@ -951,12 +952,17 @@ def _expand_files(
951
952
def set_current_module (self , modname : str , filepath : str | None = None ) -> None :
952
953
"""Set the name of the currently analyzed module and
953
954
init statistics for it.
955
+
956
+ Save current stats before init to make sure no counters for
957
+ error, statement, etc are missed.
954
958
"""
955
959
if not modname and filepath is None :
956
960
return
957
961
self .reporter .on_set_current_module (modname or "" , filepath )
958
962
self .current_name = modname
959
963
self .current_file = filepath or modname
964
+ self .all_stats .append (self .stats )
965
+ self .stats = LinterStats ()
960
966
self .stats .init_single_module (modname or "" )
961
967
962
968
# If there is an actual filepath we might need to update the config attribute
@@ -1013,7 +1019,7 @@ def _astroid_module_checker(
1013
1019
rawcheckers = rawcheckers ,
1014
1020
)
1015
1021
1016
- # notify global end
1022
+ # notify end of module if jobs>1 or use-local-configs=y, global end otherwise
1017
1023
self .stats .statement = walker .nbstatements
1018
1024
for checker in reversed (_checkers ):
1019
1025
checker .close ()
@@ -1147,14 +1153,18 @@ def generate_reports(self, verbose: bool = False) -> int | None:
1147
1153
1148
1154
if persistent run, pickle results for later comparison
1149
1155
"""
1156
+ self .config = self ._base_config
1150
1157
# Display whatever messages are left on the reporter.
1151
1158
self .reporter .display_messages (report_nodes .Section ())
1159
+ # current self.stats is needed in merge - it contains stats from last module
1160
+ # separate variable to avoid modifying any stats during reporting
1161
+ self .finished_run_stats = merge_stats ([self .stats , * self .all_stats ])
1152
1162
if not self .file_state ._is_base_filestate :
1153
1163
# load previous results if any
1154
1164
previous_stats = load_results (self .file_state .base_name )
1155
- self .reporter .on_close (self .stats , previous_stats )
1165
+ self .reporter .on_close (self .finished_run_stats , previous_stats )
1156
1166
if self .config .reports :
1157
- sect = self .make_reports (self .stats , previous_stats )
1167
+ sect = self .make_reports (self .finished_run_stats , previous_stats )
1158
1168
else :
1159
1169
sect = report_nodes .Section ()
1160
1170
@@ -1163,9 +1173,9 @@ def generate_reports(self, verbose: bool = False) -> int | None:
1163
1173
score_value = self ._report_evaluation (verbose )
1164
1174
# save results if persistent run
1165
1175
if self .config .persistent :
1166
- save_results (self .stats , self .file_state .base_name )
1176
+ save_results (self .finished_run_stats , self .file_state .base_name )
1167
1177
else :
1168
- self .reporter .on_close (self .stats , LinterStats ())
1178
+ self .reporter .on_close (self .finished_run_stats , LinterStats ())
1169
1179
score_value = None
1170
1180
return score_value
1171
1181
@@ -1175,35 +1185,35 @@ def _report_evaluation(self, verbose: bool = False) -> int | None:
1175
1185
# syntax error preventing pylint from further processing)
1176
1186
note = None
1177
1187
previous_stats = load_results (self .file_state .base_name )
1178
- if self .stats .statement == 0 :
1188
+ if self .finished_run_stats .statement == 0 :
1179
1189
return note
1180
1190
1181
1191
# get a global note for the code
1182
1192
evaluation = self .config .evaluation
1183
1193
try :
1184
1194
stats_dict = {
1185
- "fatal" : self .stats .fatal ,
1186
- "error" : self .stats .error ,
1187
- "warning" : self .stats .warning ,
1188
- "refactor" : self .stats .refactor ,
1189
- "convention" : self .stats .convention ,
1190
- "statement" : self .stats .statement ,
1191
- "info" : self .stats .info ,
1195
+ "fatal" : self .finished_run_stats .fatal ,
1196
+ "error" : self .finished_run_stats .error ,
1197
+ "warning" : self .finished_run_stats .warning ,
1198
+ "refactor" : self .finished_run_stats .refactor ,
1199
+ "convention" : self .finished_run_stats .convention ,
1200
+ "statement" : self .finished_run_stats .statement ,
1201
+ "info" : self .finished_run_stats .info ,
1192
1202
}
1193
1203
note = eval (evaluation , {}, stats_dict ) # pylint: disable=eval-used
1194
1204
except Exception as ex : # pylint: disable=broad-except
1195
1205
msg = f"An exception occurred while rating: { ex } "
1196
1206
else :
1197
- self .stats .global_note = note
1207
+ self .finished_run_stats .global_note = note
1198
1208
msg = f"Your code has been rated at { note :.2f} /10"
1199
1209
if previous_stats :
1200
1210
pnote = previous_stats .global_note
1201
1211
if pnote is not None :
1202
1212
msg += f" (previous run: { pnote :.2f} /10, { note - pnote :+.2f} )"
1203
1213
1204
1214
if verbose :
1205
- checked_files_count = self .stats .node_count ["module" ]
1206
- unchecked_files_count = self .stats .undocumented ["module" ]
1215
+ checked_files_count = self .finished_run_stats .node_count ["module" ]
1216
+ unchecked_files_count = self .finished_run_stats .undocumented ["module" ]
1207
1217
msg += f"\n Checked { checked_files_count } files, skipped { unchecked_files_count } files"
1208
1218
1209
1219
if self .config .score :
0 commit comments