macaron.output_reporter package

Submodules

macaron.output_reporter.jinja2_extensions module

This module contains the Jinja2 extension filters and tests.

All tests will have j2_test_ as a prefix. The rest of the name will be the name of that test in the Jinja2 Environment.

All filters will have j2_filter_ as a prefix. The rest of the name will be the name of that filter in the Jinja2 Environment.

References

macaron.output_reporter.jinja2_extensions.j2_test_list(obj)

Return True if the object is a list.

Parameters:

obj (Any) – The object to check.

Return type:

bool

macaron.output_reporter.jinja2_extensions.j2_test_python_enum(obj)

Return True if the object is an Enum.

Parameters:

obj (Any) – The object to check.

Return type:

bool

macaron.output_reporter.jinja2_extensions.j2_filter_get_headers(val_list)

Return the list of headers to form a table from a list of dictionaries.

The list of headers will be the set contains all unique keys from all dictionaries in the list.

Parameters:

val_list (list[dict]) – The list of all dictionaries.

Returns:

The list of header names.

Return type:

list[str]

Raises:

TemplateRuntimeError – If trying to extract headers from a non-dict object.

macaron.output_reporter.jinja2_extensions.j2_filter_get_flatten_dict(data, has_key=False)

Flatten a dictionary to only contain dict and primitives values.

This method removes all list from a nested dictionary by replacing it with a dictionary that maps from the index number (in the original list) to each element of that list.

For values that are not in primitive types, we try to return a string representation of that object.

If has_key is True, this method will return the primitive values as is (i.e. the returned value will be put in a mapping of the previous level dictionary.). If has_key is False OR the data is not a dict, list or of primitive types, this method will return a simple mapping {"0": str(data)}

Parameters:
  • data (Any) – The dictionary that we want to flatten out.

  • has_key (bool) – True if data has a key associated with it.

Returns:

The result dictionary.

Return type:

dict

Examples

>>> j2_filter_get_flatten_dict(
... {
...     "A": [1, 2, 3],
...     "B": {
...         "C": ["blah", "bar", "foo"],
...     },
... })
{'A': {0: 1, 1: 2, 2: 3}, 'B': {'C': {0: 'blah', 1: 'bar', 2: 'foo'}}}
macaron.output_reporter.jinja2_extensions.j2_filter_get_dep_status_color(repo_url_status)

Return the html class name for the color of the dep repo url status.

Parameters:

repo_url_status (str) – The dep status as string.

Returns:

The css class name with the corresponding color or an empty string if the status is not recognized.

Return type:

str

macaron.output_reporter.jinja2_extensions.j2_filter_get_check_result_color(result_type)

Return the html class name for the color of the check result.

Parameters:

result_type (str) – The result type as string.

Returns:

The css class name with the corresponding color or empty string if the result type is not recognized.

Return type:

str

macaron.output_reporter.jinja2_extensions.filter_extensions: dict[str, str] = {'get_check_result_color': 'j2_filter_get_check_result_color', 'get_dep_status_color': 'j2_filter_get_dep_status_color', 'get_flatten_dict': 'j2_filter_get_flatten_dict', 'get_headers': 'j2_filter_get_headers'}

The mappings between the name of a filter and its function’s name as defined in this module.

macaron.output_reporter.jinja2_extensions.test_extensions: dict[str, str] = {'list': 'j2_test_list', 'python_enum': 'j2_test_python_enum'}

The mappings between the name of a test and its function’s name as defined in this module.

macaron.output_reporter.reporter module

This module contains reporter classes for creating reports of Macaron analyzed results.

class macaron.output_reporter.reporter.FileReporter(mode='w', encoding='utf-8')

Bases: ABC

The reporter that handles writing data to disk files.

__init__(mode='w', encoding='utf-8')

Initialize instance.

Parameters:
  • mode (str) – The mode to open the target files, by default “w”.

  • encoding (str) – The encoding used to handle disk files, by default “utf-8”.

write_file(file_path, data)

Write the data into a file.

Parameters:
  • file_path (str) – The path to the target file.

  • data (Any) – The data to write into the file.

Returns:

True if succeeded else False.

Return type:

bool

abstract generate(target_dir, report)

Generate a report file.

This method is implemented in subclasses.

Parameters:
  • target_dir (str) – The directory to store all output files.

  • report (Report | dict) – The report to be generated.

Return type:

None

class macaron.output_reporter.reporter.JSONReporter(mode='w', encoding='utf-8', indent=4)

Bases: FileReporter

This class handles writing reports to JSON files.

__init__(mode='w', encoding='utf-8', indent=4)

Initialize instance.

Parameters:
  • mode (str) – The file operation mode.

  • encoding (str) – The encoding.

  • indent (int) – The indent for the JSON output, by default 4.

generate(target_dir, report)

Generate JSON report files.

Each record is stored in a separate JSON file, the name of each file is the name of the repo.

A dependencies.json is also created to store the information of all resolved dependencies.

Parameters:
  • target_dir (str) – The directory to store all output files.

  • report (Report | dict) – The report to be generated.

Return type:

None

class macaron.output_reporter.reporter.HTMLReporter(mode='w', encoding='utf-8', env=None, target_template='macaron.html')

Bases: FileReporter

This class handles writing reports to HTML files.

__init__(mode='w', encoding='utf-8', env=None, target_template='macaron.html')

Initialize instance.

Parameters:
  • mode (str) – The file operation mode.

  • encoding (str) – The encoding.

  • env (Environment | None) – The pre-initiated jinja2.Environment instance for the HTMLReporter. If this is not provided, a default jinja2.Environment will be initialized.

  • target_template (str) – The target template. It will be looked up from the jinja2.Environment instance.

generate(target_dir, report)

Generate HTML report files.

Each record is stored in a separate HTML file, the name of each file is the name of the repo.

The target_template is used to load the template within the initialized jinja2.Environment. If it failed to load, no HTML files will be generated.

Parameters:
  • target_dir (str) – The directory to store all output files.

  • report (Report | dict) – The report to be generated.

Return type:

None

class macaron.output_reporter.reporter.PolicyReporter(mode='w', encoding='utf-8', indent=4)

Bases: FileReporter

This class writes policy engine reports to a JSON file.

__init__(mode='w', encoding='utf-8', indent=4)

Initialize instance.

Parameters:
  • mode (str) – The file operation mode.

  • encoding (str) – The encoding.

  • indent (int) – The indent for the JSON output, by default 4.

generate(target_dir, report)

Generate JSON report files.

Each record is stored in a separate JSON file, the name of each file is the name of the repo.

A dependencies.json is also created to store the information of all resolved dependencies.

Parameters:
  • target_dir (str) – The directory to store all output files.

  • report (Report | dict) – The report to be generated.

Return type:

None

macaron.output_reporter.results module

This module contains classes that represent the result of the Macaron analysis.

class macaron.output_reporter.results.DepSummary

Bases: TypedDict

The summary of the dependency analysis.

analyzed_deps: int

The total number of dependencies analyzed.

unique_dep_repos: int

The number of unique repos analyzed for all dependencies.

checks_summary: list[dict]

This list contains mapping between each check ID and how many deps PASSED this check.

Examples

>>> dep_summary["checks_summary"]
[
    {
        "Check A": 3
    },
    {
        "Check B": 4
    }
]
dep_status: list[dict]

This list contains the summaries for all dependency Record.

class macaron.output_reporter.results.Record(record_id, description, pre_config, status, context=None, dependencies=<factory>)

Bases: Generic[RecordNode]

This class contains the analysis status and data of a repo.

Parameters:
  • record_id (str) – The id of the record.

  • description (str) – The description for this record.

  • pre_config (Configuration) – The Configuration instance used to start the analysis of this repo.

  • status (SCMStatus) – The SCM status of this repo.

  • context (AnalyzeContext or None) – The context instance for this repo.

  • dependencies (list[RecordNode]) – The list of Records for the analyzed dependencies of this repo.

See also

SCMStatus, macaron.config.configuration.Configuration, macaron.slsa_analyzer.analyze_context.AnalyzeContext

record_id: str
description: str
pre_config: Configuration
status: SCMStatus
context: AnalyzeContext | None = None
dependencies: list[TypeVar(RecordNode, bound= Record)]
get_summary()

Get a dictionary that summarizes the status of this record.

Returns:

The summary of this record.

Return type:

dict

Examples

>>> from pprint import pprint
>>> from macaron.config.target_config import Configuration
>>> from macaron.output_reporter.scm import SCMStatus
>>> from macaron.output_reporter.results import Record
>>> record = Record(
...     record_id="apache/maven",
...     description="Analysis completed",
...     pre_config=Configuration({}),
...     status=SCMStatus.MISSING_SCM,
...     context=None,
...     dependencies=[],
... )
>>> pprint(record.get_summary())
{'description': 'Analysis completed',
 'id': 'apache/maven',
 'repo_url_status': <SCMStatus.MISSING_SCM: 'MISSING REPO URL'>,
 'report': ''}
get_dict()

Get the dictionary representation of the Record instance.

Returns:

The dictionary representation of this record.

Return type:

dict

get_dep_summary()

Get the dependency analysis summary data.

Returns:

The dependency analysis summary data.

Return type:

DepSummary

__init__(record_id, description, pre_config, status, context=None, dependencies=<factory>)
class macaron.output_reporter.results.Report(root_record)

Bases: object

This class contains the report content of an analysis.

__init__(root_record)

Initialize instance.

Parameters:

root_record (Record) – The record of the main target repository.

get_records()

Get the generator for all records in the report.

Yields:

Record – The record within this report instance.

Return type:

Iterable[Record]

add_dep_record(dep_record)

Add a dependency record into the report.

Parameters:

dep_record (Record) – The record of the dependency.

Return type:

None

get_serialized_configs()

Get the generator for the configs content of all dependencies.

These dependency configurations are determined by the dependency analyzer. Note that the status of the configuration might change in the follow up analyses, e.g., if a repository is already analyzed, the status changes from “AVAILABLE” to “DUPLICATED”.

Yields:

dict – The configs dict of a dependency.

Return type:

Iterable[dict]

get_ctxs()

Get the generator for all AnalyzeContext instances.

Yields:

AnalyzeContext – The AnalyzeContext instance of a repository.

Return type:

Iterable[AnalyzeContext]

get_dependencies(root_record=None)

Get the generator for the dependency relations between repositories.

Parameters:

root_record (Record | None) – The root record to find the dependencies of, if none is provided self.root_record is used.

Yields:

Tuple[AnalyzeContext, AnalyzeContext] – The tuple containing first the parent context followed by the child context.

Return type:

Iterable[tuple[AnalyzeContext, AnalyzeContext]]

find_ctx(record_id)

Find the context instance using the configuration ID.

Parameters:

record_id (str) – The ID to look for the analyze context.

Returns:

The analyze context for the given record ID or None if cannot find.

Return type:

AnalyzeContext

macaron.output_reporter.scm module

This module implements datatypes to represent SCM results.

class macaron.output_reporter.scm.SCMStatus(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: str, Enum

The status type of each analyzed repository.

AVAILABLE = 'AVAILABLE'

The SCM url is available for this artifact.

MISSING_SCM = 'MISSING REPO URL'

Cannot find the SCM url for this artifact.

DUPLICATED_SCM = 'DUPLICATED REPO URL'

The SCM url is available but has been already analyzed for another artifact.

ANALYSIS_FAILED = 'FAILED'

When the SCM is available but the analysis could not finish for this artifact.