From 3df2695a45880b9a214ecf576bc32b34f5e1c77d Mon Sep 17 00:00:00 2001 From: Andreas Zwinkau Date: Fri, 27 Feb 2026 11:22:35 +0100 Subject: [PATCH 1/3] Add all_requirements only if missing An error might look like this: Error in fail: Some docs-as-code dependencies are in deps: accessible_pygments, alabaster, sphinx ... but others are missing: anyio, attrs, babel, basedpyright, bazel_runfiles, beautifulsoup4, cattrs, certifi, cffi, charset_normalizer, click, colorama, contourpy, cryptography, cycler, debugpy, docutils, esbonio, fonttools, gitdb, gitpython, h11, idna, imagesize, iniconfig, jinja2, jsonschema_rs, kiwisolver, lsprotocol, markdown_it_py, markupsafe, matplotlib, mdit_py_plugins, mdurl, myst_parser, needs_config_writer, nodejs_wheel_binaries, numpy, packaging, pillow, platformdirs, pluggy, pycparser, pydata_sphinx_theme, pygithub, pygls, pygments, pyjwt, pynacl, pyparsing, pyspellchecker, pytest, python_dateutil, pyyaml, requests, requests_file, rich, roman_numerals, roman_numerals_py, ruamel_yaml, six, smmap, snowballstemmer, soupsieve, sphinx_autobuild, sphinx_collections, sphinx_data_viewer, sphinx_design, sphinx_needs, sphinxcontrib_applehelp, sphinxcontrib_devhelp, sphinxcontrib_htmlhelp, sphinxcontrib_jquery, sphinxcontrib_jsmath, sphinxcontrib_mermaid, sphinxcontrib_plantuml, sphinxcontrib_qthelp, sphinxcontrib_serializinghtml, starlette, tomli, tomli_w, typing_extensions, urllib3, uvicorn, watchfiles, websockets Inconsistent deps for docs(): either include all dependencies or none of them. --- docs.bzl | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/docs.bzl b/docs.bzl index 59865265..8f728f12 100644 --- a/docs.bzl +++ b/docs.bzl @@ -89,6 +89,37 @@ def _merge_sourcelinks(name, sourcelinks): tools = ["@score_docs_as_code//scripts_bazel:merge_sourcelinks"], ) +def _missing_requirements(deps): + """Add Python hub dependencies if they are missing.""" + found = [] + missing = [] + def _target_to_packagename(target): + return target.split("/")[-1].split(":")[0] + all_packages = [_target_to_packagename(pkg) for pkg in all_requirements] + def _find(pkg): + for dep in deps: + dep_pkg = _target_to_packagename(dep) + if dep_pkg == pkg: + return True + return False + for pkg in all_packages: + if _find(pkg): + found.append(pkg) + else: + missing.append(pkg) + if len(missing) == len(all_requirements): + #print("All docs-as-code dependencies are missing, adding all of them.") + return all_requirements + if len(missing) == 0: + #print("All docs-as-code dependencies are already included, no need to add any.") + return [] + if len(found) > 0: + msg = "Some docs-as-code dependencies are in deps: " + ", ".join(found) + \ + "\n ... but others are missing: " + ", ".join(missing) + \ + "\nInconsistent deps for docs(): either include all dependencies or none of them." + fail(msg) + fail("This case should be unreachable?!") + def docs(source_dir = "docs", data = [], deps = [], scan_code = []): """Creates all targets related to documentation. @@ -107,7 +138,8 @@ def docs(source_dir = "docs", data = [], deps = [], scan_code = []): fail("docs() must be called from the root package. Current package: " + call_path) module_deps = deps - deps = deps + all_requirements + [ + deps = deps + _missing_requirements(deps) + deps = deps + [ "@score_docs_as_code//src:plantuml_for_python", "@score_docs_as_code//src/extensions/score_sphinx_bundle:score_sphinx_bundle", ] From 01378699b71ab557c078b46b00a91c77ee05442e Mon Sep 17 00:00:00 2001 From: Andreas Zwinkau Date: Fri, 27 Feb 2026 12:10:57 +0100 Subject: [PATCH 2/3] Adapt documentation --- docs/how-to/add_extensions.rst | 30 ++++++++++++++++++++++++++++++ docs/how-to/index.rst | 1 + docs/reference/bazel_macros.rst | 6 ++++-- 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 docs/how-to/add_extensions.rst diff --git a/docs/how-to/add_extensions.rst b/docs/how-to/add_extensions.rst new file mode 100644 index 00000000..6b8ac8e9 --- /dev/null +++ b/docs/how-to/add_extensions.rst @@ -0,0 +1,30 @@ +Add Extensions +=================== + +The docs-as-code module defines its own Python environment in ``MODULE.bazel`` +and as a user you cannot extend that. +If you want to add Sphinx extensions, +you must duplicate the Python environment first. + +Once you have your own Python environment, +supply all necessary packages to ``docs`` via the ``deps`` attribute. + +.. code-block:: starlark + :caption: In your BUILD file + + load("@your_python_env//:requirements.bzl", "all_requirements") + + docs( + # ...other attributes... + deps = all_requirements + ) + +Inside ``docs()``, the docs-as-code module will check if you have supplied all necessary dependencies. + +How to Create a Python Environment? +----------------------------------- + +The general documentation is `in the rules_python documentation `_. + +You can also peek into `this docs-as-code repo's MODULE.bazel file `_ +how ``docs_as_code_hub_env`` is defined and use it as a template for ``your_python_env``. diff --git a/docs/how-to/index.rst b/docs/how-to/index.rst index 4bc0ae7b..d9f2c891 100644 --- a/docs/how-to/index.rst +++ b/docs/how-to/index.rst @@ -15,3 +15,4 @@ Here you find practical guides on how to use docs-as-code. other_modules source_to_doc_links test_to_doc_links + add_extensions diff --git a/docs/reference/bazel_macros.rst b/docs/reference/bazel_macros.rst index d5f65fdf..ce7b7995 100644 --- a/docs/reference/bazel_macros.rst +++ b/docs/reference/bazel_macros.rst @@ -42,8 +42,10 @@ Minimal example (root ``BUILD``) - ``deps`` (list of bazel labels) Additional Bazel dependencies to add to the Python binaries and the virtual environment - target. Use this to add project-specific Python packages or extension libraries the docs - build requires. + target. Use this to add project-specific Python modules. + + If you don't provide the necessary Sphinx packages, + this function adds its own (but checks for conflicts). Edge cases ---------- From f386f738d8bc73b4c1a11d30f1b313c954dab380 Mon Sep 17 00:00:00 2001 From: Andreas Zwinkau Date: Mon, 2 Mar 2026 08:38:27 +0100 Subject: [PATCH 3/3] Recommend compile_pip_requirements --- docs/how-to/add_extensions.rst | 21 +++++++++++++++++++++ src/BUILD | 1 + 2 files changed, 22 insertions(+) diff --git a/docs/how-to/add_extensions.rst b/docs/how-to/add_extensions.rst index 6b8ac8e9..e35d9e0f 100644 --- a/docs/how-to/add_extensions.rst +++ b/docs/how-to/add_extensions.rst @@ -28,3 +28,24 @@ The general documentation is `in the rules_python documentation `_ how ``docs_as_code_hub_env`` is defined and use it as a template for ``your_python_env``. + +Recommendation: +Use `compile_pip_requirements `_ +because it is a solid practice anyways. +Next, get ``@score_docs_as_code//src:requirements.in`` as one of the inputs +to ensure you have all the necessary dependencies for docs-as-code. + +.. code-block:: starlark + :caption: Example BUILD file snippet + + load("@rules_python//python:pip.bzl", "compile_pip_requirements") + + compile_pip_requirements( + name = "requirements", + srcs = [ + "@score_docs_as_code//src:requirements.in", + "requirements.in", + ], + requirements_txt = "requirements_lock.txt", + visibility = ["//visibility:public"], + ) diff --git a/src/BUILD b/src/BUILD index d1b93a8c..44bd8483 100644 --- a/src/BUILD +++ b/src/BUILD @@ -24,6 +24,7 @@ load("@score_tooling//:defs.bzl", "dash_license_checker") exports_files( [ "requirements.txt", + "requirements.in", "incremental.py", "dummy.py", "generate_sourcelinks_cli.py",