mkdocs-apidescribed-plugin 1.0.1__tar.gz → 1.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mkdocs-apidescribed-plugin
3
- Version: 1.0.1
3
+ Version: 1.1.0
4
4
  Summary: mkdocs plugin to generate API documentation for Python programs
5
5
  Project-URL: Homepage, https://github.com/idlesign/mkdocs-apidescribed-plugin
6
6
  Project-URL: Documentation, https://mkdocs-apidescribed-plugin.readthedocs.org/
@@ -55,7 +55,7 @@ path = "src/mkdocs_apidescribed/__init__.py"
55
55
  packages = ["src/mkdocs_apidescribed"]
56
56
 
57
57
  [tool.hatch.build.targets.sdist]
58
- packages = ["src/mkdocs_apidescribed"]
58
+ packages = ["src/"]
59
59
 
60
60
  [tool.coverage.run]
61
61
  source = [
@@ -0,0 +1,2 @@
1
+
2
+ VERSION = '1.1.0'
@@ -25,7 +25,7 @@ class Symbol:
25
25
  type: SymbolType
26
26
  name: str
27
27
  source: str
28
- docstr: griffe.Docstring
28
+ docstr: str
29
29
  path: str
30
30
  fpath: str
31
31
  params: griffe.Parameters | None
@@ -108,7 +108,7 @@ def get_symbol(
108
108
 
109
109
  if not symbol_type:
110
110
  log.error(f'Unsupported symbol type: {obj}. Skipped.')
111
- return
111
+ return None
112
112
 
113
113
  symbol = Symbol(
114
114
  depth=depth,
@@ -116,7 +116,7 @@ def get_symbol(
116
116
  type=symbol_type,
117
117
  name=obj.name,
118
118
  source=obj.source,
119
- docstr=obj.docstring,
119
+ docstr=getattr(obj.docstring, 'value', None) or '',
120
120
  path=obj.path,
121
121
  fpath=f'{obj.relative_package_filepath}',
122
122
  params=params,
@@ -4,8 +4,6 @@ from dataclasses import dataclass, field
4
4
  from textwrap import dedent
5
5
  from typing import TYPE_CHECKING
6
6
 
7
- import griffe
8
-
9
7
  if TYPE_CHECKING:
10
8
  from .formatter import Formatter
11
9
 
@@ -25,7 +23,7 @@ class Block:
25
23
 
26
24
  def __init__(self, marker: str = '', arg: str = '', value: str = ''):
27
25
  self.marker = marker or self.unmarked
28
- self.arg = arg.strip()
26
+ self.arg = arg.strip().partition(' ')[0] # e.g.: "arg (int)"
29
27
  self.value = value
30
28
  self.addition = []
31
29
 
@@ -47,9 +45,9 @@ class DocstrParser:
47
45
  registry: dict[str, type['DocstrParser']] = {}
48
46
 
49
47
  @classmethod
50
- def parse(cls, docstr: griffe.Docstring | None, *, config: dict, formatter: 'Formatter') -> Docstring:
48
+ def parse(cls, docstr: str, *, config: dict, formatter: 'Formatter') -> Docstring:
51
49
 
52
- value = getattr(docstr, 'value', None) or ''
50
+ value = docstr
53
51
  docstring = Docstring(text=f'{value}')
54
52
 
55
53
  if value:
@@ -87,9 +85,64 @@ class DocstrParser:
87
85
  def run(self) -> Docstring | None:
88
86
  return self._parse(self.src)
89
87
 
88
+ def normalize(self, text: str) -> str:
89
+ return text
90
+
90
91
  def postprocess(self, text: str) -> str:
91
92
  return text
92
93
 
94
+ def parse_blocks(
95
+ self,
96
+ *,
97
+ pattern: re.Pattern,
98
+ value: str,
99
+ ) -> tuple[dict[str, list[Block]], list[Block]]:
100
+
101
+ blocks: dict[str, list[Block]] = defaultdict(list)
102
+ block_last: Block | None = None
103
+ marker_detected = False
104
+
105
+ processed = []
106
+
107
+ for line in value.splitlines():
108
+
109
+ is_empty = len(line.strip()) == 0
110
+
111
+ if block_last:
112
+ if line.startswith(' ') or is_empty:
113
+ # must be a continuation of a block
114
+ block_last.contribute(line)
115
+ continue
116
+
117
+ # previous block ended
118
+ processed.append(block_last)
119
+ block_last = None
120
+
121
+ if matched := pattern.match(line):
122
+ marker_detected = True
123
+ marker = matched.group('marker')
124
+
125
+ arg = matched.group('arg')
126
+ val = matched.group('value')
127
+
128
+ block = Block(marker, arg, val.strip())
129
+ blocks[marker].append(block)
130
+ block_last = block
131
+
132
+ else:
133
+ block = Block()
134
+ block.contribute(line)
135
+ blocks[Block.unmarked].append(block)
136
+ processed.append(block)
137
+
138
+ if block_last:
139
+ # block in the last line
140
+ processed.append(block_last)
141
+
142
+ self.markers_detected = self.markers_detected or marker_detected
143
+
144
+ return blocks, processed
145
+
93
146
  def _parse(self, value: str) -> Docstring | None: # pragma: nocover
94
147
  return
95
148
 
@@ -154,76 +207,84 @@ class SphinxParser(DocstrParser):
154
207
 
155
208
  return '\n'.join(lines)
156
209
 
157
- def parse_blocks(
158
- self,
159
- *,
160
- pattern: re.Pattern,
161
- value: str,
162
- ) -> tuple[dict[str, list[Block]], list[Block]]:
210
+ def _parse(self, value: str) -> Docstring | None:
163
211
 
164
- blocks: dict[str, list[Block]] = defaultdict(list)
165
- block_last: Block | None = None
166
- marker_detected = False
212
+ blocks, processed = self.parse_blocks(
213
+ pattern=self.re_markers,
214
+ value=self.normalize(value),
215
+ )
167
216
 
168
- processed = []
217
+ return Docstring(
218
+ text=self.postprocess('\n'.join(map(str, blocks[Block.unmarked]))),
219
+ params=self.to_dict(blocks['param']),
220
+ returns=self.to_list(blocks['return']),
221
+ raises=self.to_dict(blocks['raises']),
222
+ )
223
+
224
+
225
+ class GoogleParser(DocstrParser):
226
+ alias: str = 'google'
227
+
228
+ re_markers = re.compile(
229
+ r'^::(?P<marker>Args|Yields|Returns|Raises|Examples)::'
230
+ r'(?P<arg>[^:]*):\s*(?P<value>.*)'
231
+ )
232
+
233
+ re_preproc = re.compile(r'^(?P<marker>Args|Yields|Returns|Raises|Examples):$')
234
+
235
+ def normalize(self, value: str) -> str:
236
+ pattern = self.re_preproc
237
+ normalized = []
238
+ marker_stack = []
239
+ marker_depth = 0
169
240
 
170
241
  for line in value.splitlines():
171
242
 
172
243
  is_empty = len(line.strip()) == 0
173
244
 
174
- if block_last:
245
+ if marker_stack:
175
246
  if line.startswith(' ') or is_empty:
176
- # must be a continuation of a block
177
- block_last.contribute(line)
178
- continue
247
+ unindented = line.lstrip(' ')
248
+ indent_size = len(line) - len(unindented)
179
249
 
180
- # previous block ended
181
- processed.append(block_last)
182
- block_last = None
250
+ if not marker_depth or indent_size == marker_depth:
251
+ marker_depth = indent_size
252
+ marker_stack.append(f"::{marker_stack[0]}:: {unindented}")
183
253
 
184
- if matched := pattern.match(line):
185
- marker_detected = True
186
- marker = matched.group('marker')
254
+ elif indent_size > marker_depth:
255
+ # deeper: block body (continuation)
256
+ reindented = f'{" " * (indent_size-marker_depth)}{unindented}'
257
+ marker_stack[-1] = f'{marker_stack[-1]}\n{reindented}'
258
+ else:
259
+ # end of block
260
+ normalized.extend(marker_stack[1:])
261
+ marker_stack.clear()
262
+ marker_depth = 0
187
263
 
188
- arg = matched.group('arg')
189
- val = matched.group('value')
264
+ continue
190
265
 
191
- block = Block(marker, arg, val.strip())
192
- blocks[marker].append(block)
193
- block_last = block
266
+ if matched := pattern.match(line):
267
+ marker_stack.append(matched.group('marker'))
194
268
 
195
269
  else:
196
- block = Block()
197
- block.contribute(line)
198
- blocks[Block.unmarked].append(block)
199
- processed.append(block)
270
+ normalized.append(line)
200
271
 
201
- if block_last:
202
- # block in the last line
203
- processed.append(block_last)
204
-
205
- self.markers_detected = self.markers_detected or marker_detected
206
-
207
- return blocks, processed
272
+ return '\n'.join(normalized)
208
273
 
209
274
  def _parse(self, value: str) -> Docstring | None:
210
275
 
211
276
  blocks, processed = self.parse_blocks(
212
277
  pattern=self.re_markers,
213
- value=value,
278
+ value=self.normalize(value),
214
279
  )
215
280
 
216
281
  return Docstring(
217
282
  text=self.postprocess('\n'.join(map(str, blocks[Block.unmarked]))),
218
- params=self.to_dict(blocks['param']),
219
- returns=self.to_list(blocks['return']),
220
- raises=self.to_dict(blocks['raises']),
283
+ params=self.to_dict(blocks['Args']),
284
+ returns=self.to_list(blocks['Returns']),
285
+ raises=self.to_dict(blocks['Raises']),
221
286
  )
222
287
 
223
288
 
224
- class GoogleParser(DocstrParser):
225
- alias: str = 'google'
226
-
227
-
228
289
  class NumpyParser(DocstrParser):
229
290
  alias: str = 'numpy'
@@ -1,2 +0,0 @@
1
-
2
- VERSION = '1.0.1'