PK䘺NH/bbpytest_markdown/__init__.py''' A py.test plugin that runs tests its found in your Markdown files. ''' __version__ = '0.0.7' PKNHW pytest_markdown/plugin.pyimport ast import types from linecache import cache import commonmark import py import pytest from _pytest.assertion.rewrite import rewrite_asserts from _pytest.python import Module def create_pytest_module(name, path, source, config): """Return a Module from source string with its assertions rewritten""" try: tree = ast.parse(source) except SyntaxError: return None rewrite_asserts(tree, py.path.local(path), config) try: co = compile(tree, path, "exec", dont_inherit=True) except SyntaxError: return mod = types.ModuleType(name) exec(co, mod.__dict__) # Also, seed the line cache, so pytest can show source code def getsource(): return source cache[path] = (getsource,) return mod class MarkdownItem(Module): def __init__(self, name, file, code, nodeid=None, config=None): self._code_obj = create_pytest_module(name, file.name, code, config) super().__init__(name, file, nodeid=nodeid) def _getobj(self): return self._code_obj def collect_literals_from_children(token): literals = [] stack = [token.first_child] while stack: cur = stack.pop() if cur.literal: literals.append(cur.literal) if cur.nxt: stack.append(cur.nxt) if cur.first_child: stack.append(cur.first_child) return ''.join(literals) class MarkdownCollector(object): def __init__(self, item): super().__init__() self.item = item self.ast = commonmark.Parser().parse(self.item.fspath.open().read()) self.stack = [(0, self.item, self.item.name,)] self.collected = [] def collect(self): self.stack = [(0, self.item, self.item.name,)] self.collected = [] walker = self.ast.walker() event = walker.nxt() while event is not None: if not event['entering']: event = walker.nxt() continue func = 'visit_' + event['node'].t if hasattr(self, func): getattr(self, func)(event['node']) event = walker.nxt() return self.collected def visit_heading(self, token): while self.stack[-1][0] >= token.level: self.stack.pop() name = collect_literals_from_children(token).lower().replace(' ', '-') nodeid = '::'.join(s[2] for s in self.stack) + '::' + name self.stack.append(( token.level, pytest.Item(name, self.stack[-1][1], nodeid=nodeid), name )) def visit_code_block(self, token): if token.info != 'python': return output = token.literal if output.startswith('\n'): return '' name = f'line_{token.sourcepos[0][0]}' if output.lower().strip().startswith('# conftest.py\n'): nodeid = self.stack[-1][1].nodeid else: nodeid = self.stack[-1][1].nodeid + '::' + name mi = MarkdownItem( name=name, file=self.stack[-1][1], code=output, nodeid=nodeid, config=self.item.config, ) self.collected.append(mi) return '' class MarkdownFile(pytest.File): def collect(self): for item in MarkdownCollector(self).collect(): yield item def pytest_collect_file(parent, path): if path.ext == '.md': return MarkdownFile(path, parent) PK!H-1B#,0pytest_markdown-0.0.7.dist-info/entry_points.txt.,I-.14M,N/ϳz9y\\PK!HPO%pytest_markdown-0.0.7.dist-info/WHEEL HM K-*ϳR03rOK-J,/RH,szd&Y)r$[)T&UrPK!Hu{(pytest_markdown-0.0.7.dist-info/METADATA]S]o@|XW| T MhiҪ ^G|}$^KxAV2+:p&^d ᇖn]dGXśl5& 2ZE!?5ES{COU^dHcneS/FF6><[jU|"В+ZS܀䨥 ɸ("{Cޝ)x|J& <10: v{U+3`GV3A(pFP5NjL74O佈Gz'T]^ZGʲEXRzr|EV|d+25S>3K5t-*{O0NZA:ap9/\(z8K3TƖT^lN4 V%Jk] %4D՞#"]ǁ% ᱣr0#ƹ 6SUZ=UCއ듔_jePK!H+2&pytest_markdown-0.0.7.dist-info/RECORD;r@>gA>E + n/+NʙxI>XکYAD df+|B\iTDlzf܆Lr(Y^Įz)!M^:wapgW srƉ ۲ܫH5#2[gص!C~32A"NjT|č}B{5QNZm6s)&N