Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
Javagedes committed Sep 20, 2023
1 parent b777bd7 commit e0be813
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 27 deletions.
43 changes: 34 additions & 9 deletions edk2toolext/environment/reporttypes/component_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@

from edk2toollib.database import Edk2DB

COMPONENT_QUERY = """
SELECT id, path
FROM instanced_inf
WHERE
(path LIKE ? OR ? LIKE '%' || path || '%')
AND env = ?
"""

LIBRARY_QUERY = """
SELECT
instanced_inf.id,
Expand All @@ -26,7 +34,22 @@
AND junction.table2 = 'instanced_inf'
AND junction.key1 = ?
AND junction.env = ?
AND instanced_inf.component = ?
AND instanced_inf.component = ?;
"""

FLAT_LIBRARY_QUERY = """
SELECT class, path
FROM instanced_inf
WHERE
component = ?
AND path != component;
"""

ID_QUERY = """
SELECT id
FROM environment
ORDER BY date
DESC LIMIT 1;
"""

class ComponentDumpReport:
Expand All @@ -37,7 +60,7 @@ def report_info(self):
Returns:
(str, str): A tuple of (name, description)
"""
return ("component-libs", "Dumps the library instances used by a component.")
return ("component-libs", "Dumps the library instances used by component.")

def add_cli_options(self, parserobj: ArgumentParser):
"""Configure command line arguments for this report."""
Expand All @@ -50,7 +73,8 @@ def add_cli_options(self, parserobj: ArgumentParser):
help="Flatten the list of libraries used in the component.")
parserobj.add_argument("-s", "--sort", dest="sort", action="store_true",
help="Sort the libraries listed in alphabetical order.")
parserobj.add_argument("-e", "--env", dest="env_id", action="store", help="The environment id to generate the report for.")
parserobj.add_argument("-e", "--env", dest="env_id", action="store",
help="The environment id to generate the report for.")

def run_report(self, db: Edk2DB, args: Namespace) -> None:
"""Runs the report."""
Expand All @@ -63,18 +87,19 @@ def run_report(self, db: Edk2DB, args: Namespace) -> None:

self.depth = args.depth
self.sort = args.sort
self.db = db
self.conn = db.connection

self.env_id = args.env_id or db.connection.execute("SELECT id FROM environment ORDER BY date DESC LIMIT 1;").fetchone()[0]
self.env_id = args.env_id or self.conn.execute(ID_QUERY).fetchone()[0]
self.component = PurePath(args.component).as_posix()

id, inf_path = self.db.connection.execute("SELECT id, path FROM instanced_inf WHERE (path LIKE ? OR ? LIKE '%' || path || '%') AND env = ?", (f'%{self.component}%', self.component, self.env_id)).fetchone()
id, inf_path = self.conn.execute(
COMPONENT_QUERY, (f'%{self.component}%', self.component, self.env_id)).fetchone()
# Print in flat format
if args.flatten:
return self.print_libraries_flat(inf_path)

# Print in recursive format
libraries = self.db.connection.execute(LIBRARY_QUERY, (id, self.env_id, self.component)).fetchall()
libraries = self.conn.execute(LIBRARY_QUERY, (id, self.env_id, self.component)).fetchall()

if self.sort:
libraries = sorted(libraries, key=lambda x: x[1])
Expand All @@ -93,7 +118,7 @@ def print_libraries_recursive(self, library: Tuple[str, str, str], visited: list
if library_instance is None:
return

libraries = self.db.connection.execute(LIBRARY_QUERY, (id, self.env_id, self.component))
libraries = self.conn.execute(LIBRARY_QUERY, (id, self.env_id, self.component))

if self.sort:
libraries = sorted(libraries, key=lambda x: x[1])
Expand All @@ -107,7 +132,7 @@ def print_libraries_recursive(self, library: Tuple[str, str, str], visited: list

def print_libraries_flat(self, component):
"""Prints the libraries used in a provided component."""
libraries = self.db.connection.execute("SELECT class, path FROM instanced_inf WHERE component = ? AND path != component", (component,)).fetchall()
libraries = self.conn.execute(FLAT_LIBRARY_QUERY, (component,)).fetchall()

length = max(len(item[0]) for item in libraries)
if self.sort:
Expand Down
58 changes: 46 additions & 12 deletions edk2toolext/environment/reporttypes/coverage_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,37 @@
import xml.etree.ElementTree as ET
from argparse import ArgumentParser, Namespace
from pathlib import Path
import os

from edk2toollib.database import Edk2DB

from edk2toolext.environment.reporttypes.base_report import Report

SOURCE_QUERY = """

Check failure on line 21 in edk2toolext/environment/reporttypes/coverage_report.py

View workflow job for this annotation

GitHub Actions / CI / Run

Ruff (I001)

edk2toolext/environment/reporttypes/coverage_report.py:9:1: I001 Import block is un-sorted or un-formatted
SELECT inf.path, inf.library_class, junction.key2 as source
FROM
inf
LEFT JOIN junction ON inf.path = junction.key1
WHERE
junction.table1 = 'inf'
AND junction.table2 = 'source'
AND junction.env = ?;
"""

PACKAGE_PATH_QUERY = """
SELECT value
FROM environment_values
WHERE
key = 'PACKAGES_PATH'
AND id = ?;
"""

ID_QUERY = """
SELECT id
FROM environment
ORDER BY date
DESC LIMIT 1;
"""

class CoverageReport(Report):
"""A report ingests a cobertura.xml file and organizes it by INF."""
Expand Down Expand Up @@ -86,32 +112,40 @@ def _build_file_dict(self, xml_path: str) -> dict:
return file_dict

def _get_inf_cov(self, files: dict, db: Edk2DB, library_only: bool):
inf_table = db.table("inf")
env_table = db.table("environment")
packages_path = env_table.all()[-1]["PACKAGES_PATH"].split(";")
if library_only:
inf_table = inf_table.search(Query().LIBRARY_CLASS != "")
env_id, = db.connection.execute(ID_QUERY).fetchone()
pp_list, = db.connection.execute(PACKAGE_PATH_QUERY, (env_id,)).fetchone()
pp_list = pp_list.split(os.pathsep)

# Build dictionary containing source files for each INF
# If library_only, filter out INFs that do not have a library_class
entry_dict = {}
for inf, library_class, source in db.connection.execute(SOURCE_QUERY, (env_id,)):
if library_only and library_class == "":
continue
if inf not in entry_dict:
entry_dict[inf] = [source]
else:
entry_dict[inf].append(source)

root = ET.Element("coverage")

sources = ET.SubElement(root, "sources")
# Set the sources so that reports can find the right paths.
source = ET.SubElement(sources, "source")
source.text = self.args.workspace
for pp in packages_path:
for pp in pp_list:
source = ET.SubElement(sources, "source")
source.text = pp

packages = ET.SubElement(root, "packages")
for entry in inf_table:
if not entry["SOURCES_USED"]:
for path, source_list in entry_dict.items():
if not source_list:
continue
inf = ET.SubElement(packages, "package", path=entry["PATH"], name=Path(entry["PATH"]).name)
inf = ET.SubElement(packages, "package", path=path, name=Path(path).name)
classes = ET.SubElement(inf, "classes")
found = False
for source in entry["SOURCES_USED"]:
source = Path(entry["PATH"]).parent / source
match = next((key for key in files.keys() if source.is_relative_to(key)), None)
for source in source_list:
match = next((key for key in files.keys() if Path(source).is_relative_to(key)), None)
if match is not None:
found = True
classes.append(files[match])
Expand Down
36 changes: 31 additions & 5 deletions edk2toolext/environment/reporttypes/usage_report.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@

# @file usage_report.py
# A report that generates an html report about which repositories INFs (That are consumed for a platform) originate
# from
#
##
# Copyright (c) Microsoft Corporation
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
"""A report that generates an html report about which repositories INFs origin from."""
import io
import logging
from argparse import ArgumentParser, Namespace
Expand Down Expand Up @@ -50,6 +59,20 @@
inf_list.path
"""

VERSION_QUERY = """
SELECT version
FROM environment
WHERE id = ?;
"""

ID_QUERY = """
SELECT id
FROM environment
ORDER BY date
DESC LIMIT 1;
"""


class UsageReport(Report):
"""A report that generates a INF usage report for a specific build."""
def report_info(self):
Expand All @@ -62,8 +85,11 @@ def report_info(self):

def add_cli_options(self, parserobj: ArgumentParser):
"""Configure command line arguments for this report."""
parserobj.add_argument("-e", "-env", dest="env_id", action="store", help = "The environment id to generate the report for. Defaults to the latest environment.")
parserobj.add_argument("-o", "-output", dest="output", action="store", help = "The output file to write the report to. Defaults to 'usage_report.html'.", default=None)
parserobj.add_argument("-e", "-env", dest="env_id", action="store",
help = "The environment id to generate the report for. Defaults to the latest "
"environment.")
parserobj.add_argument("-o", "-output", dest="output", action="store", default=None,
help = "The output file to write the report to. Defaults to 'usage_report.html'.")

def run_report(self, db: Edk2DB, args: Namespace):
"""Generate the Usage report."""
Expand All @@ -76,15 +102,15 @@ def run_report(self, db: Edk2DB, args: Namespace):
print(" Run the following command: `pip install jinja2 plotly`")
exit(-1)

env_id = args.env_id or db.connection.execute("SELECT id FROM environment ORDER BY date DESC LIMIT 1;").fetchone()[0]
env_id = args.env_id or db.connection.execute(ID_QUERY).fetchone()[0]

# Vars for html template
env = Environment(loader=FileSystemLoader(templates.__path__))
template = env.get_template("usage_report_template.html")

# This is the data that gets passed to the html template
data = {
"version": db.connection.execute("SELECT version FROM environment WHERE id = ?;", (env_id,)).fetchone()[0],
"version": db.connection.execute(VERSION_QUERY, (env_id,)).fetchone()[0],
"env": self._get_env_vars(db.connection, env_id),
"inf_list": set(),
}
Expand Down
1 change: 0 additions & 1 deletion edk2toolext/invocables/edk2_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ def Go(self):
db_path = Path(self.GetWorkspaceRoot()) / self.GetLoggingFolderRelativeToRoot() / DB_NAME
pathobj = Edk2Path(self.GetWorkspaceRoot(), self.GetPackagesPath())
env = shell_environment.GetBuildVars()
logging.info("HELLO")

if self.clear:
db_path.unlink(missing_ok=True)
Expand Down

0 comments on commit e0be813

Please sign in to comment.