From 97788f05b6e0d636061fba970cc23e70d8113237 Mon Sep 17 00:00:00 2001 From: melechlapson Date: Fri, 5 Apr 2024 10:59:10 -0500 Subject: [PATCH] Use `sphinx.ext.linkcode` for more precise source code links (#11851) * switched from sphinx.ext.viewcode to sphinx.ext.linkcode * removed extra line * Add section header for source code links Co-authored-by: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com> * removed docstring Co-authored-by: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com> * update return string Co-authored-by: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com> * added back blank line * Added a method to determine the GitHub branch Co-authored-by: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com> * add blank line Co-authored-by: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com> * remove print statement Co-authored-by: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com> * Try to fix error for contextlib file We got this stacktrace: Traceback (most recent call last): File "/home/vsts/work/1/s/.tox/docs/lib/python3.8/site-packages/sphinx/events.py", line 96, in emit results.append(listener.handler(self.app, *args)) File "/home/vsts/work/1/s/.tox/docs/lib/python3.8/site-packages/sphinx/ext/linkcode.py", line 55, in doctree_read uri = resolve_target(domain, info) File "/home/vsts/work/1/s/docs/conf.py", line 216, in linkcode_resolve file_name = PurePath(full_file_name).relative_to(repo_root) File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/pathlib.py", line 908, in relative_to raise ValueError("{!r} does not start with {!r}" ValueError: '/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/contextlib.py' does not start with '/home/vsts/work/1/s' We shouldn't even attempt to generate a link for the file contextlib.py * Try to fix error for Jenkins run #20240221.52 New build failed with this stacktrace: Traceback (most recent call last): File "/home/vsts/work/1/s/.tox/docs/lib/python3.8/site-packages/sphinx/events.py", line 96, in emit results.append(listener.handler(self.app, *args)) File "/home/vsts/work/1/s/.tox/docs/lib/python3.8/site-packages/sphinx/ext/linkcode.py", line 55, in doctree_read uri = resolve_target(domain, info) File "/home/vsts/work/1/s/docs/conf.py", line 215, in linkcode_resolve full_file_name = inspect.getsourcefile(obj) File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/inspect.py", line 696, in getsourcefile filename = getfile(object) File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/inspect.py", line 665, in getfile raise TypeError('{!r} is a built-in class'.format(object)) TypeError: is a built-in class So I added a condition that the obj should not be a built-in * Check that qiskit in module name sooner * moved valid code object verification earlier * added try except statement to getattr call * added extra try/except block * Also support Azure Pipelines * removed unused import * Revert Azure support to keep things simple * added extra "/" to final URL * Move GitHub branch logic to GitHub Action * switched to importlib and removed redundant block of code * Apply suggestions from code review Co-authored-by: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com> * added back spaces * Clarify docs_deploy GitHub logic 1. Remove misleading PR conditional. This worfklow doesn't even run in PRs. It was bad copy-pasta from the runtime repo 2. Clarify why we point tag builds to their stable branch name * Use pathlib for relativizing file name * Fix relative_to() path * Remove tox prefix --------- Co-authored-by: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com> --- .github/workflows/docs_deploy.yml | 14 +++++++- docs/conf.py | 59 ++++++++++++++++++++++++++++++- tox.ini | 10 +++++- 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docs_deploy.yml b/.github/workflows/docs_deploy.yml index fac9c5f0ea06..9763e3cc472e 100644 --- a/.github/workflows/docs_deploy.yml +++ b/.github/workflows/docs_deploy.yml @@ -29,9 +29,21 @@ jobs: - name: Install dependencies run: tools/install_ubuntu_docs_dependencies.sh + - name: Determine GitHub branch name + run: | + # Tags like 1.0.0 and 1.0.0rc1 should point to their stable branch. We do this + # to reduce the diff in the qiskit/documentation repository between generating + # the API docs from a tag release versus a workflow_dispatch. + if [[ $GITHUB_REF_NAME =~ ^([0-9]+\.[0-9]+) ]]; then + BRANCH_NAME="stable/${BASH_REMATCH[1]}" + else + BRANCH_NAME="$GITHUB_REF_NAME" + fi + echo "Using branch '${BRANCH_NAME}' for GitHub source code links" + echo "QISKIT_DOCS_GITHUB_BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV + - name: Build documentation run: tox run -e docs - - name: Store built documentation artifact uses: actions/upload-artifact@v4 with: diff --git a/docs/conf.py b/docs/conf.py index 1ef7427db899..4a79b543ed78 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -18,6 +18,12 @@ import datetime import doctest +import importlib +import inspect +import os +import re +from pathlib import Path + project = "Qiskit" project_copyright = f"2017-{datetime.date.today().year}, Qiskit Development Team" @@ -39,7 +45,7 @@ "sphinx.ext.intersphinx", "sphinx.ext.doctest", # This is used by qiskit/documentation to generate links to github.com. - "sphinx.ext.viewcode", + "sphinx.ext.linkcode", "matplotlib.sphinxext.plot_directive", "reno.sphinxext", "sphinxcontrib.katex", @@ -155,3 +161,54 @@ # ---------------------------------------------------------------------------------- plot_html_show_formats = False + + +# ---------------------------------------------------------------------------------- +# Source code links +# ---------------------------------------------------------------------------------- + +REPO_ROOT = Path(__file__).resolve().parents[1] + + +def linkcode_resolve(domain, info): + if domain != "py": + return None + + module_name = info["module"] + if "qiskit" not in module_name: + return None + + try: + module = importlib.import_module(module_name) + except ModuleNotFoundError: + return None + + obj = module + for part in info["fullname"].split("."): + try: + obj = getattr(obj, part) + except AttributeError: + return None + + try: + full_file_name = inspect.getsourcefile(obj) + except TypeError: + return None + if full_file_name is None: + return None + try: + relative_file_name = Path(full_file_name).resolve().relative_to(REPO_ROOT) + file_name = re.sub(r"\.tox\/.+\/site-packages\/", "", str(relative_file_name)) + except ValueError: + return None + + try: + source, lineno = inspect.getsourcelines(obj) + except (OSError, TypeError): + linespec = "" + else: + ending_lineno = lineno + len(source) - 1 + linespec = f"#L{lineno}-L{ending_lineno}" + + github_branch = os.environ.get("QISKIT_DOCS_GITHUB_BRANCH_NAME", "main") + return f"https://github.com/Qiskit/qiskit/tree/{github_branch}/{file_name}{linespec}" diff --git a/tox.ini b/tox.ini index b9001f6db5d4..ef1e1a23ef60 100644 --- a/tox.ini +++ b/tox.ini @@ -15,7 +15,15 @@ setenv = QISKIT_SUPRESS_PACKAGING_WARNINGS=Y QISKIT_TEST_CAPTURE_STREAMS=1 QISKIT_PARALLEL=FALSE -passenv = RAYON_NUM_THREADS, OMP_NUM_THREADS, QISKIT_PARALLEL, RUST_BACKTRACE, SETUPTOOLS_ENABLE_FEATURES, QISKIT_TESTS, QISKIT_IN_PARALLEL +passenv = + RAYON_NUM_THREADS + OMP_NUM_THREADS + QISKIT_PARALLEL + RUST_BACKTRACE + SETUPTOOLS_ENABLE_FEATURES + QISKIT_TESTS + QISKIT_IN_PARALLEL + QISKIT_DOCS_GITHUB_BRANCH_NAME deps = setuptools_rust # This is work around for the bug of tox 3 (see #8606 for more details.) -r{toxinidir}/requirements.txt