Source code for varats.experiments.szz.pydriller_szz_experiment
"""Implements the SZZUnleashed experiment."""
import typing as tp
import yaml
from benchbuild import Project, source
from benchbuild.experiment import ProjectT
from benchbuild.utils import actions
from pygit2 import Commit
from varats.base.version_header import VersionHeader
from varats.data.reports.szz_report import PyDrillerSZZReport, SZZTool
from varats.experiment.experiment_util import (
get_varats_result_folder,
VersionExperiment,
)
from varats.project.varats_project import VProject
from varats.provider.bug.bug_provider import BugProvider
from varats.report.report import FileStatusExtension as FSE
from varats.report.report import ReportSpecification
[docs]
class CreatePyDrillerSZZReport(actions.ProjectStep): # type: ignore
"""
Create a SZZReport from the data collected by the.
:class:`~varats.provider.bug.bug_provider.BugProvider`.
"""
NAME = "CreatePyDrillerSZZReport"
DESCRIPTION = "Create a report from SZZ data"
project: VProject
def __init__(self, project: Project):
super().__init__(project=project)
def __call__(self) -> actions.StepResult:
return self.create_report()
[docs]
def create_report(self) -> actions.StepResult:
"""Create a report from SZZ data."""
bug_provider = BugProvider.get_provider_for_project(self.project)
pygit_bugs = bug_provider.find_pygit_bugs()
varats_result_folder = get_varats_result_folder(self.project)
def commit_to_hash(commit: Commit) -> str:
return str(commit.id)
bugs: tp.Dict[str, tp.List[str]] = {}
# entries are lists of the form [<fix>, <introducing>]
for bug in pygit_bugs:
bugs[commit_to_hash(bug.fixing_commit)] = sorted([
commit_to_hash(commit) for commit in bug.introducing_commits
])
raw_szz_report = {
"szz_tool": SZZTool.PYDRILLER_SZZ.tool_name,
"bugs": bugs
}
result_file = PyDrillerSZZReport.get_file_name(
"PyDrSZZ",
project_name=str(self.project.name),
binary_name="none", # we don't rely on binaries in this experiment
project_revision=self.project.version_of_primary,
project_uuid=str(self.project.run_uuid),
extension_type=FSE.SUCCESS
)
with open(f"{varats_result_folder}/{result_file}", "w") as yaml_file:
yaml_file.write(
yaml.dump_all([
VersionHeader.from_version_number("SZZReport",
1).get_dict(),
raw_szz_report
],
explicit_start=True,
explicit_end=True)
)
return actions.StepResult.OK
[docs]
class PyDrillerSZZExperiment(VersionExperiment, shorthand="PyDrillerSZZ"):
"""
Generates a PyDrillerSZZ report.
This experiment should be run only on one (preferably the newest) revision
of a project.
"""
NAME = "PyDrillerSZZ"
REPORT_SPEC = ReportSpecification(PyDrillerSZZReport)
[docs]
@classmethod
def sample(cls, prj_cls: ProjectT) -> tp.List[source.Revision]:
variants = list(source.enumerate_revisions(prj_cls))
return [variants[0]]
[docs]
def actions_for_project(self, project: Project) -> tp.List[actions.Step]:
"""Returns the specified steps to run the project(s) specified in the
call in a fixed order."""
analysis_actions = [
CreatePyDrillerSZZReport(project),
actions.Clean(project)
]
return analysis_actions