{"id":17316914,"url":"https://github.com/real-yfprojects/sphinx-polyversion","last_synced_at":"2025-09-03T01:40:34.018Z","repository":{"id":173661988,"uuid":"651005736","full_name":"real-yfprojects/sphinx-polyversion","owner":"real-yfprojects","description":"Build multiple versions of your sphinx docs and merge them into one website.","archived":false,"fork":false,"pushed_at":"2025-06-22T19:46:06.000Z","size":337,"stargazers_count":14,"open_issues_count":8,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-28T07:51:51.799Z","etag":null,"topics":["concurrency","doc-generator","documentation","documentation-generator","isolation","poetry","python","site-generator","sphinx","sphinx-extension","sphinx-multiversion","versioning"],"latest_commit_sha":null,"homepage":"https://real-yfprojects.github.io/sphinx-polyversion/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/real-yfprojects.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-06-08T09:29:39.000Z","updated_at":"2025-08-13T15:42:41.000Z","dependencies_parsed_at":"2023-12-10T21:30:05.332Z","dependency_job_id":"c07bb5cf-b3f3-48b2-bfae-23779961a55f","html_url":"https://github.com/real-yfprojects/sphinx-polyversion","commit_stats":{"total_commits":104,"total_committers":1,"mean_commits":104.0,"dds":0.0,"last_synced_commit":"6257207a98a837fa65529b1a8acab953d7289ca3"},"previous_names":["real-yfprojects/sphinx-polyversion"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/real-yfprojects/sphinx-polyversion","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/real-yfprojects%2Fsphinx-polyversion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/real-yfprojects%2Fsphinx-polyversion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/real-yfprojects%2Fsphinx-polyversion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/real-yfprojects%2Fsphinx-polyversion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/real-yfprojects","download_url":"https://codeload.github.com/real-yfprojects/sphinx-polyversion/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/real-yfprojects%2Fsphinx-polyversion/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273377149,"owners_count":25094526,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-02T02:00:09.530Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["concurrency","doc-generator","documentation","documentation-generator","isolation","poetry","python","site-generator","sphinx","sphinx-extension","sphinx-multiversion","versioning"],"created_at":"2024-10-15T13:14:46.212Z","updated_at":"2025-09-03T01:40:33.994Z","avatar_url":"https://github.com/real-yfprojects.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sphinx-polyversion\n\n[![Static Badge](https://img.shields.io/badge/docs-latest-blue?logo=github\u0026color=5cabff)](https://real-yfprojects.github.io/sphinx-polyversion/)\n[![pypi](https://img.shields.io/pypi/v/sphinx-polyversion.svg?logo=pypi\u0026logoColor=white\u0026color=0073b7)](https://pypi.org/project/sphinx-polyversion/)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/sphinx-polyversion?color=ffd43b)](https://pypi.org/project/sphinx-polyversion/)\n[![Github License](https://img.shields.io/github/license/real-yfprojects/sphinx-polyversion)](https://github.com/real-yfprojects/sphinx-polyversion/blob/main/LICENSE)\n[![PyPI - Downloads](https://img.shields.io/pypi/dm/sphinx-polyversion)](https://pypi.org/project/sphinx-polyversion/)\n[![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v0.json)](https://github.com/charliermarsh/ruff)\n[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://pre-commit.com)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n\n\u003c!-- description --\u003e\n\nBuild multiple versions of your sphinx docs and merge them into one website.\n\n- Isolated builds using venv, virtualenv or poetry\n- git support\n- Build with `sphinx-build` or custom commands\n- Access and modify all versioning data inside `conf.py`\n- Concurrent builds\n- Override build configuration from commandline easily\n- Render templates to the root directory containing the docs for each version\n- Build from local working tree easily while mocking version data\n- Not a sphinx extension -\u003e standalone tool\n- Configuration in a python script\n- Highly customizable and scriptable through OOP\n- Implement subclasses in your configuration script to add support for other VCS, Project/dependency management tools, build tools and whatever you require\n- IDE integration and autocompletion\n\n\u003c!-- end description --\u003e\n\nHave a look at the [roadmap](./ROADMAP.md) to find out about upcoming features.\n\n## Installation\n\n```\npip install sphinx-polyversion\n```\n\n```\npoetry add --group docs sphinx-polyversion\n```\n\n## Usage\n\n### Example\n\nSetup your sphinx docs in `docs/source/sphinx`. Add a `conf.py` file\nwith the following to set directory:\n\n```py\nfrom sphinx_polyversion.api import load\n\nload(globals())\n# This adds the following to the global scope\n# html_context = {\n#     \"revisions\": [GitRef('main', ...), GitRef('v6.8.9', ...), ...],\n#     \"current\": GitRef('v1.4.6', ...),\n# }\n\n# process the loaded version information as you wish\nhtml_context[\"latest\"] = max(html_context[\"revisions\"]) # latest by date\n\n# sphinx config\nproject = \"foo\"\n# ...\n```\n\nConfigure `sphinx-polyversion` in the file `docs/poly.py`.\n\n```py\nfrom pathlib import Path\n\nfrom sphinx_polyversion.api import apply_overrides\nfrom sphinx_polyversion.driver import DefaultDriver\nfrom sphinx_polyversion.git import Git, file_predicate\nfrom sphinx_polyversion.pyvenv import Poetry\nfrom sphinx_polyversion.sphinx import SphinxBuilder\n\n#: Regex matching the branches to build docs for\nBRANCH_REGEX = r\".*\"\n\n#: Regex matching the tags to build docs for\nTAG_REGEX = r\".*\"\n\n#: Output dir relative to project root\nOUTPUT_DIR = \"docs/build\"\n\n#: Source directory\nSOURCE_DIR = \"docs/source\"\n\n#: Arguments to pass to `poetry install`\nPOETRY_ARGS = \"--only sphinx --sync\".split()\n\n#: Arguments to pass to `sphinx-build`\nSPHINX_ARGS = \"-a -v\".split()\n\n#: Mock data used for building local version\nMOCK_DATA = {\n    \"revisions\": [\n        GitRef(\"v1.8.0\", \"\", \"\", GitRefType.TAG, datetime.fromtimestamp(0)),\n        GitRef(\"v1.9.3\", \"\", \"\", GitRefType.TAG, datetime.fromtimestamp(1)),\n        GitRef(\"v1.10.5\", \"\", \"\", GitRefType.TAG, datetime.fromtimestamp(2)),\n        GitRef(\"master\", \"\", \"\", GitRefType.BRANCH, datetime.fromtimestamp(3)),\n        GitRef(\"dev\", \"\", \"\", GitRefType.BRANCH, datetime.fromtimestamp(4)),\n        GitRef(\"some-feature\", \"\", \"\", GitRefType.BRANCH, datetime.fromtimestamp(5)),\n    ],\n    \"current\": GitRef(\"local\", \"\", \"\", GitRefType.BRANCH, datetime.fromtimestamp(6)),\n}\n#: Whether to build using only local files and mock data\nMOCK = False\n\n#: Whether to run the builds in sequence or in parallel\nSEQUENTIAL = False\n\n# Load overrides read from commandline to global scope\napply_overrides(globals())\n# Determine repository root directory\nroot = Git.root(Path(__file__).parent)\n\n# Setup driver and run it\nsrc = Path(SOURCE_DIR)\nDefaultDriver(\n    root,\n    OUTPUT_DIR,\n    vcs=Git(\n        branch_regex=BRANCH_REGEX,\n        tag_regex=TAG_REGEX,\n        buffer_size=1 * 10**9,  # 1 GB\n        predicate=file_predicate([src]), # exclude refs without source dir\n    ),\n    builder=SphinxBuilder(src / \"sphinx\", args=SPHINX_ARGS),\n    env=Poetry.factory(args=POETRY_ARGS),\n    template_dir=root / src / \"templates\",\n    static_dir=root / src / \"static\",\n    mock=MOCK_DATA,\n).run(MOCK, SEQUENTIAL)\n```\n\nBuild your docs by running\n\n```console\n$ sphinx-polyversion docs/poly.py\n```\n\n### Commandline Options\n\n```\nusage: sphinx-polyversion [-h] [-o [OVERRIDE [OVERRIDE...]]] [-v] [-l] [--sequential] conf [out]\n\nBuild multiple versions of your sphinx docs and merge them into one site.\n\npositional arguments:\n  conf                  Polyversion config file to load. This must be a python file that can be evaluated.\n  out                   Output directory to build the merged docs to.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -o [OVERRIDE [OVERRIDE ...]], --override [OVERRIDE [OVERRIDE ...]]\n                        Override config options. Pass them as `key=value` pairs.\n  -v, --verbosity       Increase output verbosity (decreases minimum log level). The default log level is ERROR.\n  -l, --local, --mock   Build the local version of your docs.\n  --sequential          Build the revisions sequentially.\n```\n\n### How To Build Versions Differently\n\n```py\n#: Mapping of revisions to changes in build parameters\nBUILDER = {\n    None: SphinxBuilder(Path(\"docs\")),  # default\n    \"v1.5.7\": SphinxBuilder(Path(\"docs/source\")),\n    \"v2.0.0\": CommandBuilder(\n        Path(\"docs/source\"),\n        [\"sphinx-autodoc\", Placeholder.SOURCE_DIR, Placeholder.OUTPUT_DIR],\n    ),\n    \"v2.4.0\": CommandBuilder(\n        Path(\"docs/source/sphinx\"),\n        [\"sphinx-autodoc\", Placeholder.SOURCE_DIR, Placeholder.OUTPUT_DIR],\n    ),\n}\n\n#: Mapping of revisions to changes in environment parameters\nENVIRONMENT = {\n    None: Poetry.factory(args=\"--sync\".split()),  # first version\n    \"v1.5.7\": Poetry.factory(args=\"--only sphinx --sync\".split()),\n    \"v1.8.2\": Poetry.factory(args=\"--only dev --sync\".split(), env={\"MY_VAR\": \"value\"}),\n    # use a pre-existing environment at the location ./.venv\n    \"v3.0.0\": Pip.factory(venv=Path(\".venv\"), args=\"-e . -r requirements.txt\".split()),\n    # dynamically create an environment in the temporary build directory\n    \"v4.*.*\": Pip.factory(venv=Path(\".venv\"), args=\"-e . -r requirements.txt\".split(), creator=VenvWrapper(), temporary=True),\n}\n\n# ...\n\nDefaultDriver(\n    # ...\n    builder=BUILDER,\n    env=ENVIRONMENT,\n    selector=partial(closest_tag, root),\n    # ...\n).run()\n```\n\n### Data Passed to Sphinx\n\n```py\n{\"revisions\": [GitRef(...), GitRef(...)], \"current\": GitRef(...)}\n```\n\nYou can change the format by passing your own factory.\n\n```py\ndef data(driver: DefaultDriver, rev: GitRef, env: Environment):\n    return {\n      \"tags\": list(filter(lambda r: r.type_ == GitRefType.TAG, driver.targets)),\n      \"branches\": list(filter(lambda r: r.type_ == GitRefType.BRANCH, driver.targets)),\n      \"current\": rev,\n    }\n\n# ...\n\nDefaultDriver(\n    # ...\n    data_factory=data,\n    # ...\n).run()\n```\n\n## Contributing\n\nContributions of all kinds are welcome. That explicitely includes suggestions for enhancing the API, the architecture or the documentation of the project.\nPRs are greatly appreciated as well. But please make sure that your change is wanted by opening an issue about it first before you waste your time with a PR\nthat isn't merged in the end.\n\nBy contributing you affirm the [Developer Certificate of Origin](https://developercertificate.org/) and license your work under the terms of this repository.\n\nNew top-level modules must be added to `docs/sphinx/api/sphinx_polyversion.rst`.\n\n## License\n\nMIT License \u003cbr\u003e\nSee the [LICENSE](./LICENSE) file which should be located in this directory.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freal-yfprojects%2Fsphinx-polyversion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freal-yfprojects%2Fsphinx-polyversion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freal-yfprojects%2Fsphinx-polyversion/lists"}