summaryrefslogtreecommitdiff
path: root/src/buildstream/_frontend/status.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildstream/_frontend/status.py')
-rw-r--r--src/buildstream/_frontend/status.py105
1 files changed, 87 insertions, 18 deletions
diff --git a/src/buildstream/_frontend/status.py b/src/buildstream/_frontend/status.py
index 32fda1147..38e388818 100644
--- a/src/buildstream/_frontend/status.py
+++ b/src/buildstream/_frontend/status.py
@@ -19,6 +19,7 @@
import os
import sys
import curses
+from collections import OrderedDict
import click
# Import a widget internal for formatting time codes
@@ -64,7 +65,7 @@ class Status():
self._success_profile = success_profile
self._error_profile = error_profile
self._stream = stream
- self._jobs = []
+ self._jobs = OrderedDict()
self._last_lines = 0 # Number of status lines we last printed to console
self._spacing = 1
self._colors = colors
@@ -81,6 +82,7 @@ class Status():
state.register_task_added_callback(self._add_job)
state.register_task_removed_callback(self._remove_job)
+ state.register_task_changed_callback(self._job_changed)
# clear()
#
@@ -162,6 +164,21 @@ class Status():
# Private Methods #
###################################################
+ # _job_changed()
+ #
+ # Reacts to a specified job being changed
+ #
+ # Args:
+ # action_name (str): The action name for this job
+ # full_name (str): The name of this specific job (e.g. element name)
+ #
+ def _job_changed(self, action_name, full_name):
+ job_key = (action_name, full_name)
+ task = self._state.tasks[job_key]
+ job = self._jobs[job_key]
+ if job.update(task):
+ self._need_alloc = True
+
# _init_terminal()
#
# Initialize the terminal and return the resolved terminal
@@ -260,8 +277,9 @@ class Status():
self._need_alloc = False
def _job_lines(self, columns):
+ jobs_list = list(self._jobs.values())
for i in range(0, len(self._jobs), columns):
- yield self._jobs[i:i + columns]
+ yield jobs_list[i:i + columns]
# Returns an array of integers representing the maximum
# length in characters for each column, given the current
@@ -290,11 +308,11 @@ class Status():
#
def _add_job(self, action_name, full_name):
task = self._state.tasks[(action_name, full_name)]
- start_time = task.start_time
+ elapsed = task.elapsed_offset
job = _StatusJob(self._context, action_name, full_name,
self._content_profile, self._format_profile,
- start_time)
- self._jobs.append(job)
+ elapsed)
+ self._jobs[(action_name, full_name)] = job
self._need_alloc = True
# _remove_job()
@@ -306,11 +324,7 @@ class Status():
# full_name (str): The name of this specific job (e.g. element name)
#
def _remove_job(self, action_name, full_name):
- self._jobs = [
- job for job in self._jobs
- if not (job.full_name == full_name and
- job.action_name == action_name)
- ]
+ del self._jobs[(action_name, full_name)]
self._need_alloc = True
@@ -486,12 +500,59 @@ class _StatusJob():
self._content_profile = content_profile
self._format_profile = format_profile
self._time_code = TimeCode(context, content_profile, format_profile)
+ self._current_progress = None # Progress tally to render
+ self._maximum_progress = None # Progress tally to render
+ self.size = self.calculate_size()
+
+ # calculate_size()
+ #
+ # Calculates the amount of space the job takes up when rendered
+ #
+ # Returns:
+ # int: The size of the job when rendered
+ #
+ def calculate_size(self):
# Calculate the size needed to display
- self.size = 10 # Size of time code with brackets
- self.size += len(action_name)
- self.size += len(self.full_name)
- self.size += 3 # '[' + ':' + ']'
+ size = 10 # Size of time code with brackets
+ size += len(self.action_name)
+ size += len(self.full_name)
+ size += 3 # '[' + ':' + ']'
+ if self._current_progress is not None:
+ size += len(str(self._current_progress))
+ size += 1 # ':'
+ if self._maximum_progress is not None:
+ size += len(str(self._maximum_progress))
+ size += 1 # '/'
+ return size
+
+ # update()
+ #
+ # Synchronises its internal data with the provided Task,
+ # and returns whether its size has changed
+ #
+ # Args:
+ # task (Task): The task associated with this job
+ #
+ # Returns:
+ # bool: Whether the size of the job has changed
+ #
+ def update(self, task):
+ changed = False
+ size_changed = False
+ if task.current_progress != self._current_progress:
+ changed = True
+ self._current_progress = task.current_progress
+ if task.maximum_progress != self._maximum_progress:
+ changed = True
+ self._maximum_progress = task.maximum_progress
+ if changed:
+ old_size = self.size
+ self.size = self.calculate_size()
+ if self.size != old_size:
+ size_changed = True
+
+ return size_changed
# render()
#
@@ -506,12 +567,20 @@ class _StatusJob():
self._time_code.render_time(elapsed - self._offset) + \
self._format_profile.fmt(']')
- # Add padding after the display name, before terminating ']'
- name = self.full_name + (' ' * padding)
text += self._format_profile.fmt('[') + \
self._content_profile.fmt(self.action_name) + \
self._format_profile.fmt(':') + \
- self._content_profile.fmt(name) + \
- self._format_profile.fmt(']')
+ self._content_profile.fmt(self.full_name)
+
+ if self._current_progress is not None:
+ text += self._format_profile.fmt(':') + \
+ self._content_profile.fmt(str(self._current_progress))
+ if self._maximum_progress is not None:
+ text += self._format_profile.fmt('/') + \
+ self._content_profile.fmt(str(self._maximum_progress))
+
+ # Add padding before terminating ']'
+ terminator = (' ' * padding) + ']'
+ text += terminator
return text