diff --git a/docs/_relink_references.py b/docs/_relink_references.py new file mode 100644 index 00000000..4e47477d --- /dev/null +++ b/docs/_relink_references.py @@ -0,0 +1,132 @@ +# pylint: disable=import-error, import-outside-toplevel +# pyright: reportMissingImports=false +"""Abbreviated the annotations generated by sphinx-autodoc. + +It's not necessary to generate the full path of type hints, because they are +rendered as clickable links. + +See also https://github.com/sphinx-doc/sphinx/issues/5868. +""" + +from typing import List + +import sphinx.domains.python +from docutils import nodes +from sphinx.addnodes import pending_xref +from sphinx.environment import BuildEnvironment + +__TARGET_SUBSTITUTIONS = { + "a set-like object providing a view on D's items": "typing.ItemsView", + "a set-like object providing a view on D's keys": "typing.KeysView", + "an object providing a view on D's values": "typing.ValuesView", + "typing_extensions.Protocol": "typing.Protocol", +} +__REF_TYPE_SUBSTITUTIONS = { + "None": "obj", + "qrules.quantum_numbers.EdgeQuantumNumbers.baryon_number": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.bottomness": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.c_parity": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.charge": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.charmness": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.electron_lepton_number": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.g_parity": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.isospin_magnitude": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.isospin_projection": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.mass": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.muon_lepton_number": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.parity": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.pid": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.spin_magnitude": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.spin_projection": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.strangeness": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.tau_lepton_number": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.topness": "attr", + "qrules.quantum_numbers.EdgeQuantumNumbers.width": "attr", + "qrules.quantum_numbers.NodeQuantumNumbers.l_magnitude": "attr", + "qrules.quantum_numbers.NodeQuantumNumbers.l_projection": "attr", + "qrules.quantum_numbers.NodeQuantumNumbers.parity_prefactor": "attr", + "qrules.quantum_numbers.NodeQuantumNumbers.s_magnitude": "attr", + "qrules.quantum_numbers.NodeQuantumNumbers.s_projection": "attr", + "qrules.topology.EdgeType": "obj", + "qrules.topology.KeyType": "obj", + "qrules.topology.ValueType": "obj", +} + + +try: # Sphinx >=4.4.0 + # https://github.com/sphinx-doc/sphinx/blob/v4.4.0/sphinx/domains/python.py#L110-L133 + from sphinx.addnodes import pending_xref_condition + from sphinx.domains.python import parse_reftarget + + def _new_type_to_xref( + target: str, + env: BuildEnvironment = None, + suppress_prefix: bool = False, + ) -> pending_xref: + """Convert a type string to a cross reference node.""" + reftype, target, title, refspecific = parse_reftarget( + target, suppress_prefix + ) + target = __TARGET_SUBSTITUTIONS.get(target, target) + reftype = __REF_TYPE_SUBSTITUTIONS.get(target, reftype) + + assert env is not None + return pending_xref( + "", + *__create_nodes(env, title), + refdomain="py", + reftype=reftype, + reftarget=target, + refspecific=refspecific, + **__get_env_kwargs(env), + ) + +except ImportError: # Sphinx <4.4.0 + # https://github.com/sphinx-doc/sphinx/blob/v4.3.2/sphinx/domains/python.py#L83-L107 + def _new_type_to_xref( + target: str, + env: BuildEnvironment = None, + suppress_prefix: bool = False, + ) -> pending_xref: + # pylint: disable=unused-argument + """Convert a type string to a cross reference node.""" + if target == "None": + reftype = "obj" + else: + reftype = "class" + + target = __TARGET_SUBSTITUTIONS.get(target, target) + reftype = __REF_TYPE_SUBSTITUTIONS.get(target, reftype) + + assert env is not None + return pending_xref( + "", + *__create_nodes(env, target), + refdomain="py", + reftype=reftype, + reftarget=target, + **__get_env_kwargs(env), + ) + + +def __get_env_kwargs(env: BuildEnvironment) -> dict: + if env: + return { + "py:module": env.ref_context.get("py:module"), + "py:class": env.ref_context.get("py:class"), + } + return {} + + +def __create_nodes(env: BuildEnvironment, title: str) -> List[nodes.Node]: + short_name = title.split(".")[-1] + if env.config.python_use_unqualified_type_names: + return [ + pending_xref_condition("", short_name, condition="resolved"), + pending_xref_condition("", title, condition="*"), + ] + return [nodes.Text(short_name)] + + +def relink_references() -> None: + sphinx.domains.python.type_to_xref = _new_type_to_xref diff --git a/docs/abbreviate_signature.py b/docs/abbreviate_signature.py deleted file mode 100644 index 45a66434..00000000 --- a/docs/abbreviate_signature.py +++ /dev/null @@ -1,62 +0,0 @@ -# cspell:ignore docutils -# pylint: disable=import-error -# pyright: reportMissingImports=false -"""Abbreviated the annotations generated by sphinx-autodoc. - -It's not necessary to generate the full path of type hints, because they are -rendered as clickable links. - -See also https://github.com/sphinx-doc/sphinx/issues/5868. -""" - -import sphinx.domains.python -from docutils import nodes -from sphinx import addnodes -from sphinx.environment import BuildEnvironment - - -def replace_link(text: str) -> str: - replacements = { - "a set-like object providing a view on D's items": "typing.ItemsView", - "a set-like object providing a view on D's keys": "typing.KeysView", - "an object providing a view on D's values": "typing.ValuesView", - "typing_extensions.Protocol": "typing.Protocol", - } - for old, new in replacements.items(): - if text == old: - return new - return text - - -def new_type_to_xref( - text: str, env: BuildEnvironment = None -) -> addnodes.pending_xref: - """Convert a type string to a cross reference node.""" - if text == "None": - reftype = "obj" - else: - reftype = "class" - - if env: - kwargs = { - "py:module": env.ref_context.get("py:module"), - "py:class": env.ref_context.get("py:class"), - } - else: - kwargs = {} - - text = replace_link(text) - short_text = text.split(".")[-1] - - return addnodes.pending_xref( - "", - nodes.Text(short_text), - refdomain="py", - reftype=reftype, - reftarget=text, - **kwargs, - ) - - -def abbreviate_signature() -> None: - sphinx.domains.python.type_to_xref = new_type_to_xref diff --git a/docs/conf.py b/docs/conf.py index a4c20f8b..5fe5c4c2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -73,9 +73,10 @@ def fetch_logo(url: str, output_path: str) -> None: # -- Generate API ------------------------------------------------------------ sys.path.insert(0, os.path.abspath(".")) -from abbreviate_signature import abbreviate_signature # noqa: E402 +from _relink_references import relink_references # noqa: E402 + +relink_references() -abbreviate_signature() shutil.rmtree("api", ignore_errors=True) subprocess.call( " ".join( @@ -172,6 +173,29 @@ def fetch_logo(url: str, output_path: str) -> None: ] ), } +autodoc_type_aliases = { + # qrules.argument_handling + "Rule": "qrules.argument_handling.Rule", + "Scalar": "qrules.argument_handling.Scalar", + "GraphElementPropertyMap": ( + "qrules.argument_handling.GraphElementPropertyMap" + ), + "GraphEdgePropertyMap": "qrules.argument_handling.GraphEdgePropertyMap", + "GraphNodePropertyMap": "qrules.argument_handling.GraphNodePropertyMap", + # qrules.combinatorics + "StateWithSpins": "qrules.combinatorics.StateWithSpins", + "StateDefinition": "qrules.combinatorics.StateDefinition", + # qrules.particle + "ParticleWithSpin": "qrules.particle.ParticleWithSpin", + # qrules.quantum_numbers + "EdgeQuantumNumber": "qrules.quantum_numbers.EdgeQuantumNumber", + "NodeQuantumNumber": "qrules.quantum_numbers.NodeQuantumNumber", + # qrules.topology + "EdgeType": "qrules.topology.EdgeType", + "KeyType": "qrules.topology.KeyType", + "ValueType": "qrules.topology.ValueType", +} +autodoc_typehints_format = "short" AUTODOC_INSERT_SIGNATURE_LINEBREAKS = True graphviz_output_format = "svg" html_copy_source = True # needed for download notebook button