summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan van Berkom <tristan.vanberkom@codethink.co.uk>2020-08-06 21:15:22 +0900
committerbst-marge-bot <marge-bot@buildstream.build>2020-08-10 08:33:55 +0000
commit89a1c1b7e5c192f52779aa2b7f41b0d6df88e509 (patch)
tree0a74a8924db3769e7251e72e83c1ba22a31d6db7
parent6798ea276cdabe668c3868253af9409663e85c46 (diff)
downloadbuildstream-89a1c1b7e5c192f52779aa2b7f41b0d6df88e509.tar.gz
_frontend/widget.py: Refactor the Widget.print_heading() function
This function now prints information about each loaded project in the session: * Information about each loaded project - Junction path, if any - Provenance of how the project was initially loaded, if any - Shows which projects declare the loaded project as a duplicate, if any - Shows which projects declare the loaded project as internal, if any * Plugins loaded in each project, including how they were loaded * Project option values resolved for each loaded project
-rw-r--r--src/buildstream/_frontend/widget.py121
1 files changed, 87 insertions, 34 deletions
diff --git a/src/buildstream/_frontend/widget.py b/src/buildstream/_frontend/widget.py
index 4c22723d6..a4268f62b 100644
--- a/src/buildstream/_frontend/widget.py
+++ b/src/buildstream/_frontend/widget.py
@@ -439,11 +439,11 @@ class LogLine(Widget):
# and so on.
#
# Args:
- # project (Project): The toplevel project we were invoked from
+ # toplevel_project (Project): The toplevel project we were invoked from
# stream (Stream): The stream
# log_file (file): An optional file handle for additional logging
#
- def print_heading(self, project, stream, *, log_file):
+ def print_heading(self, toplevel_project, stream, *, log_file):
context = self.context
starttime = datetime.datetime.now()
text = ""
@@ -455,7 +455,7 @@ class LogLine(Widget):
text += self.content_profile.fmt("BuildStream Version {}\n".format(bst_version), bold=True)
values = OrderedDict()
values["Session Start"] = starttime.strftime("%A, %d-%m-%Y at %H:%M:%S")
- values["Project"] = "{} ({})".format(project.name, project.directory)
+ values["Project"] = "{} ({})".format(toplevel_project.name, toplevel_project.directory)
values["Targets"] = ", ".join([t.name for t in stream.targets])
text += self._format_values(values)
@@ -476,19 +476,55 @@ class LogLine(Widget):
text += self._format_values(values)
text += "\n"
- # Project Options
- values = OrderedDict()
- project.options.printable_variables(values)
- if values:
- text += self.content_profile.fmt("Project Options\n", bold=True)
+ # Print information about each loaded project
+ #
+ for project_info in toplevel_project.loaded_projects():
+ project = project_info.project
+
+ # Project title line
+ text += (
+ self.content_profile.fmt("Project", bold=True)
+ + self.format_profile.fmt(": ", bold=True)
+ + self.content_profile.fmt(project.name, bold=True)
+ )
+ text += "\n"
+
+ # Details on how the project was loaded
+ #
+ values = OrderedDict()
+ if project.junction:
+ values["Junction path"] = project_info.project.junction._get_full_name()
+ if project_info.provenance:
+ values["Loaded by"] = str(project_info.provenance)
text += self._format_values(values)
+
+ # Print out duplicate declarations
+ if project_info.duplicates:
+ text += self.format_profile.fmt("{}Declared duplicate by:\n".format(self._indent))
+ for duplicate in project_info.duplicates:
+ text += self.content_profile.fmt("{}{}\n".format(self._indent * 2, duplicate))
+
+ # Print out internal declarations
+ if project_info.internal:
+ text += self.format_profile.fmt("{}Declared internal by:\n".format(self._indent))
+ for internal in project_info.internal:
+ text += self.content_profile.fmt("{}{}\n".format(self._indent * 2, internal))
+
text += "\n"
- # Plugins
- text += self._format_plugins(
- [p for p, _, _, _ in project.element_factory.list_plugins()],
- [p for p, _, _, _ in project.source_factory.list_plugins()],
- )
+ # Project Options
+ values = OrderedDict()
+ project.options.printable_variables(values)
+ if values:
+ text += self.format_profile.fmt("{}Project Options\n".format(self._indent))
+ text += self._format_values(values, indent=2)
+ text += "\n"
+
+ # Plugins
+ text += self._format_plugins(
+ {p: d for p, _, _, d in project.element_factory.list_plugins()},
+ {p: d for p, _, _, d in project.source_factory.list_plugins()},
+ )
# Pipeline state
text += self.content_profile.fmt("Pipeline\n", bold=True)
@@ -726,25 +762,27 @@ class LogLine(Widget):
lines = log[(end + 1) :].splitlines()
return "\n".join([line.decode("utf-8") for line in lines]).rstrip()
+ # _format_plugins()
+ #
+ # Formats the plugins loaded by a project
+ #
+ # Args:
+ # element_plugins (dict): Dict of element plugin kind and display string tuples
+ # source_plugins (dict): Dict of source plugin kind and display string tuples
+ #
+ # Returns:
+ # (str): The formatted text
+ #
def _format_plugins(self, element_plugins, source_plugins):
text = ""
-
- if not (element_plugins or source_plugins):
- return text
-
- text += self.content_profile.fmt("Loaded Plugins\n", bold=True)
-
if element_plugins:
- text += self.format_profile.fmt(" Element Plugins\n")
- for plugin in element_plugins:
- text += self.content_profile.fmt(" - {}\n".format(plugin))
-
+ text += self.format_profile.fmt("{}Element Plugins\n".format(self._indent))
+ text += self._format_values(element_plugins, style_key=True, indent=2)
+ text += "\n"
if source_plugins:
- text += self.format_profile.fmt(" Source Plugins\n")
- for plugin in source_plugins:
- text += self.content_profile.fmt(" - {}\n".format(plugin))
-
- text += "\n"
+ text += self.format_profile.fmt("{}Source Plugins\n".format(self._indent))
+ text += self._format_values(source_plugins, style_key=True, indent=2)
+ text += "\n"
return text
@@ -754,25 +792,40 @@ class LogLine(Widget):
# the values are aligned.
#
# Args:
- # values: A dictionary, usually an OrderedDict()
- # style_value: Whether to use the content profile for the values
+ # values (dict): A dictionary, usually an OrderedDict()
+ # style_key (bool): Whether to use the content profile for the keys
+ # style_value (bool): Whether to use the content profile for the values
+ # indent (number): Number of initial indentation levels
#
# Returns:
# (str): The formatted values
#
- def _format_values(self, values, style_value=True):
+ def _format_values(self, values, *, style_key=False, style_value=True, indent=1):
text = ""
max_key_len = 0
for key, value in values.items():
max_key_len = max(len(key), max_key_len)
for key, value in values.items():
+
+ key = str(key)
+ text += self._indent * indent
+ if style_key:
+ text += self.content_profile.fmt(key)
+ else:
+ text += self.format_profile.fmt(key)
+ text += self.format_profile.fmt(":")
+
+ # Special case for values containing newlines
if isinstance(value, str) and "\n" in value:
- text += self.format_profile.fmt(" {}:\n".format(key))
- text += textwrap.indent(value, self._indent)
+ text += "\n"
+ text += textwrap.indent(value, self._indent * indent)
continue
- text += self.format_profile.fmt(" {}: {}".format(key, " " * (max_key_len - len(key))))
+ # Alignment spacing
+ text += " {}".format(" " * (max_key_len - len(key)))
+
+ # Print the value
if style_value:
text += self.content_profile.fmt(str(value))
else: