diff --git a/docs/configuration.rst b/docs/configuration.rst index 98ac8a16..73850e29 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -29,6 +29,9 @@ This is what the default configuration looks like: # Determines whether remote or local git branches/tags are preferred if their output dirs conflict smv_prefer_remote_refs = False + # Callable for transforming the list of matching refs (set to None to do no transformation) + smv_refs_filter_fn = None + You can override all of these values inside your :file:`conf.py`. .. note:: @@ -106,6 +109,32 @@ Here are some examples: Have a look at `PyFormat `_ for information how to use new-style Python formatting. +Arbitrary filtering of git refs +=============================== + +In some cases the regexes above may be insufficient to determine which git refs to build, for instance to build only the most recent N builds. For those cases the ``smv_refs_filter_fn`` setting may be set to a Python function which filters, sorts, and transforms the list of matching git refs. + +For example: + +.. code-block:: python + + # Keep main and the most recent 5 releases + def git_ref_filter(git_refs): + main_ref = None + release_refs = [] + for git_ref in git_refs: + if git_ref.name == "main": + main_ref = git_ref + elif "release" in git_ref.name: + release_refs.append(git_ref) + + release_refs = sorted(release_refs, key=git_ref_to_semver)[-5:] + + return [main_ref] + release_refs + + smv_refs_filter_fn = git_ref_filter + + Overriding Configuration Variables ================================== diff --git a/sphinx_multiversion/main.py b/sphinx_multiversion/main.py index 9870b314..2fba85aa 100644 --- a/sphinx_multiversion/main.py +++ b/sphinx_multiversion/main.py @@ -12,6 +12,7 @@ import subprocess import sys import tempfile +from typing import Optional, Callable from sphinx import config as sphinx_config from sphinx import project as sphinx_project @@ -67,6 +68,9 @@ def load_sphinx_config_worker(q, confpath, confoverrides, add_defaults): str, ) current_config.add("smv_prefer_remote_refs", False, "html", bool) + current_config.add( + "smv_refs_filter_fn", None, "html", Optional[Callable] + ) current_config.pre_init_values() current_config.init_values() except Exception as err: @@ -76,14 +80,21 @@ def load_sphinx_config_worker(q, confpath, confoverrides, add_defaults): q.put(current_config) -def load_sphinx_config(confpath, confoverrides, add_defaults=False): +def load_sphinx_config( + confpath, confoverrides, add_defaults=False, in_process=False +): q = multiprocessing.Queue() - proc = multiprocessing.Process( - target=load_sphinx_config_worker, - args=(q, confpath, confoverrides, add_defaults), - ) - proc.start() - proc.join() + target = load_sphinx_config_worker + args = (q, confpath, confoverrides, add_defaults) + if in_process: + target(*args) + else: + proc = multiprocessing.Process( + target=target, + args=args, + ) + proc.start() + proc.join() result = q.get_nowait() if isinstance(result, Exception): raise result @@ -181,7 +192,10 @@ def main(argv=None): # Parse config config = load_sphinx_config( - confdir_absolute, confoverrides, add_defaults=True + confdir_absolute, + confoverrides, + add_defaults=True, + in_process=True, ) # Get relative paths to root of git repository @@ -218,6 +232,9 @@ def main(argv=None): else: gitrefs = sorted(gitrefs, key=lambda x: (x.is_remote, *x)) + if config.smv_refs_filter_fn is not None: + gitrefs = config.smv_refs_filter_fn(gitrefs) + logger = logging.getLogger(__name__) with tempfile.TemporaryDirectory() as tmp: