From 61026ebf4bdd330bd50691c848e1c1ad4e9f0289 Mon Sep 17 00:00:00 2001 From: Vitor Bandeira Date: Sat, 8 Aug 2026 14:35:21 -0300 Subject: [PATCH 1/4] docs: vendor OpenROAD sources instead of fetching master conf.py fetched three files from OpenROAD master at build time and spliced them with regex guarded by bare assert. A heading rename upstream broke the build with a message naming neither file nor fix, python -O stripped the guard entirely, and the docs tracked master rather than the pinned tools/OpenROAD submodule. Sources are vendored at the submodule SHA under docs/_vendor and refreshed by the existing update-OR cron job, so the build makes no network calls and check_vendored_docs.py fails the submodule bump instead of the docs build. Only the Supported Operating Systems section of index.md is vendored, not the whole landing page: conf.py consumes nothing else, and the surrounding prose trips this repo's blocked-content check. Vendored copies keep upstream trailing whitespace so the refresh stays idempotent, so .gitattributes exempts them from whitespace checking. Drops docs/SupportedOS, which Sphinx published as an orphan copy of OpenROAD's landing page. Signed-off-by: Vitor Bandeira --- .gitattributes | 6 + .../github-actions-cron-update-OR.yml | 7 + .gitignore | 5 +- docs/_vendor/openroad/GitGuide.md | 207 +++++++++++ docs/_vendor/openroad/README.md | 57 +++ docs/_vendor/openroad/SOURCE.json | 21 ++ docs/_vendor/openroad/index-SupportedOS.md | 23 ++ docs/_vendor/openroad/utl-README.md | 135 +++++++ docs/conf.py | 132 ++++--- docs/contrib/DeveloperGuide.md | 2 +- docs/contrib/GitGuide.md | 5 - docs/scripts/check_vendored_docs.py | 293 ++++++++++++++++ docs/scripts/refresh_openroad_docs.py | 330 ++++++++++++++++++ 13 files changed, 1172 insertions(+), 51 deletions(-) create mode 100644 docs/_vendor/openroad/GitGuide.md create mode 100644 docs/_vendor/openroad/README.md create mode 100644 docs/_vendor/openroad/SOURCE.json create mode 100644 docs/_vendor/openroad/index-SupportedOS.md create mode 100644 docs/_vendor/openroad/utl-README.md delete mode 100644 docs/contrib/GitGuide.md create mode 100755 docs/scripts/check_vendored_docs.py create mode 100755 docs/scripts/refresh_openroad_docs.py diff --git a/.gitattributes b/.gitattributes index 12a49d1bda..647009ed89 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,9 @@ # Make Github ignore the designs folder when determining repo language flow/designs/src/* linguist-vendored flow/scripts/variables.json linguist-generated=true + +# Byte-for-byte copies of OpenROAD files, regenerated by +# docs/scripts/refresh_openroad_docs.py. Upstream's trailing whitespace must +# survive verbatim, or the refresh is no longer idempotent and the vendored +# copies stop matching the commit SOURCE.json pins. +docs/_vendor/openroad/** -whitespace diff --git a/.github/workflows/github-actions-cron-update-OR.yml b/.github/workflows/github-actions-cron-update-OR.yml index 7b80699270..ec6faa2b1a 100644 --- a/.github/workflows/github-actions-cron-update-OR.yml +++ b/.github/workflows/github-actions-cron-update-OR.yml @@ -22,6 +22,13 @@ jobs: echo "::set-output name=has_update::$(git --no-pager diff --name-only origin/master..HEAD)" git checkout master git pull + - name: Refresh vendored OpenROAD docs + # docs/conf.py reads docs/_vendor/openroad/ instead of downloading from + # GitHub while Sphinx runs, so the vendored copies must be re-taken at + # the new submodule SHA. Running it here puts the docs refresh in the + # same commit as the submodule bump, which is what + # docs/scripts/check_vendored_docs.py asserts. + run: python3 docs/scripts/refresh_openroad_docs.py - if: "steps.remote-update.outputs.has_update != ''" name: Create Draft PR uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 diff --git a/.gitignore b/.gitignore index 84d1e39569..a15da1770e 100644 --- a/.gitignore +++ b/.gitignore @@ -85,12 +85,15 @@ perf.data perf.data.old # documentation specific +# Everything below is generated by docs/conf.py during `make html`; the sources +# are docs/index.md, ../README.md and docs/_vendor/openroad/ (see +# docs/_vendor/openroad/README.md). docs/main docs/build -SupportedOS.md index2.md Manpage.md mainREADME.md +docs/contrib/GitGuide.md build .scala-build/ .bsp/ diff --git a/docs/_vendor/openroad/GitGuide.md b/docs/_vendor/openroad/GitGuide.md new file mode 100644 index 0000000000..da22ff87d3 --- /dev/null +++ b/docs/_vendor/openroad/GitGuide.md @@ -0,0 +1,207 @@ +# Git Quickstart + +This tutorial serves as a quickstart to Git and contributing to our repository. If you have not already set up OpenROAD, please follow the instructions [here](../user/Build.md). + +```{tip} This basic tutorial gives instruction for basic password Git authentication. +If you would like to setup SSH authentication, please follow this [guide](https://help.github.com/set-up-git-redirect). +``` + +## Forking + +You will need your own fork to work on the code. Go to the `OpenROAD` project +[page](https://github.com/The-OpenROAD-Project/OpenROAD) and hit the `Fork` button. You will +want to clone your fork to your machine: + +```shell +git clone https://github.com/your-user-name/OpenROAD.git +cd OpenROAD +git remote add upstream https://github.com/The-OpenROAD-Project/OpenROAD.git +git fetch upstream +``` + +This creates the directory `OpenROAD` and connects your repository to +the upstream (master project) *OpenROAD* repository. + +## Creating a branch + +You want your master branch to reflect only production-ready code, so create a +feature branch for making your changes. For example: + +```shell +git checkout master && git branch shiny-new-feature +git checkout shiny-new-feature +# Or equivalently, +git checkout master && git checkout -b shiny-new-feature +``` + +This changes your working directory to the shiny-new-feature branch. Keep any +changes in this branch specific to one bug or feature so it is clear +what the branch brings to OpenROAD. You can have many shiny-new-features +and switch in between them using the git checkout command. + +When creating this branch, make sure your master branch is up to date with +the latest upstream master version. To update your local master branch, you +can do: + +```shell +git checkout master +git pull upstream master +``` + +When you want to update the feature branch with changes in master after +you created the branch, check the section on +[updating a PR](#updating-your-pull-request). + +## Committing your code +Keep style fixes to a separate commit to make your pull request more readable. Once you've made changes, you can see them by typing: + +```shell +git status +``` + +If you have created a new file, it is not being tracked by git. Add it by typing: +```shell +git add path/to/file-to-be-added.py +``` + +Doing `git status` again should give something like: +```shell +# On branch shiny-new-feature +# +# modified: /relative/path/to/file-you-added.py +# +``` + +Finally, commit your changes to your local repository with an explanatory commit +message. Do note the `-s` option is needed for developer signoff. +```shell +git commit -s -m "your commit message goes here" +``` + +## Pushing your changes + +When you want your changes to appear publicly on your GitHub page, push your +forked feature branch's commits: + +```shell +git push origin shiny-new-feature +``` + +Here `origin` is the default name given to your remote repository on GitHub. +You can see the remote repositories: + +```shell +git remote -v +``` + +If you added the upstream repository as described above you will see something +like: + +```shell +origin https://github.com/your-user-name/OpenROAD.git (fetch) +origin https://github.com/your-user-name/OpenROAD.git (push) +upstream https://github.com/The-OpenROAD-Project/OpenROAD.git (fetch) +upstream https://github.com/The-OpenROAD-Project/OpenROAD.git (push) +``` + +Now your code is on GitHub, but it is not yet a part of the OpenROAD project. For that to +happen, a pull request needs to be submitted on GitHub. + +## Review your code + +When you're ready to ask for a code review, file a pull request. Before you do, once +again make sure that you have followed all the guidelines outlined in the [Developer's Guide](./DeveloperGuide.md) +regarding code style, tests, performance tests, and documentation. You should also +double check your branch changes against the branch it was based on: + +1. Navigate to your repository on GitHub -- https://github.com/your-user-name/OpenROAD +1. Click on `Branches` +1. Click on the `Compare` button for your feature branch +1. Select the `base` and `compare` branches, if necessary. This will be `master` and + `shiny-new-feature`, respectively. + +## Submitting the pull request + +If everything looks good, you are ready to make a pull request. A pull request is how +code from a local repository becomes available to the GitHub community and can be looked +at and eventually merged into the master version. This pull request and its associated +changes will eventually be committed to the master branch and available in the next +release. To submit a pull request: + +1. Navigate to your repository on GitHub +1. Click on the ``Compare & pull request`` button +1. You can then click on ``Commits`` and ``Files Changed`` to make sure everything looks + okay one last time +1. Write a description of your changes in the ``Preview Discussion`` tab +1. Click ``Send Pull Request``. + +This request then goes to the repository maintainers, and they will review +the code. + +## Updating your pull request + +Based on the review you get on your pull request, you will probably need to make +some changes to the code. In that case, you can make them in your branch, +add a new commit to that branch, push it to GitHub, and the pull request will be +automatically updated. Pushing them to GitHub again is done by: + +```shell +git push origin shiny-new-feature +``` + +This will automatically update your pull request with the latest code and restart the +[Continuous Integration](./CI.md) tests. + +Another reason you might need to update your pull request is to solve conflicts +with changes that have been merged into the master branch since you opened your +pull request. + +To do this, you need to `merge upstream master` in your branch: + +```shell +git checkout shiny-new-feature +git fetch upstream +git merge upstream/master +``` + +If there are no conflicts (or they could be fixed automatically), a file with a +default commit message will open, and you can simply save and quit this file. + +If there are merge conflicts, you need to solve those conflicts. See +this [article](https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/) +for an explanation on how to do this. +Once the conflicts are merged and the files where the conflicts were solved are +added, you can run ``git commit`` to save those fixes. + +If you have uncommitted changes at the moment you want to update the branch with +master, you will need to ``stash`` them prior to updating. + +```{seealso} +See the stash [docs](https://git-scm.com/book/en/v2/Git-Tools-Stashing-and-Cleaning). +``` +This will effectively store your changes and they can be reapplied after updating. + +After the feature branch has been updated locally, you can now update your pull +request by pushing to the branch on GitHub: + +```shell +git push origin shiny-new-feature +``` + +## Tips for a successful pull request + +If you have made it to the `Review your code` phase, one of the core contributors may +take a look. Please note however that a handful of people are responsible for reviewing +all of the contributions, which can often lead to bottlenecks. + +To improve the chances of your pull request being reviewed, you should: + +- **Reference an open issue** for non-trivial changes to clarify the PR's purpose +- **Ensure you have appropriate tests**. These should be the first part of any PR +- **Keep your pull requests as simple as possible**. Larger PRs take longer to review +- **Ensure that CI is in a green state**. Reviewers may not even look otherwise +- **Keep updating your pull request**, either by request or every few days + +## Acknowledgements + +This page has been adapted from [pandas Developer Guide](https://pandas.pydata.org/docs/development/contributing.html). diff --git a/docs/_vendor/openroad/README.md b/docs/_vendor/openroad/README.md new file mode 100644 index 0000000000..6282b1bf72 --- /dev/null +++ b/docs/_vendor/openroad/README.md @@ -0,0 +1,57 @@ +# Vendored OpenROAD documentation sources + +**Do not edit these files by hand.** They are verbatim copies of files from the +[OpenROAD](https://github.com/The-OpenROAD-Project/OpenROAD) repository, taken at +the exact commit that the `tools/OpenROAD` submodule pins. `SOURCE.json` records +the repository, the commit SHA, and the upstream path of every file here. + +| File | Upstream path | Used by `docs/conf.py` to build | +| --- | --- | --- | +| `GitGuide.md` | `docs/contrib/GitGuide.md` | `docs/contrib/GitGuide.md` (renamed for ORFS, with `contrib/GitGuideAdapter.md` spliced in) | +| `index-SupportedOS.md` | `docs/index.md`, `## Supported Operating Systems` section only | that section, demoted to `####`, spliced into `docs/index2.md` under `### Setup` | +| `utl-README.md` | `src/utl/README.md` | `docs/Manpage.md` | + +Only what `docs/conf.py` consumes is stored. OpenROAD's `docs/index.md` is a +landing page and ORFS renders exactly one section of it, so the refresh script +extracts that section and vendors it alone — copying the whole page in would +bring unrelated project prose into this repository to render one table. + +The repo-relative links in `utl-README.md` are rewritten to absolute GitHub URLs +at the vendored SHA, because they would otherwise resolve against this +repository and 404. + +These files are exempt from the whitespace checks in `.gitattributes`: they are +byte-for-byte upstream copies, and the refresh script is only idempotent if +nothing rewrites them. + +## Why these are vendored + +`docs/conf.py` used to `requests.get()` all three files from +`raw.githubusercontent.com/.../OpenROAD/master/` while Sphinx was running. That +made the documentation build require network access, produced non-reproducible +output, tracked OpenROAD `master` rather than the version ORFS actually ships, +and overwrote files in the working tree on every local `make html`. Vendoring +gives the documentation the same hash-pinned reproducibility as +`docs/requirements_lock.txt`. + +## Refreshing + +```shell +python3 docs/scripts/refresh_openroad_docs.py +``` + +This is the only thing that downloads from GitHub, and it is wired into +`.github/workflows/github-actions-cron-update-OR.yml` so the nightly +submodule-bump PR carries the refreshed docs in the same commit. Run it by hand +whenever you bump `tools/OpenROAD` yourself. + +## Checking + +```shell +python3 docs/scripts/check_vendored_docs.py +``` + +Asserts, offline, that `SOURCE.json`'s SHA still matches +`git rev-parse HEAD:tools/OpenROAD`, that every heading `docs/conf.py` splices +on is still present, and that `index-SupportedOS.md` still holds exactly one +`##` section. Run it on any pull request that bumps `tools/OpenROAD`. diff --git a/docs/_vendor/openroad/SOURCE.json b/docs/_vendor/openroad/SOURCE.json new file mode 100644 index 0000000000..805b162380 --- /dev/null +++ b/docs/_vendor/openroad/SOURCE.json @@ -0,0 +1,21 @@ +{ + "_comment": "Generated by docs/scripts/refresh_openroad_docs.py -- do not edit by hand. Run that script to re-vendor after bumping the tools/OpenROAD submodule.", + "repo": "The-OpenROAD-Project/OpenROAD", + "sha": "ab6fd26351dc449e69059684dc6aa9ae9046eb36", + "files": { + "docs/contrib/GitGuide.md": { + "vendored": "GitGuide.md" + }, + "docs/index.md": { + "vendored": "index-SupportedOS.md", + "section": { + "start": "## Supported Operating Systems", + "end": "## Code of conduct" + } + }, + "src/utl/README.md": { + "vendored": "utl-README.md", + "links_rewritten": true + } + } +} diff --git a/docs/_vendor/openroad/index-SupportedOS.md b/docs/_vendor/openroad/index-SupportedOS.md new file mode 100644 index 0000000000..d289271d17 --- /dev/null +++ b/docs/_vendor/openroad/index-SupportedOS.md @@ -0,0 +1,23 @@ +## Supported Operating Systems + +Note that depending on the installation method, we have varying levels of +support for various operating systems. + +Legend: +- `Y` for supported. +- `-` for unsupported. + +| Operating System | Local Installation | Prebuilt Binaries | Docker Installation | Windows Subsystem for Linux | +| --- | --- | --- | --- | --- | +| Debian 12 | `Y` | `Y` | `Y` | `-` | +| Debian 13 | `Y` | `Y` | `Y` | `-` | +| Ubuntu 22.04 | `Y` | `Y` | `Y` | `-` | +| Ubuntu 24.04 | `Y` | `Y` | `Y` | `-` | +| Ubuntu 26.04 | `Y` | `Y` | `Y` | `-` | +| RHEL 8/9 | `Y` | `-` | `Y` | `-` | +| Rocky 8 | `Y` | `-` | `Y` | `-` | +| Rocky 9 | `Y` | `-` | `Y` | `-` | +| macOS | `Y` | `-` | `Y` | `-` | +| Windows 10 and above | `-` | `-` | `Y` | `Y` | + + diff --git a/docs/_vendor/openroad/utl-README.md b/docs/_vendor/openroad/utl-README.md new file mode 100644 index 0000000000..6f7c1d32e0 --- /dev/null +++ b/docs/_vendor/openroad/utl-README.md @@ -0,0 +1,135 @@ +# Utilities + +The utility module contains the `man` command. + +## Commands + +```{note} +- Parameters in square brackets `[-param param]` are optional. +- Parameters without square brackets `-param2 param2` are required. +``` + +### Prometheus Metrics + +OpenROAD includes a metrics endpoint server that can track internal tool metrics over time. + +![page](https://raw.githubusercontent.com/The-OpenROAD-Project/OpenROAD/ab6fd26351dc449e69059684dc6aa9ae9046eb36/docs/images/grafana.png) + +To use this feature you need to do the following start the prometheus and grafana collectors + +[Detailed instructions](https://github.com/The-OpenROAD-Project/OpenROAD/blob/ab6fd26351dc449e69059684dc6aa9ae9046eb36/etc/monitoring/README.md): +```shell +$ cd etc/monitoring +$ docker compose up -d +``` + +This will start a grafana endpoint ready to collect from the OpenROAD application you would +like to track. By default it's looking for an http server running on port 8080 on your localhost. + +To start the metrics endpoint in OpenROAD, run: +```tcl +utl::startPrometheusEndpoint 8080 +``` + +This is all configurable in the docker compose file, and you should be able to access grafana by going to +http://localhost:3000 username: admin, password: grafana. Go to the dashboard tab and click service, +then OpenROAD to see the pre-made dashboard. + +## Man installation + +The `man` command can be installed optionally as part of the OpenROAD +binary. For more instructions, please refer to [here](https://github.com/The-OpenROAD-Project/OpenROAD/blob/ab6fd26351dc449e69059684dc6aa9ae9046eb36/src/utl/manREADME.md). + +### Man + +The `man` command in OpenROAD is similar in functionality to Unix +(and Unix-like operating systems such as Linux) . It is used to +display the manual pages for various applications, tools and error +messages. These manual pages provide detailed information about how +to use a particular command or function, along with its syntax and options. + +This can be used for a range of commands in different levels as follows: +- Level 1: Top-level openroad command (e.g. `man openroad`) +- Level 2: Individual module commands (e.g. `man clock_tree_synthesis`) +- Level 3: Info, error, warning messages (e.g. `man CTS-0001`) + +```tcl +man + name + [-manpath manpath] + [-no_pager] +``` + +#### Options + +| Switch Name | Description | +| ----- | ----- | +| `name` | Name of the command/message to query. | +| `-manpath` | Include optional path to man pages (e.g. ~/OpenROAD/docs/cat). | +| `-no_pager` | This flag determines whether you wish to see all of the man output at once. Default value is `False`, which shows a buffered output. | + +## Example scripts + +You may run various commands or message IDs for man pages. +``` +man openroad +man clock_tree_synthesis +man CTS-0005 +``` + +### tee + +Redirect a commands output to a file and standard out. + +```tcl +tee (-file filename | -variable name) + [-append] + [-quiet] + command +``` + +#### Options + +| Switch Name | Description | +| ----- | ----- | +| `-file filename` | File to redirect output into. | +| `-variable name` | Direct output into a variable. | +| `-append` | Append to file. | +| `-quiet` | Do not send output to standard out. | +| `command` | Command to execute. | + +## Example scripts + +``` +tee -file output.rpt { report_design_area } +tee -quiet -file output.rpt { report_floating_nets } +``` + +## Regression tests + +There are a set of regression tests in `./test`. For more information, refer to this [section](https://github.com/The-OpenROAD-Project/OpenROAD/blob/ab6fd26351dc449e69059684dc6aa9ae9046eb36/README.md#regression-tests). + +For information regarding the Man page test framework, refer to this +[link](https://github.com/The-OpenROAD-Project/OpenROAD/blob/ab6fd26351dc449e69059684dc6aa9ae9046eb36/docs/src/test/README.md). + +You should also be aware of the [README](https://github.com/The-OpenROAD-Project/OpenROAD/blob/ab6fd26351dc449e69059684dc6aa9ae9046eb36/docs/contrib/ReadmeFormat.md) and [Tcl](https://github.com/The-OpenROAD-Project/OpenROAD/blob/ab6fd26351dc449e69059684dc6aa9ae9046eb36/docs/contrib/TclFormat.md) format enforced to ensure +accurate parsing of man pages. + +Simply run the following script: + +```shell +./test/regression +``` + +## Limitations + +## References + +## Authors + +MAN command is written by Jack Luar with guidance from members of the OpenROAD team, +including: Cho Moon, Matt Liberty. + +## License + +BSD 3-Clause License. See [LICENSE](https://github.com/The-OpenROAD-Project/OpenROAD/blob/ab6fd26351dc449e69059684dc6aa9ae9046eb36/LICENSE) file. diff --git a/docs/conf.py b/docs/conf.py index 96e0c84cf4..6b580ce3b0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -13,7 +13,6 @@ import docutils import os import re -import requests # -- Project information ----------------------------------------------------- @@ -71,6 +70,9 @@ # This pattern also affects html_static_path and html_extra_path. exclude_patterns = [ "_build", + # Verbatim copies of OpenROAD files; conf.py splices them into ORFS pages + # rather than publishing them directly. See docs/_vendor/openroad/README.md. + "_vendor", "Thumbs.db", ".DS_Store", "**/LICENSE", @@ -135,10 +137,31 @@ # so a file named "default.css" will overwrite the builtin "default.css". -def get_file_from_url(url, fname): - r = requests.get(url) - with open(fname, "wb") as f: - f.write(r.content) +# Files copied verbatim from the OpenROAD repository at the SHA that the +# tools/OpenROAD submodule pins. They are checked in, so this build performs no +# network access -- matching the intent of the hash-pinned requirements_lock.txt. +# Refresh them with REFRESH_CMD; docs/scripts/check_vendored_docs.py asserts +# they are still in sync with the submodule pointer. +VENDOR_DIR = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "_vendor", "openroad" +) +REFRESH_CMD = "python3 docs/scripts/refresh_openroad_docs.py" + +# Holds one extracted section of OpenROAD's docs/index.md, not the whole page. +SUPPORTED_OS_FILE = "index-SupportedOS.md" + + +def read_vendored(fname): + """Read a file vendored from the OpenROAD repository.""" + path = os.path.join(VENDOR_DIR, fname) + try: + with open(path, "r") as f: + return f.read() + except OSError as error: + raise RuntimeError( + "Cannot read the vendored OpenROAD file '%s': %s. " + "Regenerate the vendored files with: %s" % (path, error, REFRESH_CMD) + ) from error def swap_prefix(file, old, new): @@ -156,56 +179,77 @@ def setup(app): shutil.copy("../README.md", "mainREADME.md") swap_prefix("mainREADME.md", "```mermaid", "```{mermaid}\n:align: center\n") - # Grab the reference file from OR - url = "https://raw.githubusercontent.com/The-OpenROAD-Project/OpenROAD/master/docs/contrib/GitGuide.md" - get_file_from_url(url, "contrib/GitGuide.md") - - # Temporarily using commit number, will change once OR commit merged. - url = "https://raw.githubusercontent.com/The-OpenROAD-Project/OpenROAD/master/docs/index.md" - get_file_from_url(url, "SupportedOS.md") - - # Adapt the downloaded GitGuide for ORFS: rename references and inject - # ORFS-specific submodule forking instructions from GitGuideAdapter.md. - with open("contrib/GitGuide.md", "r") as f: - content = f.read() - content = ( - content.replace( - "user/Build.md", "../index.md#build-or-installing-orfs-dependencies" - ) - .replace("OpenROAD", "OpenROAD-flow-scripts") - .replace("The-OpenROAD-flow-scripts", "The-OpenROAD") + # Adapt the vendored OpenROAD GitGuide for ORFS: rename references and + # inject ORFS-specific submodule forking instructions from + # GitGuideAdapter.md. + content = read_vendored("GitGuide.md") + content = content.replace( + "user/Build.md", "../index.md#build-or-installing-orfs-dependencies" + ) + # Rename OpenROAD -> OpenROAD-flow-scripts, but leave the GitHub + # organisation name ("The-OpenROAD-Project") and anything that already + # carries the "-flow-scripts" suffix alone. Equivalent to the previous + # blanket replace + "The-OpenROAD-flow-scripts" self-patch, without + # corrupting those two forms. + content = re.sub( + r"(? str | None: + """Return the SHA the committed ``tools/OpenROAD`` gitlink points at.""" + result = subprocess.run( + ["git", "rev-parse", "HEAD:%s" % SUBMODULE_PATH], + cwd=str(REPO_ROOT), + capture_output=True, + text=True, + ) + if result.returncode != 0: + problems.append( + "could not read the pinned submodule commit: " + "`git rev-parse HEAD:%s` failed: %s" + % (SUBMODULE_PATH, result.stderr.strip()) + ) + return None + return result.stdout.strip() + + +def load_source(problems: list[str]) -> dict | None: + if not SOURCE_JSON.exists(): + problems.append( + "%s is missing. Create it with: %s" + % (SOURCE_JSON.relative_to(REPO_ROOT), REFRESH_CMD) + ) + return None + try: + return json.loads(SOURCE_JSON.read_text(encoding="utf-8")) + except json.JSONDecodeError as error: + problems.append( + "%s is not valid JSON (%s). Regenerate it with: %s" + % (SOURCE_JSON.relative_to(REPO_ROOT), error, REFRESH_CMD) + ) + return None + + +def check_sha(source: dict, problems: list[str]) -> None: + pinned = committed_submodule_sha(problems) + if pinned is None: + return + + vendored = source.get("sha") + if not vendored: + problems.append( + '%s has no "sha" field. Regenerate it with: %s' + % (SOURCE_JSON.relative_to(REPO_ROOT), REFRESH_CMD) + ) + return + + if vendored != pinned: + problems.append( + "the vendored OpenROAD docs are stale:\n" + " %s says sha = %s\n" + " git rev-parse HEAD:%s = %s\n" + " The tools/OpenROAD submodule was bumped without re-vendoring " + "the documentation it ships. Fix with: %s" + % ( + SOURCE_JSON.relative_to(REPO_ROOT), + vendored, + SUBMODULE_PATH, + pinned, + REFRESH_CMD, + ) + ) + + +def check_files_present(source: dict, problems: list[str]) -> None: + files = source.get("files") + if not isinstance(files, dict) or not files: + problems.append( + '%s has no usable "files" mapping. Regenerate it with: %s' + % (SOURCE_JSON.relative_to(REPO_ROOT), REFRESH_CMD) + ) + return + + for upstream_path, record in sorted(files.items()): + if not isinstance(record, dict) or not record.get("vendored"): + problems.append( + '%s has a malformed entry for "%s". Regenerate it with: %s' + % (SOURCE_JSON.relative_to(REPO_ROOT), upstream_path, REFRESH_CMD) + ) + continue + name = record["vendored"] + path = VENDOR_DIR / name + if not path.exists(): + problems.append( + "%s is missing (vendored from %s:%s). Fix with: %s" + % ( + path.relative_to(REPO_ROOT), + source.get("repo", "OpenROAD"), + upstream_path, + REFRESH_CMD, + ) + ) + elif not path.read_text(encoding="utf-8").strip(): + problems.append( + "%s is empty. Fix with: %s" % (path.relative_to(REPO_ROOT), REFRESH_CMD) + ) + + +def check_anchors(source: dict, problems: list[str]) -> None: + cache: dict[str, str | None] = {} + + def read(rel_path: str) -> str | None: + if rel_path not in cache: + path = REPO_ROOT / rel_path + cache[rel_path] = ( + path.read_text(encoding="utf-8") if path.exists() else None + ) + return cache[rel_path] + + for rel_path, anchor in REQUIRED_ANCHORS: + text = read(rel_path) + if text is None: + # check_files_present already reported missing vendored files. + if not rel_path.startswith("docs/_vendor/"): + problems.append( + "%s is missing; it must contain %r" % (rel_path, anchor) + ) + continue + if anchor not in text: + if rel_path.startswith("docs/_vendor/"): + remedy = ( + "OpenROAD most likely renamed it. Re-vendor with `%s`; if " + "the heading really changed, update it in docs/conf.py and " + "in docs/scripts/check_vendored_docs.py." % REFRESH_CMD + ) + else: + remedy = ( + "This is an ORFS-owned page. Restore the heading, or update " + "the anchor in docs/conf.py and in " + "docs/scripts/check_vendored_docs.py." + ) + problems.append( + "%s does not contain the heading %r, which docs/conf.py splices " + "on.\n %s" % (rel_path, anchor, remedy) + ) + + files = source.get("files") if isinstance(source.get("files"), dict) else {} + + for rel_path, upstream_path, heading in EXTRACTED_SECTIONS: + remedy = ( + "Re-vendor with `%s`. If OpenROAD really renamed or reordered the " + "heading, update the section bounds in " + "docs/scripts/refresh_openroad_docs.py, the anchor in " + "docs/conf.py, and EXTRACTED_SECTIONS here to match." % REFRESH_CMD + ) + text = read(rel_path) + if text is None: + # check_files_present already reported missing vendored files. + continue + + if not text.startswith(heading): + problems.append( + "%s does not start with %r. It must hold that one section of " + "%s and nothing else, because docs/conf.py strips the heading " + "and splices the rest into docs/index2.md.\n %s" + % (rel_path, heading, upstream_path, remedy) + ) + elif not text[len(heading) :].strip(): + problems.append( + "%s contains %r with no body under it, so docs/index2.md would " + "publish an empty supported-OS section.\n %s" + % (rel_path, heading, remedy) + ) + + extra = [h for h in _H2_RE.findall(text) if h != heading] + if extra: + problems.append( + "%s contains %d unexpected `## ` heading(s) besides %r: %s.\n" + " The extraction from %s ran past the end of the section, so " + "docs/index2.md would publish unrelated content.\n %s" + % ( + rel_path, + len(extra), + heading, + ", ".join(repr(h) for h in extra), + upstream_path, + remedy, + ) + ) + + # The declarations above must agree with what the refresh script + # recorded; otherwise conf.py and the refresh script have drifted and + # the checks above are guarding the wrong heading. + recorded = (files.get(upstream_path) or {}).get("section") or {} + if recorded.get("start") not in (None, heading): + problems.append( + "%s records that %s was cut at %r, but docs/conf.py and this " + "script expect %r.\n Reconcile " + "docs/scripts/refresh_openroad_docs.py, docs/conf.py and " + "EXTRACTED_SECTIONS here, then re-vendor with `%s`." + % ( + SOURCE_JSON.relative_to(REPO_ROOT), + upstream_path, + recorded.get("start"), + heading, + REFRESH_CMD, + ) + ) + + +def main() -> int: + problems: list[str] = [] + + source = load_source(problems) + if source is not None: + check_sha(source, problems) + check_files_present(source, problems) + check_anchors(source or {}, problems) + + if problems: + print("check_vendored_docs: FAIL (%d problem(s))" % len(problems)) + for problem in problems: + print(" - %s" % problem) + return 1 + + print( + "check_vendored_docs: OK (vendored at %s @ %s)" + % (source.get("repo"), source.get("sha")) + ) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/docs/scripts/refresh_openroad_docs.py b/docs/scripts/refresh_openroad_docs.py new file mode 100755 index 0000000000..4762ff1443 --- /dev/null +++ b/docs/scripts/refresh_openroad_docs.py @@ -0,0 +1,330 @@ +#!/usr/bin/env python3 +"""Refresh ``docs/_vendor/openroad/`` from the pinned ``tools/OpenROAD`` submodule. + +The ORFS documentation splices three files that live in the OpenROAD repository +into its own pages (see ``docs/conf.py``). Those files used to be downloaded +from ``raw.githubusercontent.com/.../OpenROAD/master/`` while Sphinx was +running, which made the docs build depend on the network, non-reproducible, and +liable to document a version of OpenROAD that ORFS does not ship. + +They are vendored instead. This script is the *only* thing that talks to the +network: it downloads the three files **at the SHA that ``tools/OpenROAD`` is +pinned to**, rewrites the repo-relative links inside them so they still resolve +when rendered from this repository, and records the SHA in ``SOURCE.json``. + +Only what ``docs/conf.py`` actually consumes is stored. For OpenROAD's +``docs/index.md`` that is a single section -- the supported-OS table -- so this +script extracts it and vendors the section alone rather than the whole landing +page, which is mostly prose ORFS never renders. + +Usage:: + + python3 docs/scripts/refresh_openroad_docs.py [--sha SHA] + +It is idempotent: running it twice in a row leaves the working tree unchanged. + +``docs/scripts/check_vendored_docs.py`` is the offline counterpart: run it to +assert the vendored tree is still in sync with the submodule pointer. +""" + +from __future__ import annotations + +import argparse +import json +import posixpath +import re +import subprocess +import sys +import urllib.error +import urllib.request +from pathlib import Path +from typing import NamedTuple + +REPO = "The-OpenROAD-Project/OpenROAD" +SUBMODULE_PATH = "tools/OpenROAD" + +REPO_ROOT = Path(__file__).resolve().parents[2] +VENDOR_DIR = REPO_ROOT / "docs" / "_vendor" / "openroad" +SOURCE_JSON = VENDOR_DIR / "SOURCE.json" + + +class Vendored(NamedTuple): + """One file to vendor out of the OpenROAD repository. + + ``section`` restricts what is stored to a single ``## `` section of the + upstream file, delimited by ``(start, end)`` headings. The vendored file + then holds ``start`` followed by everything up to -- but not including -- + ``end``; ``docs/conf.py`` strips the leading heading and splices the rest. + + ``rewrite_links`` turns repo-relative markdown links into absolute GitHub + URLs at the vendored SHA. Without it a link such as ``../../LICENSE`` + would resolve against *this* repository and 404. + """ + + upstream: str + name: str + section: tuple[str, str] | None = None + rewrite_links: bool = False + + +# Keep this in sync with the readers in docs/conf.py. +# +# GitGuide.md is deliberately not link-rewritten: conf.py adapts it for ORFS +# and its remaining relative links (./DeveloperGuide.md, ./CI.md) resolve +# against ORFS's own docs/contrib/ pages. +# +# Only the supported-OS table is taken from docs/index.md. Vendoring that page +# whole would drag OpenROAD's entire landing page -- partner and programme +# prose included -- into this repository to render one table. +VENDORED_FILES = ( + Vendored("docs/contrib/GitGuide.md", "GitGuide.md"), + Vendored( + "docs/index.md", + "index-SupportedOS.md", + section=("## Supported Operating Systems", "## Code of conduct"), + ), + Vendored("src/utl/README.md", "utl-README.md", rewrite_links=True), +) + +_LINK_RE = re.compile(r"(!?)\[([^\]]*)\]\(\s*([^)\s]+)\s*\)") +_ABSOLUTE_PREFIXES = ("http://", "https://", "mailto:", "ftp://", "//") +_IMAGE_SUFFIXES = (".png", ".jpg", ".jpeg", ".gif", ".svg", ".webp", ".ico") + +_SHA_RE = re.compile(r"^[0-9a-f]{40}$") + + +def _git(*args: str, cwd: Path = REPO_ROOT) -> str: + """Run git and return stripped stdout, or raise with a readable message.""" + result = subprocess.run( + ["git", *args], + cwd=str(cwd), + capture_output=True, + text=True, + ) + if result.returncode != 0: + raise RuntimeError( + "command failed: git %s (in %s)\n%s" + % (" ".join(args), cwd, result.stderr.strip()) + ) + return result.stdout.strip() + + +def resolve_pinned_sha() -> tuple[str, str]: + """Return ``(sha, how)`` for the OpenROAD commit ORFS pins. + + The nightly bot updates the ``tools/OpenROAD`` working tree first and only + then commits, so when the submodule is checked out its ``HEAD`` is what the + resulting commit will pin -- and that is the SHA the docs must match. When + the submodule is not initialised (a plain ``git clone`` without + ``--recursive``) fall back to the committed gitlink. + """ + submodule_dir = REPO_ROOT / SUBMODULE_PATH + if (submodule_dir / ".git").exists(): + sha = _git("rev-parse", "HEAD", cwd=submodule_dir) + how = "%s working tree (git -C %s rev-parse HEAD)" % ( + SUBMODULE_PATH, + SUBMODULE_PATH, + ) + else: + sha = _git("rev-parse", "HEAD:%s" % SUBMODULE_PATH) + how = "committed submodule pointer (git rev-parse HEAD:%s)" % SUBMODULE_PATH + + if not _SHA_RE.match(sha): + raise RuntimeError( + "resolved OpenROAD SHA %r from the %s is not a 40-character " + "commit id" % (sha, how) + ) + return sha, how + + +def download(url: str) -> str: + """Fetch ``url`` as text, failing loudly on any non-200 response. + + The old ``conf.py`` helper wrote ``r.content`` unconditionally, so a 404 or + an outage silently produced a doc page containing GitHub's error body. + """ + request = urllib.request.Request( + url, headers={"User-Agent": "orfs-refresh-openroad-docs"} + ) + try: + with urllib.request.urlopen(request, timeout=60) as response: + status = response.status + body = response.read() + except urllib.error.HTTPError as exc: + raise RuntimeError( + "GET %s failed with HTTP %s %s" % (url, exc.code, exc.reason) + ) from exc + except urllib.error.URLError as exc: + raise RuntimeError("GET %s failed: %s" % (url, exc.reason)) from exc + + if status != 200: + raise RuntimeError("GET %s returned HTTP %s, expected 200" % (url, status)) + if not body.strip(): + raise RuntimeError("GET %s returned an empty body" % url) + return body.decode("utf-8") + + +def _to_github_url(target: str, src_dir: str, sha: str) -> str | None: + """Map a repo-relative markdown target to an absolute GitHub URL. + + Returns ``None`` when the target should be left alone (already absolute, or + a pure in-page anchor). + """ + if target.startswith(_ABSOLUTE_PREFIXES) or target.startswith("#"): + return None + + path, sep, fragment = target.partition("#") + if not path: + return None + + if path.startswith("/"): + # Repo-root-relative, e.g. /docs/images/grafana.png + repo_path = path.lstrip("/") + else: + repo_path = posixpath.normpath(posixpath.join(src_dir, path)) + + if repo_path.startswith(".."): + raise RuntimeError( + "link target %r in %s/ escapes the OpenROAD repository root" + % (target, src_dir) + ) + + if repo_path.lower().endswith(_IMAGE_SUFFIXES): + # Images must point at the raw blob so they actually render. + return "https://raw.githubusercontent.com/%s/%s/%s" % (REPO, sha, repo_path) + return "https://github.com/%s/blob/%s/%s%s%s" % ( + REPO, + sha, + repo_path, + sep, + fragment, + ) + + +def rewrite_links(text: str, upstream_path: str, sha: str) -> str: + """Rewrite repo-relative links in a vendored file to absolute GitHub URLs.""" + src_dir = posixpath.dirname(upstream_path) + + def replace(match: re.Match) -> str: + bang, label, target = match.group(1), match.group(2), match.group(3) + url = _to_github_url(target, src_dir, sha) + if url is None: + return match.group(0) + return "%s[%s](%s)" % (bang, label, url) + + return _LINK_RE.sub(replace, text) + + +def extract_section(text: str, upstream_path: str, start: str, end: str) -> str: + """Return the ``start`` heading plus everything up to (not including) ``end``. + + This is the extraction ``docs/conf.py`` used to perform on the whole + downloaded file. Doing it here means an upstream heading rename fails + *now*, naming both headings, instead of vendoring a page the documentation + build cannot splice. + """ + match = re.search( + "%s(.*?)%s" % (re.escape(start), re.escape(end)), text, re.DOTALL + ) + if match is None: + raise RuntimeError( + "cannot find a section starting at '%s' and ending at '%s' in " + "%s:%s.\n" + " OpenROAD most likely renamed or reordered one of those " + "headings. Look at the upstream file, then update the section " + "bounds in this script, the anchor in docs/conf.py, and the " + "anchor in docs/scripts/check_vendored_docs.py to match." + % (start, end, REPO, upstream_path) + ) + body = match.group(1) + if not body.strip(): + raise RuntimeError( + "the section '%s' in %s:%s is empty. Vendoring it would silently " + "publish a supported-OS heading with nothing under it." + % (start, REPO, upstream_path) + ) + return start + body + + +def _write_if_changed(path: Path, content: str) -> bool: + """Write ``content`` to ``path``; return True if the file changed on disk.""" + if path.exists() and path.read_text(encoding="utf-8") == content: + return False + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(content, encoding="utf-8") + return True + + +def main(argv: list[str] | None = None) -> int: + parser = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + parser.add_argument( + "--sha", + help="OpenROAD commit to vendor from (default: the pinned " + "tools/OpenROAD submodule commit)", + ) + args = parser.parse_args(argv) + + if args.sha: + sha, how = args.sha, "--sha command-line override" + if not _SHA_RE.match(sha): + parser.error("--sha must be a full 40-character commit id") + else: + sha, how = resolve_pinned_sha() + + print("OpenROAD repo: %s" % REPO) + print("OpenROAD sha: %s" % sha) + print("resolved from: %s" % how) + + changed = [] + files = {} + for entry in VENDORED_FILES: + url = "https://raw.githubusercontent.com/%s/%s/%s" % (REPO, sha, entry.upstream) + text = download(url) + record = {"vendored": entry.name} + if entry.section is not None: + start, end = entry.section + text = extract_section(text, entry.upstream, start, end) + record["section"] = {"start": start, "end": end} + if entry.rewrite_links: + text = rewrite_links(text, entry.upstream, sha) + record["links_rewritten"] = True + files[entry.upstream] = record + if _write_if_changed(VENDOR_DIR / entry.name, text): + changed.append("docs/_vendor/openroad/%s" % entry.name) + print( + " %-24s <- %s%s" + % ( + entry.name, + entry.upstream, + " ['%s' section only]" % entry.section[0] if entry.section else "", + ) + ) + + source = { + "_comment": ( + "Generated by docs/scripts/refresh_openroad_docs.py -- do not edit " + "by hand. Run that script to re-vendor after bumping the " + "tools/OpenROAD submodule." + ), + "repo": REPO, + "sha": sha, + "files": files, + } + if _write_if_changed(SOURCE_JSON, json.dumps(source, indent=2) + "\n"): + changed.append("docs/_vendor/openroad/SOURCE.json") + + if changed: + print("updated:") + for name in changed: + print(" %s" % name) + else: + print("already up to date; nothing written.") + return 0 + + +if __name__ == "__main__": + try: + sys.exit(main()) + except RuntimeError as error: + print("error: %s" % error, file=sys.stderr) + sys.exit(1) From 62bb5b065f4bdeaaafcde994d0eea3a9c4f268e2 Mon Sep 17 00:00:00 2001 From: Vitor Bandeira Date: Mon, 10 Aug 2026 15:24:53 -0300 Subject: [PATCH 2/4] build(docs): bump RTD Python to 3.12, switch lock tool to uv Read the Docs default runtime moved past 3.10; pydata-sphinx-theme's pinned Sphinx no longer builds under 3.13+, so pin RTD to 3.12 explicitly instead of trusting the default. pip-compile has a compatibility bug with recent pip, so lock regeneration now uses `uv pip compile`. Unpin sphinx-external-toc in requirements.in so uv can resolve a compatible version, and regenerate requirements_lock.txt accordingly. Add `make venv` (docs/Makefile) to encapsulate venv creation + locked-deps install, since the interpreter and lock tool are no longer implied by a bare `pip install`. Exclude `build`, `.venv*`, and `venv` in conf.py so a local virtualenv or prior build output isn't picked up as source on a second run. Add `.venv/` to .gitignore. Update docs/README.md to match the new venv/lock workflow. Signed-off-by: Vitor Bandeira --- .gitignore | 1 + .readthedocs.yaml | 2 +- docs/Makefile | 10 +- docs/README.md | 27 +- docs/conf.py | 6 + docs/requirements.in | 2 +- docs/requirements_lock.txt | 558 +++++++++++++++++++------------------ 7 files changed, 318 insertions(+), 288 deletions(-) diff --git a/.gitignore b/.gitignore index a15da1770e..8d5142778c 100644 --- a/.gitignore +++ b/.gitignore @@ -110,4 +110,5 @@ MODULE.bazel.lock # python venv venv/ +.venv/ tmp/ diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 9c99c03866..5edb8e8edb 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -8,7 +8,7 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.10" + python: "3.12" # Build documentation in the "docs/" directory with Sphinx sphinx: diff --git a/docs/Makefile b/docs/Makefile index 486af0ac24..558768fa14 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -7,12 +7,20 @@ SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build SOURCEDIR = BUILDDIR = build +# Read the Docs builds with 3.12 (see .readthedocs.yaml); override if you want +# a specific interpreter locally. +PYTHON ?= python3 # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -.PHONY: help Makefile +# Create a local virtualenv and install the hash-pinned doc-build dependencies. +venv: + $(PYTHON) -m venv .venv + .venv/bin/pip install -r requirements_lock.txt + +.PHONY: help Makefile venv # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). diff --git a/docs/README.md b/docs/README.md index 81cddb3edd..08c99af809 100644 --- a/docs/README.md +++ b/docs/README.md @@ -11,28 +11,33 @@ repository and is published at ### Requires -- Python 3.10 — the version Read the Docs builds with (see `.readthedocs.yaml`). - The pinned Sphinx release does not run on Python 3.13 or newer. +- Python 3.10+ (tested through 3.14) — Read the Docs builds with 3.12 (see + `.readthedocs.yaml`); any recent `python3` on PATH works locally. - `pip` - `virtualenv` (or the standard-library `venv`) ### Install prerequisites -Run from the repository root: +Run from `docs/`: ``` shell -virtualenv .venv +make venv source .venv/bin/activate -pip install -r docs/requirements_lock.txt ``` +`make venv` just runs `python3 -m venv .venv && .venv/bin/pip install -r +requirements_lock.txt`; pass `PYTHON=/path/to/python3` to use a specific +interpreter instead of whatever `python3` resolves to on your PATH. + `docs/requirements_lock.txt` is the hash-pinned lock file that Read the Docs installs, so a local build matches the published one. The direct dependencies are listed in `docs/requirements.in`; after editing that file, regenerate the -lock with: +lock with [`uv`](https://docs.astral.sh/uv/) (`pip-compile` from `pip-tools` +is a documented alternative, but at time of writing has a compatibility bug +with recent `pip` releases): ``` shell -pip-compile --generate-hashes --output-file=docs/requirements_lock.txt docs/requirements.in +uv pip compile --upgrade --generate-hashes --output-file=docs/requirements_lock.txt docs/requirements.in ``` ### Build @@ -62,7 +67,7 @@ It exits non-zero when any link is unreachable. `SupportedOS.md`, `Manpage.md`, `mainREADME.md`, and — because it is fetched rather than authored here — the tracked file `contrib/GitGuide.md`. Do not commit those changes; `git checkout docs/contrib/GitGuide.md` after a build. -- Always `rm -rf docs/build` before rebuilding. The output directory is - `build/`, but `conf.py`'s `exclude_patterns` only excludes `_build`, so a - second run picks up the Markdown files written under `build/html/` as if they - were source pages. +- `conf.py`'s `exclude_patterns` excludes `build` (the actual output directory + — Sphinx's own default is `_build`) and any local `.venv`/`venv`, so re-running + a build, or building from a checkout with a local virtualenv already in + `docs/`, does not pick that up as source content. diff --git a/docs/conf.py b/docs/conf.py index 6b580ce3b0..2a096d58c1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -70,6 +70,12 @@ # This pattern also affects html_static_path and html_extra_path. exclude_patterns = [ "_build", + # The Makefile's actual BUILDDIR ("build", not the Sphinx-default "_build") + # and any local virtualenv -- without these, a second build treats its own + # previous output and installed packages' bundled images as source pages. + "build", + ".venv*", + "venv", # Verbatim copies of OpenROAD files; conf.py splices them into ORFS pages # rather than publishing them directly. See docs/_vendor/openroad/README.md. "_vendor", diff --git a/docs/requirements.in b/docs/requirements.in index df2e6dac48..818927c7ed 100644 --- a/docs/requirements.in +++ b/docs/requirements.in @@ -1,4 +1,4 @@ -sphinx-external-toc==0.3.1 +sphinx-external-toc sphinx sphinx-autobuild myst-parser diff --git a/docs/requirements_lock.txt b/docs/requirements_lock.txt index 4da13611a7..81090ca482 100644 --- a/docs/requirements_lock.txt +++ b/docs/requirements_lock.txt @@ -1,20 +1,16 @@ -# -# This file is autogenerated by pip-compile with Python 3.10 -# by the following command: -# -# pip-compile --generate-hashes --output-file=docs/requirements_lock.txt docs/requirements.in -# +# This file was autogenerated by uv via the following command: +# uv pip compile --generate-hashes --python-version 3.12 --output-file=docs/requirements_lock.txt docs/requirements.in accessible-pygments==0.0.5 \ --hash=sha256:40918d3e6a2b619ad424cb91e556bd3bd8865443d9f22f1dcdf79e33c8046872 \ --hash=sha256:88ae3211e68a1d0b011504b2ffc1691feafce124b845bd072ab6f9f66f34d4b7 # via pydata-sphinx-theme -alabaster==0.7.16 \ - --hash=sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65 \ - --hash=sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92 +alabaster==1.0.0 \ + --hash=sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e \ + --hash=sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b # via sphinx -anyio==4.13.0 \ - --hash=sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 \ - --hash=sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc +anyio==4.14.2 \ + --hash=sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494 \ + --hash=sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f # via # starlette # watchfiles @@ -24,148 +20,112 @@ babel==2.18.0 \ # via # pydata-sphinx-theme # sphinx -beautifulsoup4==4.14.3 \ - --hash=sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb \ - --hash=sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86 +beautifulsoup4==4.15.0 \ + --hash=sha256:288e3ca7d54b06f2ac191970bc275c1939cb46d450b255bf6718b04aa37ab4f7 \ + --hash=sha256:d6f88de62e1d4e38ecb1077eb9724cd0eff29d2a08ca16a401e9b9e93f117cf9 # via pydata-sphinx-theme -certifi==2026.5.20 \ - --hash=sha256:3c52e209ba0a4ad7aebe60436a4ab349c39e1e602e8c134221e546902ad25897 \ - --hash=sha256:69dea482ab64caa7b9f6aba1c6bf48bb6a5448d1c0f1b17ab42ad8c763a5344d +certifi==2026.7.22 \ + --hash=sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775 \ + --hash=sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55 # via requests -charset-normalizer==3.4.7 \ - --hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \ - --hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \ - --hash=sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67 \ - --hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \ - --hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \ - --hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \ - --hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \ - --hash=sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444 \ - --hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \ - --hash=sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9 \ - --hash=sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01 \ - --hash=sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217 \ - --hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \ - --hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \ - --hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \ - --hash=sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83 \ - --hash=sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5 \ - --hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \ - --hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \ - --hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \ - --hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \ - --hash=sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42 \ - --hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \ - --hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \ - --hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \ - --hash=sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207 \ - --hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \ - --hash=sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734 \ - --hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \ - --hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \ - --hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \ - --hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \ - --hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \ - --hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \ - --hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \ - --hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \ - --hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \ - --hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \ - --hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \ - --hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \ - --hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \ - --hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \ - --hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \ - --hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \ - --hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \ - --hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \ - --hash=sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776 \ - --hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \ - --hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \ - --hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \ - --hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \ - --hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \ - --hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \ - --hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \ - --hash=sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5 \ - --hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \ - --hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \ - --hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \ - --hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \ - --hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \ - --hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \ - --hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \ - --hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \ - --hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \ - --hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \ - --hash=sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4 \ - --hash=sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545 \ - --hash=sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706 \ - --hash=sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366 \ - --hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \ - --hash=sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a \ - --hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \ - --hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \ - --hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \ - --hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \ - --hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \ - --hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \ - --hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \ - --hash=sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319 \ - --hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \ - --hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \ - --hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \ - --hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \ - --hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \ - --hash=sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0 \ - --hash=sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686 \ - --hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \ - --hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \ - --hash=sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c \ - --hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \ - --hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \ - --hash=sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60 \ - --hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \ - --hash=sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274 \ - --hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \ - --hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \ - --hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \ - --hash=sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f \ - --hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \ - --hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \ - --hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \ - --hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \ - --hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \ - --hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \ - --hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \ - --hash=sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00 \ - --hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \ - --hash=sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3 \ - --hash=sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7 \ - --hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \ - --hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \ - --hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \ - --hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \ - --hash=sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259 \ - --hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \ - --hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \ - --hash=sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30 \ - --hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \ - --hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \ - --hash=sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24 \ - --hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \ - --hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \ - --hash=sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc \ - --hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \ - --hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \ - --hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \ - --hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \ - --hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \ - --hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464 +charset-normalizer==3.4.9 \ + --hash=sha256:0327fcd59a935777d83410750c50600ee9571af2846f71ce40f25b13da1ef380 \ + --hash=sha256:03d07803992c6c7bbc976327f34b18b6160327fc81cb82c9d504720ac0be3b62 \ + --hash=sha256:04ce310cb89c15df659582aee80a0603788732a5e017d5bd5c81158106ce249c \ + --hash=sha256:0d861473f743244d349b50f850d10eb87aeb22bbdcc8e64f79273c94af5a8226 \ + --hash=sha256:0e94703ec9684807f20cfb5eed95c70f67f2a8f21ad620146d7b5a13677b93e5 \ + --hash=sha256:0fa1aec2d32bcc03c8fa0f6f1712caad1adc38509f31142112e5c9daf5b9c833 \ + --hash=sha256:16b65ea0f2465b6fb52aa22de5eca612aa964ddfec00a912e26f4656cbef890b \ + --hash=sha256:16d10d789dd9bcca1173c95af82c58433122564b7bc39385124be735a35cbe99 \ + --hash=sha256:19ac87f93086ce37b86e098888555c4b4bc48102279bae3350098c0ed664b501 \ + --hash=sha256:1d22856ffbe153a602df38e4a5464f0b748a54002e0d69ac6d2ad0a197cc99ec \ + --hash=sha256:21e764fd1e70b6a3e205a0e46f3051701f98a8cb3fad66eeb80e48bb502f8698 \ + --hash=sha256:231ddcbb35e2ff8973e1365db41fe0572662893b99a05deb183b68ad4c0c8bd4 \ + --hash=sha256:253a4a220747e8b5faf57ec320c4f5efb0cef05f647420bf267143ec15dba10a \ + --hash=sha256:280081916dc341820640489a66e4696049401ef1cf6dd672f672e70ad915aca3 \ + --hash=sha256:2a441ea71902098ffe78c5abe6c494f44160b4af614ed16c3d9a3b1d17fd8ee2 \ + --hash=sha256:304b13570067b2547562e308af560b3963857b1fa90bd6afd978130130fe2d6a \ + --hash=sha256:32286a2c8d167e897177b673176c1e3e00d4057caf5d2b64eef9a3666b03018e \ + --hash=sha256:33bdcc2a32c0a0e861f60841a512c8acc658c87c2ac59d89e3a46dacf7d866e4 \ + --hash=sha256:375b83ed0aecfce76c16d198fbc21f3b11b337d68662bea0a995046682a11419 \ + --hash=sha256:3c09a49d6cde137258beb3d551994a2927fd35ad5cf96aed573f61bbd67c5f84 \ + --hash=sha256:3d92613ec25e43b05f042302531ec0f00b8445190e43325880cbd6ab7c2581da \ + --hash=sha256:40a126142a56b2dfc0aacbad1de8310cbf60da7656db0e6b16eebd48e3e93519 \ + --hash=sha256:416c229f77e5ea25b3dfd4b582f8d73d7e43c22320302b9ab128a2d3a0b38efe \ + --hash=sha256:432786d3561e69aeeae6c7e8648964ce0ad05736120135601f87ac26b9c83381 \ + --hash=sha256:43b9e366a31fdd1c87d0eb08f579b4a82b723ea54338f040d6b4e518a026ea29 \ + --hash=sha256:440eede837960000d74978f0eba527be106b5b9aee0daf779d395276ed0b0614 \ + --hash=sha256:45b0cc4e3556cd875e09102988d1ab8356c998b596c9fced84547c8138b487a0 \ + --hash=sha256:476743fe6dfe14a2da12e3ac79125dc84a3b2cf8094369a47a1529b0cd8549fe \ + --hash=sha256:4773092f8019072343a7447203308b176e10199920eb02d6195e81bbb3274c29 \ + --hash=sha256:4b3dac63058cc36820b0dd072f89898604e2d39686fe05321729d00d8ac185a0 \ + --hash=sha256:4d1c96a7a18b9690a4d46df09e3e3382406ae3213727cd1019ebade1c4a81917 \ + --hash=sha256:51307f5c71007673a2bf8232ad973483d281e74cb99c8c5a990af1eefa6277d9 \ + --hash=sha256:51447e9aa2684679af07ca5021c3db526e0284347ebf4ffcec1154c3350cfe32 \ + --hash=sha256:58150c9f9b9a552505912d182ccdf26f6396fb6094816ceebcbb20eecabaed94 \ + --hash=sha256:5b10cd92fc5c498b35a8635df6d5a100207f88b63a4dc1de7ef9a548e1e2cd63 \ + --hash=sha256:5e226f6218febc71f6c1fc2fafb91c226f75bdc1d8fb12d66823716e891608fd \ + --hash=sha256:609b3ba8fcc0fb5ab7af00719d0fb6ad0cb518e48e7712d12fd68f1327951198 \ + --hash=sha256:60f44ade2cf573dad7a277e6f8ca9a51a21dda572b13bd7d8539bb3cd5dbedde \ + --hash=sha256:611057cc5d5c0afc743ba8be6bd828c17e0aaa8643f9d0a9b9bb7dea80eb8012 \ + --hash=sha256:6366a16e1a25018694d6a5d784d09b046edc9eac40ea2b54065c3052672516a1 \ + --hash=sha256:65a7ff3f705e57d392f7261b6d0550fe137c3019477431f1c355e0db0a7d3e15 \ + --hash=sha256:673611bbd43f0810bec0b0f028ddeaaa501190339cac411f347ac76917c3ae7b \ + --hash=sha256:67830fc78e67501f47bb950471b2dcb9b35b140084429318e862895a8e89c993 \ + --hash=sha256:68ce9f4d6b26d5ccbf7fd4459bf75f74a0a146677ebba80597df60cbdb20e6f4 \ + --hash=sha256:68e5f26a1ad57ded6d1cfb85331d1c1a195314756471d97758c48498bb4dcdf5 \ + --hash=sha256:69b157c5d3292bcd443faca052f3096f637f1e074b98212a933c074ae23dc3b8 \ + --hash=sha256:75286256590a6320cf106a0d28970d3560aad9ee09aa7b34fb40524792436d35 \ + --hash=sha256:78841cccf1af7b40f6f716338d50c0902dbe88d9f800b3c973b7a9a0a693a642 \ + --hash=sha256:78fa18e436a1a0e58dbd7e02fc4473f3f32cceb12df9dfca542d075961c307d2 \ + --hash=sha256:79580094b00d1789d1f93ea55bc43cb2f611910c72235b7657f3482ddcc1b22d \ + --hash=sha256:7b86a2b16095d250c6f58b3d9b2eee6f4147754344f3dab0922f7c9bf7d226c9 \ + --hash=sha256:83aed2c10721ddd90f68140685391b50811a880af20654c59af6b6c66c40513c \ + --hash=sha256:84fd18bcc17526fc2b3c1af7d2b9217d32c9c04448c16ec693b9b4f1985c3d33 \ + --hash=sha256:871ff67ea1aad4dfd91736464934d56b32dac49f9fbe16cddba36198a7b3a0db \ + --hash=sha256:898f0e9068ca27d37f8e83a5b962821df851532e6c4a7d615c1c033f9da6eedf \ + --hash=sha256:8a79d9f4d8001473a30c163556b3c3bfebec837495a412dde78b51672f6134f9 \ + --hash=sha256:8c041122946b7ba21bb32c45b1aa57b1be35527690aeb3c5c234521085632eee \ + --hash=sha256:90c44bc373b7687f6948b693cceaea1348ae0975d7474746559494468e3c1d84 \ + --hash=sha256:9104ed0bd76a429d46f9ec0dbc9b08ad1d2dcdf2b00a5a0daa1c145329b35b44 \ + --hash=sha256:920079c3f7456fa213e0829ed2073aaa727fd39d889ead5b4f35d0de5460d04f \ + --hash=sha256:93d59d504b230e83c7a843251681959a0b6a9cd76f6e146ce1b8a80eb8739af9 \ + --hash=sha256:9b2aff1c7b3884512b9512c3eaadd9bab39fb45042ffaaa1dd08ff2b9f8109d9 \ + --hash=sha256:9b8e0f3107e2200b76f6054de99016eac3ee6762713587b36baaa7e4bd2ae177 \ + --hash=sha256:9bb41182d93ea91f60b4bc8fbf4c820c69ef8a12ab2d917f3f1834f1acad07e8 \ + --hash=sha256:9cdef90ae47919cae358d8ab15797a800ed41da7aba5d72419fb510729e2ed4b \ + --hash=sha256:a1786910334ed46ab1dd73222f2cd1e05c2c3bb39f6dddb4f8b36fc382058a39 \ + --hash=sha256:a4cfde78a9f2880208d16a93b795726a3017d5977e08d1e162a7a31322479c41 \ + --hash=sha256:a4fbdde9dd4a9ce5fd52c2b3a347bb50cc89483ef783f1cb00d408c13f7a96c0 \ + --hash=sha256:aa99adc8f081b475a12843953db36831eaf83ec33eb46a90629ca6a5de45a616 \ + --hash=sha256:ac351b3b8014eead140e77e9717e2992c6bbe30b63bc3422422eb84865412e3d \ + --hash=sha256:ad41ba96094304aa090f5a30cb6e4fb3b3f1c264c523394b4c39bbacc4dc92ba \ + --hash=sha256:b5314963fce9b0b12743891de876e724997864ee22aa496f903f426c7e2fa5b2 \ + --hash=sha256:bcf74c1df76758a395bf0af608c04c82257523f55c9868b334f06270d0f2112b \ + --hash=sha256:bd47ba7fc3ca94896759ea0109775132d3e7ab921fbf54038e1bab2e46c313c9 \ + --hash=sha256:c0323c9daef75ef2e5083624b4585018a0c9d5e3b40f607eed81a311270b934b \ + --hash=sha256:c1225416b463483160e4af85d5fc3a9690ccb53fd4b1865a6437825f5ede3209 \ + --hash=sha256:c1c948747b03be832dceed96ca815cef7360de9aa19d37c730f8e3f6101aca48 \ + --hash=sha256:c25fe15c70c59eb7c5ce8c06a1f3fa1da0ecc5ea1e7a5922c40fd2fa9b0d5046 \ + --hash=sha256:cc1b0fff8ead343dae06305f954eb8468ba0ec1a97881f42489d198e4ce3c632 \ + --hash=sha256:cd6280cf040f233bd7d3407b743b4b4c74f70e8e1c4199cb112a62c941c0772a \ + --hash=sha256:cd6c3d4b783c556fa00bf540854e42f135e2f256abd29669fcd0da0f2dec79c2 \ + --hash=sha256:d4d6fcde76f94f5cb9e43e9e9a61f16dacefd228cbbf6f1a09bd9b219a92f1a1 \ + --hash=sha256:ddf4af30b417d9fe16481e9b81c27ab2a7cde1ff7ba3e85653b02db7d145dc7b \ + --hash=sha256:df115d4d83168fdf2cae48ef1ff6d1cb4c466364e30861b37121de0f3bf1b990 \ + --hash=sha256:df7276909358e5635ae203673ab7e509ddd224225a8d6b0790bf13eb2bde1cc5 \ + --hash=sha256:e4fd89cc178bced6ad29cb3e6dd4aa63fa5017c3524dbd0b25998fb64a87cc8b \ + --hash=sha256:e9701d0049d92c16703a42771b98d560b95248949f23f8cf7b4eddd201814fb9 \ + --hash=sha256:ee2f2a527e3c1a6e6411eb4209642e138b544a2d72fe5d0d76daf77b24063534 \ + --hash=sha256:f7fb7d750cfa0a070d2c24e831fd3481019a60dd317ea2b39acbcebc08b6ed81 \ + --hash=sha256:f840ed6d8ecba8255df8c42b87fadeda98ddfc6eeec05e2dc66e26d46dd6f58a \ + --hash=sha256:f86c6358749bd4fda175388691e3ba8c46e24c5347d0afd20f9b7edfc9faf07d \ + --hash=sha256:fa36ec09ef71d158186bc79e359ff5fdd6e7996fe8ab638f00d6b93139ba4fcf \ + --hash=sha256:fe2c7201c642b7c308f1675355ad7ff7b66acfe3541625efe5a3ad38f29d6115 # via requests -click==8.4.1 \ - --hash=sha256:482be17c6991b8c19c5429a1e995d9b0efdbb63172824c41f99965dc0ade8ec2 \ - --hash=sha256:918b5633eddf6b41c32d4f454bf0de810065c74e3f7dbf8ee5452f8be88d3e96 +click==8.4.2 \ + --hash=sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6 \ + --hash=sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76 # via # sphinx-external-toc # uvicorn @@ -173,25 +133,21 @@ colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 # via sphinx-autobuild -docutils==0.19 \ - --hash=sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6 \ - --hash=sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc +docutils==0.22.4 \ + --hash=sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968 \ + --hash=sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de # via # myst-parser # pydata-sphinx-theme # sphinx # sphinx-markdown-builder -exceptiongroup==1.3.1 \ - --hash=sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219 \ - --hash=sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598 - # via anyio h11==0.16.0 \ --hash=sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1 \ --hash=sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86 # via uvicorn -idna==3.17 \ - --hash=sha256:466e48829084efe2548012b855df21540b96f2e20e51bd124c851536556a592c \ - --hash=sha256:5eb0cb53bc467c12eadcf6de83163ad8527cec9416f44b9b61b19caedad2b87f +idna==3.18 \ + --hash=sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2 \ + --hash=sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848 # via # anyio # requests @@ -204,11 +160,12 @@ jinja2==3.1.6 \ --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 # via # myst-parser + # pydata-sphinx-theme # sphinx # sphinxcontrib-mermaid -markdown-it-py==2.2.0 \ - --hash=sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30 \ - --hash=sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1 +markdown-it-py==4.2.0 \ + --hash=sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49 \ + --hash=sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a # via # mdit-py-plugins # myst-parser @@ -303,27 +260,25 @@ markupsafe==3.0.3 \ --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 # via jinja2 -mdit-py-plugins==0.3.5 \ - --hash=sha256:ca9a0714ea59a24b2b044a1831f48d817dd0c817e84339f20e7889f392d77c4e \ - --hash=sha256:eee0adc7195e5827e17e02d2a258a2ba159944a0748f59c5099a4a27f78fcf6a +mdit-py-plugins==0.6.1 \ + --hash=sha256:214c82fb2ac524472ab6a5bcab1de80f73b50443e187f401bfd77efbc7c6481d \ + --hash=sha256:a2bca0f039f39dbd35fb74ae1b5f998608c437463371f0ff7f49a19a17a114d0 # via myst-parser mdurl==0.1.2 \ --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba # via markdown-it-py -myst-parser==1.0.0 \ - --hash=sha256:502845659313099542bd38a2ae62f01360e7dd4b1310f025dd014dfc0439cdae \ - --hash=sha256:69fb40a586c6fa68995e6521ac0a525793935db7e724ca9bac1d33be51be9a4c +myst-parser==5.1.0 \ + --hash=sha256:9c91c52b3cdb4d94a6506e4fab4e2f296c7623a0da0dcbe6de1565c3dad67a8a \ + --hash=sha256:ab69322dc6719dcc7f296479dbb70181b66df6ed315064f92dbc85c0e1bf2f02 # via -r docs/requirements.in -packaging==26.2 \ - --hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \ - --hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661 - # via - # pydata-sphinx-theme - # sphinx -pydata-sphinx-theme==0.15.4 \ - --hash=sha256:2136ad0e9500d0949f96167e63f3e298620040aea8f9c74621959eda5d4cf8e6 \ - --hash=sha256:7762ec0ac59df3acecf49fd2f889e1b4565dbce8b88b2e29ee06fdd90645a06d +packaging==26.3 \ + --hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \ + --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c + # via sphinx +pydata-sphinx-theme==0.20.0 \ + --hash=sha256:0da172d41e19a66de875f4002f7054b385372ec65763852193791e658d50bb4a \ + --hash=sha256:56744483c9d72c783e075de716ab95d486108b69605df7528078090b73f11f69 # via sphinx-book-theme pygments==2.20.0 \ --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ @@ -413,18 +368,24 @@ pyyaml==6.0.3 \ requests==2.34.2 \ --hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \ --hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed + # via + # pydata-sphinx-theme + # sphinx +roman-numerals==4.1.0 \ + --hash=sha256:1af8b147eb1405d5839e78aeb93131690495fe9da5c91856cb33ad55a7f1e5b2 \ + --hash=sha256:647ba99caddc2cc1e55a51e4360689115551bf4476d90e8162cf8c345fe233c7 # via sphinx -snowballstemmer==3.1.0 \ - --hash=sha256:17e6d1da216aa07db6dad37139ea70cf13c4b2e9a096f6e64a9648fc657d3154 \ - --hash=sha256:fd9e34526b23340cd23ffea6c9f9760974ecc2c2ac9e1d81401443ccdb2a801f +snowballstemmer==3.1.1 \ + --hash=sha256:7e207fa178741da09cdee59d3ecec3827ad5f92b1fc5c9ff3755b639f71f5752 \ + --hash=sha256:e07bbc54a0d798fe6010a12398422e62a8bfbba95c394fd0956ef58cb4d3e260 # via sphinx -soupsieve==2.8.4 \ - --hash=sha256:e121fd02e975c695e4e9e8774a5ee35d74714b59307868dcc5319ad2d9e3328e \ - --hash=sha256:e7e6b0769c8f51ed59acab6e994b00621096cfb1c640a7509295987388fbaf65 +soupsieve==2.9.2 \ + --hash=sha256:4a55d8cf158a9c2e587fa4922f1bbb91d68ac829e2d6f25403a85747c71daf74 \ + --hash=sha256:8089a26fd974ca7a1f30276d3d8492ab266ab15af581642dfe8aa162e0c1c823 # via beautifulsoup4 -sphinx==5.3.0 \ - --hash=sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d \ - --hash=sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5 +sphinx==9.1.0 \ + --hash=sha256:7741722357dd75f8190766926071fed3bdc211c74dd2d7d4df5404da95930ddb \ + --hash=sha256:c84fdd4e782504495fe4f2c0b3413d6c2bf388589bb352d439b2a3bb99991978 # via # -r docs/requirements.in # myst-parser @@ -435,22 +396,23 @@ sphinx==5.3.0 \ # sphinx-external-toc # sphinx-llm # sphinx-markdown-builder + # sphinx-multitoc-numbering # sphinxcontrib-mermaid -sphinx-autobuild==2024.10.3 \ - --hash=sha256:158e16c36f9d633e613c9aaf81c19b0fc458ca78b112533b20dafcda430d60fa \ - --hash=sha256:248150f8f333e825107b6d4b86113ab28fa51750e5f9ae63b59dc339be951fb1 +sphinx-autobuild==2025.8.25 \ + --hash=sha256:9cf5aab32853c8c31af572e4fecdc09c997e2b8be5a07daf2a389e270e85b213 \ + --hash=sha256:b750ac7d5a18603e4665294323fd20f6dcc0a984117026d1986704fa68f0379a # via -r docs/requirements.in -sphinx-book-theme==1.1.3 \ - --hash=sha256:1f25483b1846cb3d353a6bc61b3b45b031f4acf845665d7da90e01ae0aef5b4d \ - --hash=sha256:a554a9a7ac3881979a87a2b10f633aa2a5706e72218a10f71be38b3c9e831ae9 +sphinx-book-theme==1.4.0 \ + --hash=sha256:10fd57d667ee0b565928c3ce95562e281c5d1b94bd5a2aafc5cd41a5d498dcd0 \ + --hash=sha256:fee3cd70573d9a8cd4ab380a3cb1f11139c24dcaa2cf47d06d7f924f1b44eaff # via -r docs/requirements.in sphinx-copybutton==0.5.2 \ --hash=sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd \ --hash=sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e # via -r docs/requirements.in -sphinx-external-toc==0.3.1 \ - --hash=sha256:9c8ea9980ea0e57bf3ce98f6a400f9b69eb1df808f7dd796c9c8cc1873d8b355 \ - --hash=sha256:cd93c1e7599327b2a728db12d9819068ce719c4b037ffc62e47f20ffb6310fb3 +sphinx-external-toc==1.1.0 \ + --hash=sha256:26c390b8d85aa641366fed2d3674910ec6820f48b91027affef485a2655ad7d0 \ + --hash=sha256:f81833865006f6b4a9b2550a2474a6e3d7e7f2cb23ba23309260577ea65552f6 # via -r docs/requirements.in sphinx-llm==0.4.1 \ --hash=sha256:0789185dcbbecc00b5e25aa3db6342b98dad6a9def96088a9e50fa0203fda090 \ @@ -460,6 +422,10 @@ sphinx-markdown-builder==0.6.10 \ --hash=sha256:16d86738b9ac69fcbc86e373c31c6402c30af1fa8d98d0f62cc5f38bfe5fc26e \ --hash=sha256:cd5acf88d52ea0146a712fd557404f10326dff3428a78ba928e59b1727fd4a86 # via sphinx-llm +sphinx-multitoc-numbering==0.1.3 \ + --hash=sha256:33d2e707a9b2b8ad636b3d4302e658a008025106fe0474046c651144c26d8514 \ + --hash=sha256:c9607671ac511236fa5d61a7491c1031e700e8d498c9d2418e6c61d1251209ae + # via sphinx-external-toc sphinxcontrib-applehelp==2.0.0 \ --hash=sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1 \ --hash=sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5 @@ -476,9 +442,9 @@ sphinxcontrib-jsmath==1.0.1 \ --hash=sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178 \ --hash=sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8 # via sphinx -sphinxcontrib-mermaid==2.0.2 \ - --hash=sha256:d862e514991279fb4816302c5cfe167d2557bf3ce7125ae0cb47dac80a0f46ce \ - --hash=sha256:f09576c78ca93fa0e3034fd9c45aaffa7c44ab449de9c43b8b8d262afe52bc66 +sphinxcontrib-mermaid==2.1.0 \ + --hash=sha256:13c5f9ac395cb6abf403eca34e228dc9fb3a30c9d960dbf3e40e9a8cef969549 \ + --hash=sha256:417cd144ec4b28852f46ba653f02ce8e538881c812111671a4c30344e87f2112 # via -r docs/requirements.in sphinxcontrib-qthelp==2.0.0 \ --hash=sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab \ @@ -488,31 +454,28 @@ sphinxcontrib-serializinghtml==2.0.0 \ --hash=sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331 \ --hash=sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d # via sphinx -starlette==1.2.0 \ - --hash=sha256:36e0c76ac59157e75dc4b3bdeafba97fb04eaf1878045f15dbef666a6f092ed7 \ - --hash=sha256:3c5a6b23fff42492914e93890bb80cbfea72dbf37de268eec06185d62a4ca553 +starlette==1.6.0 \ + --hash=sha256:a86dd39d14bb45f85a3d18525215a9ef0cfd1f192ac793220e72598c90335f0c \ + --hash=sha256:d4e3ac5e546444960c710297a3c9fc3f7ebae1b7e963f3d36173b49da535be9b # via sphinx-autobuild tabulate==0.10.0 \ --hash=sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d \ --hash=sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 # via sphinx-markdown-builder -typing-extensions==4.15.0 \ - --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \ - --hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548 +typing-extensions==4.16.0 \ + --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \ + --hash=sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5 # via # anyio # beautifulsoup4 - # exceptiongroup - # pydata-sphinx-theme # starlette - # uvicorn urllib3==2.7.0 \ --hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \ --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 # via requests -uvicorn==0.48.0 \ - --hash=sha256:48097851328b87ec36117d3d575234519eb58c2b22d79666e9bbc6c49a761dad \ - --hash=sha256:a5504207195d08c2511bf9125ede5ac4a4b71725d519e758d01dcf0bc2d31c37 +uvicorn==0.52.1 \ + --hash=sha256:112ec661814189acbccd3f7b86460147cc065fc92c0821afa78918780e4354dd \ + --hash=sha256:e4403f9d93188cf9d1088e9f40e3acd12630e2df8675316704379a7fc20fff6a # via sphinx-autobuild watchfiles==1.2.0 \ --hash=sha256:01859b11fd9fbca670f4d5da00fbac282cfea9bd67a2125d8b2833a3b5617ea9 \ @@ -623,66 +586,113 @@ watchfiles==1.2.0 \ --hash=sha256:faea288b6f0ab1902ef08f4ca6de005dccf856c4e0c4f21b8c5fce02d90a1b08 \ --hash=sha256:fff610d7bb2256a317bb1e96f0d7862c7aa8076733ee5df0fd41bbe76a24a4f4 # via sphinx-autobuild -websockets==16.0 \ - --hash=sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c \ - --hash=sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a \ - --hash=sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe \ - --hash=sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e \ - --hash=sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec \ - --hash=sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1 \ - --hash=sha256:1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64 \ - --hash=sha256:2b9f1e0d69bc60a4a87349d50c09a037a2607918746f07de04df9e43252c77a3 \ - --hash=sha256:31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8 \ - --hash=sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206 \ - --hash=sha256:335c23addf3d5e6a8633f9f8eda77efad001671e80b95c491dd0924587ece0b3 \ - --hash=sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156 \ - --hash=sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d \ - --hash=sha256:37b31c1623c6605e4c00d466c9d633f9b812ea430c11c8a278774a1fde1acfa9 \ - --hash=sha256:417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad \ - --hash=sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2 \ - --hash=sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03 \ - --hash=sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8 \ - --hash=sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230 \ - --hash=sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8 \ - --hash=sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea \ - --hash=sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641 \ - --hash=sha256:583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957 \ - --hash=sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6 \ - --hash=sha256:5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6 \ - --hash=sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5 \ - --hash=sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f \ - --hash=sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00 \ - --hash=sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e \ - --hash=sha256:7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b \ - --hash=sha256:7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72 \ - --hash=sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39 \ - --hash=sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9 \ - --hash=sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79 \ - --hash=sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0 \ - --hash=sha256:8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac \ - --hash=sha256:8e1dab317b6e77424356e11e99a432b7cb2f3ec8c5ab4dabbcee6add48f72b35 \ - --hash=sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0 \ - --hash=sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5 \ - --hash=sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c \ - --hash=sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8 \ - --hash=sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1 \ - --hash=sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244 \ - --hash=sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3 \ - --hash=sha256:a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767 \ - --hash=sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a \ - --hash=sha256:af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d \ - --hash=sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd \ - --hash=sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e \ - --hash=sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944 \ - --hash=sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82 \ - --hash=sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d \ - --hash=sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4 \ - --hash=sha256:d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5 \ - --hash=sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904 \ - --hash=sha256:df57afc692e517a85e65b72e165356ed1df12386ecb879ad5693be08fac65dde \ - --hash=sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f \ - --hash=sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c \ - --hash=sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89 \ - --hash=sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da \ - --hash=sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4 +websockets==17.0.1 \ + --hash=sha256:02ed63bf26dda9fa27df730a41f6664586c4ee05972c8fb667ce1725b3fd13d3 \ + --hash=sha256:02f0b037a737d0cb0c33866c97bcd1a0b73170dfbf42d69d8fb86f51002fd5ae \ + --hash=sha256:038cfad5d5417f8bb09295abe986029a26d22f34bda622ccc79b670efd4dab56 \ + --hash=sha256:07abc3bd196a48af476a82fd47f3f79a6a3f70937a9f930cef703cfa0c9d83b6 \ + --hash=sha256:07d78a509c3333f5908c83d7f78144ea68a6c9ec28110f5c54d81d8fcdc262c4 \ + --hash=sha256:0b52c76b8a870b141b7ca0705289452183ce7a523101954ccfe29a25986a673f \ + --hash=sha256:10b1587c599fa0f2c89154587c80e0fda98ade6c9fa8c0260a2823fb1800b685 \ + --hash=sha256:10f461191125c63902ea7394ae9e752b1b5785641850c1d365bb30b0f88bc53f \ + --hash=sha256:15920057a6b723f84734f0641403bca163a4b176e5af809ee4f0c4a1e75e9fed \ + --hash=sha256:17ac37716c0244e82c9e384c41653c090b1864c6610224ca3857e7f7b58fce10 \ + --hash=sha256:18ded646ce98cdd3c0235825b3252f1df55765ba49b616bb10282f758667b4d0 \ + --hash=sha256:1b363bfd72a52c0658a3154a4cff219f15a474b35a235057d38853bf151acce7 \ + --hash=sha256:1bdd8c4be420905dd732e00dcd669852d8128cc723efa585a0c0e51adb00a28a \ + --hash=sha256:1d4cf7e8e5b8b1fa40758ac7524843a00237b124ab217e227542cafcfeb7a946 \ + --hash=sha256:1df81d174c1561292de9e40b141cafc04f69077272f6c352afe1d743e20810df \ + --hash=sha256:20a92f78ac8250984ed459faa9ca48c285adbfc0038ddc3fdac6046990a9c9ed \ + --hash=sha256:22bd00f8bae2bccdb5dbe41e20f58ba44ca9fff0b4b561aaf39099c35da762ed \ + --hash=sha256:2437d4ca208cc0f246d3a2297ae7474b4ba18261aaf5b9c79c84c031ecf348e1 \ + --hash=sha256:246927ae9ae06ca0d42a483a4bdb80d4862e1ee5b4cab37c354a5e1ad8356448 \ + --hash=sha256:2503c7e2a5049a12d5dac917a46d5d52591283a766165b8176bb167560421b38 \ + --hash=sha256:2604de7228506b13a44a256a9d223943340c0e725af5d367dc068e192b027761 \ + --hash=sha256:28012a54510fe8301bb893ef143cec30a2780a2d3bc20b7bbdf4379d7a63945d \ + --hash=sha256:2a855b6dfe21c4d3420be265ae031829ba8ba0be0ea350d9f7c3ef30ae63ebe2 \ + --hash=sha256:2abb1ba0a5133b7d2ef3c1c9f4b0c1e8a101012dce0b594ab2b2888d9a64820e \ + --hash=sha256:2b3f3020171202b135ca078e20434977c6b2b02af647130d6980c9e39b9462e3 \ + --hash=sha256:2bc14b481e05e331811108daa1aeb41a5e237a5564ef2f02ec5a356a0f102f78 \ + --hash=sha256:2fa2cb465a131c347ba6717a78c887746e73edb1c131d01c982d6ef0d68b82e0 \ + --hash=sha256:409d93efcaa14f7a99592c5baaef5ec6ca94fba0f5aec1a86f693977c69c9c1c \ + --hash=sha256:41d6aa06b5ab832aee72fedf47a149535b121ac900b6bb4d3fe14712afac9a79 \ + --hash=sha256:49266e4488309b38783257293a38298942b9a03aa106fcb45195377a77c0c1e2 \ + --hash=sha256:4d1d99db29b5444e3982f1ce2ba8a833508ad44b2f1fbd0bd99e81d825c0b461 \ + --hash=sha256:4d41c0a1d47a478bc432b3b9068097bee1ce0c5b19327ea6f75c2ab34ab1f2fb \ + --hash=sha256:5033ffe6804dd53afafa7d08e8c3eef2d2431f34d58ca30507a8442dd04a033a \ + --hash=sha256:53b90c00bc6201ab6695c7ff51a04d0e425514c37515e9eeecd2c1b978ac6c0e \ + --hash=sha256:54cdcaa56f5d3eafd57058f0fa4a3de93a310b43a3c4699f06efc4c0bd054a5a \ + --hash=sha256:5508f38c98ac29def9e747b87543b008a58b075df6da70b2cf2e0b47073d33bb \ + --hash=sha256:55383d8177b3c99fd873ee5db0e0193f4c1dd4a3feaccf1a4a03c1b7cf539cac \ + --hash=sha256:55b12e47dcee83673a40d07686cfb6f9d6dfc285976ade9463f61d2bef3fad22 \ + --hash=sha256:5661f868ef191d33dfc6a0cc7c5b3d495f0cc8bb3f8b30d87bda8755c61c95f5 \ + --hash=sha256:57d2ee9b24b404ce75f3814f92073c0ed88106c950148d2427fe8d25ca254d1f \ + --hash=sha256:599b03beb77633bffc095334338fad79cafc2b01fbd58953838130a9ae967d7b \ + --hash=sha256:5baa9bc0dfbae8c507e51c8cf1b6d4628086f7a87bbd3a9952bd5f035451f1cc \ + --hash=sha256:5f33a649bfcb8312524173cc4bbafa7dbb236e18eee9aa31a1d324ca0ddda28c \ + --hash=sha256:6740be6d1bab69f08ab52cb15b08f76c143b6fe61c580ba62bd929f3ab7a1d42 \ + --hash=sha256:6a434e59962a4fb9016bea327e1d14d6cd67670ecfb8942b4f4a0c24036634ce \ + --hash=sha256:6db9e5bf3649ab506c6ae8a3ac85a00fb1ae3816d75962771b2df8adbc5d40d2 \ + --hash=sha256:6fd88365da261c53d3e943fb37e0d0721b9cde119f6b2e3fc84369b6ab234d63 \ + --hash=sha256:7002d5f9e1c3ddd991cdfdbfee18cc8c8b196b2445022892badacd6cb338bbbc \ + --hash=sha256:70d438268e49f1a4bd096b6b6f7010f3ab48b5db2574dbf7d8c864c46ce7a06a \ + --hash=sha256:72d7f2a5aeb4e82daa4ee18f125b4277f427033359be5c745ad709608446cc2c \ + --hash=sha256:733e3cc7171fa1b899edbe725ef9382d0e960657dc1fd933f3281ae910c01dab \ + --hash=sha256:734d20364dc2cfe03674883cafcf580b6e431c5ce42b476312b9285310230cf9 \ + --hash=sha256:759adeb5b0c5775b563254ec63b5b79089fc0045b479143a0b1b8c0ebaae1253 \ + --hash=sha256:769ce7e2acfd9a89f2bed3a9c0da229459516bbc00bd4c9e2ca492c613ae4861 \ + --hash=sha256:810cb3fb5fa6e447216f4e82d9a85cb8aed0929ae3538153ddfe8a6e3121a58d \ + --hash=sha256:81ce19c6046ace11da7001781be7317bb1dc389f399af4b2ed962190f76f9add \ + --hash=sha256:846a4a8b0833e3cad57523d9e3bd50ec8ea05ab9d06c582f82a1340ba096af5f \ + --hash=sha256:872273e629ca7e3d35f16a2dc6ede84e1d5c831e616b8277de6e4f83114e7c58 \ + --hash=sha256:8848c207049ad49d318e5f64a3d4d7bb189f8328d0d98e65647788f2a085785c \ + --hash=sha256:884af729b8ab50486acd94d9768c2b60914bf39b579ebba0a5cb73bfdfd61fd2 \ + --hash=sha256:8c07f145d0b9e90cbd96035f31fb79199aef4da1872854e36ebeb258e3d57594 \ + --hash=sha256:8cd3369e42c0246afaf9d669cfc19797e3a49e8c0a639544459c57597108b966 \ + --hash=sha256:8e387adb0c692c6b5571bdeafc8ac9d1901ea30f10309134780b16ecd35e6605 \ + --hash=sha256:90246fa9e6cb192a778ce6ce024057ec54317a894db7899c922dcdc1f4cbf6a5 \ + --hash=sha256:90973a3a00f23afdfd1c9b06fb84289bf0220f247ef8a62501a1967c7af54f7b \ + --hash=sha256:9493314a99e599163c854fb5900ad7f7ea38c5cb9d9103aa30b3c6b8181c01fa \ + --hash=sha256:9f7747d3daa41a11f25f7cca5dc988fc51da97b311bed4c9d843860f79779283 \ + --hash=sha256:a39ce3a7b0e6059be093213d637963101380157bcbad355916738fafb490698d \ + --hash=sha256:a60fa1a25cca1bcc2bf87b8d6be37a741f0a3239fb5e9cfb7a37173b68ffcf87 \ + --hash=sha256:a68e604c6d1b0338e46652e2688cbce8096ad9c03548b075fda9e2ea19a9b7dd \ + --hash=sha256:a8af570fc29cd998a921c7131c8ac81d9434466d6d25300cb12a690fb56a8a08 \ + --hash=sha256:aadc298969ad229d8e3029fc5cc751fdad286696230f9cf014e90ff9cd8e6ea0 \ + --hash=sha256:ab56439c9f74c52770690c7b2f616b3bf775cb3920453ee355ac765c032d8bbf \ + --hash=sha256:ab9f962a5b64a5c3c845d556b7dc4e6fb683f7b67179f8205e814bb2e0213ffe \ + --hash=sha256:afbce6e3f0fac32dc87c2a0d84869d1a706460d64f39f3889386413e6e4d3d26 \ + --hash=sha256:b3ff0ad440ad52dda64138f16895f66403f40192365e39b1010e889f289746b0 \ + --hash=sha256:b580794e926cab7ff42ee4371ef14e0b22cb2bb722a607f77769136468f49a3f \ + --hash=sha256:b85b960a4507b0714c0a1246d031be9118d908ee974dc085257297a955205f1d \ + --hash=sha256:b98860aefbd3d9bc8e3c7f0eefb83b11142b16110739c68cd33d3b4d6e84e536 \ + --hash=sha256:bb31f42ea095ea826463c770829aa188a86c9a5c976b1467cbbf583c811de833 \ + --hash=sha256:bc0bca48ba24c6c866847fd20478a51dd547fa0ad258dab9615c414ec534bbc0 \ + --hash=sha256:bd1470d2c53fe53269bf5619da7725d30dd9b9693f1689f7a85eab8dea734442 \ + --hash=sha256:c09e097d0e46e3c289bedab9a475ae344b70c30ff5646e46af22b4e6fdc97b21 \ + --hash=sha256:c1bec5d6a19f5fbe87e4940739cfc65e7bb53d8b353e1029b8037a1653b321bc \ + --hash=sha256:c1c118a6b0e25bfc9a6802075d748fa6321714ffbdf3c88d29d9a0e3c7386c75 \ + --hash=sha256:c23e532c8a2325a1e7486de8763a60dc43e83f01bcaeca07e3ba79652c156db1 \ + --hash=sha256:c356dbddab0a529ed7574f78f559d75a223735c321c28f6f587fbf02b11ed301 \ + --hash=sha256:c38515cb54902f7e97d0239e81ef46c4444f9475f4807fb9bbdb789b4089abcf \ + --hash=sha256:c395bda8e7d8f51a02e80261fb57127979e5c472675d9a96b2860619ad47da48 \ + --hash=sha256:c6be9cba65c65cc76dfa3d4619e359ff02a4476c74e179b215236c11a0b32345 \ + --hash=sha256:cd526c8228e759c1006c4b7c9ac71dc4e925ced1a6a6a5a8e94643709738f63e \ + --hash=sha256:cddc675ec31bca65473321f9a9794e488b43b3b8de5d02c8ef4810c5d5792163 \ + --hash=sha256:cffc84ddec6da7f447677266fee2a3c40ecc78172f00752aa1150b8a8d65df1d \ + --hash=sha256:d41e9845514754a42d1d83b2fca9d27fee2ca7b3b0bee6843ba5a9bb2b6e25ac \ + --hash=sha256:d69fd559f9f0e8a52d2fce6f04ee143f86e70df0a189cd95164eddac599e810f \ + --hash=sha256:d7d72843691f50b91127c50688df10cb72ec6f4c4b1d7e2c11ab33b16acf8e51 \ + --hash=sha256:d9aac6081513f02eac3f8caace800dbfc5c608b69e4a7bef69e414eabfc95aa1 \ + --hash=sha256:dbfae8e75b342e31fc6fd1a8bbb393b7cbb91d6cfd581650300a94381e7b7e2b \ + --hash=sha256:e8208f2729cba030ff872a92064c97584eeb9502f53d32a05a0f05d5a17ca6c6 \ + --hash=sha256:e95e321d0d763f2b6633512605f6112ebd70d5746f3ce05c941909d4a25233f2 \ + --hash=sha256:e98ec9ec61cce5bc4b8b218322ad090b0994eb060bb04da704c62ef0a3d864e6 \ + --hash=sha256:eab6de8a98b9a7772cf686d00b4de439fc7efb8ab05ae106ef227291d06f87c5 \ + --hash=sha256:efe0ae052a8d023b87198921e8a7ce1dc7768816bcd2fbc20df171ac73a04891 \ + --hash=sha256:f11a398d8170b7ac5000baf7f258dcda579ef3ea744e0cc6a165e0dfbc0d3198 \ + --hash=sha256:f3fd9a1f87f8f0f3f8e9f9bd0195f7516562d13f5b178db8c5784d1f60b60bed \ + --hash=sha256:f47b0815af3948ec6a440b3afa02f05b18cc0939549e91b5c677b5d9c2c8472a \ + --hash=sha256:f991247276797d0c61ab7770bc9791eadc16f683b4d83517f624932adc1a8bab \ + --hash=sha256:ffad64ce7ad3703d652a3fd9af26238377d24ce52c6ad8ff35d26d82f61f493f # via sphinx-autobuild From 4ce74062f0f84509303437275f5d8522ea03d84a Mon Sep 17 00:00:00 2001 From: Vitor Bandeira Date: Wed, 12 Aug 2026 09:23:47 -0300 Subject: [PATCH 3/4] docs: review comments and linting Signed-off-by: Vitor Bandeira --- docs/conf.py | 22 +++++++++++----------- docs/scripts/refresh_openroad_docs.py | 4 +--- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 2a096d58c1..0806ef78e1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -161,7 +161,7 @@ def read_vendored(fname): """Read a file vendored from the OpenROAD repository.""" path = os.path.join(VENDOR_DIR, fname) try: - with open(path, "r") as f: + with open(path, "r", encoding="utf-8") as f: return f.read() except OSError as error: raise RuntimeError( @@ -171,10 +171,10 @@ def read_vendored(fname): def swap_prefix(file, old, new): - with open(file, "r") as f: + with open(file, "r", encoding="utf-8") as f: lines = f.read() lines = lines.replace(old, new) - with open(file, "wt") as f: + with open(file, "wt", encoding="utf-8") as f: f.write(lines) @@ -211,10 +211,10 @@ def setup(app): "anchor here and in docs/scripts/check_vendored_docs.py." % (gitguide_anchor, os.path.join(VENDOR_DIR, "GitGuide.md"), REFRESH_CMD) ) - with open("contrib/GitGuideAdapter.md", "r") as f: + with open("contrib/GitGuideAdapter.md", "r", encoding="utf-8") as f: adapter_content = f.read() content = content.replace(gitguide_anchor, adapter_content + "\n" + gitguide_anchor) - with open("contrib/GitGuide.md", "w") as f: + with open("contrib/GitGuide.md", "w", encoding="utf-8") as f: f.write(content) # Create a copy of the index.md file @@ -240,12 +240,12 @@ def setup(app): REFRESH_CMD, ) ) - extracted_content = "\n#### Supported Operating Systems" + section[ - len(start_pattern) : - ] + extracted_content = ( + "\n#### Supported Operating Systems" + section[len(start_pattern) :] + ) # Find insert position - with open("index2.md", "r") as f: + with open("index2.md", "r", encoding="utf-8") as f: existing_content = f.read() insert_anchor = "### Setup" match = re.search(re.escape(insert_anchor), existing_content) @@ -256,7 +256,7 @@ def setup(app): "or update the anchor here and in " "docs/scripts/check_vendored_docs.py." % insert_anchor ) - with open("index2.md", "w") as f: + with open("index2.md", "w", encoding="utf-8") as f: insert_position = match.end() + 1 before_insert = existing_content[:insert_position] after_insert = existing_content[insert_position:] @@ -267,5 +267,5 @@ def setup(app): f.write(updated_content) # Manpage page, vendored from OpenROAD's src/utl/README.md - with open("Manpage.md", "w") as f: + with open("Manpage.md", "w", encoding="utf-8") as f: f.write(read_vendored("utl-README.md")) diff --git a/docs/scripts/refresh_openroad_docs.py b/docs/scripts/refresh_openroad_docs.py index 4762ff1443..3fe1026f84 100755 --- a/docs/scripts/refresh_openroad_docs.py +++ b/docs/scripts/refresh_openroad_docs.py @@ -223,9 +223,7 @@ def extract_section(text: str, upstream_path: str, start: str, end: str) -> str: *now*, naming both headings, instead of vendoring a page the documentation build cannot splice. """ - match = re.search( - "%s(.*?)%s" % (re.escape(start), re.escape(end)), text, re.DOTALL - ) + match = re.search("%s(.*?)%s" % (re.escape(start), re.escape(end)), text, re.DOTALL) if match is None: raise RuntimeError( "cannot find a section starting at '%s' and ending at '%s' in " From 7d7bfd6e19e9a91098fca5a5703c7a122832370d Mon Sep 17 00:00:00 2001 From: Vitor Bandeira Date: Wed, 12 Aug 2026 11:59:34 -0300 Subject: [PATCH 4/4] Update docs/contrib/DeveloperGuide.md Signed-off-by: Vitor Bandeira --- docs/contrib/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contrib/DeveloperGuide.md b/docs/contrib/DeveloperGuide.md index 3e5ad6511d..caf89db775 100644 --- a/docs/contrib/DeveloperGuide.md +++ b/docs/contrib/DeveloperGuide.md @@ -4,7 +4,7 @@ - Adding a new design: [Guide](../user/AddingNewDesign.md). - Continuous Integration: [Guide](./CI.md). - How do I update the codebase? There are different ways to update your codebase depending on the method you installed it. We provide detailed instructions in this [guide](../user/FAQS.md). -- How do I contribute? Follow our Git Quickstart guide [here](https://openroad-flow-scripts.readthedocs.io/en/latest/contrib/GitGuide.html). It is assembled at documentation build time from OpenROAD's Git guide plus the ORFS-specific fork instructions in `contrib/GitGuideAdapter.md`, so it exists only on the published site. +- How do I contribute? Follow our Git Quickstart guide [here](https://openroad-flow-scripts.readthedocs.io/en/latest/contrib/GitGuide.html). ## Timing and Logging (`run_command.py`)