nwb-linkml/nwb_linkml/conftest.py

70 lines
2 KiB
Python

import re
import textwrap
from doctest import NORMALIZE_WHITESPACE, ELLIPSIS
from sybil import Document
from sybil import Sybil, Region
from sybil.parsers.codeblock import PythonCodeBlockParser
from sybil.parsers.doctest import DocTestParser
import yaml
from nwb_linkml import adapters
# Test adapter generation examples
ADAPTER_START = re.compile(r"\.\.\s*adapter::")
ADAPTER_END = re.compile(r"\n\s*\n")
NWB_KEYS = re.compile(r"(^\s*datasets:\s*\n)|^groups:")
def _strip_nwb(nwb: str) -> str:
# strip 'datasets:' keys and decoration left in for readability/context
nwb = re.sub(NWB_KEYS, "", nwb)
nwb = re.sub(r"-", " ", nwb)
nwb = textwrap.dedent(nwb)
return nwb
def test_adapter_block(example):
"""
The linkml generated from a nwb example input should match
that provided in the docstring.
See adapters/dataset.py for example usage of .. adapter:: directive
"""
cls_name, nwb, linkml_expected = example.parsed
# get adapter and generate
adapter_cls = getattr(adapters, cls_name)
adapter = adapter_cls(cls=nwb)
res = adapter.build()
# compare
generated = yaml.safe_load(res.as_linkml())
expected = yaml.safe_load(linkml_expected)
assert generated == expected
def parse_adapter_blocks(document: Document):
for start_match, end_match, source in document.find_region_sources(ADAPTER_START, ADAPTER_END):
# parse
sections = re.split(r":\w+?:", source, re.MULTILINE)
sections = [textwrap.dedent(section).strip() for section in sections]
sections[1] = _strip_nwb(sections[1])
yield Region(start_match.start(), end_match.end(), sections, test_adapter_block)
adapter_parser = Sybil(
parsers=[
parse_adapter_blocks
],
patterns=["adapters/*.py"],
)
doctest_parser = Sybil(
parsers=[DocTestParser(optionflags=ELLIPSIS + NORMALIZE_WHITESPACE), PythonCodeBlockParser()],
patterns=["*.py"],
)
pytest_collect_file = (adapter_parser + doctest_parser).pytest()