diff --git a/hoverxref/domains.py b/hoverxref/domains.py index c70af5c7..f8c36515 100644 --- a/hoverxref/domains.py +++ b/hoverxref/domains.py @@ -52,6 +52,16 @@ def _get_docpath(self, builder, docname): return docpath def _is_ignored_ref(self, env, target): + # HACK: skip all references if the builder is non-html. We shouldn't + # have overridden the Domain in first instance at ``setup_domains`` + # function, but at that time ``app.builder`` is not yet initialized. If + # we suscribe ourselves to ``builder-initied`` it's too late and our + # override does not take effect. Other builders (e.g. LatexBuilder) may + # fail with internal functions we use (e.g. builder.get_outfilename). + # So, we are skipping it here :( + if env.app.builder.format != 'html': + return True + if target in env.config.hoverxref_ignore_refs: logger.info( 'Ignoring reference in hoverxref_ignore_refs. target=%s', diff --git a/hoverxref/extension.py b/hoverxref/extension.py index 8ee4e576..d2f2b5aa 100644 --- a/hoverxref/extension.py +++ b/hoverxref/extension.py @@ -147,31 +147,32 @@ def setup_translators(app): and our own ``HoverXRefHTMLTranslatorMixin`` that includes the logic to ``_hoverxref`` attributes. """ - if not app.registry.translators.items(): + + if app.builder.format != 'html': + # do not modify non-html builders + return + + for name, klass in app.registry.translators.items(): translator = types.new_class( 'HoverXRefHTMLTranslator', ( HoverXRefHTMLTranslatorMixin, - app.builder.default_translator_class, + klass, ), {}, ) - app.set_translator(app.builder.name, translator, override=True) - else: - for name, klass in app.registry.translators.items(): - if app.builder.format != 'html': - # Skip translators that are not HTML - continue - - translator = types.new_class( - 'HoverXRefHTMLTranslator', - ( - HoverXRefHTMLTranslatorMixin, - klass, - ), - {}, - ) - app.set_translator(name, translator, override=True) + app.set_translator(name, translator, override=True) + + translator = types.new_class( + 'HoverXRefHTMLTranslator', + ( + HoverXRefHTMLTranslatorMixin, + app.builder.default_translator_class, + ), + {}, + ) + app.set_translator(app.builder.name, translator, override=True) + def is_hoverxref_configured(app, config): diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..15841b8d --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,14 @@ +import os +import shutil +import pytest + +from .utils import srcdir, prefixdocumentsrcdir, customobjectsrcdir, pythondomainsrcdir + + +@pytest.fixture(autouse=True, scope='function') +def remove_sphinx_build_output(): + """Remove _build/ folder, if exist.""" + for path in (srcdir, prefixdocumentsrcdir, customobjectsrcdir, pythondomainsrcdir): + build_path = os.path.join(path, '_build') + if os.path.exists(build_path): + shutil.rmtree(build_path) diff --git a/tests/examples/default/conf.py b/tests/examples/default/conf.py index 6eb08bcb..4e612d00 100644 --- a/tests/examples/default/conf.py +++ b/tests/examples/default/conf.py @@ -5,3 +5,8 @@ 'sphinx.ext.autosectionlabel', 'hoverxref.extension', ] + +latex_documents = [ + (master_doc, 'test.tex', u'test Documentation', + u'test', 'manual'), +] diff --git a/tests/examples/default/index.rst b/tests/examples/default/index.rst index d528f10a..4461a286 100644 --- a/tests/examples/default/index.rst +++ b/tests/examples/default/index.rst @@ -9,3 +9,10 @@ Using ``hoverxref`` (or ``ref`` if ``hoverxref_auto_ref=True``) should add an `` :ref:`This a :ref: to Chapter I `. :hoverxref:`This a :hoverxref: to Chapter I, Section I
`. + +.. _example-reference: + +Example Reference +----------------- + +This is a reference to :ref:`example-reference`. diff --git a/tests/test_htmltag.py b/tests/test_htmltag.py index 340234a2..6077d369 100644 --- a/tests/test_htmltag.py +++ b/tests/test_htmltag.py @@ -1,43 +1,6 @@ -import os import pytest -import shutil - -srcdir = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - 'examples', - 'default', -) - -# srcdir with ``autosectionlabel_prefix_document = True`` config -prefixdocumentsrcdir = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - 'examples', - 'prefixdocument', -) - -# srcdir with ``Sphinx.add_object_type`` call -customobjectsrcdir = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - 'examples', - 'custom-object', -) - -# srcdir with ``:py:class:`` call -pythondomainsrcdir = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - 'examples', - 'python-domain', -) - - -@pytest.fixture(autouse=True, scope='function') -def remove_sphinx_build_output(): - """Remove _build/ folder, if exist.""" - for path in (srcdir, prefixdocumentsrcdir, customobjectsrcdir, pythondomainsrcdir): - build_path = os.path.join(path, '_build') - if os.path.exists(build_path): - shutil.rmtree(build_path) +from .utils import srcdir, prefixdocumentsrcdir, customobjectsrcdir, pythondomainsrcdir @pytest.mark.sphinx( diff --git a/tests/test_internals.py b/tests/test_internals.py new file mode 100644 index 00000000..d031a88e --- /dev/null +++ b/tests/test_internals.py @@ -0,0 +1,80 @@ +import inspect +import os +import pytest +import shutil +from unittest import mock + +from hoverxref.translators import HoverXRefHTMLTranslatorMixin + +from .utils import srcdir + + +@pytest.mark.sphinx( + srcdir=srcdir, + buildername='latex', + confoverrides={ + 'hoverxref_project': 'myproject', + 'hoverxref_version': 'myversion', + }, +) +def test_dont_override_translator_non_html_builder(app, status, warning): + app.build() + path = app.outdir / 'test.tex' + assert path.exists() is True + content = open(path).read() + + assert app.builder.format == 'latex' + for name, klass in app.registry.translators.items(): + assert not issubclass(klass, HoverXRefHTMLTranslatorMixin) + + +@pytest.mark.sphinx( + srcdir=srcdir, + buildername='html', + confoverrides={ + 'hoverxref_project': 'myproject', + 'hoverxref_version': 'myversion', + }, +) +def test_override_translator_non_html_builder(app, status, warning): + app.build() + path = app.outdir / 'index.html' + assert path.exists() is True + content = open(path).read() + + assert app.builder.format == 'html' + for name, klass in app.registry.translators.items(): + assert issubclass(klass, HoverXRefHTMLTranslatorMixin) + + +@pytest.mark.sphinx( + srcdir=srcdir, + buildername='latex', + confoverrides={ + 'hoverxref_project': 'myproject', + 'hoverxref_version': 'myversion', + 'hoverxref_auto_ref': True, + }, +) +def test_dont_fail_non_html_builder(app, status, warning): + """ + Test our resolver is not used by non-HTML builder. + + When running the build with ``latex`` as builder and + ``hoverxref_auto_ref=True`` it should not fail with + + def _get_docpath(self, builder, docname): + docpath = builder.get_outfilename(docname) + AttributeError: 'LaTeXBuilder' object has no attribute 'get_outfilename' + + LaTeXBuilder should never use our resolver. + """ + + with mock.patch('hoverxref.domains.HoverXRefBaseDomain._get_docpath') as _get_docpath: + app.build() + assert not _get_docpath.called + path = app.outdir / 'test.tex' + assert path.exists() is True + content = open(path).read() + + assert app.builder.format == 'latex' diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 00000000..a2c609ab --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,29 @@ +import os + + +srcdir = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + 'examples', + 'default', +) + +# srcdir with ``autosectionlabel_prefix_document = True`` config +prefixdocumentsrcdir = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + 'examples', + 'prefixdocument', +) + +# srcdir with ``Sphinx.add_object_type`` call +customobjectsrcdir = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + 'examples', + 'custom-object', +) + +# srcdir with ``:py:class:`` call +pythondomainsrcdir = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + 'examples', + 'python-domain', +)