Skip to content

Commit 75c839a

Browse files
authored
Merge pull request #2250 from strictdoc-project/stanislaw/nodes_migration
backend/sdoc: Prepare automatic migration: [SECTION] -> [[SECTION]]
2 parents 2e365eb + 02ad820 commit 75c839a

File tree

5 files changed

+215
-7
lines changed

5 files changed

+215
-7
lines changed

strictdoc/backend/sdoc/models/document_grammar.py

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,9 @@ def __init__(
278278
self.ng_col_start: Optional[int] = None
279279

280280
@staticmethod
281-
def create_default(parent: Optional[SDocDocumentIF]) -> "DocumentGrammar":
281+
def create_default(
282+
parent: Optional[SDocDocumentIF], create_section_element: bool = False
283+
) -> "DocumentGrammar":
282284
text_element: GrammarElement = (
283285
DocumentGrammar.create_default_text_element()
284286
)
@@ -354,7 +356,17 @@ def create_default(parent: Optional[SDocDocumentIF]) -> "DocumentGrammar":
354356
requirement_element
355357
)
356358

357-
elements: List[GrammarElement] = [text_element, requirement_element]
359+
elements: List[GrammarElement] = []
360+
361+
if create_section_element:
362+
section_element: GrammarElement = (
363+
DocumentGrammar.create_default_section_element()
364+
)
365+
elements.append(section_element)
366+
367+
elements.append(text_element)
368+
elements.append(requirement_element)
369+
358370
grammar = DocumentGrammar(
359371
parent=parent, elements=elements, import_from_file=None
360372
)
@@ -531,6 +543,52 @@ def create_default_text_element(
531543
)
532544
return text_element
533545

546+
@staticmethod
547+
def create_default_section_element(
548+
parent: Optional["DocumentGrammar"] = None, enable_mid: bool = False
549+
) -> GrammarElement:
550+
fields: List[
551+
Union[
552+
GrammarElementFieldString,
553+
GrammarElementFieldSingleChoice,
554+
GrammarElementFieldMultipleChoice,
555+
]
556+
] = []
557+
if enable_mid:
558+
fields.append(
559+
GrammarElementFieldString(
560+
parent=None,
561+
title=RequirementFieldName.MID,
562+
human_title=None,
563+
required="True",
564+
)
565+
)
566+
fields.append(
567+
GrammarElementFieldString(
568+
parent=None,
569+
title=RequirementFieldName.UID,
570+
human_title=None,
571+
required="False",
572+
)
573+
)
574+
fields.append(
575+
GrammarElementFieldString(
576+
parent=None,
577+
title=RequirementFieldName.TITLE,
578+
human_title=None,
579+
required="True",
580+
),
581+
)
582+
section_element = GrammarElement(
583+
parent=parent,
584+
tag="SECTION",
585+
property_is_composite="True",
586+
property_view_style="",
587+
fields=fields,
588+
relations=[],
589+
)
590+
return section_element
591+
534592

535593
class DocumentGrammarWrapper:
536594
def __init__(self, grammar: DocumentGrammar):

strictdoc/backend/sdoc/models/node.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@ def __init__(
184184
self.reserved_mid: MID = MID(mid) if mid is not None else MID.create()
185185
self.mid_permanent: bool = mid is not None
186186

187-
# HEF4
188187
self.ng_resolved_custom_level: Optional[str] = None
189188
self.custom_level: Optional[str] = None
190189
if RequirementFieldName.LEVEL in ordered_fields_lookup:

strictdoc/backend/sdoc/models/section.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ def __init__(
4949

5050
self.section_contents = section_contents
5151

52-
# HEF4
5352
self.custom_level: Optional[str] = custom_level
5453
self.ng_resolved_custom_level: Optional[str] = custom_level
5554

strictdoc/backend/sdoc/reader.py

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# mypy: disable-error-code="no-any-return,no-untyped-call,no-untyped-def"
22
import sys
33
import traceback
4+
from copy import copy
45
from typing import Tuple
56

67
from textx import metamodel_from_str
@@ -9,6 +10,9 @@
910
from strictdoc.backend.sdoc.grammar.grammar_builder import SDocGrammarBuilder
1011
from strictdoc.backend.sdoc.models.constants import DOCUMENT_MODELS
1112
from strictdoc.backend.sdoc.models.document import SDocDocument
13+
from strictdoc.backend.sdoc.models.document_grammar import DocumentGrammar
14+
from strictdoc.backend.sdoc.models.node import SDocNode, SDocNodeField
15+
from strictdoc.backend.sdoc.models.section import SDocSection
1216
from strictdoc.backend.sdoc.pickle_cache import PickleCache
1317
from strictdoc.backend.sdoc.processor import ParseContext, SDocParsingProcessor
1418
from strictdoc.core.project_config import ProjectConfig
@@ -41,15 +45,24 @@ def _read(input_string, file_path=None):
4145
return document, parse_context
4246

4347
@staticmethod
44-
def read(input_string, file_path=None) -> SDocDocument:
45-
document, _ = SDReader.read_with_parse_context(input_string, file_path)
48+
def read(
49+
input_string, file_path=None, migrate_sections: bool = False
50+
) -> SDocDocument:
51+
document, _ = SDReader.read_with_parse_context(
52+
input_string, file_path, migrate_sections=migrate_sections
53+
)
4654
return document
4755

4856
@staticmethod
4957
def read_with_parse_context(
50-
input_string, file_path=None
58+
input_string, file_path=None, migrate_sections: bool = False
5159
) -> Tuple[SDocDocument, ParseContext]:
5260
document, parse_context = SDReader._read(input_string, file_path)
61+
62+
if migrate_sections:
63+
SDReader.migrate_sections(document)
64+
SDReader.migration_sections_grammar(document)
65+
5366
return document, parse_context
5467

5568
def read_from_file(
@@ -102,3 +115,74 @@ def read_from_file(
102115
# TODO: when --debug is provided
103116
traceback.print_exc()
104117
sys.exit(1)
118+
119+
@staticmethod
120+
def convert(section: SDocSection) -> SDocNode:
121+
"""
122+
FIXME: Handle LEVEL, REQ_PREFIX
123+
"""
124+
fields = []
125+
126+
if section.mid_permanent:
127+
fields.append(
128+
SDocNodeField.create_from_string(
129+
None,
130+
field_name="MID",
131+
field_value=section.reserved_mid,
132+
multiline=False,
133+
)
134+
)
135+
if section.reserved_uid is not None:
136+
fields.append(
137+
SDocNodeField.create_from_string(
138+
None,
139+
field_name="UID",
140+
field_value=section.reserved_uid,
141+
multiline=False,
142+
)
143+
)
144+
fields.append(
145+
SDocNodeField.create_from_string(
146+
None,
147+
field_name="TITLE",
148+
field_value=section.reserved_title,
149+
multiline=False,
150+
)
151+
)
152+
node: SDocNode = SDocNode(
153+
parent=section,
154+
node_type="SECTION",
155+
fields=fields,
156+
relations=[],
157+
is_composite=True,
158+
section_contents=section.section_contents,
159+
node_type_close="SECTION",
160+
)
161+
for field_ in fields:
162+
field_.parent = node
163+
return node
164+
165+
@staticmethod
166+
def migrate_sections(sdoc):
167+
for node_idx_, node_ in enumerate(copy(sdoc.section_contents)):
168+
if isinstance(node_, SDocSection):
169+
SDReader.migrate_sections(node_)
170+
171+
new_node = SDReader.convert(node_)
172+
sdoc.section_contents[node_idx_] = new_node
173+
174+
@staticmethod
175+
def migration_sections_grammar(sdoc: SDocDocument):
176+
grammar: DocumentGrammar = assert_cast(sdoc.grammar, DocumentGrammar)
177+
section_element_exists = any(
178+
element_.tag == "SECTION" for element_ in grammar.elements
179+
)
180+
if not section_element_exists:
181+
grammar.update_with_elements(
182+
[
183+
DocumentGrammar.create_default_section_element(
184+
grammar, enable_mid=sdoc.config.enable_mid or False
185+
)
186+
]
187+
+ grammar.elements
188+
)
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from strictdoc.backend.sdoc.models.document import SDocDocument
2+
from strictdoc.backend.sdoc.reader import SDReader
3+
from strictdoc.backend.sdoc.writer import SDWriter
4+
5+
6+
def test_010_multiple_sections(default_project_config):
7+
input_sdoc = """\
8+
[DOCUMENT]
9+
TITLE: Test Doc
10+
11+
[SECTION]
12+
TITLE: Test Section
13+
14+
[SECTION]
15+
TITLE: Test Section (Nested)
16+
17+
[SECTION]
18+
TITLE: Test Section (Sub-nested)
19+
20+
[REQUIREMENT]
21+
STATEMENT: >>>
22+
This is a statement 1
23+
This is a statement 2
24+
This is a statement 3
25+
<<<
26+
27+
[/SECTION]
28+
29+
[/SECTION]
30+
31+
[/SECTION]
32+
"""
33+
34+
output_sdoc = """\
35+
[DOCUMENT]
36+
TITLE: Test Doc
37+
38+
[[SECTION]]
39+
TITLE: Test Section
40+
41+
[[SECTION]]
42+
TITLE: Test Section (Nested)
43+
44+
[[SECTION]]
45+
TITLE: Test Section (Sub-nested)
46+
47+
[REQUIREMENT]
48+
STATEMENT: >>>
49+
This is a statement 1
50+
This is a statement 2
51+
This is a statement 3
52+
<<<
53+
54+
[[/SECTION]]
55+
56+
[[/SECTION]]
57+
58+
[[/SECTION]]
59+
"""
60+
61+
reader = SDReader()
62+
63+
document = reader.read(input_sdoc, migrate_sections=True)
64+
assert isinstance(document, SDocDocument)
65+
66+
writer = SDWriter(default_project_config)
67+
output = writer.write(document)
68+
assert output == output_sdoc

0 commit comments

Comments
 (0)