Skip to content

Commit

Permalink
TST: use sybil for doctests (#250)
Browse files Browse the repository at this point in the history
* TST: use sybil for doctests

* Hand fixtures to sybil

* Add filesystem_backend fixture

* Further work on sybil for docstrings

* Fix doctests

* Add further ideas

* Clean up doctests

* Test usage documentation as well

* Move filesystem fixture

* Avoid creation of file outside tmpdir

* Remove dependency on jupyer-sphinx

* Update legacy backend section

* Remove jupyter-sphinx from docs/conf.py

* Try to fix under MacOS

* Fix typo

* Try to fix under Windows

* Add missing SkipParser

* Update docs/usage.rst

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
  • Loading branch information
hagenw and sourcery-ai[bot] authored Nov 15, 2024
1 parent b8d71ac commit 2647892
Show file tree
Hide file tree
Showing 18 changed files with 355 additions and 451 deletions.
2 changes: 1 addition & 1 deletion audbackend/core/backend/minio.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Minio(Base):
>>> auth = ("Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG")
>>> repository = "my-data" + audeer.uid()
>>> Minio.create(host, repository, authentication=auth)
>>> file = audeer.touch("file.txt")
>>> file = audeer.touch("src.txt")
>>> backend = Minio(host, repository, authentication=auth)
>>> try:
... with backend:
Expand Down
104 changes: 71 additions & 33 deletions audbackend/core/conftest.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,88 @@
import datetime
import os
import tempfile
import doctest

import pytest
import sybil
from sybil.parsers.rest import DocTestParser

import audeer

import audbackend


class DoctestFileSystem(audbackend.backend.FileSystem):
def _date(
self,
path: str,
) -> str:
# Collect doctests
pytest_collect_file = sybil.Sybil(
parsers=[DocTestParser(optionflags=doctest.ELLIPSIS)],
patterns=["*.py"],
fixtures=[
"filesystem",
"mock_date",
"mock_owner",
"mock_repr",
"prepare_docstring_tests",
],
).pytest()


@pytest.fixture(scope="function")
def filesystem(tmpdir):
"""Filesystem backend.
A repository with unique name is created
for the filesystem backend.
The filesystem backend is marked as opened
and returned.
Args:
tmpdir: tmpdir fixture
Returns:
filesystem backend object
"""
repo = f"repo-{audeer.uid()[:8]}"
host = audeer.mkdir(tmpdir, "host")
audeer.mkdir(host, repo)
backend = audbackend.backend.FileSystem(host, repo)
backend.opened = True
yield backend


@pytest.fixture(scope="function")
def mock_date():
r"""Custom date method to return a fixed date."""

def date(path: str, version: str = None) -> str:
date = datetime.datetime(1991, 2, 20)
date = audbackend.core.utils.date_format(date)
return date

def _owner(
self,
path: str,
) -> str:
yield date


@pytest.fixture(scope="function")
def mock_owner():
r"""Custom owner method to return a fixed owner."""

def owner(path: str, version: str = None) -> str:
return "doctest"

yield owner


@pytest.fixture(scope="function")
def mock_repr():
"""Custom __repr__ method to return fixed string."""
return 'audbackend.interface.FileSystem("host", "repo")'


@pytest.fixture(scope="function", autouse=True)
def prepare_docstring_tests(doctest_namespace):
with tempfile.TemporaryDirectory() as tmp:
# Change to tmp dir
current_dir = os.getcwd()
os.chdir(tmp)
# Prepare backend
audeer.mkdir("host")
audbackend.backend.FileSystem.create("host", "repo")
# Provide example file `src.txt`
audeer.touch("src.txt")
# Provide DoctestFileSystem as FileSystem,
# and audbackend
# in docstring examples
doctest_namespace["DoctestFileSystem"] = DoctestFileSystem
doctest_namespace["audbackend"] = audbackend

yield

# Remove backend
audbackend.backend.FileSystem.delete("host", "repo")
# Change back to current dir
os.chdir(current_dir)
def prepare_docstring_tests(tmpdir, monkeypatch):
r"""Code to be run before each doctest."""
# Change to tmp dir
monkeypatch.chdir(tmpdir)

# Provide example file `src.txt`
audeer.touch("src.txt")

yield
7 changes: 4 additions & 3 deletions audbackend/core/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ class BackendError(Exception):
.. Prepare backend and interface for docstring examples
>>> import audeer
>>> audeer.rmdir("host", "repo")
>>> _ = audeer.mkdir("host", "repo")
>>> import audbackend
Examples:
>>> backend = audbackend.backend.FileSystem("host", "repo")
>>> host = audeer.mkdir("host")
>>> audbackend.backend.FileSystem.create(host, "repo")
>>> backend = audbackend.backend.FileSystem(host, "repo")
>>> backend.open()
>>> try:
... interface = audbackend.interface.Unversioned(backend)
Expand Down
21 changes: 1 addition & 20 deletions audbackend/core/interface/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def backend(self) -> Backend:
backend object
..
>>> import audbackend
>>> backend = audbackend.backend.FileSystem("host", "repo")
>>> interface = Base(backend)
Expand All @@ -52,10 +53,6 @@ def host(self) -> str:
Returns: host path
..
>>> backend = audbackend.backend.FileSystem("host", "repo")
>>> interface = Base(backend)
Examples:
>>> interface.host
'host'
Expand All @@ -82,10 +79,6 @@ def join(
or does not start with ``'/'``,
or if joined path contains invalid character
..
>>> backend = audbackend.backend.FileSystem("host", "repo")
>>> interface = Base(backend)
Examples:
>>> interface.join("/", "file.txt")
'/file.txt'
Expand All @@ -104,10 +97,6 @@ def repository(self) -> str:
Returns:
repository name
..
>>> backend = audbackend.backend.FileSystem("host", "repo")
>>> interface = Base(backend)
Examples:
>>> interface.repository
'repo'
Expand All @@ -122,10 +111,6 @@ def sep(self) -> str:
Returns:
file separator
..
>>> backend = audbackend.backend.FileSystem("host", "repo")
>>> interface = Base(backend)
Examples:
>>> interface.sep
'/'
Expand All @@ -149,10 +134,6 @@ def split(
ValueError: if ``path`` does not start with ``'/'`` or
does not match ``'[A-Za-z0-9/._-]+'``
..
>>> backend = audbackend.backend.FileSystem("host", "repo")
>>> interface = Base(backend)
Examples:
>>> interface.split("/")
('/', '')
Expand Down
14 changes: 9 additions & 5 deletions audbackend/core/interface/maven.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,17 @@ class Maven(Versioned):
...
as extensions
..
>>> import audbackend
>>> import audeer
Examples:
>>> file = "src.txt"
>>> backend = audbackend.backend.FileSystem("host", "repo")
>>> host = audeer.mkdir("host")
>>> audbackend.backend.FileSystem.create(host, "repo")
>>> backend = audbackend.backend.FileSystem(host, "repo")
>>> backend.open()
>>> interface = Maven(backend)
>>> file = "src.txt"
>>> interface.put_archive(".", "/sub/archive.zip", "1.0.0", files=[file])
>>> for version in ["1.0.0", "2.0.0"]:
... interface.put_file(file, "/file.txt", version)
Expand Down Expand Up @@ -139,9 +145,7 @@ def ls(
RuntimeError: if backend was not opened
..
>>> backend = audbackend.backend.FileSystem("host", "repo")
>>> backend.open()
>>> interface = Maven(backend)
>>> interface = Maven(filesystem)
Examples:
>>> file = "src.txt"
Expand Down
Loading

0 comments on commit 2647892

Please sign in to comment.