StrictDoc Documentation
strictdoc/export/html/generators/source_file_coverage.py
Source file coverage
Path:
strictdoc/export/html/generators/source_file_coverage.py
Lines:
149
Non-empty lines:
131
Non-empty lines covered with requirements:
131 / 131 (100.0%)
Functions:
15
Functions covered by requirements:
15 / 15 (100.0%)
1
"""
2
@relation(SDOC-SRS-35, scope=file)
3
"""
4
 
5
from typing import Optional
6
 
7
from markupsafe import Markup
8
 
9
from strictdoc import __version__
10
from strictdoc.backend.sdoc_source_code.models.source_file_info import (
11
    SourceFileTraceabilityInfo,
12
)
13
from strictdoc.core.file_system.source_tree import SourceFile
14
from strictdoc.core.project_config import ProjectConfig
15
from strictdoc.core.traceability_index import TraceabilityIndex
16
from strictdoc.export.html.html_templates import HTMLTemplates, JinjaEnvironment
17
from strictdoc.export.html.renderers.link_renderer import LinkRenderer
18
 
19
 
20
class SourceCoverageViewObject:
21
    def __init__(
22
        self,
23
        *,
24
        traceability_index: TraceabilityIndex,
25
        project_config: ProjectConfig,
26
    ) -> None:
27
        self.traceability_index: TraceabilityIndex = traceability_index
28
        self.project_config: ProjectConfig = project_config
29
        self.link_renderer: LinkRenderer = LinkRenderer(
30
            root_path="", static_path=project_config.dir_for_sdoc_assets
31
        )
32
        self.is_running_on_server: bool = project_config.is_running_on_server
33
        self.strictdoc_version = __version__
34
 
35
    def get_document_level(self) -> int:
36
        return 0
37
 
38
    def render_screen(self, jinja_environment: JinjaEnvironment) -> Markup:
39
        return jinja_environment.render_template_as_markup(
40
            "screens/source_file_coverage/index.jinja", view_object=self
41
        )
42
 
43
    def render_static_url(self, url: str) -> str:
44
        return self.link_renderer.render_static_url(url)
45
 
46
    def render_url(self, url: str) -> str:
47
        # FIXME: Switch to Markup(...).
48
        return self.link_renderer.render_url(url)
49
 
50
    def get_file_stats_lines_total(self, source_file: SourceFile) -> str:
51
        trace_info: Optional[SourceFileTraceabilityInfo] = (
52
            self.traceability_index.get_coverage_info_weak(
53
                source_file.in_doctree_source_file_rel_path_posix
54
            )
55
        )
56
        if trace_info is None:
57
            return "0"
58
        return str(trace_info.file_stats.lines_total)
59
 
60
    def get_file_stats_lines_total_non_empty(
61
        self, source_file: SourceFile
62
    ) -> str:
63
        trace_info: Optional[SourceFileTraceabilityInfo] = (
64
            self.traceability_index.get_coverage_info_weak(
65
                source_file.in_doctree_source_file_rel_path_posix
66
            )
67
        )
68
        if trace_info is None:
69
            return "0"
70
        return str(trace_info.file_stats.lines_non_empty)
71
 
72
    def get_file_stats_non_empty_lines_covered(
73
        self, source_file: SourceFile
74
    ) -> str:
75
        trace_info: Optional[SourceFileTraceabilityInfo] = (
76
            self.traceability_index.get_coverage_info_weak(
77
                source_file.in_doctree_source_file_rel_path_posix
78
            )
79
        )
80
        if trace_info is None:
81
            return "0"
82
        return str(trace_info.ng_lines_covered)
83
 
84
    def get_file_stats_non_empty_lines_covered_percentage(
85
        self, source_file: SourceFile
86
    ) -> str:
87
        trace_info: Optional[SourceFileTraceabilityInfo] = (
88
            self.traceability_index.get_coverage_info_weak(
89
                source_file.in_doctree_source_file_rel_path_posix
90
            )
91
        )
92
        if trace_info is None:
93
            return f"{0:.1f}"
94
        covered = trace_info.ng_lines_covered
95
        total_non_empty = trace_info.file_stats.lines_non_empty
96
        percentage = (
97
            (covered / total_non_empty * 100) if total_non_empty > 0 else 0
98
        )
99
        return f"{percentage:.1f}"
100
 
101
    def get_file_stats_functions_total(self, source_file: SourceFile) -> str:
102
        trace_info: Optional[SourceFileTraceabilityInfo] = (
103
            self.traceability_index.get_coverage_info_weak(
104
                source_file.in_doctree_source_file_rel_path_posix
105
            )
106
        )
107
        if trace_info is None:
108
            return "0"
109
        return str(len(trace_info.functions))
110
 
111
    def get_file_stats_functions_covered(self, source_file: SourceFile) -> str:
112
        trace_info: Optional[SourceFileTraceabilityInfo] = (
113
            self.traceability_index.get_coverage_info_weak(
114
                source_file.in_doctree_source_file_rel_path_posix
115
            )
116
        )
117
        if trace_info is None:
118
            return "0"
119
        return str(trace_info.covered_functions)
120
 
121
    def get_file_stats_functions_covered_percentage(
122
        self, source_file: SourceFile
123
    ) -> str:
124
        trace_info: Optional[SourceFileTraceabilityInfo] = (
125
            self.traceability_index.get_coverage_info_weak(
126
                source_file.in_doctree_source_file_rel_path_posix
127
            )
128
        )
129
        if trace_info is None:
130
            return f"{0:.1f}"
131
        covered = trace_info.covered_functions
132
        total = len(trace_info.functions)
133
        percentage = (covered / total * 100) if total > 0 else 0
134
        return f"{percentage:.1f}"
135
 
136
 
137
class SourceFileCoverageHTMLGenerator:
138
    @staticmethod
139
    def export(
140
        *,
141
        project_config: ProjectConfig,
142
        traceability_index: TraceabilityIndex,
143
        html_templates: HTMLTemplates,
144
    ) -> Markup:
145
        view_object = SourceCoverageViewObject(
146
            traceability_index=traceability_index,
147
            project_config=project_config,
148
        )
149
        return view_object.render_screen(html_templates.jinja_environment())