From: Simon Glass <simon.glass@canonical.com> Move the print_result_summary() method and baseline state management from Builder to ResultHandler. This includes: - Baseline state attributes (_base_board_dict, _base_err_lines, etc.) - reset_result_summary() to initialise baseline state - print_result_summary() to display build result deltas - get_error_lines() to access the error line count Builder now delegates to ResultHandler for result display and baseline tracking. The OUTCOME_* constants are passed as parameters since they remain defined in builder.py. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- tools/buildman/builder.py | 139 +++------------------------- tools/buildman/resulthandler.py | 154 ++++++++++++++++++++++++++++++-- 2 files changed, 161 insertions(+), 132 deletions(-) diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py index a2d4470b70c..412acfa9e4b 100644 --- a/tools/buildman/builder.py +++ b/tools/buildman/builder.py @@ -305,7 +305,6 @@ class Builder: self._next_delay_update = datetime.now() self._start_time = None self._step = step - self._error_lines = 0 self.no_subdirs = no_subdirs self.full_path = full_path self.verbose_build = verbose_build @@ -364,14 +363,7 @@ class Builder: self._timestamps = None self._verbose = False - # Attributes for result summaries - self._base_board_dict = {} - self._base_err_lines = [] - self._base_warn_lines = [] - self._base_err_line_boards = {} - self._base_warn_line_boards = {} - self._base_config = None - self._base_environment = None + # Note: baseline state for result summaries is now in ResultHandler self._setup_threads(mrproper, per_board_out_dir, test_thread_exceptions) @@ -580,7 +572,7 @@ class Builder: elif self._verbose: terminal.print_clear() boards_selected = {target : result.brd} - self.reset_result_summary(boards_selected) + self._result_handler.reset_result_summary(boards_selected) self.produce_result_summary(result.commit_upto, self.commits, boards_selected) else: @@ -1011,113 +1003,6 @@ class Builder: return (board_dict, err_lines_summary, err_lines_boards, warn_lines_summary, warn_lines_boards, config, environment) - def reset_result_summary(self, board_selected): - """Reset the results summary ready for use. - - Set up the base board list to be all those selected, and set the - error lines to empty. - - Following this, calls to print_result_summary() will use this - information to work out what has changed. - - Args: - board_selected (dict): Dict containing boards to summarise, keyed - by board.target - """ - self._base_board_dict = {} - for brd in board_selected: - self._base_board_dict[brd] = Outcome(0, [], [], {}, {}, {}) - self._base_err_lines = [] - self._base_warn_lines = [] - self._base_err_line_boards = {} - self._base_warn_line_boards = {} - self._base_config = None - self._base_environment = None - - def print_result_summary(self, board_selected, board_dict, err_lines, - err_line_boards, warn_lines, warn_line_boards, - config, environment, show_sizes, show_detail, - show_bloat, show_config, show_environment): - """Compare results with the base results and display delta. - - Only boards mentioned in board_selected will be considered. This - function is intended to be called repeatedly with the results of - each commit. It therefore shows a 'diff' between what it saw in - the last call and what it sees now. - - Args: - board_selected (dict): Dict containing boards to summarise, keyed - by board.target - board_dict (dict): Dict containing boards for which we built this - commit, keyed by board.target. The value is an Outcome object. - err_lines (list): A list of errors for this commit, or [] if there - is none, or we don't want to print errors - err_line_boards (dict): Dict keyed by error line, containing a list - of the Board objects with that error - warn_lines (list): A list of warnings for this commit, or [] if - there is none, or we don't want to print errors - warn_line_boards (dict): Dict keyed by warning line, containing a - list of the Board objects with that warning - config (dict): Dictionary keyed by filename - e.g. '.config'. Each - value is itself a dictionary: - key: config name - value: config value - environment (dict): Dictionary keyed by environment variable, Each - value is the value of environment variable. - show_sizes (bool): Show image size deltas - show_detail (bool): Show size delta detail for each board if - show_sizes - show_bloat (bool): Show detail for each function - show_config (bool): Show config changes - show_environment (bool): Show environment changes - """ - brd_status = ResultHandler.classify_boards( - board_selected, board_dict, self._base_board_dict) - - # Get a list of errors and warnings that have appeared, and disappeared - better_err, worse_err = ResultHandler.calc_error_delta( - self._base_err_lines, self._base_err_line_boards, err_lines, - err_line_boards, '', self._opts.list_error_boards) - better_warn, worse_warn = ResultHandler.calc_error_delta( - self._base_warn_lines, self._base_warn_line_boards, warn_lines, - warn_line_boards, 'w', self._opts.list_error_boards) - - # For the IDE mode, print out all the output - if self._opts.ide: - self._result_handler.print_ide_output(board_selected, board_dict) - - # Display results by arch - if not self._opts.ide: - self._error_lines += self._result_handler.display_arch_results( - board_selected, brd_status, better_err, worse_err, better_warn, - worse_warn, self._opts.show_unknown) - - if show_sizes: - self._result_handler.print_size_summary( - board_selected, board_dict, self._base_board_dict, - show_detail, show_bloat) - - if show_environment and self._base_environment: - self._result_handler.show_environment_changes( - board_selected, board_dict, environment, self._base_environment) - - if show_config and self._base_config: - self._result_handler.show_config_changes( - board_selected, board_dict, config, self._base_config, - self.config_filenames) - - - # Save our updated information for the next call to this function - self._base_board_dict = board_dict - self._base_err_lines = err_lines - self._base_warn_lines = warn_lines - self._base_err_line_boards = err_line_boards - self._base_warn_line_boards = warn_line_boards - self._base_config = config - self._base_environment = environment - - ResultHandler.show_not_built(board_selected, board_dict) - def produce_result_summary(self, commit_upto, commits, board_selected): """Produce a summary of the results for a single commit @@ -1135,11 +1020,14 @@ class Builder: if commits: msg = f'{commit_upto + 1:02d}: {commits[commit_upto].subject}' tprint(msg, colour=self.col.BLUE) - self.print_result_summary(board_selected, board_dict, - err_lines if self._opts.show_errors else [], err_line_boards, - warn_lines if self._opts.show_errors else [], warn_line_boards, - config, environment, self._opts.show_sizes, self._opts.show_detail, - self._opts.show_bloat, self._opts.show_config, self._opts.show_environment) + self._result_handler.print_result_summary( + board_selected, board_dict, + err_lines if self._opts.show_errors else [], err_line_boards, + warn_lines if self._opts.show_errors else [], warn_line_boards, + config, environment, self._opts.show_sizes, self._opts.show_detail, + self._opts.show_bloat, self._opts.show_config, self._opts.show_environment, + self._opts.show_unknown, self._opts.ide, self._opts.list_error_boards, + self.config_filenames) def show_summary(self, commits, board_selected): """Show a build summary for U-Boot for a given board list. @@ -1153,12 +1041,11 @@ class Builder: """ self.commit_count = len(commits) if commits else 1 self.commits = commits - self.reset_result_summary(board_selected) - self._error_lines = 0 + self._result_handler.reset_result_summary(board_selected) for commit_upto in range(0, self.commit_count, self._step): self.produce_result_summary(commit_upto, commits, board_selected) - if not self._error_lines: + if not self._result_handler.get_error_lines(): tprint('(no errors to report)', colour=self.col.GREEN) @@ -1328,7 +1215,7 @@ class Builder: self.commits = commits self._verbose = verbose - self.reset_result_summary(board_selected) + self._result_handler.reset_result_summary(board_selected) builderthread.mkdir(self.base_dir, parents = True) self._prepare_working_space(min(self.num_threads, len(board_selected)), commits is not None) diff --git a/tools/buildman/resulthandler.py b/tools/buildman/resulthandler.py index a2064986729..d1d6232ff97 100644 --- a/tools/buildman/resulthandler.py +++ b/tools/buildman/resulthandler.py @@ -8,8 +8,9 @@ import sys -from buildman.outcome import (BoardStatus, ErrLine, OUTCOME_OK, - OUTCOME_WARNING, OUTCOME_ERROR, OUTCOME_UNKNOWN) +from buildman.outcome import (BoardStatus, ErrLine, Outcome, + OUTCOME_OK, OUTCOME_WARNING, OUTCOME_ERROR, + OUTCOME_UNKNOWN) from u_boot_pylib.terminal import tprint @@ -18,10 +19,19 @@ class ResultHandler: This class is responsible for displaying size information from builds, including per-architecture summaries, per-board details, and per-function - bloat analysis. + bloat analysis. It also manages baseline state for comparing results + between commits. Attributes: col: terminal.Color object for coloured output + _base_board_dict: Last-summarised Dict of boards + _base_err_lines: Last-summarised list of errors + _base_warn_lines: Last-summarised list of warnings + _base_err_line_boards: Dict of error lines to boards + _base_warn_line_boards: Dict of warning lines to boards + _base_config: Last-summarised config + _base_environment: Last-summarised environment + _error_lines: Number of error lines output """ def __init__(self, col, opts): @@ -34,6 +44,16 @@ class ResultHandler: self._col = col self._opts = opts self._builder = None + self._error_lines = 0 + + # Baseline state for result comparisons + self._base_board_dict = {} + self._base_err_lines = [] + self._base_warn_lines = [] + self._base_err_line_boards = {} + self._base_warn_line_boards = {} + self._base_config = None + self._base_environment = None def set_builder(self, builder): """Set the builder for this result handler @@ -43,6 +63,128 @@ class ResultHandler: """ self._builder = builder + def reset_result_summary(self, board_selected): + """Reset the results summary ready for use. + + Set up the base board list to be all those selected, and set the + error lines to empty. + + Following this, calls to print_result_summary() will use this + information to work out what has changed. + + Args: + board_selected (dict): Dict containing boards to summarise, keyed + by board.target + """ + outcome_init = Outcome(0, [], [], {}, {}, {}) + self._base_board_dict = {} + for brd in board_selected: + self._base_board_dict[brd] = outcome_init + self._base_err_lines = [] + self._base_warn_lines = [] + self._base_err_line_boards = {} + self._base_warn_line_boards = {} + self._base_config = None + self._base_environment = None + self._error_lines = 0 + + def print_result_summary(self, board_selected, board_dict, err_lines, + err_line_boards, warn_lines, warn_line_boards, + config, environment, show_sizes, show_detail, + show_bloat, show_config, show_environment, + show_unknown, ide, list_error_boards, + config_filenames): + """Compare results with the base results and display delta. + + Only boards mentioned in board_selected will be considered. This + function is intended to be called repeatedly with the results of + each commit. It therefore shows a 'diff' between what it saw in + the last call and what it sees now. + + Args: + board_selected (dict): Dict containing boards to summarise, keyed + by board.target + board_dict (dict): Dict containing boards for which we built this + commit, keyed by board.target. The value is an Outcome object. + err_lines (list): A list of errors for this commit, or [] if there + is none, or we don't want to print errors + err_line_boards (dict): Dict keyed by error line, containing a list + of the Board objects with that error + warn_lines (list): A list of warnings for this commit, or [] if + there is none, or we don't want to print errors + warn_line_boards (dict): Dict keyed by warning line, containing a + list of the Board objects with that warning + config (dict): Dictionary keyed by filename - e.g. '.config'. Each + value is itself a dictionary: + key: config name + value: config value + environment (dict): Dictionary keyed by environment variable, Each + value is the value of environment variable. + show_sizes (bool): Show image size deltas + show_detail (bool): Show size delta detail for each board if + show_sizes + show_bloat (bool): Show detail for each function + show_config (bool): Show config changes + show_environment (bool): Show environment changes + show_unknown (bool): Show unknown boards in summary + ide (bool): IDE mode - output to stderr + list_error_boards (bool): Include board list with error lines + config_filenames (list): List of config filenames + """ + brd_status = self.classify_boards( + board_selected, board_dict, self._base_board_dict) + + # Get a list of errors and warnings that have appeared, and disappeared + better_err, worse_err = self.calc_error_delta( + self._base_err_lines, self._base_err_line_boards, err_lines, + err_line_boards, '', list_error_boards) + better_warn, worse_warn = self.calc_error_delta( + self._base_warn_lines, self._base_warn_line_boards, warn_lines, + warn_line_boards, 'w', list_error_boards) + + # For the IDE mode, print out all the output + if ide: + self.print_ide_output(board_selected, board_dict) + + # Display results by arch + if not ide: + self._error_lines += self.display_arch_results( + board_selected, brd_status, better_err, worse_err, better_warn, + worse_warn, show_unknown) + + if show_sizes: + self.print_size_summary( + board_selected, board_dict, self._base_board_dict, + show_detail, show_bloat) + + if show_environment and self._base_environment: + self.show_environment_changes( + board_selected, board_dict, environment, self._base_environment) + + if show_config and self._base_config: + self.show_config_changes( + board_selected, board_dict, config, self._base_config, + config_filenames) + + # Save our updated information for the next call to this function + self._base_board_dict = board_dict + self._base_err_lines = err_lines + self._base_warn_lines = warn_lines + self._base_err_line_boards = err_line_boards + self._base_warn_line_boards = warn_line_boards + self._base_config = config + self._base_environment = environment + + self.show_not_built(board_selected, board_dict) + + def get_error_lines(self): + """Get the number of error lines output + + Returns: + int: Number of error lines output + """ + return self._error_lines + def colour_num(self, num): """Format a number with colour depending on its value @@ -476,11 +618,11 @@ class ResultHandler: continue col = None if line[0] == '+': - col = self.col.GREEN + col = self._col.GREEN elif line[0] == '-': - col = self.col.RED + col = self._col.RED elif line[0] == 'c': - col = self.col.YELLOW + col = self._col.YELLOW tprint(' ' + line, newline=True, colour=col) def show_environment_changes(self, board_selected, board_dict, -- 2.43.0