Coverage for pystratum_common/DocBlockReflection.py : 90%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import os
2import re
3from typing import List, Tuple
6class DocBlockReflection:
7 """
8 A simple DocBlock reflection.
9 """
11 # ------------------------------------------------------------------------------------------------------------------
12 def __init__(self, comment: List[str]):
13 """
14 Object constructor.
16 :param list[str] comment: The comment as a list of strings.
17 """
18 self._comment: List[str] = comment
19 """
20 The DocBlock as a list of strings.
21 """
23 self._description: str = ''
24 """
25 The description.
26 """
28 self._tags: List[Tuple[str, str]] = list()
29 """
30 The tags in the DocBlock
31 """
33 self.__reflect()
35 # ------------------------------------------------------------------------------------------------------------------
36 def get_description(self) -> str:
37 """
38 Returns the description.
40 :rtype: str
41 """
42 return self._description
44 # ------------------------------------------------------------------------------------------------------------------
45 def get_tag(self, name: str) -> str:
46 """
47 Returns a tag.
49 @param str name: The name of the tag.
51 :rtype: str
52 """
53 for tag in self._tags:
54 if tag[0] == name:
55 return tag[1]
57 return ''
59 # ------------------------------------------------------------------------------------------------------------------
60 def get_tags(self, name: str) -> List[str]:
61 """
62 Returns a list of tags.
64 @param str name: The name of the tag.
66 :rtype: list[str]
67 """
68 tags = list()
69 for tag in self._tags:
70 if tag[0] == name: 70 ↛ 69line 70 didn't jump to line 69, because the condition on line 70 was never false
71 tags.append(tag[1])
73 return tags
75 # ------------------------------------------------------------------------------------------------------------------
76 def __reflect(self) -> None:
77 """
78 Parses the DocBlock.
79 """
80 self.__clean_doc_block()
81 self.__extract_description()
82 self.__extract_tags()
84 # ------------------------------------------------------------------------------------------------------------------
85 @staticmethod
86 def __remove_leading_empty_lines(lines: List[str]) -> List[str]:
87 """
88 Removes leading empty lines from a list of lines.
90 :param list[str] lines: The lines.
91 """
92 tmp = list()
93 empty = True
94 for i in range(0, len(lines)):
95 empty = empty and lines[i] == ''
96 if not empty:
97 tmp.append(lines[i])
99 return tmp
101 # ------------------------------------------------------------------------------------------------------------------
102 @staticmethod
103 def __remove_trailing_empty_lines(lines: List[str]) -> List[str]:
104 """
105 Removes leading empty lines from a list of lines.
107 :param list[str] lines: The lines.
108 """
109 lines.reverse()
110 tmp = DocBlockReflection.__remove_leading_empty_lines(lines)
111 lines.reverse()
112 tmp.reverse()
114 return tmp
116 # ------------------------------------------------------------------------------------------------------------------
117 def __clean_doc_block(self) -> None:
118 """
119 Cleans the DocBlock from leading and trailing white space and comment tokens.
120 """
121 # Return immediately if the DockBlock is empty.
122 if not self._comment:
123 return
125 for i in range(1, len(self._comment) - 1):
126 self._comment[i] = re.sub(r'^\s*\*', '', self._comment[i])
128 self._comment[0] = re.sub(r'^\s*/\*\*', '', self._comment[0])
130 self._comment[-1] = re.sub(r'\*/\s*$', '', self._comment[-1])
132 for i, line in enumerate(self._comment):
133 self._comment[i] = line.strip()
135 self._comment = self.__remove_leading_empty_lines(self._comment)
136 self._comment = self.__remove_trailing_empty_lines(self._comment)
138 # ------------------------------------------------------------------------------------------------------------------
139 def __extract_description(self) -> None:
140 """
141 Extracts the description from the DocBlock. The description start at the first line and stops at the first tag
142 or the end of the DocBlock.
143 """
144 tmp = list()
145 for line in self._comment:
146 if len(line) >= 1 and line[0] == '@':
147 break
149 tmp.append(line)
151 tmp = self.__remove_trailing_empty_lines(tmp)
153 self._description = os.linesep.join(tmp)
155 # ------------------------------------------------------------------------------------------------------------------
156 def __extract_tags(self) -> None:
157 """
158 Extract tags from the DocBlock.
159 """
160 tags = list()
161 current = None
162 for line in self._comment:
163 parts = re.match(r'^@(\w+)', line)
164 if parts:
165 current = (parts.group(1), list())
166 tags.append(current)
168 if current:
169 if line == '': 169 ↛ 170line 169 didn't jump to line 170, because the condition on line 169 was never true
170 current = None
171 else:
172 current[1].append(line)
174 for tag in tags:
175 self._tags.append((tag[0], os.linesep.join(tag[1])))
177# ----------------------------------------------------------------------------------------------------------------------