diff --git a/Makefile b/Makefile index 618b514..4f30bb4 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ GPG_SIGNER_FINGERPRINT := "91CD826E74B0174D181903DEF97C70941CD8C4EF" .PHONY: chore configure requirements-dev.txt requirements.txt publish archive -chore: requirements.txt requirements-dev.txt bitbucket-pipelines.yml +chore: requirements.txt requirements-dev.txt bitbucket-pipelines.yaml Pipfile.lock: Pipfile python3 -m pipenv lock -v diff --git a/Pipfile b/Pipfile index 5c10bcc..bae3a1c 100644 --- a/Pipfile +++ b/Pipfile @@ -4,7 +4,7 @@ verify_ssl = true name = "pypi" [packages] -byteb4rb1e_sphinxcontrib = { editable = true, path = '.'} +byteb4rb1e.sphinxcontrib = { editable = true, path = '.'} [dev-packages] sphinx = "*" diff --git a/Pipfile.lock b/Pipfile.lock index e78939e..c4c3851 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "48c822d9e7bedd5ee25106b31093ce10a0071d7b12f7861e4e4cc46c5549c9ed" + "sha256": "4eac08fb6ab8c543a1fa6030c3c69a57aa6ae6de69e4f47ec483128bb61b2867" }, "pipfile-spec": 6, "requires": { @@ -32,8 +32,9 @@ "markers": "python_version >= '3.8'", "version": "==2.17.0" }, - "byteb4rb1e.sphinxcontrib": { - "version": "==0.1.dev5+g3c348d5.d20250526" + "byteb4rb1e.utils": { + "git": "https://bitbucket.org/byteb4rb1e/py-utils.git", + "ref": "d0dfa1cb12702e6d25f3a9eeab02968eda8d06ba" }, "certifi": { "hashes": [ @@ -381,11 +382,11 @@ }, "cachetools": { "hashes": [ - "sha256:82e73ba88f7b30228b5507dce1a1f878498fc669d972aef2dde4f3a3c24f103e", - "sha256:f225782b84438f828328fc2ad74346522f27e5b1440f4e9fd18b20ebfd1aa2cf" + "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4", + "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a" ], - "markers": "python_version >= '3.9'", - "version": "==6.0.0" + "markers": "python_version >= '3.7'", + "version": "==5.5.2" }, "certifi": { "hashes": [ @@ -832,11 +833,11 @@ }, "setuptools": { "hashes": [ - "sha256:49f7af965996f26d43c8ae34539c8d99c5042fbff34302ea151eaa9c207cd257", - "sha256:95a60484590d24103af13b686121328cc2736bee85de8936383111e421b9edc0" + "sha256:ca5cc1069b85dc23070a6628e6bcecb3292acac802399c7f8edc0100619f9009", + "sha256:f6ffc5f0142b1bd8d0ca94ee91b30c0ca862ffd50826da1ea85258a06fd94552" ], "markers": "python_version >= '3.9'", - "version": "==80.8.0" + "version": "==80.7.1" }, "setuptools-scm": { "hashes": [ diff --git a/docs/byteb4rb1e-sphinxcontrib/authorship.rst b/docs/byteb4rb1e-sphinxcontrib/authorship.rst index 1eab1b1..4ef6859 100644 --- a/docs/byteb4rb1e-sphinxcontrib/authorship.rst +++ b/docs/byteb4rb1e-sphinxcontrib/authorship.rst @@ -1,21 +1,3 @@ ################################### byteb4rb1e_sphinxcontrib.authorship ################################### - -An implementation of the IMJE recommendations on authorship applied to Sphinx -documents. - -.. code-block:: rst - - .. contribution:: Review - :name: Adam Smith - :organization: Example Corp. - :group: contributions - -.. code-block:: rst - - .. acknowledgment:: - :name: Adam Smith - :organization: Example Corp. - :group: contributions - diff --git a/docs/byteb4rb1e-sphinxcontrib/index.rst b/docs/byteb4rb1e-sphinxcontrib/index.rst index 0051fb6..bf6a3a4 100644 --- a/docs/byteb4rb1e-sphinxcontrib/index.rst +++ b/docs/byteb4rb1e-sphinxcontrib/index.rst @@ -12,7 +12,7 @@ via pip (PyPi) .. code-block:: - $> python3 -m pip install byteb4rb1e-sphinxcontrib + $> python3 -m pip install byteb4rb1ie-sphinxcontrib via pip (Git) ------------- @@ -21,6 +21,20 @@ via pip (Git) $> python3 -m pip git+https://bitbucket.org/byteb4rb1e/sphinxcontrib@master +via Git +------- + +.. code-block:: + + $> git clone https://bitbucket.org/byteb4rb1e/sphinxcontrib + +with pipenv +~~~~~~~~~~~ + +.. code-block:: + + $> sh ./configure --with-pipenv .pipenv + Usage ===== @@ -28,140 +42,5 @@ Usage :caption: Sphinx Extensions authorship - authorship_svc + svc_authorship svc - -Installation (Development) -========================== - -.. code-block:: - - $> git clone https://bitbucket.org/byteb4rb1e/sphinxcontrib - -.. warning:: - - (Non-MSYS2) Windows users MUST use ``.venv/Scripts/python3.exe``, instead of - ``.venv/bin/python3`` - -.. warning:: - - (Non-MSYS2) Windows users MUST execute ``python3 -m pipenv install -d - --skip-lock``, instead of ``sh ./configure``. - -with pipenv ------------ - -``pipenv`` expected to be installed system-wide - -.. code-block:: - - $> sh ./configure - -with venv ---------- - -.. code-block:: - - $> python3 -m venv --system-site-packages .venv - $> .venv/bin/python3 -m pip install pipenv - $> .venv/bin/python3 -m pipenv run sh ./configure - -with venv (but without configuration) -------------------------------------- - -.. code-block:: - - $> python3 -m venv --system-site-packages .venv - $> .venv/bin/python3 -m pip install -r requirements-dev.txt - -Development -=========== - -Static Code Analysis --------------------- - -.. code-block:: - - $> python3 -m pipenv run test-static - -Audit -~~~~~ - -.. code-block:: - - $> python3 -m tox -e audit - -Format -~~~~~~ - -.. code-block:: - - $> python3 -m tox -e format -- --inline - -Lint -~~~~ - -.. code-block:: - - $> python3 -m tox -e lint - - -Unit Testing ------------- - -.. code-block:: - - $> python3 -m pipenv run test-unit - -Test Suite -~~~~~~~~~~ - -.. code-block:: - - $> python3 -m pipenv run test-unit -- -p tests/unit - -Test Case -~~~~~~~~~ - -.. code-block:: - - $> python3 -m pipenv run test-unit -- -p tests/unit - -Integration Testing -------------------- - -.. code-block:: - - $> python3 -m pipenv run test-integration - -Test Suite -~~~~~~~~~~ - -.. code-block:: - - $> python3 -m pipenv run test-integration -- \ - -p tests/integration/byteb4rb1e_sphinxcontrib/authorship - -Test Case -~~~~~~~~~ - -.. code-block:: - - $> python3 -m pipenv run test-integration -- \ - -p tests/integration/byteb4rb1e_sphinxcontrib/authorship/test_setup.py - -with a definitive Python and Sphinx major version (e.g. *Python* ``3.10``, and *Sphinx* -``6``) - -.. code-block:: - - $> python3 -m tox -e py310-sphinx6-integration -- \ - -p tests/unit - -Documentation -------------- - -.. code-block:: - - $> python3 -m pipenv run doc - diff --git a/docs/byteb4rb1e-sphinxcontrib/authorship_svc.rst b/docs/byteb4rb1e-sphinxcontrib/svc_authorship.rst similarity index 66% rename from docs/byteb4rb1e-sphinxcontrib/authorship_svc.rst rename to docs/byteb4rb1e-sphinxcontrib/svc_authorship.rst index c9605b2..5075e15 100644 --- a/docs/byteb4rb1e-sphinxcontrib/authorship_svc.rst +++ b/docs/byteb4rb1e-sphinxcontrib/svc_authorship.rst @@ -1,3 +1,3 @@ ####################################### -byteb4rb1e_sphinxcontrib.authorship_svc +byteb4rb1e_sphinxcontrib.svc_authorship ####################################### diff --git a/pyproject.toml b/pyproject.toml index 26079fb..28e550e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ requires = [ build-backend = "setuptools.build_meta" [project] -name = "byteb4rb1e.sphinxcontrib" +name = "byteb4rb1e.sphinxcontrib.ext" description = "" authors = [ { name = "Tiara Rodney", email = "tiara.rodney@byteb4rb1e.me" } @@ -30,19 +30,17 @@ classifiers = [ ] dependencies = [ "sphinx>=5.1", + "byteb4rb1e.utils @ git+https://bitbucket.org/byteb4rb1e/py-utils.git@32ae99c5fa0174761f4053fce1130f3cd7a2a68b" ] - dynamic = ["version"] requires-python = ">=3.8" -[project.optional-dependencies] -git = ["pygit2>=1.18.0,<2",] - [project.urls] Bitbucket = "https://bitbucket.org/byteb4rb1e/sphinxcontrib" [tool.setuptools.packages.find] where = ["src"] +namespaces = true [tool.autopep8] diff --git a/requirements-dev.txt b/requirements-dev.txt index 21f8c8e..b06e105 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,7 +2,7 @@ alabaster==1.0.0 babel==2.17.0 build==1.2.2.post1 -cachetools==6.0.0 +cachetools==5.5.2 certifi==2025.4.26 chardet==5.2.0 charset-normalizer==3.4.2 @@ -37,7 +37,7 @@ requests-toolbelt==1.0.0 rfc3986==2.0.0 rich==14.0.0 roman-numerals-py==3.1.0 -setuptools==80.8.0 +setuptools==80.7.1 setuptools-scm==8.3.1 snowballstemmer==3.0.1 sphinx==8.2.3 diff --git a/requirements.txt b/requirements.txt index f121830..a12eeeb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ -i https://pypi.org/simple alabaster==1.0.0 babel==2.17.0 -byteb4rb1e.sphinxcontrib==0.1.dev5+g3c348d5.d20250526 +-e . certifi==2025.4.26 charset-normalizer==3.4.2 colorama==0.4.6 diff --git a/src/byteb4rb1e/sphinxcontrib/authorship/__init__.py b/src/byteb4rb1e/sphinxcontrib/authorship/__init__.py deleted file mode 100644 index ade89a5..0000000 --- a/src/byteb4rb1e/sphinxcontrib/authorship/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from sphinx.application import Sphinx -from sphinx.util.typing import ExtensionMetadata - - -def setup(app: Sphinx) -> ExtensionMetadata: - """add this extension and its children to a Sphinx application""" - return {} diff --git a/src/byteb4rb1e/sphinxcontrib/authorship/parsers/__init__.py b/src/byteb4rb1e/sphinxcontrib/authorship/parsers/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/byteb4rb1e/sphinxcontrib/authorship/parsers/rst/__init__.py b/src/byteb4rb1e/sphinxcontrib/authorship/parsers/rst/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/byteb4rb1e/sphinxcontrib/authorship/parsers/rst/directives/__init__.py b/src/byteb4rb1e/sphinxcontrib/authorship/parsers/rst/directives/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/byteb4rb1e/sphinxcontrib/authorship/parsers/rst/directives/contribution.py b/src/byteb4rb1e/sphinxcontrib/authorship/parsers/rst/directives/contribution.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/byteb4rb1e/sphinxcontrib/authorship_svc/__init__.py b/src/byteb4rb1e/sphinxcontrib/authorship_svc/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/byteb4rb1e/sphinxcontrib/ext/html_static_archive/__init__.py b/src/byteb4rb1e/sphinxcontrib/ext/html_static_archive/__init__.py new file mode 100644 index 0000000..3c4eb85 --- /dev/null +++ b/src/byteb4rb1e/sphinxcontrib/ext/html_static_archive/__init__.py @@ -0,0 +1,86 @@ +import importlib.resources +import mimetypes +from pathlib import Path +import urllib.request +import tarfile +from typing import Tuple, Optional, Dict +from io import IOBase + +from sphinx.application import Sphinx +from sphinx.environment import BuildEnvironment +from sphinx.util.logging import getLogger + +from byteb4rb1e.utils.urllib.request import PkgHandler + + +logger = getLogger(__name__) + + +_static_archives: Dict[str, IOBase] = {} +_opener: urllib.request.OpenerDirector = urllib.request.build_opener( + PkgHandler() +) + + +def on_config_inited( + app: Sphinx, + env: BuildEnvironment +): + """ + """ + global _static_archives + + static_archives = app.config['html_static_archive'] + + if not static_archives: + return + + if isinstance(static_archives, str): + static_archives = [static_archives] + + for url in static_archives: + _static_archives[url] = _opener.open(url) + + +def on_env_updated( + app: Sphinx, + env: BuildEnvironment +): + """ + """ + static_dir = Path(app.outdir) / '_static' + + for url, fh in _static_archives.items(): + modes = { + 'application/x-tar': 'r', + 'application/x-tar+gzip': 'r:gz', + 'application/x-tar+bzip2': 'r:bz2', + 'application/x-tar+xz': 'r:xz', + } + + mime_type = fh.headers.get('Content-Type') + + if mime_type not in modes.keys(): + raise Exception('') + + archive = tarfile.open(fileobj=fh, mode=modes[mime_type]) + + for file in archive.getmembers(): + if file.isdir(): + continue + + shadow_file = static_dir / file.name + + if not shadow_file.exists(): + logger.info(f'html_static_archive (extract): {url}::{file.name}') + archive.extract(file, path=static_dir, filter='data') + + archive.close() + fh.close() + + +def setup(app: Sphinx): + app.add_config_value('html_static_archive', [], True) + app.connect('env-check-consistency', on_config_inited) + app.connect('env-check-consistency', on_env_updated) + diff --git a/src/byteb4rb1e/sphinxcontrib/svc/__init__.py b/src/byteb4rb1e/sphinxcontrib/svc/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/byteb4rb1e/sphinxcontrib/testing/pytest/fixtures.py b/src/byteb4rb1e/sphinxcontrib/testing/pytest/fixtures.py new file mode 100644 index 0000000..dbee461 --- /dev/null +++ b/src/byteb4rb1e/sphinxcontrib/testing/pytest/fixtures.py @@ -0,0 +1,108 @@ +from collections import namedtuple +import json +import logging +import os +from pathlib import Path +import shutil +from typing import Any, Tuple, Callable, Iterator, Dict +import warnings + +import pytest + +try: + from sphinx.deprecation import RemovedInSphinx90Warning +except ImportError: + RemovedInSphinx90Warning = None + +from sphinx.testing.util import SphinxTestApp +from sphinx.testing.fixtures import make_app, test_params +USE_PATHLIB = True +with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + from sphinx.testing.path import path as sphinxtesting_path + if w and issubclass(w[-1].message.__class__, RemovedInSphinx90Warning): + USE_PATHLIB = True + else: + USE_PATHLIB = False + +from byteb4rb1e.testing.pytest.fixtures import current_test + +_SPHINX_TESTAPP_COUNTER: Dict[str, int] = {} +_SPHINX_TESTSRC_COUNTER: Dict[str, int] = {} + + +@pytest.fixture +def mock_sphinx_testsrc_dir( + tmp_path: Path, +): + global _SPHINX_TESTSRC_COUNTER + + _SPHINX_TESTSRC_COUNTER.setdefault(tmp_path, 0) + + testsrc_id = _SPHINX_TESTSRC_COUNTER[tmp_path] + _SPHINX_TESTSRC_COUNTER[tmp_path] += 1 + + srcdir = tmp_path / f'sphinx-testsrc-{testsrc_id}' + + def wrap(): + srcdir.mkdir(parents=True) + + (srcdir / 'conf.py').write_text(""" +project = 'foobar' +master_doc = 'index' +""") + + (srcdir / 'index.rst').write_text(""" +###### +Foobar +###### + +Hello world! +""") + + return srcdir + + return wrap + + +@pytest.fixture +def mock_sphinx_testapp( + make_app: Callable[[], SphinxTestApp], + tmp_path: Path, + caplog +): + global _SPHINX_TESTAPP_COUNTER + + _SPHINX_TESTAPP_COUNTER.setdefault(tmp_path, 0) + + testapp_id = _SPHINX_TESTAPP_COUNTER[tmp_path] + _SPHINX_TESTAPP_COUNTER[tmp_path] += 1 + + """Provides the 'sphinx.application.Sphinx' object""" + def wrap(*args, **kwargs) -> Iterator[SphinxTestApp]: + assert kwargs.get('srcdir'), 'srcdir keyword argument missing' + + caplog.set_level(logging.DEBUG) + logger = logging.getLogger() + + basedir = tmp_path / f'sphinx-testapp-{testapp_id}' + srcdir = basedir / 'src' + builddir = basedir / 'build' + + shutil.copytree(kwargs['srcdir'], srcdir, dirs_exist_ok=True) + + kwargs['srcdir'] = sphinxtesting_path(srcdir) if not USE_PATHLIB else srcdir + + kwargs.setdefault('builddir', sphinxtesting_path(builddir) if not USE_PATHLIB else builddir) + + app_ = make_app(*args, **kwargs) + + logger.debug(json.dumps({ + 'builder': app_.builder.name, + 'srcdir': str(app_.srcdir), + 'outdir': str(app_.outdir) + }, indent = 4)) + + return app_ + + return wrap diff --git a/tests/integration/_fixtures/srcdir/byteb4rb1e/sphinxcontrib/ext/html_static_archive/default/_build/doctrees/index.doctree b/tests/integration/_fixtures/srcdir/byteb4rb1e/sphinxcontrib/ext/html_static_archive/default/_build/doctrees/index.doctree new file mode 100644 index 0000000..9765c4c Binary files /dev/null and b/tests/integration/_fixtures/srcdir/byteb4rb1e/sphinxcontrib/ext/html_static_archive/default/_build/doctrees/index.doctree differ diff --git a/src/byteb4rb1e/sphinxcontrib/__init__.py b/tests/integration/_fixtures/srcdir/byteb4rb1e/sphinxcontrib/ext/html_static_archive/default/conf.py similarity index 100% rename from src/byteb4rb1e/sphinxcontrib/__init__.py rename to tests/integration/_fixtures/srcdir/byteb4rb1e/sphinxcontrib/ext/html_static_archive/default/conf.py diff --git a/src/byteb4rb1e/sphinxcontrib/abc.py b/tests/integration/_fixtures/srcdir/byteb4rb1e/sphinxcontrib/ext/html_static_archive/default/index.rst similarity index 100% rename from src/byteb4rb1e/sphinxcontrib/abc.py rename to tests/integration/_fixtures/srcdir/byteb4rb1e/sphinxcontrib/ext/html_static_archive/default/index.rst diff --git a/tests/integration/byteb4rb1e/sphinxcontrib/ext/test_html_static_archive.py b/tests/integration/byteb4rb1e/sphinxcontrib/ext/test_html_static_archive.py new file mode 100644 index 0000000..9de8a8e --- /dev/null +++ b/tests/integration/byteb4rb1e/sphinxcontrib/ext/test_html_static_archive.py @@ -0,0 +1,117 @@ +from pathlib import Path +import tarfile + +import pytest + +from byteb4rb1e.sphinxcontrib.testing.pytest.fixtures import ( + mock_sphinx_testapp, + mock_sphinx_testsrc_dir +) +from byteb4rb1e.testing.pytest.decorators import run_in_subprocess_once +from byteb4rb1e.testing.pytest.fixtures import mock_system_site_package_dir + + + +@run_in_subprocess_once() +def test_default( + mock_sphinx_testapp, + mock_sphinx_testsrc_dir, + mock_system_site_package_dir, + tmp_path, +) -> None: + """ + """ + pkg_dir = mock_system_site_package_dir('dummypkg') + + mock_static_archive = tarfile.open(pkg_dir / 'data.tar', 'w') + + (tmp_path / 'foobar.txt').write_text("Hello world!") + + mock_static_archive.addfile( + mock_static_archive.gettarinfo( + arcname='foobar.txt', + fileobj=(tmp_path / 'foobar.txt').open('r') + ) + ) + + mock_static_archive.close() + + app = mock_sphinx_testapp(srcdir=mock_sphinx_testsrc_dir()) + + app.setup_extension('byteb4rb1e.sphinxcontrib.ext.html_static_archive') + + app.config['html_static_archive'] = f'pkg://dummypkg/data.tar' + + app.build(force_all=True) + + assert (Path(app.outdir) / '_static' / 'foobar.txt').exists() + + +@run_in_subprocess_once() +def test_compression( + mock_sphinx_testapp, + mock_sphinx_testsrc_dir, + mock_system_site_package_dir, + tmp_path, +) -> None: + """ + """ + pkg_dir = mock_system_site_package_dir('dummypkg') + + mock_static_archive = tarfile.open(pkg_dir / 'data.tar.gz', 'w:gz') + + (tmp_path / 'foobar.txt').write_text("Hello world!") + + mock_static_archive.addfile( + mock_static_archive.gettarinfo( + arcname='foobar.txt', + fileobj=(tmp_path / 'foobar.txt').open('r') + ) + ) + + mock_static_archive.close() + + app = mock_sphinx_testapp(srcdir=mock_sphinx_testsrc_dir()) + + app.setup_extension('byteb4rb1e.sphinxcontrib.ext.html_static_archive') + + app.config['html_static_archive'] = f'pkg://dummypkg/data.tar.gz' + + app.build(force_all=True) + + assert (Path(app.outdir) / '_static' / 'foobar.txt').exists() + + +@run_in_subprocess_once() +def test_subdirs( + mock_sphinx_testapp, + mock_sphinx_testsrc_dir, + mock_system_site_package_dir, + tmp_path, +) -> None: + """ + """ + pkg_dir = mock_system_site_package_dir('dummypkg') + + mock_static_archive = tarfile.open(pkg_dir / 'data.tar.gz', 'w:gz') + + (tmp_path / 'foobar.txt').write_text("Hello world!") + + mock_static_archive.addfile( + mock_static_archive.gettarinfo( + arcname='foo/bar/foobar.txt', + fileobj=(tmp_path / 'foobar.txt').open('r') + ) + ) + + mock_static_archive.close() + + app = mock_sphinx_testapp(srcdir=mock_sphinx_testsrc_dir()) + + app.setup_extension('byteb4rb1e.sphinxcontrib.ext.html_static_archive') + + app.config['html_static_archive'] = f'pkg://dummypkg/data.tar.gz' + + app.build(force_all=True) + + assert (Path(app.outdir) / '_static' / 'foo' / 'bar' / 'foobar.txt').exists() diff --git a/tests/integration/byteb4rb1e/sphinxcontrib/testing/pytest/test_fixtures.py b/tests/integration/byteb4rb1e/sphinxcontrib/testing/pytest/test_fixtures.py new file mode 100644 index 0000000..9d66cde --- /dev/null +++ b/tests/integration/byteb4rb1e/sphinxcontrib/testing/pytest/test_fixtures.py @@ -0,0 +1,32 @@ +from pathlib import Path + +import pytest + +pytestmark = pytest.mark.pytest + +from byteb4rb1e.sphinxcontrib.testing.pytest.fixtures import ( + mock_sphinx_testapp, + mock_sphinx_testsrc_dir +) + + +def test_mock_sphinx_testsrc_dir(mock_sphinx_testsrc_dir): + """ + """ + srcdir = mock_sphinx_testsrc_dir() + + assert (srcdir / 'conf.py').exists() + assert (srcdir / 'index.rst').exists() + + +def test_mock_sphinx_testapp(mock_sphinx_testapp, mock_sphinx_testsrc_dir): + """ + """ + srcdir = mock_sphinx_testsrc_dir() + + app = mock_sphinx_testapp(srcdir=srcdir) + + assert app.builder is not None + assert Path(app.srcdir).samefile(srcdir) is False # Should be copied to internal src + + app.build(force_all=True) diff --git a/tests/integration/byteb4rb1e_sphinxcontrib/test_authorship.py b/tests/integration/byteb4rb1e_sphinxcontrib/test_authorship.py deleted file mode 100644 index 3519ad0..0000000 --- a/tests/integration/byteb4rb1e_sphinxcontrib/test_authorship.py +++ /dev/null @@ -1,2 +0,0 @@ -def test_default() -> None: - assert 1 == 1 diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py new file mode 100644 index 0000000..7c5f5e3 --- /dev/null +++ b/tests/integration/conftest.py @@ -0,0 +1,17 @@ +from pathlib import Path + +import pytest + +pytest_plugins = ['byteb4rb1e.sphinxcontrib.testing.pytest.fixtures'] + +_TESTS_ROOT = Path(__file__).resolve().parent + +def pytest_configure(config): + # register an additional marker + config.addinivalue_line( + "markers", "pytest: test pytest integration" + ) + +@pytest.fixture(scope='session') +def rootdir() -> Path: + return _TESTS_ROOT diff --git a/tox.ini b/tox.ini index b81dd10..5db0db9 100644 --- a/tox.ini +++ b/tox.ini @@ -2,8 +2,9 @@ requires = tox>=4.19 env_list = - py3{8-12}-{unit} - py3{8-12}-sphinx{5-8}-{integration} + unit-py3{9-13} + integration-py3{9-13}-sphinx{5-8} + integration-py3{9-13}-sphinx{5-8}-pytest8 lint format @@ -35,17 +36,17 @@ deps = commands = black --check src tests -[testenv:py3{9-13}-unit] +[testenv:unit-py3{9-13}] description = run type check on code base labels = unit deps = {[testenv]deps} pytest commands = - pytest tests/unit --junitxml=test-reports/{env_name}.xml + pytest tests/unit --junitxml=test-reports/{env_name}.xml {posargs} -[testenv:py3{9-13}-sphinx{5-7}-integration] -description = run type check on code base +[testenv:integration-py3{9-13}-sphinx{5-7}] +description = run sphinx 5-7 integration tests labels = integration deps = {[testenv]deps} @@ -54,14 +55,27 @@ deps = sphinx7: sphinx>=7.0,<=8.0 pytest commands = - pytest tests/integration --junitxml=test-reports/{env_name}.xml + pytest tests/integration --junitxml=test-reports/{env_name}.xml {posargs} -[testenv:py3{10-13}-sphinx8-integration] -description = run type check on code base +[testenv:integration-py3{10-13}-sphinx8] +description = run sphinx 8 integration tests labels = integration deps = {[testenv]deps} sphinx8: sphinx>=8.0,<=9.0 pytest commands = - pytest tests/integration --junitxml=test-reports/{env_name}.xml + pytest tests/integration --junitxml=test-reports/{env_name}.xml {posargs} + +[testenv:integration-py3{10-13}-sphinx{5-8}-pytest8] +description = run pytest 8 testing integration tests (excluding Python 3.9) +labels = integration +deps = + {[testenv]deps} + sphinx5: sphinx>=5.0,<=6.0 + sphinx6: sphinx>=6.0,<=7.0 + sphinx7: sphinx>=7.0,<=8.0 + sphinx8: sphinx>=8.0,<=9.0 + pytest8: pytest>=8.0,<=9.0 +commands = + pytest tests/integration -m pytest --junitxml=test-reports/{env_name}.xml {posargs}