codeclimate/python-test-reporter

View on GitHub
codeclimate_test_reporter/components/formatter.py

Summary

Maintainability
A
0 mins
Test Coverage
import xml.etree.ElementTree as ET

from ..__init__ import __version__ as reporter_version
from .ci import CI
from .file_coverage import FileCoverage
from .git_command import GitCommand


class InvalidReportVersion(Exception):
    pass


class Formatter:
    def __init__(self, xml_report_path, debug=False):
        self.debug = debug
        tree = ET.parse(xml_report_path)
        self.root = tree.getroot()

    def payload(self):
        self.__validate_report_version()

        total_line_counts = {"covered": 0, "missed": 0, "total": 0}
        total_covered_strength = 0.0
        total_covered_percent = 0.0

        source_files = self.__source_files()

        for source_file in source_files:
            total_covered_strength += source_file["covered_strength"]
            total_covered_percent += source_file["covered_percent"]

            for key, value in source_file["line_counts"].items():
                total_line_counts[key] += value

        total_covered_strength = round(total_covered_strength / len(source_files), 2)
        total_covered_percent = round(total_covered_percent / len(source_files), 2)

        return {
            "run_at": self.__timestamp(),
            "covered_percent": total_covered_percent,
            "covered_strength": total_covered_strength,
            "line_counts": total_line_counts,
            "partial": False,
            "git": self.__git_info(),
            "environment": {
                "pwd": self.root.find("sources").find("source").text,
                "reporter_version": reporter_version
            },
            "ci_service": self.__ci_data(),
            "source_files": source_files
        }

    def __validate_report_version(self):
        report_version = self.root.get("version")

        if report_version < "4.0" or report_version >= "4.4":
            message = """
            This reporter is compatible with Coverage.py versions >=4.0,<4.4.
            Your Coverage.py report version is %s.

            Consider locking your version of Coverage.py to >4,0,<4.4 until the
            following Coverage.py issue is addressed:
            https://bitbucket.org/ned/coveragepy/issues/578/incomplete-file-path-in-xml-report
            """ % (report_version)

            raise InvalidReportVersion(message)

    def __ci_data(self):
        return CI().data()

    def __source_files(self):
        source_files = []

        for file_node in self.__file_nodes():
            if self.debug:
                print("Processing file path=%s" % file_node.get("filename"))

            file_coverage = FileCoverage(file_node)
            payload = file_coverage.payload()
            source_files.append(payload)

        return source_files

    def __file_nodes(self):
        return self.root.findall("packages/package/classes/class")

    def __timestamp(self):
        return self.root.get("timestamp")

    def __git_info(self):
        ci_data = self.__ci_data()
        command = GitCommand()

        return {
            "branch": ci_data.get("branch") or command.branch(),
            "committed_at": command.committed_at(),
            "head": ci_data.get("commit_sha") or command.head()
        }