diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 67153706..bff292d5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -266,8 +266,6 @@ jobs: - run: rm -r target/wheels - run: python -m unittest working-directory: ./python/tests - - run: sphinx-build -M doctest . build - working-directory: ./python/docs - run: sphinx-build -M html . build working-directory: ./python/docs - run: python generate_stubs.py pyoxigraph pyoxigraph.pyi --ruff diff --git a/python/src/io.rs b/python/src/io.rs index b8c42443..8258fda2 100644 --- a/python/src/io.rs +++ b/python/src/io.rs @@ -111,6 +111,7 @@ pub fn parse( /// >>> serialize([Triple(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'))], format=RdfFormat.TURTLE) /// b' "1" .\n' /// +/// >>> import io /// >>> output = io.BytesIO() /// >>> serialize([Triple(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'))], output, RdfFormat.TURTLE) /// >>> output.getvalue() @@ -182,6 +183,9 @@ impl PyQuadReader { /// * `TriG `_ (:py:attr:`RdfFormat.TRIG`) /// * `N3 `_ (:py:attr:`RdfFormat.N3`) /// * `RDF/XML `_ (:py:attr:`RdfFormat.RDF_XML`) +/// +/// >>> RdfFormat.N3.media_type +/// 'text/n3' #[pyclass(name = "RdfFormat", module = "pyoxigraph")] #[derive(Clone)] pub struct PyRdfFormat { diff --git a/python/src/store.rs b/python/src/store.rs index 90b3858c..ccc56e35 100644 --- a/python/src/store.rs +++ b/python/src/store.rs @@ -518,6 +518,7 @@ impl PyStore { /// >>> store.dump(format=RdfFormat.TRIG) /// b' "1" .\n' /// + /// >>> import io /// >>> store = Store() /// >>> store.add(Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g'))) /// >>> output = io.BytesIO() diff --git a/python/tests/test_doc.py b/python/tests/test_doc.py new file mode 100644 index 00000000..c0ba505b --- /dev/null +++ b/python/tests/test_doc.py @@ -0,0 +1,37 @@ +# type: ignore +import inspect +from doctest import DocTestFinder, DocTestSuite + +import pyoxigraph + + +class ExtendedDocTestFinder(DocTestFinder): + """ + More aggressive doctest lookup + """ + + def _find(self, tests, obj, name, module, source_lines, globs, seen): + # If we've already processed this object, then ignore it. + if id(obj) in seen: + return + seen[id(obj)] = 1 + + # Find a test for this object, and add it to the list of tests. + test = self._get_test(obj, name, module, globs, source_lines) + if test is not None: + tests.append(test) + + # Look for tests in a module's contained objects. + if inspect.ismodule(obj) or inspect.isclass(obj): + for valname, val in obj.__dict__.items(): + if valname == "__doc__": + continue + # Special handling for staticmethod/classmethod. + if isinstance(val, (staticmethod, classmethod)): + val = val.__func__ + self._find(tests, val, f"{name}.{valname}", module, source_lines, globs, seen) + + +def load_tests(_loader, tests, _ignore): + tests.addTests(DocTestSuite(pyoxigraph, test_finder=ExtendedDocTestFinder())) + return tests