Skip to content

Commit 61df6db

Browse files
authored
Merge pull request #2263 from strictdoc-project/stanislaw/merge_nodes
[[NODE]] migration: carry over SECTION reset UID behavior
2 parents a27b13e + c316d3c commit 61df6db

File tree

18 files changed

+174
-18
lines changed

18 files changed

+174
-18
lines changed

strictdoc/backend/sdoc/models/model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def get_display_title(self, include_toc_number: bool = True) -> str:
9696
raise NotImplementedError # pragma: no cover
9797

9898

99-
class SDocDocumentFromFileIF:
99+
class SDocDocumentFromFileIF(ABC):
100100
parent: Union[SDocDocumentIF, SDocSectionIF]
101101
ng_resolved_custom_level: Optional[str]
102102

strictdoc/backend/sdoc/reader.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import sys
33
import traceback
44
from copy import copy
5-
from typing import Tuple
5+
from typing import Any, Tuple
66

77
from textx import metamodel_from_str
88

@@ -65,9 +65,11 @@ def read_with_parse_context(
6565
) -> Tuple[SDocDocument, ParseContext]:
6666
document, parse_context = SDReader._read(input_string, file_path)
6767

68+
# FIXME: When the [SECTION] is gone, remove this.
6869
if migrate_sections:
6970
SDReader.migrate_sections(document)
7071
SDReader.migration_sections_grammar(document)
72+
SDReader.fixup_composite_requirements(document)
7173

7274
return document, parse_context
7375

@@ -197,20 +199,26 @@ def convert(section: SDocSection) -> SDocNode:
197199
return node
198200

199201
@staticmethod
200-
def migrate_sections(sdoc):
202+
def fixup_composite_requirements(sdoc: SDocDocument) -> None:
203+
for _, node_ in enumerate(copy(sdoc.section_contents)):
204+
if isinstance(node_, SDocCompositeNode):
205+
SDReader.migration_sections_grammar(sdoc)
206+
break
207+
208+
@staticmethod
209+
def migrate_sections(sdoc: Any) -> None:
201210
for node_idx_, node_ in enumerate(copy(sdoc.section_contents)):
202211
if isinstance(node_, SDocSection):
203212
SDReader.migrate_sections(node_)
204213

205214
new_node = SDReader.convert(node_)
206215
sdoc.section_contents[node_idx_] = new_node
207216

208-
elif isinstance(node_, SDocCompositeNode):
209-
SDReader.migration_sections_grammar(sdoc)
210-
211217
@staticmethod
212-
def migration_sections_grammar(sdoc: SDocDocument):
218+
def migration_sections_grammar(sdoc: SDocDocument) -> None:
213219
grammar: DocumentGrammar = assert_cast(sdoc.grammar, DocumentGrammar)
220+
if not grammar.is_default:
221+
return
214222
section_element_exists = any(
215223
element_.tag == "SECTION" for element_ in grammar.elements
216224
)

strictdoc/core/analyzers/document_stats.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ class DocumentStats:
2121
requirements_per_prefix: Dict[str, SinglePrefixRequirements] = field(
2222
default_factory=dict
2323
)
24-
sections_without_uid: List[SDocSection] = field(default_factory=list)
24+
sections_without_uid: List[typing.Union[SDocNode, SDocSection]] = field(
25+
default_factory=list
26+
)
2527
section_uids_so_far: typing.Counter[str] = field(default_factory=Counter)
2628

2729

@@ -53,9 +55,14 @@ def get_next_requirement_uid_number(self, prefix: str) -> int:
5355
return next_number
5456

5557
def get_auto_section_uid(
56-
self, document_acronym: str, section: SDocSection
58+
self,
59+
document_acronym: str,
60+
section: typing.Union[SDocNode, SDocSection],
5761
) -> str:
58-
section_title = create_safe_title_string(section.title)
62+
if section.reserved_title is None:
63+
return ""
64+
65+
section_title = create_safe_title_string(section.reserved_title)
5966
auto_uid = f"SECTION-{document_acronym}-{section_title}"
6067

6168
count_so_far = self.section_uids_so_far[auto_uid]

strictdoc/core/analyzers/document_uid_analyzer.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ def analyze_document(
6868
this_document_stats = DocumentStats(document)
6969
document_iterator = DocumentCachingIterator(document)
7070
for node in document_iterator.all_content():
71-
if isinstance(node, SDocSection):
71+
if isinstance(node, SDocSection) or (
72+
isinstance(node, SDocNode) and node.node_type == "SECTION"
73+
):
7274
if node.reserved_uid is not None:
7375
this_document_stats.section_uids_so_far[
7476
node.reserved_uid
@@ -78,7 +80,7 @@ def analyze_document(
7880
continue
7981
if not isinstance(node, SDocNode):
8082
continue
81-
if node.node_type == "TEXT":
83+
if node.node_type in ("TEXT", "SECTION"):
8284
continue
8385
requirement: SDocNode = node
8486
node_prefix: typing.Optional[str] = requirement.get_prefix()

strictdoc/server/routers/main_router.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,19 +1034,22 @@ def reset_uid(reference_mid: str):
10341034
MID(reference_mid)
10351035
)
10361036
next_uid: str = ""
1037-
if isinstance(reference_node, SDocNode):
1038-
if (node_prefix := reference_node.get_prefix()) is not None:
1039-
next_uid = document_tree_stats.get_next_requirement_uid(
1040-
node_prefix
1041-
)
1042-
elif isinstance(reference_node, SDocSection):
1037+
if isinstance(reference_node, SDocSection) or (
1038+
isinstance(reference_node, SDocNode)
1039+
and reference_node.node_type == "SECTION"
1040+
):
10431041
document: SDocDocument = assert_cast(
10441042
reference_node.get_document(), SDocDocument
10451043
)
10461044
document_acronym = create_safe_acronym(document.title)
10471045
next_uid = document_tree_stats.get_auto_section_uid(
10481046
document_acronym, reference_node
10491047
)
1048+
elif isinstance(reference_node, SDocNode):
1049+
if (node_prefix := reference_node.get_prefix()) is not None:
1050+
next_uid = document_tree_stats.get_next_requirement_uid(
1051+
node_prefix
1052+
)
10501053
else:
10511054
raise NotImplementedError(reference_node) # pragma: no cover
10521055

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[DOCUMENT]
2+
TITLE: Document 1
3+
4+
[[SECTION]]
5+
UID: SECTION-D-First-section
6+
TITLE: Modified title
7+
8+
[[/SECTION]]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[DOCUMENT]
2+
TITLE: Document 1
3+
4+
[[SECTION]]
5+
TITLE: First section
6+
7+
[[/SECTION]]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import os
2+
3+
from tests.end2end.e2e_case import E2ECase
4+
from tests.end2end.end2end_test_setup import End2EndTestSetup
5+
from tests.end2end.helpers.screens.document.form_edit_requirement import (
6+
Form_EditRequirement,
7+
)
8+
from tests.end2end.helpers.screens.project_index.screen_project_index import (
9+
Screen_ProjectIndex,
10+
)
11+
from tests.end2end.server import SDocTestServer
12+
13+
path_to_this_test_file_folder = os.path.dirname(os.path.abspath(__file__))
14+
15+
16+
class Test(E2ECase):
17+
def test(self):
18+
test_setup = End2EndTestSetup(path_to_test_file=__file__)
19+
20+
with SDocTestServer(
21+
input_path=test_setup.path_to_sandbox,
22+
) as test_server:
23+
self.open(test_server.get_host_and_port())
24+
25+
screen_project_index = Screen_ProjectIndex(self)
26+
27+
screen_project_index.assert_on_screen()
28+
screen_project_index.assert_contains_document("Document 1")
29+
30+
screen_document = screen_project_index.do_click_on_first_document()
31+
32+
screen_document.assert_on_screen_document()
33+
screen_document.assert_header_document_title("Document 1")
34+
35+
section_node = screen_document.get_node()
36+
form_edit_section: Form_EditRequirement = (
37+
section_node.do_open_form_edit_requirement()
38+
)
39+
form_edit_section.do_reset_uid_field()
40+
form_edit_section.do_fill_in("TITLE", "Modified title")
41+
form_edit_section.do_form_submit()
42+
43+
section_node.assert_requirement_title("Modified title", "1")
44+
screen_document.assert_toc_contains("Modified title")
45+
46+
assert test_setup.compare_sandbox_and_expected_output()

0 commit comments

Comments
 (0)