diff --git a/.readthedocs.yml b/.readthedocs.yml index c0d2bba55e9..969b5f50d85 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -12,3 +12,4 @@ sphinx: python: install: - requirements: docs/requirements.txt + - requirements: docs/html/requirements.txt diff --git a/MANIFEST.in b/MANIFEST.in index 814da8265ca..f3dcf96830f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -13,6 +13,7 @@ recursive-include src/pip/_vendor *COPYING* include docs/docutils.conf include docs/requirements.txt +include docs/html/requirements.txt exclude .git-blame-ignore-revs exclude .coveragerc diff --git a/docs/common_conf.py b/docs/common_conf.py new file mode 100644 index 00000000000..9096035dc4d --- /dev/null +++ b/docs/common_conf.py @@ -0,0 +1,29 @@ +import os +import re +from typing import Tuple + + +def read_version() -> Tuple[str, str]: + # Find the version and release information. + # We have a single source of truth for our version number: pip's __init__.py file. + # This next bit of code reads from it. + file_with_version = os.path.join( + os.path.dirname(__file__), "..", "src", "pip", "__init__.py" + ) + with open(file_with_version) as f: + for line in f: + m = re.match(r'__version__ = "(.*)"', line) + if m: + __version__ = m.group(1) + # The short X.Y version. + version = ".".join(__version__.split(".")[:2]) + # The full version, including alpha/beta/rc tags. + release = __version__ + return version, release + return "dev", "dev" + + +# General information about the project. +project = "pip" +copyright = "The pip developers" +version, release = read_version() diff --git a/docs/html/conf.py b/docs/html/conf.py index 683ea7b87d8..430cac0a31f 100644 --- a/docs/html/conf.py +++ b/docs/html/conf.py @@ -1,16 +1,16 @@ """Sphinx configuration file for pip's documentation.""" -import glob import os import pathlib -import re import sys -from typing import List, Tuple -# Add the docs/ directory to sys.path, because pip_sphinxext.py is there. +# Add the docs/ directory to sys.path to load the common config, +# and pip_sphinxext.py docs_dir = os.path.dirname(os.path.dirname(__file__)) sys.path.insert(0, docs_dir) +from common_conf import copyright, project, release, version # noqa: E402, F401 + # -- General configuration ------------------------------------------------------------ extensions = [ @@ -28,27 +28,6 @@ "sphinxcontrib.towncrier", ] -# General information about the project. -project = "pip" -copyright = "The pip developers" - -# Find the version and release information. -# We have a single source of truth for our version number: pip's __init__.py file. -# This next bit of code reads from it. -file_with_version = os.path.join(docs_dir, "..", "src", "pip", "__init__.py") -with open(file_with_version) as f: - for line in f: - m = re.match(r'__version__ = "(.*)"', line) - if m: - __version__ = m.group(1) - # The short X.Y version. - version = ".".join(__version__.split(".")[:2]) - # The full version, including alpha/beta/rc tags. - release = __version__ - break - else: # AKA no-break - version = release = "dev" - print("pip version:", version) print("pip release:", release) @@ -95,43 +74,6 @@ html_use_modindex = False html_use_index = False -# -- Options for Manual Pages --------------------------------------------------------- - - -# List of manual pages generated -def determine_man_pages() -> List[Tuple[str, str, str, str, int]]: - """Determine which man pages need to be generated.""" - - def to_document_name(path: str, base_dir: str) -> str: - """Convert a provided path to a Sphinx "document name".""" - relative_path = os.path.relpath(path, base_dir) - root, _ = os.path.splitext(relative_path) - return root.replace(os.sep, "/") - - # Crawl the entire man/commands/ directory and list every file with appropriate - # name and details. - man_dir = os.path.join(docs_dir, "man") - raw_subcommands = glob.glob(os.path.join(man_dir, "commands/*.rst")) - if not raw_subcommands: - raise FileNotFoundError( - "The individual subcommand manpages could not be found!" - ) - - retval = [ - ("index", "pip", "package manager for Python packages", "pip developers", 1), - ] - for fname in raw_subcommands: - fname_base = to_document_name(fname, man_dir) - outname = "pip-" + fname_base.split("/")[1] - description = "description of {} command".format(outname.replace("-", " ")) - - retval.append((fname_base, outname, description, "pip developers", 1)) - - return retval - - -man_pages = determine_man_pages() - # -- Options for sphinx_copybutton ---------------------------------------------------- copybutton_prompt_text = r"\$ | C\:\> " diff --git a/docs/html/requirements.txt b/docs/html/requirements.txt new file mode 100644 index 00000000000..4a5c23400a9 --- /dev/null +++ b/docs/html/requirements.txt @@ -0,0 +1,8 @@ +# currently incompatible with sphinxcontrib-towncrier +# https://github.com/sphinx-contrib/sphinxcontrib-towncrier/issues/92 +towncrier < 24 +furo +myst_parser +sphinx-copybutton +sphinx-inline-tabs +sphinxcontrib-towncrier >= 0.2.0a0 diff --git a/docs/man/__init__.py b/docs/man/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/docs/man/conf.py b/docs/man/conf.py new file mode 100644 index 00000000000..2d5a5d894fd --- /dev/null +++ b/docs/man/conf.py @@ -0,0 +1,53 @@ +import glob +import os +import sys +from typing import List, Tuple + +# Add the docs/ directory to sys.path to load the common config +docs_dir = os.path.dirname(os.path.dirname(__file__)) +sys.path.insert(0, docs_dir) + +from common_conf import copyright, project, release, version # noqa: E402, F401 + +extensions = [ + # our extensions + "pip_sphinxext", +] + +print("pip version:", version) +print("pip release:", release) + + +# List of manual pages generated +def determine_man_pages() -> List[Tuple[str, str, str, str, int]]: + """Determine which man pages need to be generated.""" + + def to_document_name(path: str, base_dir: str) -> str: + """Convert a provided path to a Sphinx "document name".""" + relative_path = os.path.relpath(path, base_dir) + root, _ = os.path.splitext(relative_path) + return root.replace(os.sep, "/") + + # Crawl the entire man/commands/ directory and list every file with appropriate + # name and details. + man_dir = os.path.join(docs_dir, "man") + raw_subcommands = glob.glob(os.path.join(man_dir, "commands/*.rst")) + if not raw_subcommands: + raise FileNotFoundError( + "The individual subcommand manpages could not be found!" + ) + + retval = [ + ("index", "pip", "package manager for Python packages", "pip developers", 1), + ] + for fname in raw_subcommands: + fname_base = to_document_name(fname, man_dir) + outname = "pip-" + fname_base.split("/")[1] + description = "description of {} command".format(outname.replace("-", " ")) + + retval.append((fname_base, outname, description, "pip developers", 1)) + + return retval + + +man_pages = determine_man_pages() diff --git a/docs/requirements.txt b/docs/requirements.txt index b3ea82a9de1..35768edd252 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,12 +1,4 @@ sphinx ~= 7.0 -# currently incompatible with sphinxcontrib-towncrier -# https://github.com/sphinx-contrib/sphinxcontrib-towncrier/issues/92 -towncrier < 24 -furo -myst_parser -sphinx-copybutton -sphinx-inline-tabs -sphinxcontrib-towncrier >= 0.2.0a0 # `docs.pipext` uses pip's internals to generate documentation. So, we install # the current directory to make it work. diff --git a/news/a75401cc-cba6-4eb2-ac22-5225ed3bf448.trivial.rst b/news/a75401cc-cba6-4eb2-ac22-5225ed3bf448.trivial.rst new file mode 100644 index 00000000000..e69de29bb2d diff --git a/noxfile.py b/noxfile.py index 2051362769c..ed2cdf86654 100644 --- a/noxfile.py +++ b/noxfile.py @@ -26,6 +26,7 @@ } REQUIREMENTS = { "docs": "docs/requirements.txt", + "docs-html": "docs/html/requirements.txt", "tests": "tests/requirements.txt", "common-wheels": "tests/requirements-common_wheels.txt", } @@ -131,7 +132,10 @@ def docs(session: nox.Session) -> None: session.install("-r", REQUIREMENTS["docs"]) def get_sphinx_build_command(kind: str) -> List[str]: - # Having the conf.py in the docs/html is weird but needed because we + req_file = REQUIREMENTS.get(f"docs-{kind}") + if req_file is not None: + session.install("--requirement", req_file) + # Having the conf.py in the docs/{html,man} is weird but needed because we # can not use a different configuration directory vs source directory # on RTD currently. So, we'll pass "-c docs/html" here. # See https://github.com/rtfd/readthedocs.org/issues/1543. @@ -139,10 +143,10 @@ def get_sphinx_build_command(kind: str) -> List[str]: return [ "sphinx-build", "--keep-going", - "-W", - "-c", "docs/html", # see note above - "-d", "docs/build/doctrees/" + kind, - "-b", kind, + "--fail-on-warning", + "--conf-dir", "docs/" + kind, # see note above + "--doctree-dir", "docs/build/doctrees/" + kind, + "--builder", kind, "docs/" + kind, "docs/build/" + kind, ] @@ -155,7 +159,13 @@ def get_sphinx_build_command(kind: str) -> List[str]: @nox.session(name="docs-live") def docs_live(session: nox.Session) -> None: session.install("-e", ".") - session.install("-r", REQUIREMENTS["docs"], "sphinx-autobuild") + session.install( + "-r", + REQUIREMENTS["docs"], + "-r", + REQUIREMENTS["docs-html"], + "sphinx-autobuild", + ) session.run( "sphinx-autobuild",