From 4d7472b825b7a58babc32c289032f944e1c6a005 Mon Sep 17 00:00:00 2001 From: getzze Date: Fri, 5 Jul 2024 23:22:19 +0100 Subject: [PATCH] fix sphinx linkcheck --- changelog.d/1147.doc.rst | 1 + docs/_intersphinx/README.md | 82 ++++++++++++++++++ .../importlib_metadata_objects.inv | Bin 0 -> 230 bytes .../importlib_metadata_objects.txt | 6 ++ docs/api/cache.rst | 3 +- docs/conf.py | 15 +++- pyproject.toml | 1 + subliminal/extensions.py | 6 +- subliminal/providers/__init__.py | 22 ++--- subliminal/utils.py | 4 +- 10 files changed, 120 insertions(+), 20 deletions(-) create mode 100644 changelog.d/1147.doc.rst create mode 100644 docs/_intersphinx/README.md create mode 100644 docs/_intersphinx/importlib_metadata_objects.inv create mode 100644 docs/_intersphinx/importlib_metadata_objects.txt diff --git a/changelog.d/1147.doc.rst b/changelog.d/1147.doc.rst new file mode 100644 index 000000000..645a2a035 --- /dev/null +++ b/changelog.d/1147.doc.rst @@ -0,0 +1 @@ +Fix sphinx linkcheck errors diff --git a/docs/_intersphinx/README.md b/docs/_intersphinx/README.md new file mode 100644 index 000000000..9577cd428 --- /dev/null +++ b/docs/_intersphinx/README.md @@ -0,0 +1,82 @@ +# Creating a Custom Intersphinx Mapping + +Copied from [exhale documentation.](https://github.com/svenevs/exhale/blob/master/docs/_intersphinx/README.md) + +## The Issue + +The BeautifulSoup intersphinx mapping does not work; see [bug here][bug]. + +[bug]: https://bugs.launchpad.net/beautifulsoup/+bug/1453370 + +So we'll just do it manually. + +## The Tool + +Use the tool `sphobjinv` to do this (`pip install sphobjinv`). + +- [Explanation of syntax][syntax]. + +[syntax]: https://sphinx-objectsinv-encoderdecoder.readthedocs.io/en/latest/syntax.html + +## How to Reproduce + +1. Downloaded original objects.inv from bs4 docs + + ```console + $ curl -O https://www.crummy.com/software/BeautifulSoup/bs4/doc/objects.inv + $ mv objects.inv bs4_objects.inv + ``` + +2. Converted that bad boy to human readable (the file `bs4_objects.txt`). + + ```console + $ sphobjinv convert plain bs4_objects.inv bs4_objects.txt + ``` + +3. Any time I have a class I want to add a reference for, just add that line to + `bs4_objects.txt`. Recall that there is a specific [syntax][syntax] associated + with these files. + +4. When you add a new line, simply run (assuming you are in this directory) + + ```console + $ sphobjinv convert zlib bs4_objects.txt bs4_objects.inv + ``` + +5. Re-run sphinx, usually you need to clean it for the doctree index to be rebuilt. + + ```console + $ make clean html + ``` + +## Note + +These changes apply because we have **2** things in `conf.py`: + +1. In the `extensions` list, we have `"sphinx.ext.intersphinx"`. +2. We have configured our intersphinx mapping to point to here (as opposed to the + one being hosted online): + + ```py + intersphinx_mapping = { + 'bs4': ('https://www.crummy.com/software/BeautifulSoup/bs4/doc/', "_intersphinx/bs4_objects.inv") + } + ``` + +## In the Documentation + +So now we can do something like + +```rst +- See :class:`bs4.BeautifulSoup` +- See :meth:`bs4.BeautifulSoup.get_text` +- See :class:`bs4.element.Tag` +``` + +because we added the following line to our `bs4_objects.txt`: + +``` +bs4.BeautifulSoup py:class 1 index.html#beautifulsoup - +bs4.BeautifulSoup.get_text py:method 1 index.html#get-text - +bs4.element.Tag py:class 1 index.html#tag - +``` diff --git a/docs/_intersphinx/importlib_metadata_objects.inv b/docs/_intersphinx/importlib_metadata_objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..66d334be46167c7974115450f1b9d325d8fbd5a9 GIT binary patch literal 230 zcmY#Z2rkIT%&Sny%qvUHE6FdaR47X=D$dN$Q!wIERtPA{&q_@$u~Nv)Eyyn_$;nKL z&rK~!Oi3(B1j>d%R9Y!m=o#o4>ZPQX8EB`c8Cx0{npxFu0~Lm3q$(7p z<|bz5rKA=q?~)Z*gQ6ot~_%)E4kDxf`jTot!YpV2*` zuXXaI&!yA8x}H9sI-XaG&uVL~;yH2tjCP>LiY;E}JazQK3_=*RG`)0IT{(Z`%7nm4 Zvlq|dy0kQ!;ZoR|1*cgV9-LPc0RZlZRj~j7 literal 0 HcmV?d00001 diff --git a/docs/_intersphinx/importlib_metadata_objects.txt b/docs/_intersphinx/importlib_metadata_objects.txt new file mode 100644 index 000000000..99ecc24d8 --- /dev/null +++ b/docs/_intersphinx/importlib_metadata_objects.txt @@ -0,0 +1,6 @@ +# Sphinx inventory version 2 +# Project: importlib_metadata +# Version: 8.0.1.dev0+gf390168.d20240623 +# From https://github.com/svenevs/exhale/tree/master/docs/_intersphinx +# The remainder of this file is compressed using zlib. +importlib.metadata.EntryPoint py:class 1 library/importlib.metadata.html#entry-points - diff --git a/docs/api/cache.rst b/docs/api/cache.rst index c446b64e4..039cc49a4 100644 --- a/docs/api/cache.rst +++ b/docs/api/cache.rst @@ -18,4 +18,5 @@ Cache Refer to dogpile.cache's `region configuration documentation -`_ to see how to configure the region +`_ +to see how to configure the region. diff --git a/docs/conf.py b/docs/conf.py index 4fd55708b..42da56a9d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -39,6 +39,7 @@ 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode', 'sphinxcontrib.programoutput', + 'sphinx_autodoc_typehints', ] # Add any paths that contain templates here, relative to this directory. @@ -307,10 +308,22 @@ 'dogpilecache': ('https://dogpilecache.sqlalchemy.org/en/latest', None), 'stevedore': ('https://docs.openstack.org/stevedore/latest', None), 'click': ('https://click.palletsprojects.com/en/latest/', None), + 'requests': ('https://docs.python-requests.org/en/latest/', None), + 'sympy': ('https://docs.sympy.org/latest/', None), + 'bs4': ('https://www.crummy.com/software/BeautifulSoup/bs4/doc/', None), + 'importlib.metadata': ('https://docs.python.org/3/', '_intersphinx/importlib_metadata_objects.inv'), } -# -- Options for autodoc ------------------------------------------------------- +# -- Options for autodoc ----------------------------------------------------- autodoc_member_order = 'bysource' autodoc_default_flags = ['members'] + + +# -- Options for sphinx-autodoc-typehints ------------------------------------ +# https://github.com/tox-dev/sphinx-autodoc-typehints + +always_use_bars_union = True + +set_type_checking_flag = False diff --git a/pyproject.toml b/pyproject.toml index cc0587e98..880d8d95c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,6 +57,7 @@ docs = [ "sphinx", "sphinx_rtd_theme", "sphinxcontrib-programoutput", + "sphinx_autodoc_typehints", "towncrier", ] test = [ diff --git a/subliminal/extensions.py b/subliminal/extensions.py index 949b5695c..c7e9a7254 100644 --- a/subliminal/extensions.py +++ b/subliminal/extensions.py @@ -13,7 +13,7 @@ class RegistrableExtensionManager(ExtensionManager): - """:class:`stevedore.extensions.ExtensionManager` with support for registration. + """:class:`stevedore.extension.ExtensionManager` with support for registration. It allows loading of internal extensions without setup and registering/unregistering additional extensions. @@ -23,9 +23,9 @@ class RegistrableExtensionManager(ExtensionManager): * Internal extensions * Registered extensions - :param str namespace: namespace argument for :class:`stevedore.extensions.ExtensionManager`. + :param str namespace: namespace argument for :class:`stevedore.extension.ExtensionManager`. :param list internal_extensions: internal extensions to use with entry point syntax. - :param kwargs: additional parameters for the :class:`stevedore.extensions.ExtensionManager` constructor. + :param kwargs: additional parameters for the :class:`stevedore.extension.ExtensionManager` constructor. """ diff --git a/subliminal/providers/__init__.py b/subliminal/providers/__init__.py index eb6c88bfc..eab253599 100644 --- a/subliminal/providers/__init__.py +++ b/subliminal/providers/__init__.py @@ -1,12 +1,9 @@ """ Providers list and download subtitles for a :class:`~subliminal.video.Video` object. -A Provider is a ContextManager with :meth:`~subliminal.Provider.__enter__` and -:meth:`~subliminal.Provider.__exit__` -methods and two public methods, -:py:meth:`~subliminal.Provider.list_subtitles(video, languages)` and -:py:meth:`~subliminal.Provider.download_subtitle(subtitle)`. - +A Provider is a ContextManager with ``__enter__`` and ``__exit__`` methods and +two public methods: :meth:`~subliminal.providers.Provider.list_subtitles` and +:meth:`~subliminal.providers.Provider.download_subtitle`. """ from __future__ import annotations @@ -16,6 +13,8 @@ from typing import TYPE_CHECKING, Any, ClassVar, Generic, TypeVar from xmlrpc.client import SafeTransport +# Do not put babelfish in a TYPE_CHECKING block for intersphinx to work properly +from babelfish import Language # type: ignore[import-untyped] # noqa: TCH002 from bs4 import BeautifulSoup, FeatureNotFound from requests import adapters from urllib3 import poolmanager # type: ignore[import-untyped] @@ -29,9 +28,6 @@ from http.client import HTTPSConnection from types import TracebackType from typing import Self - from xmlrpc.client import _HostType - - from babelfish import Language # type: ignore[import-untyped] logger = logging.getLogger(__name__) @@ -54,7 +50,7 @@ def init_poolmanager(self, connections: int, maxsize: int, block: bool = False, class TimeoutSafeTransport(SafeTransport): - """Timeout support for :class:`~xmlrpc.client.SafeTransport`.""" + """Timeout support for :library/xmlrpc.client:class:`~xmlrpc.client.SafeTransport`.""" timeout: float | None @@ -62,13 +58,13 @@ def __init__(self, timeout: float | None, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.timeout = timeout - def make_connection(self, host: _HostType) -> HTTPSConnection: + def make_connection(self, host: Any) -> HTTPSConnection: """Make connection to host. :param host: the connection host. - :type host: :class:`~xmlrpc.client._HostType` + :type host: ``xmlrpc.client._HostType`` :return: the HTTPS connection. - :rtype: :class:`~http.client import HTTPSConnection` + :rtype: :library/http.client:class:`~http.client.HTTPSConnection` """ c = SafeTransport.make_connection(self, host) diff --git a/subliminal/utils.py b/subliminal/utils.py index bf343fc42..3afb26bd7 100644 --- a/subliminal/utils.py +++ b/subliminal/utils.py @@ -148,7 +148,7 @@ def handle_exception(e: Exception, msg: str) -> None: Exception traceback is only logged for specific cases. - :param exception e: The exception to handle. + :param Exception e: The exception to handle. :param str msg: The message to log. """ if isinstance(e, (requests.Timeout, socket.timeout)): @@ -174,7 +174,7 @@ def is_iterable(obj: Any) -> TypeGuard[Iterable]: def ensure_list(value: T | Sequence[T] | None) -> list[T]: """Ensure to return a list of values. - From :func:`rebulk.loose.ensure_list`. + From ``rebulk.loose.ensure_list``. """ if value is None: return []