Skip to content

Commit becd506

Browse files
committed
Use a couple of dataclasses to make code easier to read
1 parent 096d286 commit becd506

File tree

1 file changed

+44
-35
lines changed

1 file changed

+44
-35
lines changed

src/pytest_markdown_docs/plugin.py

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import traceback
44
import types
55
import pathlib
6+
from dataclasses import dataclass
7+
68
import pytest
79
import typing
810
from enum import Enum
@@ -31,6 +33,20 @@ class FenceSyntax(Enum):
3133
superfences = "superfences"
3234

3335

36+
@dataclass
37+
class FenceTest:
38+
code_block: str
39+
fixture_names: typing.List[str]
40+
start_line: int
41+
42+
43+
@dataclass
44+
class ObjectTest:
45+
intra_object_index: int
46+
object_name: str
47+
fence_test: FenceTest
48+
49+
3450
class MarkdownInlinePythonItem(pytest.Item):
3551
def __init__(
3652
self,
@@ -161,11 +177,11 @@ def reportinfo(self):
161177
return self.name, 0, self.nodeid
162178

163179

164-
def extract_code_blocks(
180+
def extract_fence_tests(
165181
markdown_string: str,
166182
markdown_type: str = "md",
167183
fence_syntax: FenceSyntax = FenceSyntax.default,
168-
) -> typing.Generator[typing.Tuple[str, typing.List[str], int], None, None]:
184+
) -> typing.Generator[FenceTest, None, None]:
169185
import markdown_it
170186

171187
mi = markdown_it.MarkdownIt(config="commonmark")
@@ -176,7 +192,7 @@ def extract_code_blocks(
176192
if block.type != "fence" or not block.map:
177193
continue
178194

179-
startline = block.map[0] + 1 # skip the info line when counting
195+
start_line = block.map[0] + 1 # skip the info line when counting
180196
if fence_syntax == FenceSyntax.superfences:
181197
code_info = parse_superfences_block_info(block.info)
182198
else:
@@ -204,12 +220,12 @@ def extract_code_blocks(
204220

205221
if "continuation" in code_options:
206222
code_block = prev + code_block
207-
startline = -1 # this disables proper line numbers, TODO: adjust line numbers *per snippet*
223+
start_line = -1 # this disables proper line numbers, TODO: adjust line numbers *per snippet*
208224

209225
fixture_names = [
210226
f[len("fixture:") :] for f in code_options if f.startswith("fixture:")
211227
]
212-
yield code_block, fixture_names, startline
228+
yield FenceTest(code_block, fixture_names, start_line)
213229
prev = code_block
214230

215231

@@ -268,43 +284,36 @@ def collect(self):
268284
self.path, root=self.config.rootpath, consider_namespace_packages=True
269285
)
270286
else:
271-
# but unsupported before 8.1...
287+
# but unsupported before pytest 8.1...
272288
module = import_path(self.path, root=self.config.rootpath)
273289

274-
for code_block_idx, obj, (
275-
test_code,
276-
fixture_names,
277-
start_line,
278-
) in self.find_object_tests_recursive(module.__name__, module):
279-
obj_name = (
280-
getattr(obj, "__qualname__", None)
281-
or getattr(obj, "__name__", None)
282-
or "<Unnamed obj>"
283-
)
290+
for object_test in self.find_object_tests_recursive(module.__name__, module):
291+
fence_test = object_test.fence_test
284292
yield MarkdownInlinePythonItem.from_parent(
285293
self,
286-
name=f"{obj_name}[CodeBlock#{code_block_idx+1}][rel.line:{start_line}]",
287-
code=test_code,
288-
fixture_names=fixture_names,
289-
start_line=start_line,
294+
name=f"{object_test.object_name}[CodeBlock#{object_test.intra_object_index+1}][rel.line:{fence_test.start_line}]",
295+
code=fence_test.code_block,
296+
fixture_names=fence_test.fixture_names,
297+
start_line=fence_test.start_line,
290298
fake_line_numbers=True, # TODO: figure out where docstrings are in file to offset line numbers properly
291299
)
292300

293301
def find_object_tests_recursive(
294302
self, module_name: str, object: typing.Any
295-
) -> typing.Generator[
296-
typing.Tuple[int, typing.Any, typing.Tuple[str, typing.List[str], int]],
297-
None,
298-
None,
299-
]:
303+
) -> typing.Generator[ObjectTest, None, None]:
300304
docstr = inspect.getdoc(object)
301305

302306
if docstr:
307+
obj_name = (
308+
getattr(object, "__qualname__", None)
309+
or getattr(object, "__name__", None)
310+
or "<Unnamed obj>"
311+
)
303312
fence_syntax = FenceSyntax(self.config.option.markdowndocs_syntax)
304-
for i, code_block in enumerate(
305-
extract_code_blocks(docstr, fence_syntax=fence_syntax)
313+
for i, fence_test in enumerate(
314+
extract_fence_tests(docstr, fence_syntax=fence_syntax)
306315
):
307-
yield i, object, code_block
316+
yield ObjectTest(i, obj_name, fence_test)
308317

309318
for member_name, member in inspect.getmembers(object):
310319
if member_name.startswith("_"):
@@ -323,20 +332,20 @@ def collect(self):
323332
markdown_content = self.path.read_text("utf8")
324333
fence_syntax = FenceSyntax(self.config.option.markdowndocs_syntax)
325334

326-
for i, (code_block, fixture_names, start_line) in enumerate(
327-
extract_code_blocks(
335+
for i, fence_test in enumerate(
336+
extract_fence_tests(
328337
markdown_content,
329338
markdown_type=self.path.suffix.replace(".", ""),
330339
fence_syntax=fence_syntax,
331340
)
332341
):
333342
yield MarkdownInlinePythonItem.from_parent(
334343
self,
335-
name=f"[CodeBlock#{i+1}][line:{start_line}]",
336-
code=code_block,
337-
fixture_names=fixture_names,
338-
start_line=start_line,
339-
fake_line_numbers=start_line == -1,
344+
name=f"[CodeBlock#{i+1}][line:{fence_test.start_line}]",
345+
code=fence_test.code_block,
346+
fixture_names=fence_test.fixture_names,
347+
start_line=fence_test.start_line,
348+
fake_line_numbers=fence_test.start_line == -1,
340349
)
341350

342351

0 commit comments

Comments
 (0)