StrictDoc Documentation
strictdoc/backend/sdoc/models/document_config.py
Source file coverage
Path:
strictdoc/backend/sdoc/models/document_config.py
Lines:
202
Non-empty lines:
174
Non-empty lines covered with requirements:
174 / 174 (100.0%)
Functions:
15
Functions covered by requirements:
15 / 15 (100.0%)
1
"""
2
@relation(SDOC-SRS-110, SDOC-SRS-151, scope=file)
3
"""
4
 
5
from typing import TYPE_CHECKING, List, Optional, Tuple
6
 
7
from strictdoc.backend.sdoc.constants import SDocMarkup
8
from strictdoc.helpers.auto_described import auto_described
9
 
10
if TYPE_CHECKING:
11
    from strictdoc.backend.sdoc.models.document import SDocDocument
12
 
13
 
14
@auto_described
15
class DocumentCustomMetadataKeyValuePair:
16
    def __init__(
17
        self,
18
        *,
19
        parent: Optional["DocumentCustomMetadata"] = None,
20
        key: Optional[str],
21
        value: Optional[str],
22
    ) -> None:
23
        _ = parent
24
        self.key = key
25
        self.value = value
26
 
27
 
28
@auto_described
29
class DocumentCustomMetadata:
30
    def __init__(
31
        self,
32
        *,
33
        parent: Optional["DocumentConfig"] = None,
34
        entries: List[DocumentCustomMetadataKeyValuePair],
35
    ) -> None:
36
        _ = parent
37
        self.entries: List[DocumentCustomMetadataKeyValuePair] = entries
38
 
39
 
40
@auto_described
41
class DocumentConfig:
42
    @staticmethod
43
    def default_config(document: Optional["SDocDocument"]) -> "DocumentConfig":
44
        return DocumentConfig(
45
            parent=document,
46
            version=None,
47
            date=None,
48
            uid=None,
49
            classification=None,
50
            requirement_prefix=None,
51
            root=None,
52
            enable_mid=None,
53
            relation_field=None,
54
            markup=None,
55
            auto_levels=None,
56
            layout=None,
57
            requirement_style=None,
58
            requirement_in_toc=None,
59
            default_view=None,
60
            custom_metadata=None,
61
        )
62
 
63
    def __init__(
64
        self,
65
        *,
66
        parent: Optional["SDocDocument"],
67
        version: Optional[str],
68
        date: Optional[str],
69
        uid: Optional[str],
70
        classification: Optional[str],
71
        requirement_prefix: Optional[str],
72
        root: Optional[str],
73
        enable_mid: Optional[str],
74
        relation_field: Optional[str],
75
        markup: Optional[str],
76
        auto_levels: Optional[str],
77
        layout: Optional[str],
78
        requirement_style: Optional[str],
79
        requirement_in_toc: Optional[str],
80
        default_view: Optional[str],
81
        custom_metadata: Optional[DocumentCustomMetadata],
82
        view_style_tag: Optional[str] = None,
83
        node_in_toc_tag: Optional[str] = None,
84
    ) -> None:
85
        self.parent = parent
86
        self.version: Optional[str] = version
87
        self.date: Optional[str] = date
88
 
89
        meaningful_uid: Optional[str] = None
90
        if uid is not None and len(uid) > 0:
91
            meaningful_uid = uid
92
        self.uid: Optional[str] = meaningful_uid
93
 
94
        self.classification: Optional[str] = classification
95
        self.requirement_prefix: Optional[str] = requirement_prefix
96
 
97
        self.root: Optional[bool] = (
98
            True if root == "True" else (False if root == "False" else None)
99
        )
100
        self.enable_mid: Optional[bool] = (
101
            True
102
            if enable_mid == "True"
103
            else (False if root == "False" else None)
104
        )
105
        self.relation_field: Optional[str] = (
106
            relation_field
107
            if relation_field is not None and len(relation_field) > 0
108
            else None
109
        )
110
 
111
        self.markup: Optional[str] = markup
112
        self.auto_levels: bool = auto_levels is None or auto_levels == "On"
113
 
114
        if layout is not None:
115
            if len(layout) > 0:
116
                assert layout in ("Default", "Website")
117
            else:
118
                layout = None
119
        self.layout: Optional[str] = layout
120
 
121
        # Possible requirement styles:
122
        # Simple, Table, Rows.
123
        self.requirement_style: Optional[str] = requirement_style
124
        self.view_style_tag: Optional[str] = view_style_tag
125
 
126
        self.requirement_in_toc: Optional[str] = requirement_in_toc
127
        self.node_in_toc_tag: Optional[str] = node_in_toc_tag
128
 
129
        self.default_view: Optional[str] = default_view
130
        self.ng_auto_levels_specified = auto_levels is not None
131
 
132
        self.ng_line_start: int = 0
133
        self.ng_col_start: int = 0
134
 
135
        self.custom_metadata: Optional[DocumentCustomMetadata] = custom_metadata
136
 
137
    def get_markup(self) -> str:
138
        if self.markup is None:
139
            return SDocMarkup.RST
140
        return self.markup
141
 
142
    def get_requirement_style_mode(self) -> str:
143
        if (
144
            self.requirement_style is None
145
            or self.requirement_style == "Narrative"
146
        ):
147
            return "narrative"
148
        if self.requirement_style == "Plain":
149
            return "plain"
150
        if self.requirement_style in (
151
            "Inline",
152
            "Simple",
153
        ):
154
            return "simple"
155
        if self.requirement_style == "Table":
156
            return "table"
157
        if self.requirement_style == "Zebra":
158
            return "zebra"
159
        raise NotImplementedError(self.requirement_style)
160
 
161
    def is_requirement_in_toc(self) -> bool:
162
        return (
163
            self.requirement_in_toc is None or self.requirement_in_toc == "True"
164
        )
165
 
166
    def get_prefix(self) -> str:
167
        if self.requirement_prefix is not None:
168
            return self.requirement_prefix
169
        return "REQ-"
170
 
171
    def get_relation_field(self) -> str:
172
        return self.relation_field or "UID"
173
 
174
    def has_meta(self) -> bool:
175
        # TODO: When OPTIONS are not provided to a document, the self.number and
176
        # self.version are both None. Otherwise, they become empty strings "".
177
        # This issue might deserve a bug report to TextX.
178
        return (
179
            (self.uid is not None and len(self.uid) > 0)
180
            or (self.version is not None and len(self.version) > 0)
181
            or (
182
                self.classification is not None and len(self.classification) > 0
183
            )
184
        )
185
 
186
    def has_custom_metadata(self) -> bool:
187
        return (
188
            self.custom_metadata is not None
189
            and self.custom_metadata.entries is not None
190
        )
191
 
192
    def get_custom_metadata(self) -> List[Tuple[str, str]]:
193
        if (
194
            self.custom_metadata is not None
195
            and self.custom_metadata.entries is not None
196
        ):
197
            return [
198
                (entry.key, entry.value)
199
                for entry in self.custom_metadata.entries
200
                if entry.key is not None and entry.value is not None
201
            ]
202
        return []