sdoc.sdoc2.node.DocumentNode   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 155
Duplicated Lines 89.03 %

Test Coverage

Coverage 77.59%

Importance

Changes 0
Metric Value
wmc 17
eloc 59
dl 138
loc 155
ccs 45
cts 58
cp 0.7759
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A DocumentNode.prepare_content_tree() 13 13 2
A DocumentNode.is_block_command() 5 5 1
A DocumentNode.get_hierarchy_name() 5 5 1
A DocumentNode.get_command() 5 5 1
A DocumentNode.__set_document_info() 17 17 4
A DocumentNode.__check_document_info() 15 15 2
A DocumentNode.is_document_root() 5 5 1
A DocumentNode.get_hierarchy_level() 5 5 1
A DocumentNode.__remove_document_info_nodes() 7 7 1
A DocumentNode.is_inline_command() 5 5 1
A DocumentNode.__init__() 21 21 1
A DocumentNode.is_phrasing() 5 5 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1 1
from typing import Dict, Optional
2
3 1
from cleo.io.io import IO
4
5 1
from sdoc.sdoc2 import in_scope, out_scope
6 1
from sdoc.sdoc2.node.DateNode import DateNode
7 1
from sdoc.sdoc2.node.Node import Node
8 1
from sdoc.sdoc2.node.TitleNode import TitleNode
9 1
from sdoc.sdoc2.node.VersionNode import VersionNode
10 1
from sdoc.sdoc2.NodeStore import NodeStore
11
12
13 1 View Code Duplication
class DocumentNode(Node):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
14
    """
15
    SDoc2 node for documents.
16
    """
17
18
    # ------------------------------------------------------------------------------------------------------------------
19 1
    def __init__(self, io: IO, options: Dict[str, str]):
20
        """
21
        Object constructor.
22
23
        :param OutputStyle io: The IO object.
24
        :param dict[str,str] options: The options of this document.
25
        """
26 1
        super().__init__(io, 'document', options)
27
28 1
        self.title_node_id: Optional[int] = None
29
        """
30
        The ID of the node the title of the sdoc document.
31
        """
32
33 1
        self.date_node_id: Optional[int] = None
34
        """
35
        The ID of the node the date of the sdoc document.
36
        """
37
38 1
        self.version_node_id: Optional[int] = None
39 1
        """
40
        The ID of the node with the version of the sdoc document.
41
        """
42
43
    # ------------------------------------------------------------------------------------------------------------------
44 1
    def get_command(self) -> str:
45
        """
46
        Returns the command of this node, i.e. document.
47
        """
48 1
        return 'document'
49
50
    # ------------------------------------------------------------------------------------------------------------------
51 1
    def get_hierarchy_level(self, parent_hierarchy_level: int = -1) -> int:
52
        """
53
        Returns 0.
54
        """
55 1
        return 0
56
57
    # ------------------------------------------------------------------------------------------------------------------
58 1
    def get_hierarchy_name(self) -> str:
59
        """
60
        Returns 'sectioning'.
61
        """
62 1
        return 'sectioning'
63
64
    # ------------------------------------------------------------------------------------------------------------------
65 1
    def is_block_command(self) -> bool:
66
        """
67
        Returns True.
68
        """
69 1
        return True
70
71
    # ------------------------------------------------------------------------------------------------------------------
72 1
    def is_document_root(self) -> bool:
73
        """
74
        Returns True.
75
        """
76 1
        return True
77
78
    # ------------------------------------------------------------------------------------------------------------------
79 1
    def is_inline_command(self) -> bool:
80
        """
81
        Returns False.
82
        """
83
        return False
84
85
    # ------------------------------------------------------------------------------------------------------------------
86 1
    def is_phrasing(self) -> bool:
87
        """
88
        Returns False.
89
        """
90
        return False
91
92
    # ------------------------------------------------------------------------------------------------------------------
93 1
    def prepare_content_tree(self) -> None:
94
        """
95
        Prepares this node for further processing.
96
        """
97 1
        for node_id in self.child_nodes:
98 1
            node = in_scope(node_id)
99
100 1
            node.prepare_content_tree()
101 1
            self.__set_document_info(node)
102
103 1
            out_scope(node)
104
105 1
        self.__remove_document_info_nodes()
106
107
    # ------------------------------------------------------------------------------------------------------------------
108 1
    def __set_document_info(self, node: Node) -> None:
109
        """
110
        Sets the info of a document (i.e. date, version or title) to DocumentNode attributes.
111
112
        :param Node node: The current node.
113
        """
114 1
        if isinstance(node, DateNode):
115
            self.__check_document_info(self.date_node_id, node)
116
            self.date_node_id = node.id
117
118 1
        elif isinstance(node, TitleNode):
119
            self.__check_document_info(self.title_node_id, node)
120
            self.title_node_id = node.id
121
122 1
        elif isinstance(node, VersionNode):
123
            self.__check_document_info(self.version_node_id, node)
124
            self.version_node_id = node.id
125
126
    # ------------------------------------------------------------------------------------------------------------------
127 1
    @staticmethod
128 1
    def __check_document_info(info_node_current: Optional[int], info_node_new: Node) -> None:
129
        """
130
        Checks if a document info node has been set already. If so, an error will be logged.
131
132
        :param int|None info_node_current: The current document info node (i.e. a property of the document).
133
        :param Node info_node_new: The (new) document info node.
134
        """
135
        if info_node_current:
136
            node = in_scope(info_node_current)
137
            position = node.position
138
            out_scope(node)
139
140
            NodeStore.error("Document info {0} can be specified only once. Previous definition at {1}.".format(
141
                    info_node_new.name, str(position)), info_node_new)
142
143
    # ------------------------------------------------------------------------------------------------------------------
144 1
    def __remove_document_info_nodes(self):
145
        """
146
        Removes the nodes with document info from the list of child nodes.
147
        """
148 1
        obsolete_node_ids = [self.date_node_id, self.title_node_id, self.version_node_id]
149 1
        obsolete_node_ids = [node_id for node_id in obsolete_node_ids if node_id is not None]
150 1
        self._remove_child_nodes(obsolete_node_ids)
151
152
153
# ----------------------------------------------------------------------------------------------------------------------
154
NodeStore.register_block_command('document', DocumentNode)
155