From 65ef8bc4cb17b8a18a37b0f0e422f0803354b6d5 Mon Sep 17 00:00:00 2001
From: Alex Sullivan <115666116+asullivan-blze@users.noreply.github.com>
Date: Wed, 6 Nov 2024 15:02:06 -0800
Subject: [PATCH 1/6] documentation: Use Sphinx for building HTML documentation
Implements Sphinx to have some HTML-based documentation, so referencing documentation that is
not directly in Python source code files is possible. While this branch is not intended to
fully document all available functions, this _does_ provide the necessary framework which
allows future documentation of the code -- within the code itself by way of docstrings -- to
auto-generate updated documentation.
Additionally, while not strictly needed -- and I'll probably look into making this a
change that's available in boardwalk/boardwalkd themselves by default -- I built some
tooling to make pretty HTML output of the `--help` documentation for commands using
rich-click. Right now this isn't baked into the existing documentation build process,
though I _might_ look into seeing if it can be in the future. (I made an attempt, at
least, but the Bash script which does this was the 'good enough' compromise, since
it felt like I was fighting with Python for an excessive length of time to get it to
do what I wanted it to do.
Changes that would be needed on the main Backblaze/boardwalk repository are the usual
ones when enabling GitHub Pages; for my fork, this was -- after the first run of the
workflow to build and populate the `gh-pages` branch -- set the Repository's GitHub
Pages settings to deploy from a branch, using the `gh-pages` branch, and from the root.
Aside from that, the Sphinx documentation will auto-publish on push to the main branch,
or on a version tag being pushed/created.
---
.github/dependabot.yml | 24 +
.github/workflows/make-test.yml | 6 +-
.github/workflows/sphinx.yml | 106 ++
Makefile | 6 +
README.md | 21 +-
docs/Boardwalkfile.py | 10 +
docs/Makefile | 22 +
docs/build_cli_help_pages.sh | 63 +
docs/requirements.txt | 8 +
docs/source/_img/diagrams | 1 +
.../src/boardwalkd/static/boardwalk_icon.jpg | 1 +
docs/source/_static/custom.css | 3 +
.../apidocs/boardwalk/boardwalk.__main__.md | 8 +
.../apidocs/boardwalk/boardwalk.ansible.md | 144 ++
.../boardwalk/boardwalk.app_exceptions.md | 36 +
.../source/apidocs/boardwalk/boardwalk.cli.md | 75 ++
.../apidocs/boardwalk/boardwalk.cli_catch.md | 42 +
.../apidocs/boardwalk/boardwalk.cli_init.md | 53 +
.../apidocs/boardwalk/boardwalk.cli_login.md | 31 +
.../apidocs/boardwalk/boardwalk.cli_run.md | 289 ++++
.../boardwalk/boardwalk.cli_workspace.md | 97 ++
.../apidocs/boardwalk/boardwalk.host.md | 211 +++
.../apidocs/boardwalk/boardwalk.manifest.md | 610 +++++++++
docs/source/apidocs/boardwalk/boardwalk.md | 29 +
.../apidocs/boardwalk/boardwalk.state.md | 186 +++
.../apidocs/boardwalk/boardwalk.utils.md | 31 +
.../apidocs/boardwalkd/boardwalkd.__main__.md | 8 +
.../boardwalkd/boardwalkd.broadcast.md | 32 +
.../apidocs/boardwalkd/boardwalkd.cli.md | 76 ++
docs/source/apidocs/boardwalkd/boardwalkd.md | 23 +
.../apidocs/boardwalkd/boardwalkd.protocol.md | 554 ++++++++
.../apidocs/boardwalkd/boardwalkd.server.md | 1005 ++++++++++++++
.../apidocs/boardwalkd/boardwalkd.slack.md | 207 +++
.../apidocs/boardwalkd/boardwalkd.state.md | 305 +++++
docs/source/apidocs/index.rst | 12 +
.../cli_helpdocs/boardwalk/boardwalk.md | 33 +
.../cli_helpdocs/boardwalk/boardwalk_catch.md | 18 +
.../cli_helpdocs/boardwalk/boardwalk_check.md | 32 +
.../cli_helpdocs/boardwalk/boardwalk_init.md | 23 +
.../cli_helpdocs/boardwalk/boardwalk_login.md | 17 +
.../boardwalk/boardwalk_release.md | 17 +
.../cli_helpdocs/boardwalk/boardwalk_run.md | 40 +
.../boardwalk/boardwalk_version.md | 17 +
.../boardwalk/boardwalk_workspace.md | 22 +
.../boardwalk/boardwalk_workspace_dump.md | 17 +
.../boardwalk/boardwalk_workspace_list.md | 17 +
.../boardwalk/boardwalk_workspace_reset.md | 18 +
.../boardwalk/boardwalk_workspace_show.md | 17 +
.../boardwalk/boardwalk_workspace_use.md | 15 +
docs/source/cli_helpdocs/boardwalk/index.md | 22 +
.../cli_helpdocs/boardwalkd/boardwalkd.md | 23 +
.../boardwalkd/boardwalkd_serve.md | 98 ++
.../boardwalkd/boardwalkd_version.md | 17 +
docs/source/cli_helpdocs/boardwalkd/index.md | 11 +
docs/source/cli_helpdocs/index.md | 12 +
docs/source/conf.py | 140 ++
docs/source/index.md | 32 +
docs/source/overview.md | 10 +
poetry.lock | 1196 ++++++++++++++---
pyproject.toml | 23 +-
src/boardwalk/cli.py | 3 +-
61 files changed, 5997 insertions(+), 228 deletions(-)
create mode 100644 .github/dependabot.yml
create mode 100644 .github/workflows/sphinx.yml
create mode 100644 docs/Boardwalkfile.py
create mode 100644 docs/Makefile
create mode 100755 docs/build_cli_help_pages.sh
create mode 100644 docs/requirements.txt
create mode 120000 docs/source/_img/diagrams
create mode 120000 docs/source/_img/src/boardwalkd/static/boardwalk_icon.jpg
create mode 100644 docs/source/_static/custom.css
create mode 100644 docs/source/apidocs/boardwalk/boardwalk.__main__.md
create mode 100644 docs/source/apidocs/boardwalk/boardwalk.ansible.md
create mode 100644 docs/source/apidocs/boardwalk/boardwalk.app_exceptions.md
create mode 100644 docs/source/apidocs/boardwalk/boardwalk.cli.md
create mode 100644 docs/source/apidocs/boardwalk/boardwalk.cli_catch.md
create mode 100644 docs/source/apidocs/boardwalk/boardwalk.cli_init.md
create mode 100644 docs/source/apidocs/boardwalk/boardwalk.cli_login.md
create mode 100644 docs/source/apidocs/boardwalk/boardwalk.cli_run.md
create mode 100644 docs/source/apidocs/boardwalk/boardwalk.cli_workspace.md
create mode 100644 docs/source/apidocs/boardwalk/boardwalk.host.md
create mode 100644 docs/source/apidocs/boardwalk/boardwalk.manifest.md
create mode 100644 docs/source/apidocs/boardwalk/boardwalk.md
create mode 100644 docs/source/apidocs/boardwalk/boardwalk.state.md
create mode 100644 docs/source/apidocs/boardwalk/boardwalk.utils.md
create mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.__main__.md
create mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.broadcast.md
create mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.cli.md
create mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.md
create mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.protocol.md
create mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.server.md
create mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.slack.md
create mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.state.md
create mode 100644 docs/source/apidocs/index.rst
create mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk.md
create mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_catch.md
create mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_check.md
create mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_init.md
create mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_login.md
create mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_release.md
create mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_run.md
create mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_version.md
create mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_workspace.md
create mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_dump.md
create mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_list.md
create mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_reset.md
create mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_show.md
create mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_use.md
create mode 100644 docs/source/cli_helpdocs/boardwalk/index.md
create mode 100644 docs/source/cli_helpdocs/boardwalkd/boardwalkd.md
create mode 100644 docs/source/cli_helpdocs/boardwalkd/boardwalkd_serve.md
create mode 100644 docs/source/cli_helpdocs/boardwalkd/boardwalkd_version.md
create mode 100644 docs/source/cli_helpdocs/boardwalkd/index.md
create mode 100644 docs/source/cli_helpdocs/index.md
create mode 100644 docs/source/conf.py
create mode 100644 docs/source/index.md
create mode 100644 docs/source/overview.md
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..af35054
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,24 @@
+# Please see the documentation for all configuration options:
+# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
+
+version: 2
+updates:
+ # To monitor pyproject.toml / Poetry.lock files
+ - package-ecosystem: "pip"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ # Keep the requirements.txt for Sphinx builds in `/docs` up to date, also.
+ - package-ecosystem: "pip"
+ directory: "/docs"
+ schedule:
+ interval: "daily"
+ # For keeping workflows up-to-date.
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ labels:
+ - "CI/CD"
+ commit-message:
+ prefix: ci
diff --git a/.github/workflows/make-test.yml b/.github/workflows/make-test.yml
index dd0e455..ffa1a43 100644
--- a/.github/workflows/make-test.yml
+++ b/.github/workflows/make-test.yml
@@ -22,7 +22,7 @@ jobs:
- name: Set up python
id: setup-python
- uses: actions/setup-python@v5
+ uses: actions/setup-python@v5.3.0
with:
python-version: '3.11'
@@ -31,7 +31,7 @@ jobs:
#----------------------------------------------
- name: Load cached Poetry installation
id: cached-poetry
- uses: actions/cache@v3
+ uses: actions/cache@v4.1.2
with:
path: ~/.local # the path depends on the OS
key: poetry-0 # increment to reset cache
@@ -49,7 +49,7 @@ jobs:
#----------------------------------------------
- name: Load cached venv
id: cached-poetry-dependencies
- uses: actions/cache@v3
+ uses: actions/cache@v4.1.2
with:
path: .venv
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml
new file mode 100644
index 0000000..dd84095
--- /dev/null
+++ b/.github/workflows/sphinx.yml
@@ -0,0 +1,106 @@
+name: "Sphinx: Render docs"
+
+on:
+ pull_request:
+ push:
+ branches:
+ - main
+ tags:
+ - 'v*.*.*'
+ workflow_dispatch:
+ inputs:
+ debug_enabled:
+ type: boolean
+ description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
+ required: false
+ default: false
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ permissions:
+ contents: write
+ steps:
+ #----------------------------------------------
+ # check-out repo and set-up python
+ #----------------------------------------------
+ - name: Check out repository
+ uses: actions/checkout@v4
+
+ # Manually triggered debugging; see: https://github.com/mxschmitt/action-tmate?tab=readme-ov-file#manually-triggered-debug
+ - name: Setup tmate session
+ uses: mxschmitt/action-tmate@v3
+ # Need to run this always in the development; cause this is in a PR, it doesn't allow manual workflows to be triggered?
+ # if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
+ with:
+ # Starts the tmate session, prints connection details, then resumes the workflow
+ detached: true
+ # Requires the initiating user's SSH key to be provided
+ limit-access-to-actor: true
+
+ - name: Set up python
+ id: setup-python
+ uses: actions/setup-python@v5.3.0
+ with:
+ python-version: '3.11'
+
+ #----------------------------------------------
+ # Install and configure Poetry, or restore from cache
+ #----------------------------------------------
+ - name: Load cached Poetry installation
+ id: cached-poetry
+ uses: actions/cache@v4.1.2
+ with:
+ path: ~/.local # the path depends on the OS
+ key: poetry-docs-0 # increment to reset cache
+
+ - name: Install Poetry
+ if: steps.cached-poetry.outputs.cache-hit != 'true'
+ uses: snok/install-poetry@v1
+ with:
+ virtualenvs-create: true
+ virtualenvs-in-project: true
+ installer-parallel: true
+
+ #----------------------------------------------
+ # load cached venv if cache exists
+ #----------------------------------------------
+ - name: Load cached venv
+ id: cached-poetry-dependencies
+ uses: actions/cache@v4.1.2
+ with:
+ path: .venv
+ key: boardwalk-docs-venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
+
+ #----------------------------------------------
+ # install your root project, if required
+ #----------------------------------------------
+ - name: Install project, with dependencies foor building documentation
+ run: poetry install --no-interaction --with=docs --sync
+
+ - name: Run 'make docs', to build documentation
+ run: poetry run make docs
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: html-docs
+ path: docs/build/
+
+ # - name: Deploy main branch docs to gh-pages branch
+ # uses: peaceiris/actions-gh-pages@v4
+ # if: github.ref == 'refs/heads/main'
+ # with:
+ # github_token: ${{ secrets.GITHUB_TOKEN }}
+ # publish_dir: docs/build/
+
+ # Since it doesn't seem GHActions supports `or`, using this as an intermediate testing step.
+ # The above will remain once we merge this workflow back into the main repo.
+ - name: Deploy testing docs to gh-pages branch
+ uses: peaceiris/actions-gh-pages@v4
+ if: github.ref == 'refs/heads/dev'
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: docs/build/
diff --git a/Makefile b/Makefile
index 4fb50a7..7ab6159 100644
--- a/Makefile
+++ b/Makefile
@@ -50,6 +50,12 @@ endif
dist: clean
poetry build
+# Builds the Sphinx HTML documentation -- Shortcut for `cd docs && make html`
+.PHONY: docs
+docs: develop
+ poetry install --with=docs --sync
+ poetry run make --directory=./docs/ html
+
# Applies fixable errors, and formats code
.PHONY: format
format:
diff --git a/README.md b/README.md
index c1b77e7..eedfb31 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
Boardwalk
=========
+
+
Boardwalk is an open-source linear [Ansible](https://www.ansible.com/) workflow engine. It's
purpose-built to help systems engineers automate low-and-slow background jobs
@@ -17,7 +19,8 @@ stopping and resuming long-running Ansible workflows easy and efficient.
š„ __Boardwalk is alpha software. Interfaces and behaviors may change between
updates.__ š„
-
+
+
# Table of Contents
- [Motivation & Goals](#motivation--goals)
- [Open-Source License](#open-source-license)
@@ -30,10 +33,12 @@ updates.__ š„
- [Remote State](#remote-state)
- [Usage](#usage)
- [Installation](#installation)
- - [The `Boardwalkfile.py`](#the-boardwalkfilepy)
+ - [The `Boardwalkfile.py`](#the-boardwalkfile)
- [Command-line Interface](#environment-variables)
- [`boardwalkd` Server](#boardwalkd-server)
+
+
# Motivation & Goals
Ansible is already a very capable agentless, modular, remote execution engine.
@@ -72,11 +77,11 @@ interface used by [AWX](https://github.com/ansible/awx).
# Open-Source License
-Boardwalk is open source, licensed under the terms of the [MIT license](LICENSE).
+Boardwalk is open source, licensed under the terms of the [MIT license](https://github.com/Backblaze/boardwalk/blob/main/LICENSE).
# Contributing
-See [CONTRIBUTING.md](./CONTRIBUTING.md).
+See [CONTRIBUTING.md](https://github.com/Backblaze/boardwalk/blob/main/CONTRIBUTING.md).
# Concepts
@@ -88,7 +93,7 @@ Workspaces define isolated configurations and state for working on projects with
Boardwalk. They define the Ansible host pattern Boardwalk should target, the
Workflow Boardwalk will use, and some essential configuration options.
-Workspaces are defined in the [Boardwalkfile.py](#the-boardwalkfile-py). The
+Workspaces are defined in the [Boardwalkfile.py](#the-boardwalkfile). The
active Workspace is selected with `boardwalk workspace use `.
## Workflow
@@ -100,7 +105,7 @@ purpose of a Workflow is to mutate a host from one state to another. Typically
Workflows depend upon some Ansible fact(s) having changed after the Workflow has
completed all of its Jobs.
-Workflows are defined in the [Boardwalkfile.py](#the-boardwalkfile-py).
+Workflows are defined in the [Boardwalkfile.py](#the-boardwalkfile).
Workflows can be dry-run with `boardwalk check`, which runs Ansible in `--check`
mode. Workflows are run with `boardwalk run`.
@@ -111,7 +116,7 @@ that are run against hosts. They accept options that can be passed into them and
used in tasks. They define preconditions that a host must meet before a Workflow
will run against it.
-Jobs are defined in the [Boardwalkfile.py](#the-boardwalkfile-py).
+Jobs are defined in the [Boardwalkfile.py](#the-boardwalkfile).
### Job Preconditions
@@ -216,7 +221,7 @@ Boardwalk may be built as a container image by running `make container`.
The entrypoint is simply `python -m` so either `boardwalk` or `boardwalkd`
must be specified as the command when running.
-## The `Boardwalkfile.py`
+## The `Boardwalkfile`
Boardwalk is both a python library and command-line tool. The `boardwalk`
command-line tool expects a file called `Boardwalkfile.py` to exist in the
diff --git a/docs/Boardwalkfile.py b/docs/Boardwalkfile.py
new file mode 100644
index 0000000..12c22f5
--- /dev/null
+++ b/docs/Boardwalkfile.py
@@ -0,0 +1,10 @@
+# Dummy file to let help be generated...
+# TODO: Figure out how to let things like the below work without erroring; it should "just work"
+#
+# rich-click --output html boardwalk workspace --help
+# 2024-10-31 16:33:18.521 | INFO | boardwalk.cli:cli:77 - Log level is INFO
+
+# āā Error āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+# ā No Boardwalkfile.py found ā
+# ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+# (boardwalk-py3.12) asullivan@MBP-NT9RPG2XV7 boardwalk %
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..c99ffc2
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,22 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = source
+BUILDDIR = build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+livehtml:
+ sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs/build_cli_help_pages.sh b/docs/build_cli_help_pages.sh
new file mode 100755
index 0000000..7ce4220
--- /dev/null
+++ b/docs/build_cli_help_pages.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+# TODO / Possibility: Integrate rich-click into boardwalk/boardwalkd directly,
+# so this workaround isn't needed to generate a pretty help text.
+
+commands=(
+ "boardwalk"
+ "boardwalk catch"
+ "boardwalk check"
+ "boardwalk init"
+ "boardwalk login"
+ "boardwalk release"
+ "boardwalk run"
+ "boardwalk version"
+ "boardwalk workspace"
+ "boardwalk workspace dump"
+ "boardwalk workspace list"
+ "boardwalk workspace reset"
+ "boardwalk workspace show"
+ "boardwalk workspace use"
+
+ "boardwalkd"
+ "boardwalkd serve"
+ "boardwalkd version"
+)
+
+OUTPUT_WIDTH_COLUMMNS=110
+
+GET_PAGE_NAME() {
+ echo '`'"$1"'`'
+}
+
+for cmd in "${commands[@]}"; do
+ # Define regular expression patterns for 'boardwalk' and 'boardwalkd', so we
+ # can sort them into the correct subdirectories. Note that we need to use
+ # POSIX-compliant EREs, here, since this is portable between MacOS/Linux.
+ # See: https://stackoverflow.com/a/12696899
+ # This is, effectively, '\bboardwalk\b' and '\bboardwalkd\b'
+ BOARDWALK_REGEX="^[[:<:]]boardwalk[[:>:]]"
+ BOARDWALKD_REGEX="^[[:<:]]boardwalkd[[:>:]]"
+ if [[ $cmd =~ $BOARDWALK_REGEX ]]; then
+ SUBDIR=boardwalk
+ elif [[ $cmd =~ $BOARDWALKD_REGEX ]]; then
+ SUBDIR=boardwalkd
+ else
+ # Don't assume if we cannot correctly parse the command being generated
+ echo "[!] Skipping generation for $cmd; is this a boardwalk or boardwalkd command?"
+ continue
+ fi
+ FILENAME=./source/cli_helpdocs/$SUBDIR/$(echo "$cmd" | tr ' ' _).md
+ echo "[+] Generating doc page for $FILENAME"
+ {
+ echo "# $(GET_PAGE_NAME "$cmd")"
+ echo ""
+ echo ''
+ echo '
'
+ # shellcheck disable=SC2086 # We actually want word splitting, here
+ COLUMNS=$OUTPUT_WIDTH_COLUMMNS rich-click --output html $cmd --help
+ echo '
'
+ echo '
'
+ echo ''
+ } > "$FILENAME"
+done
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 0000000..db831ac
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1,8 @@
+# Requirements file for the GitHub ammaraskar/sphinx-action, which builds Sphinx
+# documentation
+
+sphinx-autobuild >= 2024.10.3
+sphinx-autodoc2 >= 0.5.0, < 1.0
+sphinx-book-theme >= 1.1.3, < 2.0
+sphinx-copybutton >= 0.5.2, < 1.0
+myst-parser [linkify] >= 4.0.0, < 5.0
diff --git a/docs/source/_img/diagrams b/docs/source/_img/diagrams
new file mode 120000
index 0000000..dd2b380
--- /dev/null
+++ b/docs/source/_img/diagrams
@@ -0,0 +1 @@
+../../../diagrams
\ No newline at end of file
diff --git a/docs/source/_img/src/boardwalkd/static/boardwalk_icon.jpg b/docs/source/_img/src/boardwalkd/static/boardwalk_icon.jpg
new file mode 120000
index 0000000..80a4bb8
--- /dev/null
+++ b/docs/source/_img/src/boardwalkd/static/boardwalk_icon.jpg
@@ -0,0 +1 @@
+../../../../../../src/boardwalkd/static/boardwalk_icon.jpg
\ No newline at end of file
diff --git a/docs/source/_static/custom.css b/docs/source/_static/custom.css
new file mode 100644
index 0000000..4ae01bb
--- /dev/null
+++ b/docs/source/_static/custom.css
@@ -0,0 +1,3 @@
+div#boardwalk-readme-icon {
+ max-width: 200px;
+}
\ No newline at end of file
diff --git a/docs/source/apidocs/boardwalk/boardwalk.__main__.md b/docs/source/apidocs/boardwalk/boardwalk.__main__.md
new file mode 100644
index 0000000..2c9c9d2
--- /dev/null
+++ b/docs/source/apidocs/boardwalk/boardwalk.__main__.md
@@ -0,0 +1,8 @@
+# {py:mod}`boardwalk.__main__`
+
+```{py:module} boardwalk.__main__
+```
+
+```{autodoc2-docstring} boardwalk.__main__
+:allowtitles:
+```
diff --git a/docs/source/apidocs/boardwalk/boardwalk.ansible.md b/docs/source/apidocs/boardwalk/boardwalk.ansible.md
new file mode 100644
index 0000000..32c2cd6
--- /dev/null
+++ b/docs/source/apidocs/boardwalk/boardwalk.ansible.md
@@ -0,0 +1,144 @@
+# {py:mod}`boardwalk.ansible`
+
+```{py:module} boardwalk.ansible
+```
+
+```{autodoc2-docstring} boardwalk.ansible
+:allowtitles:
+```
+
+## Module Contents
+
+### Functions
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`ansible_runner_cancel_callback `
+ - ```{autodoc2-docstring} boardwalk.ansible.ansible_runner_cancel_callback
+ :summary:
+ ```
+* - {py:obj}`ansible_runner_errors_to_output `
+ - ```{autodoc2-docstring} boardwalk.ansible.ansible_runner_errors_to_output
+ :summary:
+ ```
+* - {py:obj}`ansible_runner_run_tasks `
+ - ```{autodoc2-docstring} boardwalk.ansible.ansible_runner_run_tasks
+ :summary:
+ ```
+* - {py:obj}`ansible_inventory `
+ - ```{autodoc2-docstring} boardwalk.ansible.ansible_inventory
+ :summary:
+ ```
+````
+
+### API
+
+````{py:function} ansible_runner_cancel_callback(ws: boardwalk.manifest.Workspace)
+:canonical: boardwalk.ansible.ansible_runner_cancel_callback
+
+```{autodoc2-docstring} boardwalk.ansible.ansible_runner_cancel_callback
+```
+````
+
+````{py:function} ansible_runner_errors_to_output(runner: ansible_runner.Runner, include_msg: bool = True) -> str
+:canonical: boardwalk.ansible.ansible_runner_errors_to_output
+
+```{autodoc2-docstring} boardwalk.ansible.ansible_runner_errors_to_output
+```
+````
+
+````{py:function} ansible_runner_run_tasks(hosts: str, invocation_msg: str, job_type: boardwalk.manifest.JobTypes, tasks: boardwalk.ansible.AnsibleTasksType, become: bool = False, become_password: str | None = None, check: bool = False, gather_facts: bool = True, limit: str | None = None, quiet: bool = True, timeout: int | None = None, verbosity: int = 0, extra_vars: dict = {}) -> ansible_runner.Runner
+:canonical: boardwalk.ansible.ansible_runner_run_tasks
+
+```{autodoc2-docstring} boardwalk.ansible.ansible_runner_run_tasks
+```
+````
+
+````{py:function} ansible_inventory() -> boardwalk.ansible.InventoryData
+:canonical: boardwalk.ansible.ansible_inventory
+
+```{autodoc2-docstring} boardwalk.ansible.ansible_inventory
+```
+````
+
+````{py:exception} AnsibleRunnerBaseException(message: str, runner_msg: str, runner: ansible_runner.Runner)
+:canonical: boardwalk.ansible.AnsibleRunnerBaseException
+
+Bases: {py:obj}`Exception`
+
+```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerBaseException
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerBaseException.__init__
+```
+
+````
+
+````{py:exception} AnsibleRunnerGeneralError(message: str, runner_msg: str, runner: ansible_runner.Runner)
+:canonical: boardwalk.ansible.AnsibleRunnerGeneralError
+
+Bases: {py:obj}`boardwalk.ansible.AnsibleRunnerBaseException`
+
+```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerGeneralError
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerGeneralError.__init__
+```
+
+````
+
+````{py:exception} AnsibleRunError(message: str, runner_msg: str, runner: ansible_runner.Runner)
+:canonical: boardwalk.ansible.AnsibleRunError
+
+Bases: {py:obj}`boardwalk.ansible.AnsibleRunnerBaseException`
+
+```{autodoc2-docstring} boardwalk.ansible.AnsibleRunError
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.ansible.AnsibleRunError.__init__
+```
+
+````
+
+````{py:exception} AnsibleRunnerUnreachableHost(message: str, runner_msg: str, runner: ansible_runner.Runner)
+:canonical: boardwalk.ansible.AnsibleRunnerUnreachableHost
+
+Bases: {py:obj}`boardwalk.ansible.AnsibleRunnerBaseException`
+
+```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerUnreachableHost
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerUnreachableHost.__init__
+```
+
+````
+
+````{py:exception} AnsibleRunnerFailedHost(message: str, runner_msg: str, runner: ansible_runner.Runner)
+:canonical: boardwalk.ansible.AnsibleRunnerFailedHost
+
+Bases: {py:obj}`boardwalk.ansible.AnsibleRunnerBaseException`
+
+```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerFailedHost
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerFailedHost.__init__
+```
+
+````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.app_exceptions.md b/docs/source/apidocs/boardwalk/boardwalk.app_exceptions.md
new file mode 100644
index 0000000..23c03eb
--- /dev/null
+++ b/docs/source/apidocs/boardwalk/boardwalk.app_exceptions.md
@@ -0,0 +1,36 @@
+# {py:mod}`boardwalk.app_exceptions`
+
+```{py:module} boardwalk.app_exceptions
+```
+
+```{autodoc2-docstring} boardwalk.app_exceptions
+:allowtitles:
+```
+
+## Module Contents
+
+### API
+
+`````{py:exception} BoardwalkException(message: str)
+:canonical: boardwalk.app_exceptions.BoardwalkException
+
+Bases: {py:obj}`click.ClickException`
+
+```{autodoc2-docstring} boardwalk.app_exceptions.BoardwalkException
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.app_exceptions.BoardwalkException.__init__
+```
+
+````{py:method} show(file: typing.IO[str] | None = None) -> None
+:canonical: boardwalk.app_exceptions.BoardwalkException.show
+
+```{autodoc2-docstring} boardwalk.app_exceptions.BoardwalkException.show
+```
+
+````
+
+`````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.cli.md b/docs/source/apidocs/boardwalk/boardwalk.cli.md
new file mode 100644
index 0000000..b693e4e
--- /dev/null
+++ b/docs/source/apidocs/boardwalk/boardwalk.cli.md
@@ -0,0 +1,75 @@
+# {py:mod}`boardwalk.cli`
+
+```{py:module} boardwalk.cli
+```
+
+```{autodoc2-docstring} boardwalk.cli
+:allowtitles:
+```
+
+## Module Contents
+
+### Functions
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`handle_signal `
+ - ```{autodoc2-docstring} boardwalk.cli.handle_signal
+ :summary:
+ ```
+* - {py:obj}`cli `
+ - ```{autodoc2-docstring} boardwalk.cli.cli
+ :summary:
+ ```
+* - {py:obj}`version `
+ - ```{autodoc2-docstring} boardwalk.cli.version
+ :summary:
+ ```
+````
+
+### Data
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`terminating `
+ - ```{autodoc2-docstring} boardwalk.cli.terminating
+ :summary:
+ ```
+````
+
+### API
+
+````{py:data} terminating
+:canonical: boardwalk.cli.terminating
+:value: >
+ False
+
+```{autodoc2-docstring} boardwalk.cli.terminating
+```
+
+````
+
+````{py:function} handle_signal(sig: int, frame: typing.Any)
+:canonical: boardwalk.cli.handle_signal
+
+```{autodoc2-docstring} boardwalk.cli.handle_signal
+```
+````
+
+````{py:function} cli(ctx: click.Context, verbose: int)
+:canonical: boardwalk.cli.cli
+
+```{autodoc2-docstring} boardwalk.cli.cli
+```
+````
+
+````{py:function} version()
+:canonical: boardwalk.cli.version
+
+```{autodoc2-docstring} boardwalk.cli.version
+```
+````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.cli_catch.md b/docs/source/apidocs/boardwalk/boardwalk.cli_catch.md
new file mode 100644
index 0000000..0d7af96
--- /dev/null
+++ b/docs/source/apidocs/boardwalk/boardwalk.cli_catch.md
@@ -0,0 +1,42 @@
+# {py:mod}`boardwalk.cli_catch`
+
+```{py:module} boardwalk.cli_catch
+```
+
+```{autodoc2-docstring} boardwalk.cli_catch
+:allowtitles:
+```
+
+## Module Contents
+
+### Functions
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`catch `
+ - ```{autodoc2-docstring} boardwalk.cli_catch.catch
+ :summary:
+ ```
+* - {py:obj}`release `
+ - ```{autodoc2-docstring} boardwalk.cli_catch.release
+ :summary:
+ ```
+````
+
+### API
+
+````{py:function} catch()
+:canonical: boardwalk.cli_catch.catch
+
+```{autodoc2-docstring} boardwalk.cli_catch.catch
+```
+````
+
+````{py:function} release()
+:canonical: boardwalk.cli_catch.release
+
+```{autodoc2-docstring} boardwalk.cli_catch.release
+```
+````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.cli_init.md b/docs/source/apidocs/boardwalk/boardwalk.cli_init.md
new file mode 100644
index 0000000..2bc9fb0
--- /dev/null
+++ b/docs/source/apidocs/boardwalk/boardwalk.cli_init.md
@@ -0,0 +1,53 @@
+# {py:mod}`boardwalk.cli_init`
+
+```{py:module} boardwalk.cli_init
+```
+
+```{autodoc2-docstring} boardwalk.cli_init
+:allowtitles:
+```
+
+## Module Contents
+
+### Functions
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`init `
+ - ```{autodoc2-docstring} boardwalk.cli_init.init
+ :summary:
+ ```
+* - {py:obj}`add_gathered_facts_to_state `
+ - ```{autodoc2-docstring} boardwalk.cli_init.add_gathered_facts_to_state
+ :summary:
+ ```
+* - {py:obj}`handle_failed_init_hosts `
+ - ```{autodoc2-docstring} boardwalk.cli_init.handle_failed_init_hosts
+ :summary:
+ ```
+````
+
+### API
+
+````{py:function} init(ctx: click.Context, limit: str, retry: bool)
+:canonical: boardwalk.cli_init.init
+
+```{autodoc2-docstring} boardwalk.cli_init.init
+```
+````
+
+````{py:function} add_gathered_facts_to_state(event: ansible_runner.RunnerEvent, ws: boardwalk.manifest.Workspace)
+:canonical: boardwalk.cli_init.add_gathered_facts_to_state
+
+```{autodoc2-docstring} boardwalk.cli_init.add_gathered_facts_to_state
+```
+````
+
+````{py:function} handle_failed_init_hosts(event: ansible_runner.RunnerEvent, retry_file_path: pathlib.Path)
+:canonical: boardwalk.cli_init.handle_failed_init_hosts
+
+```{autodoc2-docstring} boardwalk.cli_init.handle_failed_init_hosts
+```
+````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.cli_login.md b/docs/source/apidocs/boardwalk/boardwalk.cli_login.md
new file mode 100644
index 0000000..906cc41
--- /dev/null
+++ b/docs/source/apidocs/boardwalk/boardwalk.cli_login.md
@@ -0,0 +1,31 @@
+# {py:mod}`boardwalk.cli_login`
+
+```{py:module} boardwalk.cli_login
+```
+
+```{autodoc2-docstring} boardwalk.cli_login
+:allowtitles:
+```
+
+## Module Contents
+
+### Functions
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`login `
+ - ```{autodoc2-docstring} boardwalk.cli_login.login
+ :summary:
+ ```
+````
+
+### API
+
+````{py:function} login()
+:canonical: boardwalk.cli_login.login
+
+```{autodoc2-docstring} boardwalk.cli_login.login
+```
+````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.cli_run.md b/docs/source/apidocs/boardwalk/boardwalk.cli_run.md
new file mode 100644
index 0000000..488349e
--- /dev/null
+++ b/docs/source/apidocs/boardwalk/boardwalk.cli_run.md
@@ -0,0 +1,289 @@
+# {py:mod}`boardwalk.cli_run`
+
+```{py:module} boardwalk.cli_run
+```
+
+```{autodoc2-docstring} boardwalk.cli_run
+:allowtitles:
+```
+
+## Module Contents
+
+### Functions
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`run `
+ - ```{autodoc2-docstring} boardwalk.cli_run.run
+ :summary:
+ ```
+* - {py:obj}`check `
+ - ```{autodoc2-docstring} boardwalk.cli_run.check
+ :summary:
+ ```
+* - {py:obj}`run_workflow `
+ - ```{autodoc2-docstring} boardwalk.cli_run.run_workflow
+ :summary:
+ ```
+* - {py:obj}`run_failure_mode_handler `
+ - ```{autodoc2-docstring} boardwalk.cli_run.run_failure_mode_handler
+ :summary:
+ ```
+* - {py:obj}`filter_hosts_by_limit `
+ - ```{autodoc2-docstring} boardwalk.cli_run.filter_hosts_by_limit
+ :summary:
+ ```
+* - {py:obj}`sort_host_list `
+ - ```{autodoc2-docstring} boardwalk.cli_run.sort_host_list
+ :summary:
+ ```
+* - {py:obj}`check_host_preconditions_locally `
+ - ```{autodoc2-docstring} boardwalk.cli_run.check_host_preconditions_locally
+ :summary:
+ ```
+* - {py:obj}`handle_workflow_catch `
+ - ```{autodoc2-docstring} boardwalk.cli_run.handle_workflow_catch
+ :summary:
+ ```
+* - {py:obj}`lock_remote_host `
+ - ```{autodoc2-docstring} boardwalk.cli_run.lock_remote_host
+ :summary:
+ ```
+* - {py:obj}`bootstrap_with_server `
+ - ```{autodoc2-docstring} boardwalk.cli_run.bootstrap_with_server
+ :summary:
+ ```
+* - {py:obj}`update_host_facts_in_local_state `
+ - ```{autodoc2-docstring} boardwalk.cli_run.update_host_facts_in_local_state
+ :summary:
+ ```
+* - {py:obj}`directly_confirm_host_preconditions `
+ - ```{autodoc2-docstring} boardwalk.cli_run.directly_confirm_host_preconditions
+ :summary:
+ ```
+* - {py:obj}`execute_workflow_jobs `
+ - ```{autodoc2-docstring} boardwalk.cli_run.execute_workflow_jobs
+ :summary:
+ ```
+* - {py:obj}`execute_host_workflow `
+ - ```{autodoc2-docstring} boardwalk.cli_run.execute_host_workflow
+ :summary:
+ ```
+````
+
+### Data
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`become_password `
+ - ```{autodoc2-docstring} boardwalk.cli_run.become_password
+ :summary:
+ ```
+* - {py:obj}`boardwalkd_client `
+ - ```{autodoc2-docstring} boardwalk.cli_run.boardwalkd_client
+ :summary:
+ ```
+* - {py:obj}`boardwalkd_send_broadcasts `
+ - ```{autodoc2-docstring} boardwalk.cli_run.boardwalkd_send_broadcasts
+ :summary:
+ ```
+* - {py:obj}`_check_mode `
+ - ```{autodoc2-docstring} boardwalk.cli_run._check_mode
+ :summary:
+ ```
+* - {py:obj}`_stomp_locks `
+ - ```{autodoc2-docstring} boardwalk.cli_run._stomp_locks
+ :summary:
+ ```
+````
+
+### API
+
+````{py:data} become_password
+:canonical: boardwalk.cli_run.become_password
+:type: str | None
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalk.cli_run.become_password
+```
+
+````
+
+````{py:data} boardwalkd_client
+:canonical: boardwalk.cli_run.boardwalkd_client
+:type: boardwalkd.protocol.WorkspaceClient | None
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalk.cli_run.boardwalkd_client
+```
+
+````
+
+````{py:data} boardwalkd_send_broadcasts
+:canonical: boardwalk.cli_run.boardwalkd_send_broadcasts
+:type: bool
+:value: >
+ False
+
+```{autodoc2-docstring} boardwalk.cli_run.boardwalkd_send_broadcasts
+```
+
+````
+
+````{py:data} _check_mode
+:canonical: boardwalk.cli_run._check_mode
+:type: bool
+:value: >
+ True
+
+```{autodoc2-docstring} boardwalk.cli_run._check_mode
+```
+
+````
+
+````{py:data} _stomp_locks
+:canonical: boardwalk.cli_run._stomp_locks
+:type: bool
+:value: >
+ False
+
+```{autodoc2-docstring} boardwalk.cli_run._stomp_locks
+```
+
+````
+
+````{py:function} run(ctx: click.Context, ask_become_pass: bool, check: bool, limit: str, server_connect: bool, sort_hosts: str, stomp_locks: bool)
+:canonical: boardwalk.cli_run.run
+
+```{autodoc2-docstring} boardwalk.cli_run.run
+```
+````
+
+````{py:function} check(ctx: click.Context, ask_become_pass: bool, limit: str, server_connect: bool, sort_hosts: str)
+:canonical: boardwalk.cli_run.check
+
+```{autodoc2-docstring} boardwalk.cli_run.check
+```
+````
+
+````{py:function} run_workflow(hosts: list[boardwalk.host.Host], inventory_vars: boardwalk.ansible.HostVarsType, workspace: boardwalk.manifest.Workspace, verbosity: int)
+:canonical: boardwalk.cli_run.run_workflow
+
+```{autodoc2-docstring} boardwalk.cli_run.run_workflow
+```
+````
+
+````{py:function} run_failure_mode_handler(exception: Exception, hostname: str, workspace: boardwalk.manifest.Workspace)
+:canonical: boardwalk.cli_run.run_failure_mode_handler
+
+```{autodoc2-docstring} boardwalk.cli_run.run_failure_mode_handler
+```
+````
+
+````{py:function} filter_hosts_by_limit(workspace: boardwalk.manifest.Workspace, hosts: collections.abc.ItemsView[str, boardwalk.host.Host], pattern: str) -> list[boardwalk.host.Host]
+:canonical: boardwalk.cli_run.filter_hosts_by_limit
+
+```{autodoc2-docstring} boardwalk.cli_run.filter_hosts_by_limit
+```
+````
+
+````{py:function} sort_host_list(hosts: list[boardwalk.host.Host], sort_method: str)
+:canonical: boardwalk.cli_run.sort_host_list
+
+```{autodoc2-docstring} boardwalk.cli_run.sort_host_list
+```
+````
+
+````{py:function} check_host_preconditions_locally(hosts: list[boardwalk.host.Host], inventory_vars: boardwalk.ansible.HostVarsType, workspace: boardwalk.manifest.Workspace) -> list[boardwalk.host.Host]
+:canonical: boardwalk.cli_run.check_host_preconditions_locally
+
+```{autodoc2-docstring} boardwalk.cli_run.check_host_preconditions_locally
+```
+````
+
+````{py:function} handle_workflow_catch(workspace: boardwalk.manifest.Workspace, hostname: str)
+:canonical: boardwalk.cli_run.handle_workflow_catch
+
+```{autodoc2-docstring} boardwalk.cli_run.handle_workflow_catch
+```
+````
+
+````{py:function} lock_remote_host(host: boardwalk.host.Host)
+:canonical: boardwalk.cli_run.lock_remote_host
+
+```{autodoc2-docstring} boardwalk.cli_run.lock_remote_host
+```
+````
+
+````{py:function} bootstrap_with_server(workspace: boardwalk.manifest.Workspace, ctx: click.Context)
+:canonical: boardwalk.cli_run.bootstrap_with_server
+
+```{autodoc2-docstring} boardwalk.cli_run.bootstrap_with_server
+```
+````
+
+````{py:function} update_host_facts_in_local_state(host: boardwalk.host.Host, workspace: boardwalk.manifest.Workspace)
+:canonical: boardwalk.cli_run.update_host_facts_in_local_state
+
+```{autodoc2-docstring} boardwalk.cli_run.update_host_facts_in_local_state
+```
+````
+
+````{py:function} directly_confirm_host_preconditions(host: boardwalk.host.Host, inventory_vars: boardwalk.ansible.InventoryHostVars, workspace: boardwalk.manifest.Workspace) -> bool
+:canonical: boardwalk.cli_run.directly_confirm_host_preconditions
+
+```{autodoc2-docstring} boardwalk.cli_run.directly_confirm_host_preconditions
+```
+````
+
+````{py:function} execute_workflow_jobs(host: boardwalk.host.Host, workspace: boardwalk.manifest.Workspace, job_kind: str, verbosity: int)
+:canonical: boardwalk.cli_run.execute_workflow_jobs
+
+```{autodoc2-docstring} boardwalk.cli_run.execute_workflow_jobs
+```
+````
+
+````{py:function} execute_host_workflow(host: boardwalk.host.Host, workspace: boardwalk.manifest.Workspace, verbosity: int)
+:canonical: boardwalk.cli_run.execute_host_workflow
+
+```{autodoc2-docstring} boardwalk.cli_run.execute_host_workflow
+```
+````
+
+````{py:exception} NoHostsMatched()
+:canonical: boardwalk.cli_run.NoHostsMatched
+
+Bases: {py:obj}`Exception`
+
+```{autodoc2-docstring} boardwalk.cli_run.NoHostsMatched
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.cli_run.NoHostsMatched.__init__
+```
+
+````
+
+````{py:exception} HostPreConditionsUnmet()
+:canonical: boardwalk.cli_run.HostPreConditionsUnmet
+
+Bases: {py:obj}`Exception`
+
+```{autodoc2-docstring} boardwalk.cli_run.HostPreConditionsUnmet
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.cli_run.HostPreConditionsUnmet.__init__
+```
+
+````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.cli_workspace.md b/docs/source/apidocs/boardwalk/boardwalk.cli_workspace.md
new file mode 100644
index 0000000..0969251
--- /dev/null
+++ b/docs/source/apidocs/boardwalk/boardwalk.cli_workspace.md
@@ -0,0 +1,97 @@
+# {py:mod}`boardwalk.cli_workspace`
+
+```{py:module} boardwalk.cli_workspace
+```
+
+```{autodoc2-docstring} boardwalk.cli_workspace
+:allowtitles:
+```
+
+## Module Contents
+
+### Functions
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`workspace `
+ - ```{autodoc2-docstring} boardwalk.cli_workspace.workspace
+ :summary:
+ ```
+* - {py:obj}`workspace_show `
+ - ```{autodoc2-docstring} boardwalk.cli_workspace.workspace_show
+ :summary:
+ ```
+* - {py:obj}`workspace_use_completion `
+ - ```{autodoc2-docstring} boardwalk.cli_workspace.workspace_use_completion
+ :summary:
+ ```
+* - {py:obj}`workspace_use `
+ - ```{autodoc2-docstring} boardwalk.cli_workspace.workspace_use
+ :summary:
+ ```
+* - {py:obj}`workspace_list `
+ - ```{autodoc2-docstring} boardwalk.cli_workspace.workspace_list
+ :summary:
+ ```
+* - {py:obj}`workspace_reset `
+ - ```{autodoc2-docstring} boardwalk.cli_workspace.workspace_reset
+ :summary:
+ ```
+* - {py:obj}`workspace_dump `
+ - ```{autodoc2-docstring} boardwalk.cli_workspace.workspace_dump
+ :summary:
+ ```
+````
+
+### API
+
+````{py:function} workspace()
+:canonical: boardwalk.cli_workspace.workspace
+
+```{autodoc2-docstring} boardwalk.cli_workspace.workspace
+```
+````
+
+````{py:function} workspace_show()
+:canonical: boardwalk.cli_workspace.workspace_show
+
+```{autodoc2-docstring} boardwalk.cli_workspace.workspace_show
+```
+````
+
+````{py:function} workspace_use_completion(ctx, param, incomplete)
+:canonical: boardwalk.cli_workspace.workspace_use_completion
+
+```{autodoc2-docstring} boardwalk.cli_workspace.workspace_use_completion
+```
+````
+
+````{py:function} workspace_use(workspace_name: str)
+:canonical: boardwalk.cli_workspace.workspace_use
+
+```{autodoc2-docstring} boardwalk.cli_workspace.workspace_use
+```
+````
+
+````{py:function} workspace_list()
+:canonical: boardwalk.cli_workspace.workspace_list
+
+```{autodoc2-docstring} boardwalk.cli_workspace.workspace_list
+```
+````
+
+````{py:function} workspace_reset()
+:canonical: boardwalk.cli_workspace.workspace_reset
+
+```{autodoc2-docstring} boardwalk.cli_workspace.workspace_reset
+```
+````
+
+````{py:function} workspace_dump()
+:canonical: boardwalk.cli_workspace.workspace_dump
+
+```{autodoc2-docstring} boardwalk.cli_workspace.workspace_dump
+```
+````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.host.md b/docs/source/apidocs/boardwalk/boardwalk.host.md
new file mode 100644
index 0000000..1d72ed0
--- /dev/null
+++ b/docs/source/apidocs/boardwalk/boardwalk.host.md
@@ -0,0 +1,211 @@
+# {py:mod}`boardwalk.host`
+
+```{py:module} boardwalk.host
+```
+
+```{autodoc2-docstring} boardwalk.host
+:allowtitles:
+```
+
+## Module Contents
+
+### Classes
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`Host `
+ - ```{autodoc2-docstring} boardwalk.host.Host
+ :summary:
+ ```
+````
+
+### API
+
+`````{py:class} Host(/, **data: typing.Any)
+:canonical: boardwalk.host.Host
+
+Bases: {py:obj}`pydantic.BaseModel`
+
+```{autodoc2-docstring} boardwalk.host.Host
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.host.Host.__init__
+```
+
+````{py:attribute} ansible_facts
+:canonical: boardwalk.host.Host.ansible_facts
+:type: dict[str, typing.Any]
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalk.host.Host.ansible_facts
+```
+
+````
+
+````{py:attribute} name
+:canonical: boardwalk.host.Host.name
+:type: str
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalk.host.Host.name
+```
+
+````
+
+````{py:attribute} meta
+:canonical: boardwalk.host.Host.meta
+:type: dict[str, str | int | bool]
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalk.host.Host.meta
+```
+
+````
+
+````{py:attribute} remote_mutex_path
+:canonical: boardwalk.host.Host.remote_mutex_path
+:type: str
+:value: >
+ '/opt/boardwalk.mutex'
+
+```{autodoc2-docstring} boardwalk.host.Host.remote_mutex_path
+```
+
+````
+
+````{py:attribute} remote_alert_msg
+:canonical: boardwalk.host.Host.remote_alert_msg
+:type: str
+:value: >
+ 'ALERT: Boardwalk is running a workflow against this host. Services may be interrupted'
+
+```{autodoc2-docstring} boardwalk.host.Host.remote_alert_msg
+```
+
+````
+
+````{py:attribute} remote_alert_string_formatted
+:canonical: boardwalk.host.Host.remote_alert_string_formatted
+:type: str
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalk.host.Host.remote_alert_string_formatted
+```
+
+````
+
+````{py:attribute} remote_alert_motd
+:canonical: boardwalk.host.Host.remote_alert_motd
+:type: str
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalk.host.Host.remote_alert_motd
+```
+
+````
+
+````{py:attribute} remote_alert_motd_path
+:canonical: boardwalk.host.Host.remote_alert_motd_path
+:type: str
+:value: >
+ '/etc/update-motd.d/99-boardwalk-alert'
+
+```{autodoc2-docstring} boardwalk.host.Host.remote_alert_motd_path
+```
+
+````
+
+````{py:attribute} remote_alert_wall_cmd
+:canonical: boardwalk.host.Host.remote_alert_wall_cmd
+:type: str
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalk.host.Host.remote_alert_wall_cmd
+```
+
+````
+
+````{py:method} ansible_run(invocation_msg: str, tasks: boardwalk.ansible.AnsibleTasksType, job_type: boardwalk.manifest.JobTypes, verbosity: int = 0, become: bool = False, become_password: str | None = None, check: bool = False, gather_facts: bool = True, quiet: bool = True, extra_vars: dict = {}) -> ansible_runner.Runner
+:canonical: boardwalk.host.Host.ansible_run
+
+```{autodoc2-docstring} boardwalk.host.Host.ansible_run
+```
+
+````
+
+````{py:method} is_locked() -> str | bool
+:canonical: boardwalk.host.Host.is_locked
+
+```{autodoc2-docstring} boardwalk.host.Host.is_locked
+```
+
+````
+
+````{py:method} lock(become_password: str | None = None, check: bool = False, stomp_existing_locks: bool = False)
+:canonical: boardwalk.host.Host.lock
+
+```{autodoc2-docstring} boardwalk.host.Host.lock
+```
+
+````
+
+````{py:method} release(become_password: str | None = None, check: bool = False) -> None
+:canonical: boardwalk.host.Host.release
+
+```{autodoc2-docstring} boardwalk.host.Host.release
+```
+
+````
+
+````{py:method} gather_facts() -> dict[str, typing.Any]
+:canonical: boardwalk.host.Host.gather_facts
+
+```{autodoc2-docstring} boardwalk.host.Host.gather_facts
+```
+
+````
+
+````{py:method} get_remote_state() -> boardwalk.state.RemoteStateModel
+:canonical: boardwalk.host.Host.get_remote_state
+
+```{autodoc2-docstring} boardwalk.host.Host.get_remote_state
+```
+
+````
+
+````{py:method} set_remote_state(remote_state_obj: boardwalk.state.RemoteStateModel, become_password: str | None = None, check: bool = False)
+:canonical: boardwalk.host.Host.set_remote_state
+
+```{autodoc2-docstring} boardwalk.host.Host.set_remote_state
+```
+
+````
+
+`````
+
+````{py:exception} RemoteHostLocked(message: str)
+:canonical: boardwalk.host.RemoteHostLocked
+
+Bases: {py:obj}`boardwalk.app_exceptions.BoardwalkException`
+
+```{autodoc2-docstring} boardwalk.host.RemoteHostLocked
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.host.RemoteHostLocked.__init__
+```
+
+````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.manifest.md b/docs/source/apidocs/boardwalk/boardwalk.manifest.md
new file mode 100644
index 0000000..dc4f498
--- /dev/null
+++ b/docs/source/apidocs/boardwalk/boardwalk.manifest.md
@@ -0,0 +1,610 @@
+# {py:mod}`boardwalk.manifest`
+
+```{py:module} boardwalk.manifest
+```
+
+```{autodoc2-docstring} boardwalk.manifest
+:allowtitles:
+```
+
+## Module Contents
+
+### Classes
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`JobTypes `
+ -
+* - {py:obj}`BaseJob `
+ - ```{autodoc2-docstring} boardwalk.manifest.BaseJob
+ :summary:
+ ```
+* - {py:obj}`TaskJob `
+ - ```{autodoc2-docstring} boardwalk.manifest.TaskJob
+ :summary:
+ ```
+* - {py:obj}`Job `
+ - ```{autodoc2-docstring} boardwalk.manifest.Job
+ :summary:
+ ```
+* - {py:obj}`PlaybookJob `
+ - ```{autodoc2-docstring} boardwalk.manifest.PlaybookJob
+ :summary:
+ ```
+* - {py:obj}`WorkflowConfig `
+ - ```{autodoc2-docstring} boardwalk.manifest.WorkflowConfig
+ :summary:
+ ```
+* - {py:obj}`Workflow `
+ - ```{autodoc2-docstring} boardwalk.manifest.Workflow
+ :summary:
+ ```
+* - {py:obj}`WorkspaceConfig `
+ - ```{autodoc2-docstring} boardwalk.manifest.WorkspaceConfig
+ :summary:
+ ```
+* - {py:obj}`Workspace `
+ - ```{autodoc2-docstring} boardwalk.manifest.Workspace
+ :summary:
+ ```
+````
+
+### Functions
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`get_ws `
+ - ```{autodoc2-docstring} boardwalk.manifest.get_ws
+ :summary:
+ ```
+* - {py:obj}`get_boardwalkd_url `
+ - ```{autodoc2-docstring} boardwalk.manifest.get_boardwalkd_url
+ :summary:
+ ```
+* - {py:obj}`path `
+ - ```{autodoc2-docstring} boardwalk.manifest.path
+ :summary:
+ ```
+````
+
+### Data
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`workspaces_dir `
+ - ```{autodoc2-docstring} boardwalk.manifest.workspaces_dir
+ :summary:
+ ```
+* - {py:obj}`active_workspace_file `
+ - ```{autodoc2-docstring} boardwalk.manifest.active_workspace_file
+ :summary:
+ ```
+````
+
+### API
+
+````{py:data} workspaces_dir
+:canonical: boardwalk.manifest.workspaces_dir
+:value: >
+ 'joinpath(...)'
+
+```{autodoc2-docstring} boardwalk.manifest.workspaces_dir
+```
+
+````
+
+````{py:data} active_workspace_file
+:canonical: boardwalk.manifest.active_workspace_file
+:value: >
+ 'joinpath(...)'
+
+```{autodoc2-docstring} boardwalk.manifest.active_workspace_file
+```
+
+````
+
+````{py:exception} DuplicateManifestClass()
+:canonical: boardwalk.manifest.DuplicateManifestClass
+
+Bases: {py:obj}`Exception`
+
+```{autodoc2-docstring} boardwalk.manifest.DuplicateManifestClass
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.manifest.DuplicateManifestClass.__init__
+```
+
+````
+
+````{py:exception} ManifestNotFound()
+:canonical: boardwalk.manifest.ManifestNotFound
+
+Bases: {py:obj}`Exception`
+
+```{autodoc2-docstring} boardwalk.manifest.ManifestNotFound
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.manifest.ManifestNotFound.__init__
+```
+
+````
+
+`````{py:exception} NoActiveWorkspace()
+:canonical: boardwalk.manifest.NoActiveWorkspace
+
+Bases: {py:obj}`Exception`
+
+```{autodoc2-docstring} boardwalk.manifest.NoActiveWorkspace
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.manifest.NoActiveWorkspace.__init__
+```
+
+````{py:attribute} message
+:canonical: boardwalk.manifest.NoActiveWorkspace.message
+:value: >
+ 'No workspace selected. Use `boardwalk workspace list` to list workspaces and `boardwalk workspace us...'
+
+```{autodoc2-docstring} boardwalk.manifest.NoActiveWorkspace.message
+```
+
+````
+
+`````
+
+````{py:exception} WorkspaceNotFound()
+:canonical: boardwalk.manifest.WorkspaceNotFound
+
+Bases: {py:obj}`Exception`
+
+```{autodoc2-docstring} boardwalk.manifest.WorkspaceNotFound
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.manifest.WorkspaceNotFound.__init__
+```
+
+````
+
+````{py:function} get_ws() -> Workspace
+:canonical: boardwalk.manifest.get_ws
+
+```{autodoc2-docstring} boardwalk.manifest.get_ws
+```
+````
+
+````{py:function} get_boardwalkd_url() -> str
+:canonical: boardwalk.manifest.get_boardwalkd_url
+
+```{autodoc2-docstring} boardwalk.manifest.get_boardwalkd_url
+```
+````
+
+`````{py:class} JobTypes(*args, **kwds)
+:canonical: boardwalk.manifest.JobTypes
+
+Bases: {py:obj}`enum.Enum`
+
+````{py:attribute} TASK
+:canonical: boardwalk.manifest.JobTypes.TASK
+:value: >
+ 1
+
+```{autodoc2-docstring} boardwalk.manifest.JobTypes.TASK
+```
+
+````
+
+````{py:attribute} PLAYBOOK
+:canonical: boardwalk.manifest.JobTypes.PLAYBOOK
+:value: >
+ 2
+
+```{autodoc2-docstring} boardwalk.manifest.JobTypes.PLAYBOOK
+```
+
+````
+
+`````
+
+`````{py:class} BaseJob(options: dict[str, typing.Any] = dict())
+:canonical: boardwalk.manifest.BaseJob
+
+```{autodoc2-docstring} boardwalk.manifest.BaseJob
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.manifest.BaseJob.__init__
+```
+
+````{py:attribute} options
+:canonical: boardwalk.manifest.BaseJob.options
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalk.manifest.BaseJob.options
+```
+
+````
+
+````{py:method} required_options() -> tuple[str]
+:canonical: boardwalk.manifest.BaseJob.required_options
+
+```{autodoc2-docstring} boardwalk.manifest.BaseJob.required_options
+```
+
+````
+
+````{py:method} preconditions(facts: boardwalk.ansible.AnsibleFacts, inventory_vars: boardwalk.ansible.InventoryHostVars) -> bool
+:canonical: boardwalk.manifest.BaseJob.preconditions
+
+```{autodoc2-docstring} boardwalk.manifest.BaseJob.preconditions
+```
+
+````
+
+````{py:method} _required_options() -> tuple[str]
+:canonical: boardwalk.manifest.BaseJob._required_options
+
+```{autodoc2-docstring} boardwalk.manifest.BaseJob._required_options
+```
+
+````
+
+````{py:method} _check_options(options: dict[str, typing.Any])
+:canonical: boardwalk.manifest.BaseJob._check_options
+
+```{autodoc2-docstring} boardwalk.manifest.BaseJob._check_options
+```
+
+````
+
+`````
+
+`````{py:class} TaskJob(options: dict[str, typing.Any] = dict())
+:canonical: boardwalk.manifest.TaskJob
+
+Bases: {py:obj}`boardwalk.manifest.BaseJob`
+
+```{autodoc2-docstring} boardwalk.manifest.TaskJob
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.manifest.TaskJob.__init__
+```
+
+````{py:method} tasks() -> boardwalk.ansible.AnsibleTasksType
+:canonical: boardwalk.manifest.TaskJob.tasks
+
+```{autodoc2-docstring} boardwalk.manifest.TaskJob.tasks
+```
+
+````
+
+`````
+
+````{py:class} Job(options: dict[str, typing.Any] = dict())
+:canonical: boardwalk.manifest.Job
+
+Bases: {py:obj}`boardwalk.manifest.TaskJob`
+
+```{autodoc2-docstring} boardwalk.manifest.Job
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.manifest.Job.__init__
+```
+
+````
+
+`````{py:class} PlaybookJob(options: dict[str, typing.Any] = dict())
+:canonical: boardwalk.manifest.PlaybookJob
+
+Bases: {py:obj}`boardwalk.manifest.BaseJob`
+
+```{autodoc2-docstring} boardwalk.manifest.PlaybookJob
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.manifest.PlaybookJob.__init__
+```
+
+````{py:method} tasks() -> boardwalk.ansible.AnsibleTasksType
+:canonical: boardwalk.manifest.PlaybookJob.tasks
+
+```{autodoc2-docstring} boardwalk.manifest.PlaybookJob.tasks
+```
+
+````
+
+````{py:method} playbooks() -> boardwalk.ansible.AnsibleTasksType
+:canonical: boardwalk.manifest.PlaybookJob.playbooks
+
+```{autodoc2-docstring} boardwalk.manifest.PlaybookJob.playbooks
+```
+
+````
+
+`````
+
+````{py:class} WorkflowConfig(always_retry_failed_hosts: bool = True)
+:canonical: boardwalk.manifest.WorkflowConfig
+
+```{autodoc2-docstring} boardwalk.manifest.WorkflowConfig
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.manifest.WorkflowConfig.__init__
+```
+
+````
+
+`````{py:class} Workflow()
+:canonical: boardwalk.manifest.Workflow
+
+Bases: {py:obj}`abc.ABC`
+
+```{autodoc2-docstring} boardwalk.manifest.Workflow
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.manifest.Workflow.__init__
+```
+
+````{py:method} config() -> boardwalk.manifest.WorkflowConfig
+:canonical: boardwalk.manifest.Workflow.config
+
+```{autodoc2-docstring} boardwalk.manifest.Workflow.config
+```
+
+````
+
+````{py:method} jobs()
+:canonical: boardwalk.manifest.Workflow.jobs
+:abstractmethod:
+
+```{autodoc2-docstring} boardwalk.manifest.Workflow.jobs
+```
+
+````
+
+````{py:method} exit_jobs() -> boardwalk.manifest.TaskJob | boardwalk.manifest.PlaybookJob | tuple[boardwalk.manifest.TaskJob | boardwalk.manifest.PlaybookJob, ...]
+:canonical: boardwalk.manifest.Workflow.exit_jobs
+
+```{autodoc2-docstring} boardwalk.manifest.Workflow.exit_jobs
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceConfig(host_pattern: str, workflow: boardwalk.manifest.Workflow, default_sort_order: str = 'shuffle', require_limit: bool = False)
+:canonical: boardwalk.manifest.WorkspaceConfig
+
+```{autodoc2-docstring} boardwalk.manifest.WorkspaceConfig
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.manifest.WorkspaceConfig.__init__
+```
+
+````{py:attribute} valid_sort_orders
+:canonical: boardwalk.manifest.WorkspaceConfig.valid_sort_orders
+:value: >
+ ['ascending', 'descending', 'shuffle']
+
+```{autodoc2-docstring} boardwalk.manifest.WorkspaceConfig.valid_sort_orders
+```
+
+````
+
+````{py:property} default_sort_order
+:canonical: boardwalk.manifest.WorkspaceConfig.default_sort_order
+:type: str
+
+```{autodoc2-docstring} boardwalk.manifest.WorkspaceConfig.default_sort_order
+```
+
+````
+
+````{py:method} _is_valid_sort_order(value: str)
+:canonical: boardwalk.manifest.WorkspaceConfig._is_valid_sort_order
+
+```{autodoc2-docstring} boardwalk.manifest.WorkspaceConfig._is_valid_sort_order
+```
+
+````
+
+`````
+
+`````{py:class} Workspace()
+:canonical: boardwalk.manifest.Workspace
+
+Bases: {py:obj}`abc.ABC`
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace.__init__
+```
+
+````{py:attribute} _initialized
+:canonical: boardwalk.manifest.Workspace._initialized
+:type: bool
+:value: >
+ False
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace._initialized
+```
+
+````
+
+````{py:attribute} _instance
+:canonical: boardwalk.manifest.Workspace._instance
+:type: boardwalk.manifest.Workspace | None
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace._instance
+```
+
+````
+
+````{py:method} __new__()
+:canonical: boardwalk.manifest.Workspace.__new__
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace.__new__
+```
+
+````
+
+````{py:method} assert_host_pattern_unchanged() -> None
+:canonical: boardwalk.manifest.Workspace.assert_host_pattern_unchanged
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace.assert_host_pattern_unchanged
+```
+
+````
+
+````{py:method} config() -> boardwalk.manifest.WorkspaceConfig
+:canonical: boardwalk.manifest.Workspace.config
+:abstractmethod:
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace.config
+```
+
+````
+
+````{py:method} flush()
+:canonical: boardwalk.manifest.Workspace.flush
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace.flush
+```
+
+````
+
+````{py:method} reset()
+:canonical: boardwalk.manifest.Workspace.reset
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace.reset
+```
+
+````
+
+````{py:method} mutex()
+:canonical: boardwalk.manifest.Workspace.mutex
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace.mutex
+```
+
+````
+
+````{py:method} has_mutex()
+:canonical: boardwalk.manifest.Workspace.has_mutex
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace.has_mutex
+```
+
+````
+
+````{py:method} unmutex()
+:canonical: boardwalk.manifest.Workspace.unmutex
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace.unmutex
+```
+
+````
+
+````{py:method} catch()
+:canonical: boardwalk.manifest.Workspace.catch
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace.catch
+```
+
+````
+
+````{py:method} caught()
+:canonical: boardwalk.manifest.Workspace.caught
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace.caught
+```
+
+````
+
+````{py:method} release()
+:canonical: boardwalk.manifest.Workspace.release
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace.release
+```
+
+````
+
+````{py:method} use(name: str)
+:canonical: boardwalk.manifest.Workspace.use
+:staticmethod:
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace.use
+```
+
+````
+
+````{py:method} exists(name: str) -> bool
+:canonical: boardwalk.manifest.Workspace.exists
+:staticmethod:
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace.exists
+```
+
+````
+
+````{py:method} fetch_subclass(name: str) -> collections.abc.Callable[..., boardwalk.manifest.Workspace]
+:canonical: boardwalk.manifest.Workspace.fetch_subclass
+:staticmethod:
+
+```{autodoc2-docstring} boardwalk.manifest.Workspace.fetch_subclass
+```
+
+````
+
+`````
+
+````{py:function} path(file_path: str) -> str
+:canonical: boardwalk.manifest.path
+
+```{autodoc2-docstring} boardwalk.manifest.path
+```
+````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.md b/docs/source/apidocs/boardwalk/boardwalk.md
new file mode 100644
index 0000000..2fc7be8
--- /dev/null
+++ b/docs/source/apidocs/boardwalk/boardwalk.md
@@ -0,0 +1,29 @@
+# {py:mod}`boardwalk`
+
+```{py:module} boardwalk
+```
+
+```{autodoc2-docstring} boardwalk
+:allowtitles:
+```
+
+## Submodules
+
+```{toctree}
+:titlesonly:
+:maxdepth: 1
+
+boardwalk.ansible
+boardwalk.manifest
+boardwalk.cli_login
+boardwalk.cli_catch
+boardwalk.host
+boardwalk.app_exceptions
+boardwalk.cli_init
+boardwalk.cli_run
+boardwalk.cli
+boardwalk.utils
+boardwalk.cli_workspace
+boardwalk.__main__
+boardwalk.state
+```
diff --git a/docs/source/apidocs/boardwalk/boardwalk.state.md b/docs/source/apidocs/boardwalk/boardwalk.state.md
new file mode 100644
index 0000000..5a6eaef
--- /dev/null
+++ b/docs/source/apidocs/boardwalk/boardwalk.state.md
@@ -0,0 +1,186 @@
+# {py:mod}`boardwalk.state`
+
+```{py:module} boardwalk.state
+```
+
+```{autodoc2-docstring} boardwalk.state
+:allowtitles:
+```
+
+## Module Contents
+
+### Classes
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`StateBaseModel `
+ - ```{autodoc2-docstring} boardwalk.state.StateBaseModel
+ :summary:
+ ```
+* - {py:obj}`LocalState `
+ - ```{autodoc2-docstring} boardwalk.state.LocalState
+ :summary:
+ ```
+* - {py:obj}`RemoteStateWorkflow `
+ - ```{autodoc2-docstring} boardwalk.state.RemoteStateWorkflow
+ :summary:
+ ```
+* - {py:obj}`RemoteStateWorkspace `
+ - ```{autodoc2-docstring} boardwalk.state.RemoteStateWorkspace
+ :summary:
+ ```
+* - {py:obj}`RemoteStateModel `
+ - ```{autodoc2-docstring} boardwalk.state.RemoteStateModel
+ :summary:
+ ```
+````
+
+### API
+
+````{py:class} StateBaseModel(/, **data: typing.Any)
+:canonical: boardwalk.state.StateBaseModel
+
+Bases: {py:obj}`pydantic.BaseModel`
+
+```{autodoc2-docstring} boardwalk.state.StateBaseModel
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.state.StateBaseModel.__init__
+```
+
+````
+
+`````{py:class} LocalState(/, **data: typing.Any)
+:canonical: boardwalk.state.LocalState
+
+Bases: {py:obj}`boardwalk.state.StateBaseModel`
+
+```{autodoc2-docstring} boardwalk.state.LocalState
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.state.LocalState.__init__
+```
+
+````{py:attribute} host_pattern
+:canonical: boardwalk.state.LocalState.host_pattern
+:type: str
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalk.state.LocalState.host_pattern
+```
+
+````
+
+````{py:attribute} hosts
+:canonical: boardwalk.state.LocalState.hosts
+:type: dict[str, boardwalk.host.Host]
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalk.state.LocalState.hosts
+```
+
+````
+
+`````
+
+`````{py:class} RemoteStateWorkflow(/, **data: typing.Any)
+:canonical: boardwalk.state.RemoteStateWorkflow
+
+Bases: {py:obj}`boardwalk.state.StateBaseModel`
+
+```{autodoc2-docstring} boardwalk.state.RemoteStateWorkflow
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.state.RemoteStateWorkflow.__init__
+```
+
+````{py:attribute} started
+:canonical: boardwalk.state.RemoteStateWorkflow.started
+:type: bool
+:value: >
+ False
+
+```{autodoc2-docstring} boardwalk.state.RemoteStateWorkflow.started
+```
+
+````
+
+````{py:attribute} succeeded
+:canonical: boardwalk.state.RemoteStateWorkflow.succeeded
+:type: bool
+:value: >
+ False
+
+```{autodoc2-docstring} boardwalk.state.RemoteStateWorkflow.succeeded
+```
+
+````
+
+`````
+
+`````{py:class} RemoteStateWorkspace(/, **data: typing.Any)
+:canonical: boardwalk.state.RemoteStateWorkspace
+
+Bases: {py:obj}`boardwalk.state.StateBaseModel`
+
+```{autodoc2-docstring} boardwalk.state.RemoteStateWorkspace
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.state.RemoteStateWorkspace.__init__
+```
+
+````{py:attribute} workflow
+:canonical: boardwalk.state.RemoteStateWorkspace.workflow
+:type: boardwalk.state.RemoteStateWorkflow
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalk.state.RemoteStateWorkspace.workflow
+```
+
+````
+
+`````
+
+`````{py:class} RemoteStateModel(/, **data: typing.Any)
+:canonical: boardwalk.state.RemoteStateModel
+
+Bases: {py:obj}`boardwalk.state.StateBaseModel`
+
+```{autodoc2-docstring} boardwalk.state.RemoteStateModel
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalk.state.RemoteStateModel.__init__
+```
+
+````{py:attribute} workspaces
+:canonical: boardwalk.state.RemoteStateModel.workspaces
+:type: dict[str, boardwalk.state.RemoteStateWorkspace]
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalk.state.RemoteStateModel.workspaces
+```
+
+````
+
+`````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.utils.md b/docs/source/apidocs/boardwalk/boardwalk.utils.md
new file mode 100644
index 0000000..d4951e3
--- /dev/null
+++ b/docs/source/apidocs/boardwalk/boardwalk.utils.md
@@ -0,0 +1,31 @@
+# {py:mod}`boardwalk.utils`
+
+```{py:module} boardwalk.utils
+```
+
+```{autodoc2-docstring} boardwalk.utils
+:allowtitles:
+```
+
+## Module Contents
+
+### Functions
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`strtobool `
+ - ```{autodoc2-docstring} boardwalk.utils.strtobool
+ :summary:
+ ```
+````
+
+### API
+
+````{py:function} strtobool(val: str) -> bool
+:canonical: boardwalk.utils.strtobool
+
+```{autodoc2-docstring} boardwalk.utils.strtobool
+```
+````
diff --git a/docs/source/apidocs/boardwalkd/boardwalkd.__main__.md b/docs/source/apidocs/boardwalkd/boardwalkd.__main__.md
new file mode 100644
index 0000000..ea70e29
--- /dev/null
+++ b/docs/source/apidocs/boardwalkd/boardwalkd.__main__.md
@@ -0,0 +1,8 @@
+# {py:mod}`boardwalkd.__main__`
+
+```{py:module} boardwalkd.__main__
+```
+
+```{autodoc2-docstring} boardwalkd.__main__
+:allowtitles:
+```
diff --git a/docs/source/apidocs/boardwalkd/boardwalkd.broadcast.md b/docs/source/apidocs/boardwalkd/boardwalkd.broadcast.md
new file mode 100644
index 0000000..f20c618
--- /dev/null
+++ b/docs/source/apidocs/boardwalkd/boardwalkd.broadcast.md
@@ -0,0 +1,32 @@
+# {py:mod}`boardwalkd.broadcast`
+
+```{py:module} boardwalkd.broadcast
+```
+
+```{autodoc2-docstring} boardwalkd.broadcast
+:allowtitles:
+```
+
+## Module Contents
+
+### Functions
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`handle_slack_broadcast `
+ - ```{autodoc2-docstring} boardwalkd.broadcast.handle_slack_broadcast
+ :summary:
+ ```
+````
+
+### API
+
+````{py:function} handle_slack_broadcast(event: boardwalkd.protocol.WorkspaceEvent, workspace: str, webhook_url: str | None, error_webhook_url: str | None, server_url: str)
+:canonical: boardwalkd.broadcast.handle_slack_broadcast
+:async:
+
+```{autodoc2-docstring} boardwalkd.broadcast.handle_slack_broadcast
+```
+````
diff --git a/docs/source/apidocs/boardwalkd/boardwalkd.cli.md b/docs/source/apidocs/boardwalkd/boardwalkd.cli.md
new file mode 100644
index 0000000..7b7aa96
--- /dev/null
+++ b/docs/source/apidocs/boardwalkd/boardwalkd.cli.md
@@ -0,0 +1,76 @@
+# {py:mod}`boardwalkd.cli`
+
+```{py:module} boardwalkd.cli
+```
+
+```{autodoc2-docstring} boardwalkd.cli
+:allowtitles:
+```
+
+## Module Contents
+
+### Functions
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`cli `
+ - ```{autodoc2-docstring} boardwalkd.cli.cli
+ :summary:
+ ```
+* - {py:obj}`serve `
+ - ```{autodoc2-docstring} boardwalkd.cli.serve
+ :summary:
+ ```
+* - {py:obj}`version `
+ - ```{autodoc2-docstring} boardwalkd.cli.version
+ :summary:
+ ```
+````
+
+### Data
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`CONTEXT_SETTINGS `
+ - ```{autodoc2-docstring} boardwalkd.cli.CONTEXT_SETTINGS
+ :summary:
+ ```
+````
+
+### API
+
+````{py:data} CONTEXT_SETTINGS
+:canonical: boardwalkd.cli.CONTEXT_SETTINGS
+:type: dict
+:value: >
+ 'dict(...)'
+
+```{autodoc2-docstring} boardwalkd.cli.CONTEXT_SETTINGS
+```
+
+````
+
+````{py:function} cli()
+:canonical: boardwalkd.cli.cli
+
+```{autodoc2-docstring} boardwalkd.cli.cli
+```
+````
+
+````{py:function} serve(auth_expire_days: float, auth_method: str, develop: bool, host_header_pattern: str, owner: str | None, port: int | None, slack_error_webhook_url: str, slack_webhook_url: str, slack_app_token: str | None, slack_bot_token: str | None, slack_slash_command_prefix: str, tls_crt: str | None, tls_key: str | None, tls_port: int | None, url: str)
+:canonical: boardwalkd.cli.serve
+
+```{autodoc2-docstring} boardwalkd.cli.serve
+```
+````
+
+````{py:function} version()
+:canonical: boardwalkd.cli.version
+
+```{autodoc2-docstring} boardwalkd.cli.version
+```
+````
diff --git a/docs/source/apidocs/boardwalkd/boardwalkd.md b/docs/source/apidocs/boardwalkd/boardwalkd.md
new file mode 100644
index 0000000..f1847e5
--- /dev/null
+++ b/docs/source/apidocs/boardwalkd/boardwalkd.md
@@ -0,0 +1,23 @@
+# {py:mod}`boardwalkd`
+
+```{py:module} boardwalkd
+```
+
+```{autodoc2-docstring} boardwalkd
+:allowtitles:
+```
+
+## Submodules
+
+```{toctree}
+:titlesonly:
+:maxdepth: 1
+
+boardwalkd.server
+boardwalkd.protocol
+boardwalkd.cli
+boardwalkd.broadcast
+boardwalkd.__main__
+boardwalkd.slack
+boardwalkd.state
+```
diff --git a/docs/source/apidocs/boardwalkd/boardwalkd.protocol.md b/docs/source/apidocs/boardwalkd/boardwalkd.protocol.md
new file mode 100644
index 0000000..1f1babe
--- /dev/null
+++ b/docs/source/apidocs/boardwalkd/boardwalkd.protocol.md
@@ -0,0 +1,554 @@
+# {py:mod}`boardwalkd.protocol`
+
+```{py:module} boardwalkd.protocol
+```
+
+```{autodoc2-docstring} boardwalkd.protocol
+:allowtitles:
+```
+
+## Module Contents
+
+### Classes
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`ProtocolBaseModel `
+ - ```{autodoc2-docstring} boardwalkd.protocol.ProtocolBaseModel
+ :summary:
+ ```
+* - {py:obj}`ApiLoginMessage `
+ - ```{autodoc2-docstring} boardwalkd.protocol.ApiLoginMessage
+ :summary:
+ ```
+* - {py:obj}`WorkspaceDetails `
+ - ```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails
+ :summary:
+ ```
+* - {py:obj}`WorkspaceEvent `
+ - ```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent
+ :summary:
+ ```
+* - {py:obj}`WorkspaceSemaphores `
+ - ```{autodoc2-docstring} boardwalkd.protocol.WorkspaceSemaphores
+ :summary:
+ ```
+* - {py:obj}`Client `
+ - ```{autodoc2-docstring} boardwalkd.protocol.Client
+ :summary:
+ ```
+* - {py:obj}`WorkspaceClient `
+ - ```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient
+ :summary:
+ ```
+````
+
+### API
+
+````{py:class} ProtocolBaseModel(/, **data: typing.Any)
+:canonical: boardwalkd.protocol.ProtocolBaseModel
+
+Bases: {py:obj}`pydantic.BaseModel`
+
+```{autodoc2-docstring} boardwalkd.protocol.ProtocolBaseModel
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.protocol.ProtocolBaseModel.__init__
+```
+
+````
+
+`````{py:class} ApiLoginMessage(/, **data: typing.Any)
+:canonical: boardwalkd.protocol.ApiLoginMessage
+
+Bases: {py:obj}`boardwalkd.protocol.ProtocolBaseModel`
+
+```{autodoc2-docstring} boardwalkd.protocol.ApiLoginMessage
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.protocol.ApiLoginMessage.__init__
+```
+
+````{py:attribute} login_url
+:canonical: boardwalkd.protocol.ApiLoginMessage.login_url
+:type: str
+:value:
+
+```{autodoc2-docstring} boardwalkd.protocol.ApiLoginMessage.login_url
+```
+
+````
+
+````{py:attribute} token
+:canonical: boardwalkd.protocol.ApiLoginMessage.token
+:type: str
+:value:
+
+```{autodoc2-docstring} boardwalkd.protocol.ApiLoginMessage.token
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceDetails(/, **data: typing.Any)
+:canonical: boardwalkd.protocol.WorkspaceDetails
+
+Bases: {py:obj}`boardwalkd.protocol.ProtocolBaseModel`
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails.__init__
+```
+
+````{py:attribute} host_pattern
+:canonical: boardwalkd.protocol.WorkspaceDetails.host_pattern
+:type: str
+:value:
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails.host_pattern
+```
+
+````
+
+````{py:attribute} workflow
+:canonical: boardwalkd.protocol.WorkspaceDetails.workflow
+:type: str
+:value:
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails.workflow
+```
+
+````
+
+````{py:attribute} worker_command
+:canonical: boardwalkd.protocol.WorkspaceDetails.worker_command
+:type: str
+:value:
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails.worker_command
+```
+
+````
+
+````{py:attribute} worker_hostname
+:canonical: boardwalkd.protocol.WorkspaceDetails.worker_hostname
+:type: str
+:value:
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails.worker_hostname
+```
+
+````
+
+````{py:attribute} worker_limit
+:canonical: boardwalkd.protocol.WorkspaceDetails.worker_limit
+:type: str
+:value:
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails.worker_limit
+```
+
+````
+
+````{py:attribute} worker_username
+:canonical: boardwalkd.protocol.WorkspaceDetails.worker_username
+:type: str
+:value:
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails.worker_username
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceEvent(**kwargs: str)
+:canonical: boardwalkd.protocol.WorkspaceEvent
+
+Bases: {py:obj}`boardwalkd.protocol.ProtocolBaseModel`
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent.__init__
+```
+
+````{py:attribute} message
+:canonical: boardwalkd.protocol.WorkspaceEvent.message
+:type: str
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent.message
+```
+
+````
+
+````{py:attribute} severity
+:canonical: boardwalkd.protocol.WorkspaceEvent.severity
+:type: str
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent.severity
+```
+
+````
+
+````{py:attribute} create_time
+:canonical: boardwalkd.protocol.WorkspaceEvent.create_time
+:type: datetime.datetime | None
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent.create_time
+```
+
+````
+
+````{py:attribute} received_time
+:canonical: boardwalkd.protocol.WorkspaceEvent.received_time
+:type: datetime.datetime | None
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent.received_time
+```
+
+````
+
+````{py:method} severity_level(v: str)
+:canonical: boardwalkd.protocol.WorkspaceEvent.severity_level
+:classmethod:
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent.severity_level
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceSemaphores(/, **data: typing.Any)
+:canonical: boardwalkd.protocol.WorkspaceSemaphores
+
+Bases: {py:obj}`boardwalkd.protocol.ProtocolBaseModel`
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceSemaphores
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceSemaphores.__init__
+```
+
+````{py:attribute} caught
+:canonical: boardwalkd.protocol.WorkspaceSemaphores.caught
+:type: bool
+:value: >
+ False
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceSemaphores.caught
+```
+
+````
+
+````{py:attribute} has_mutex
+:canonical: boardwalkd.protocol.WorkspaceSemaphores.has_mutex
+:type: bool
+:value: >
+ False
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceSemaphores.has_mutex
+```
+
+````
+
+`````
+
+````{py:exception} WorkspaceNotFound()
+:canonical: boardwalkd.protocol.WorkspaceNotFound
+
+Bases: {py:obj}`Exception`
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceNotFound
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceNotFound.__init__
+```
+
+````
+
+````{py:exception} WorkspaceHasMutex()
+:canonical: boardwalkd.protocol.WorkspaceHasMutex
+
+Bases: {py:obj}`Exception`
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceHasMutex
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceHasMutex.__init__
+```
+
+````
+
+`````{py:class} Client(url: str)
+:canonical: boardwalkd.protocol.Client
+
+```{autodoc2-docstring} boardwalkd.protocol.Client
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.__init__
+```
+
+````{py:method} get_api_token() -> str
+:canonical: boardwalkd.protocol.Client.get_api_token
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.get_api_token
+```
+
+````
+
+````{py:method} api_login()
+:canonical: boardwalkd.protocol.Client.api_login
+:async:
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.api_login
+```
+
+````
+
+````{py:method} authenticated_request(path: str, method: str = 'GET', body: bytes | str | None = None, auto_login_prompt: bool = True) -> tornado.httpclient.HTTPResponse
+:canonical: boardwalkd.protocol.Client.authenticated_request
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.authenticated_request
+```
+
+````
+
+````{py:method} workspace_delete_mutex(workspace_name: str)
+:canonical: boardwalkd.protocol.Client.workspace_delete_mutex
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_delete_mutex
+```
+
+````
+
+````{py:method} workspace_get_details(workspace_name: str) -> boardwalkd.protocol.WorkspaceDetails
+:canonical: boardwalkd.protocol.Client.workspace_get_details
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_get_details
+```
+
+````
+
+````{py:method} workspace_post_catch(workspace_name: str)
+:canonical: boardwalkd.protocol.Client.workspace_post_catch
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_post_catch
+```
+
+````
+
+````{py:method} workspace_post_details(workspace_name: str, workspace_details: boardwalkd.protocol.WorkspaceDetails)
+:canonical: boardwalkd.protocol.Client.workspace_post_details
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_post_details
+```
+
+````
+
+````{py:method} workspace_post_heartbeat(workspace_name: str)
+:canonical: boardwalkd.protocol.Client.workspace_post_heartbeat
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_post_heartbeat
+```
+
+````
+
+````{py:method} workspace_heartbeat_keepalive(workspace_name: str, quit: threading.Event) -> None
+:canonical: boardwalkd.protocol.Client.workspace_heartbeat_keepalive
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_heartbeat_keepalive
+```
+
+````
+
+````{py:method} workspace_heartbeat_keepalive_connect(workspace_name: str) -> threading.Event
+:canonical: boardwalkd.protocol.Client.workspace_heartbeat_keepalive_connect
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_heartbeat_keepalive_connect
+```
+
+````
+
+````{py:method} workspace_post_event(workspace_name: str, workspace_event: boardwalkd.protocol.WorkspaceEvent, broadcast: bool = False)
+:canonical: boardwalkd.protocol.Client.workspace_post_event
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_post_event
+```
+
+````
+
+````{py:method} workspace_queue_event(workspace_name: str, workspace_event: boardwalkd.protocol.WorkspaceEvent, broadcast: bool = False)
+:canonical: boardwalkd.protocol.Client.workspace_queue_event
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_queue_event
+```
+
+````
+
+````{py:method} flush_event_queue()
+:canonical: boardwalkd.protocol.Client.flush_event_queue
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.flush_event_queue
+```
+
+````
+
+````{py:method} workspace_post_mutex(workspace_name: str)
+:canonical: boardwalkd.protocol.Client.workspace_post_mutex
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_post_mutex
+```
+
+````
+
+````{py:method} workspace_get_semaphores(workspace_name: str) -> boardwalkd.protocol.WorkspaceSemaphores
+:canonical: boardwalkd.protocol.Client.workspace_get_semaphores
+
+```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_get_semaphores
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceClient(url: str, workspace_name: str)
+:canonical: boardwalkd.protocol.WorkspaceClient
+
+Bases: {py:obj}`boardwalkd.protocol.Client`
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.__init__
+```
+
+````{py:method} get_semaphores() -> boardwalkd.protocol.WorkspaceSemaphores
+:canonical: boardwalkd.protocol.WorkspaceClient.get_semaphores
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.get_semaphores
+```
+
+````
+
+````{py:method} has_mutex() -> bool
+:canonical: boardwalkd.protocol.WorkspaceClient.has_mutex
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.has_mutex
+```
+
+````
+
+````{py:method} post_catch()
+:canonical: boardwalkd.protocol.WorkspaceClient.post_catch
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.post_catch
+```
+
+````
+
+````{py:method} caught() -> bool
+:canonical: boardwalkd.protocol.WorkspaceClient.caught
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.caught
+```
+
+````
+
+````{py:method} heartbeat_keepalive_connect()
+:canonical: boardwalkd.protocol.WorkspaceClient.heartbeat_keepalive_connect
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.heartbeat_keepalive_connect
+```
+
+````
+
+````{py:method} mutex()
+:canonical: boardwalkd.protocol.WorkspaceClient.mutex
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.mutex
+```
+
+````
+
+````{py:method} post_details(workspace_details: boardwalkd.protocol.WorkspaceDetails)
+:canonical: boardwalkd.protocol.WorkspaceClient.post_details
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.post_details
+```
+
+````
+
+````{py:method} post_heartbeat()
+:canonical: boardwalkd.protocol.WorkspaceClient.post_heartbeat
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.post_heartbeat
+```
+
+````
+
+````{py:method} post_event(workspace_event: boardwalkd.protocol.WorkspaceEvent, broadcast: bool = False)
+:canonical: boardwalkd.protocol.WorkspaceClient.post_event
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.post_event
+```
+
+````
+
+````{py:method} queue_event(workspace_event: boardwalkd.protocol.WorkspaceEvent, broadcast: bool = False)
+:canonical: boardwalkd.protocol.WorkspaceClient.queue_event
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.queue_event
+```
+
+````
+
+````{py:method} unmutex()
+:canonical: boardwalkd.protocol.WorkspaceClient.unmutex
+
+```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.unmutex
+```
+
+````
+
+`````
diff --git a/docs/source/apidocs/boardwalkd/boardwalkd.server.md b/docs/source/apidocs/boardwalkd/boardwalkd.server.md
new file mode 100644
index 0000000..1f93a9c
--- /dev/null
+++ b/docs/source/apidocs/boardwalkd/boardwalkd.server.md
@@ -0,0 +1,1005 @@
+# {py:mod}`boardwalkd.server`
+
+```{py:module} boardwalkd.server
+```
+
+```{autodoc2-docstring} boardwalkd.server
+:allowtitles:
+```
+
+## Module Contents
+
+### Classes
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`UIBaseHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.UIBaseHandler
+ :summary:
+ ```
+* - {py:obj}`AdminUIBaseHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.AdminUIBaseHandler
+ :summary:
+ ```
+* - {py:obj}`AdminHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.AdminHandler
+ :summary:
+ ```
+* - {py:obj}`UserEnableHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.UserEnableHandler
+ :summary:
+ ```
+* - {py:obj}`UserRoleHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.UserRoleHandler
+ :summary:
+ ```
+* - {py:obj}`AnonymousLoginHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.AnonymousLoginHandler
+ :summary:
+ ```
+* - {py:obj}`GoogleOAuth2LoginHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.GoogleOAuth2LoginHandler
+ :summary:
+ ```
+* - {py:obj}`IndexHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.IndexHandler
+ :summary:
+ ```
+* - {py:obj}`WorkspaceCatchHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.WorkspaceCatchHandler
+ :summary:
+ ```
+* - {py:obj}`WorkspaceEventsHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.WorkspaceEventsHandler
+ :summary:
+ ```
+* - {py:obj}`WorkspaceEventsTableHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.WorkspaceEventsTableHandler
+ :summary:
+ ```
+* - {py:obj}`WorkspaceMutexHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.WorkspaceMutexHandler
+ :summary:
+ ```
+* - {py:obj}`WorkspaceDeleteHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.WorkspaceDeleteHandler
+ :summary:
+ ```
+* - {py:obj}`WorkspacesHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.WorkspacesHandler
+ :summary:
+ ```
+* - {py:obj}`APIBaseHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.APIBaseHandler
+ :summary:
+ ```
+* - {py:obj}`AuthLoginApiHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.AuthLoginApiHandler
+ :summary:
+ ```
+* - {py:obj}`AuthLoginApiWebsocketHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.AuthLoginApiWebsocketHandler
+ :summary:
+ ```
+* - {py:obj}`AuthApiDenied `
+ - ```{autodoc2-docstring} boardwalkd.server.AuthApiDenied
+ :summary:
+ ```
+* - {py:obj}`WorkspaceCatchApiHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.WorkspaceCatchApiHandler
+ :summary:
+ ```
+* - {py:obj}`WorkspaceDetailsApiHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.WorkspaceDetailsApiHandler
+ :summary:
+ ```
+* - {py:obj}`WorkspaceHeartbeatApiHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.WorkspaceHeartbeatApiHandler
+ :summary:
+ ```
+* - {py:obj}`WorkspaceEventApiHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.WorkspaceEventApiHandler
+ :summary:
+ ```
+* - {py:obj}`WorkspaceMutexApiHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.WorkspaceMutexApiHandler
+ :summary:
+ ```
+* - {py:obj}`WorkspaceSemaphoresApiHandler `
+ - ```{autodoc2-docstring} boardwalkd.server.WorkspaceSemaphoresApiHandler
+ :summary:
+ ```
+````
+
+### Functions
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`ui_method_sha256 `
+ - ```{autodoc2-docstring} boardwalkd.server.ui_method_sha256
+ :summary:
+ ```
+* - {py:obj}`ui_method_secondsdelta `
+ - ```{autodoc2-docstring} boardwalkd.server.ui_method_secondsdelta
+ :summary:
+ ```
+* - {py:obj}`ui_method_server_version `
+ - ```{autodoc2-docstring} boardwalkd.server.ui_method_server_version
+ :summary:
+ ```
+* - {py:obj}`ui_method_sort_events_by_date `
+ - ```{autodoc2-docstring} boardwalkd.server.ui_method_sort_events_by_date
+ :summary:
+ ```
+* - {py:obj}`log_request `
+ - ```{autodoc2-docstring} boardwalkd.server.log_request
+ :summary:
+ ```
+* - {py:obj}`internal_workspace_event `
+ - ```{autodoc2-docstring} boardwalkd.server.internal_workspace_event
+ :summary:
+ ```
+* - {py:obj}`make_app `
+ - ```{autodoc2-docstring} boardwalkd.server.make_app
+ :summary:
+ ```
+* - {py:obj}`run `
+ - ```{autodoc2-docstring} boardwalkd.server.run
+ :summary:
+ ```
+````
+
+### Data
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`module_dir `
+ - ```{autodoc2-docstring} boardwalkd.server.module_dir
+ :summary:
+ ```
+* - {py:obj}`state `
+ - ```{autodoc2-docstring} boardwalkd.server.state
+ :summary:
+ ```
+* - {py:obj}`SLACK_TOKENS `
+ - ```{autodoc2-docstring} boardwalkd.server.SLACK_TOKENS
+ :summary:
+ ```
+* - {py:obj}`SLACK_SLASH_COMMAND_PREFIX `
+ - ```{autodoc2-docstring} boardwalkd.server.SLACK_SLASH_COMMAND_PREFIX
+ :summary:
+ ```
+* - {py:obj}`SERVER_URL `
+ - ```{autodoc2-docstring} boardwalkd.server.SERVER_URL
+ :summary:
+ ```
+````
+
+### API
+
+````{py:data} module_dir
+:canonical: boardwalkd.server.module_dir
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalkd.server.module_dir
+```
+
+````
+
+````{py:data} state
+:canonical: boardwalkd.server.state
+:value: >
+ 'load_state(...)'
+
+```{autodoc2-docstring} boardwalkd.server.state
+```
+
+````
+
+````{py:data} SLACK_TOKENS
+:canonical: boardwalkd.server.SLACK_TOKENS
+:type: dict[str, str | None]
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalkd.server.SLACK_TOKENS
+```
+
+````
+
+````{py:data} SLACK_SLASH_COMMAND_PREFIX
+:canonical: boardwalkd.server.SLACK_SLASH_COMMAND_PREFIX
+:type: str
+:value: >
+ 'brdwlk'
+
+```{autodoc2-docstring} boardwalkd.server.SLACK_SLASH_COMMAND_PREFIX
+```
+
+````
+
+````{py:data} SERVER_URL
+:canonical: boardwalkd.server.SERVER_URL
+:type: str | None
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalkd.server.SERVER_URL
+```
+
+````
+
+`````{py:class} UIBaseHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.UIBaseHandler
+
+Bases: {py:obj}`tornado.web.RequestHandler`
+
+```{autodoc2-docstring} boardwalkd.server.UIBaseHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.UIBaseHandler.__init__
+```
+
+````{py:method} prepare()
+:canonical: boardwalkd.server.UIBaseHandler.prepare
+
+````
+
+````{py:method} get_current_user() -> bytes | None
+:canonical: boardwalkd.server.UIBaseHandler.get_current_user
+
+```{autodoc2-docstring} boardwalkd.server.UIBaseHandler.get_current_user
+```
+
+````
+
+`````
+
+````{py:function} ui_method_sha256(handler: boardwalkd.server.UIBaseHandler, value: str) -> str
+:canonical: boardwalkd.server.ui_method_sha256
+
+```{autodoc2-docstring} boardwalkd.server.ui_method_sha256
+```
+````
+
+````{py:function} ui_method_secondsdelta(handler: boardwalkd.server.UIBaseHandler, time: datetime.datetime) -> float
+:canonical: boardwalkd.server.ui_method_secondsdelta
+
+```{autodoc2-docstring} boardwalkd.server.ui_method_secondsdelta
+```
+````
+
+````{py:function} ui_method_server_version(handler: boardwalkd.server.UIBaseHandler) -> str
+:canonical: boardwalkd.server.ui_method_server_version
+
+```{autodoc2-docstring} boardwalkd.server.ui_method_server_version
+```
+````
+
+````{py:function} ui_method_sort_events_by_date(handler: boardwalkd.server.UIBaseHandler, events: collections.deque[boardwalkd.protocol.WorkspaceEvent]) -> list[boardwalkd.protocol.WorkspaceEvent]
+:canonical: boardwalkd.server.ui_method_sort_events_by_date
+
+```{autodoc2-docstring} boardwalkd.server.ui_method_sort_events_by_date
+```
+````
+
+`````{py:class} AdminUIBaseHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.AdminUIBaseHandler
+
+Bases: {py:obj}`boardwalkd.server.UIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.AdminUIBaseHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.AdminUIBaseHandler.__init__
+```
+
+````{py:method} prepare()
+:canonical: boardwalkd.server.AdminUIBaseHandler.prepare
+
+````
+
+`````
+
+`````{py:class} AdminHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.AdminHandler
+
+Bases: {py:obj}`boardwalkd.server.AdminUIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.AdminHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.AdminHandler.__init__
+```
+
+````{py:method} get()
+:canonical: boardwalkd.server.AdminHandler.get
+
+```{autodoc2-docstring} boardwalkd.server.AdminHandler.get
+```
+
+````
+
+`````
+
+`````{py:class} UserEnableHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.UserEnableHandler
+
+Bases: {py:obj}`boardwalkd.server.AdminUIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.UserEnableHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.UserEnableHandler.__init__
+```
+
+````{py:method} post(user: str)
+:canonical: boardwalkd.server.UserEnableHandler.post
+
+```{autodoc2-docstring} boardwalkd.server.UserEnableHandler.post
+```
+
+````
+
+````{py:method} delete(user: str)
+:canonical: boardwalkd.server.UserEnableHandler.delete
+
+```{autodoc2-docstring} boardwalkd.server.UserEnableHandler.delete
+```
+
+````
+
+`````
+
+`````{py:class} UserRoleHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.UserRoleHandler
+
+Bases: {py:obj}`boardwalkd.server.AdminUIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.UserRoleHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.UserRoleHandler.__init__
+```
+
+````{py:method} post(user: str)
+:canonical: boardwalkd.server.UserRoleHandler.post
+
+```{autodoc2-docstring} boardwalkd.server.UserRoleHandler.post
+```
+
+````
+
+````{py:method} delete(user: str)
+:canonical: boardwalkd.server.UserRoleHandler.delete
+
+```{autodoc2-docstring} boardwalkd.server.UserRoleHandler.delete
+```
+
+````
+
+`````
+
+`````{py:class} AnonymousLoginHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.AnonymousLoginHandler
+
+Bases: {py:obj}`boardwalkd.server.UIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.AnonymousLoginHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.AnonymousLoginHandler.__init__
+```
+
+````{py:method} get()
+:canonical: boardwalkd.server.AnonymousLoginHandler.get
+:async:
+
+```{autodoc2-docstring} boardwalkd.server.AnonymousLoginHandler.get
+```
+
+````
+
+`````
+
+`````{py:class} GoogleOAuth2LoginHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.GoogleOAuth2LoginHandler
+
+Bases: {py:obj}`boardwalkd.server.UIBaseHandler`, {py:obj}`tornado.auth.GoogleOAuth2Mixin`
+
+```{autodoc2-docstring} boardwalkd.server.GoogleOAuth2LoginHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.GoogleOAuth2LoginHandler.__init__
+```
+
+````{py:attribute} url_encryption_key
+:canonical: boardwalkd.server.GoogleOAuth2LoginHandler.url_encryption_key
+:value: >
+ 'generate_key(...)'
+
+```{autodoc2-docstring} boardwalkd.server.GoogleOAuth2LoginHandler.url_encryption_key
+```
+
+````
+
+````{py:method} get(*args: typing.Any, **kwargs: typing.Any)
+:canonical: boardwalkd.server.GoogleOAuth2LoginHandler.get
+:async:
+
+```{autodoc2-docstring} boardwalkd.server.GoogleOAuth2LoginHandler.get
+```
+
+````
+
+````{py:method} encode_url(url: str) -> str
+:canonical: boardwalkd.server.GoogleOAuth2LoginHandler.encode_url
+
+```{autodoc2-docstring} boardwalkd.server.GoogleOAuth2LoginHandler.encode_url
+```
+
+````
+
+````{py:method} decrypt_url(encoded_url: str) -> str
+:canonical: boardwalkd.server.GoogleOAuth2LoginHandler.decrypt_url
+
+```{autodoc2-docstring} boardwalkd.server.GoogleOAuth2LoginHandler.decrypt_url
+```
+
+````
+
+`````
+
+`````{py:class} IndexHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.IndexHandler
+
+Bases: {py:obj}`boardwalkd.server.UIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.IndexHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.IndexHandler.__init__
+```
+
+````{py:method} get()
+:canonical: boardwalkd.server.IndexHandler.get
+
+```{autodoc2-docstring} boardwalkd.server.IndexHandler.get
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceCatchHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.WorkspaceCatchHandler
+
+Bases: {py:obj}`boardwalkd.server.UIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceCatchHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceCatchHandler.__init__
+```
+
+````{py:method} post(workspace: str)
+:canonical: boardwalkd.server.WorkspaceCatchHandler.post
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceCatchHandler.post
+```
+
+````
+
+````{py:method} delete(workspace: str)
+:canonical: boardwalkd.server.WorkspaceCatchHandler.delete
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceCatchHandler.delete
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceEventsHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.WorkspaceEventsHandler
+
+Bases: {py:obj}`boardwalkd.server.UIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceEventsHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceEventsHandler.__init__
+```
+
+````{py:method} get(workspace: str)
+:canonical: boardwalkd.server.WorkspaceEventsHandler.get
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceEventsHandler.get
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceEventsTableHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.WorkspaceEventsTableHandler
+
+Bases: {py:obj}`boardwalkd.server.UIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceEventsTableHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceEventsTableHandler.__init__
+```
+
+````{py:method} get(workspace: str)
+:canonical: boardwalkd.server.WorkspaceEventsTableHandler.get
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceEventsTableHandler.get
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceMutexHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.WorkspaceMutexHandler
+
+Bases: {py:obj}`boardwalkd.server.UIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceMutexHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceMutexHandler.__init__
+```
+
+````{py:method} delete(workspace: str)
+:canonical: boardwalkd.server.WorkspaceMutexHandler.delete
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceMutexHandler.delete
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceDeleteHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.WorkspaceDeleteHandler
+
+Bases: {py:obj}`boardwalkd.server.UIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceDeleteHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceDeleteHandler.__init__
+```
+
+````{py:method} post(workspace: str)
+:canonical: boardwalkd.server.WorkspaceDeleteHandler.post
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceDeleteHandler.post
+```
+
+````
+
+`````
+
+`````{py:class} WorkspacesHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.WorkspacesHandler
+
+Bases: {py:obj}`boardwalkd.server.UIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.WorkspacesHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.WorkspacesHandler.__init__
+```
+
+````{py:method} get()
+:canonical: boardwalkd.server.WorkspacesHandler.get
+
+```{autodoc2-docstring} boardwalkd.server.WorkspacesHandler.get
+```
+
+````
+
+`````
+
+`````{py:class} APIBaseHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.APIBaseHandler
+
+Bases: {py:obj}`tornado.web.RequestHandler`
+
+```{autodoc2-docstring} boardwalkd.server.APIBaseHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.APIBaseHandler.__init__
+```
+
+````{py:method} prepare()
+:canonical: boardwalkd.server.APIBaseHandler.prepare
+
+````
+
+````{py:method} check_xsrf_cookie()
+:canonical: boardwalkd.server.APIBaseHandler.check_xsrf_cookie
+
+```{autodoc2-docstring} boardwalkd.server.APIBaseHandler.check_xsrf_cookie
+```
+
+````
+
+````{py:method} get_current_user() -> bytes | None
+:canonical: boardwalkd.server.APIBaseHandler.get_current_user
+
+```{autodoc2-docstring} boardwalkd.server.APIBaseHandler.get_current_user
+```
+
+````
+
+````{py:method} get_login_url() -> str
+:canonical: boardwalkd.server.APIBaseHandler.get_login_url
+
+```{autodoc2-docstring} boardwalkd.server.APIBaseHandler.get_login_url
+```
+
+````
+
+`````
+
+````{py:exception} AuthLoginApiWebsocketIDNotFound()
+:canonical: boardwalkd.server.AuthLoginApiWebsocketIDNotFound
+
+Bases: {py:obj}`Exception`
+
+```{autodoc2-docstring} boardwalkd.server.AuthLoginApiWebsocketIDNotFound
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.AuthLoginApiWebsocketIDNotFound.__init__
+```
+
+````
+
+`````{py:class} AuthLoginApiHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.AuthLoginApiHandler
+
+Bases: {py:obj}`boardwalkd.server.UIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.AuthLoginApiHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.AuthLoginApiHandler.__init__
+```
+
+````{py:method} get()
+:canonical: boardwalkd.server.AuthLoginApiHandler.get
+
+```{autodoc2-docstring} boardwalkd.server.AuthLoginApiHandler.get
+```
+
+````
+
+`````
+
+`````{py:class} AuthLoginApiWebsocketHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.AuthLoginApiWebsocketHandler
+
+Bases: {py:obj}`tornado.websocket.WebSocketHandler`
+
+```{autodoc2-docstring} boardwalkd.server.AuthLoginApiWebsocketHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.AuthLoginApiWebsocketHandler.__init__
+```
+
+````{py:attribute} clients
+:canonical: boardwalkd.server.AuthLoginApiWebsocketHandler.clients
+:type: dict[boardwalkd.server.AuthLoginApiWebsocketHandler, str]
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalkd.server.AuthLoginApiWebsocketHandler.clients
+```
+
+````
+
+````{py:method} open()
+:canonical: boardwalkd.server.AuthLoginApiWebsocketHandler.open
+
+````
+
+````{py:method} on_close()
+:canonical: boardwalkd.server.AuthLoginApiWebsocketHandler.on_close
+
+````
+
+````{py:method} on_pong(data: bytes)
+:canonical: boardwalkd.server.AuthLoginApiWebsocketHandler.on_pong
+
+````
+
+````{py:method} write_to_client_by_id(id: str, msg: bytes | str | dict[str, typing.Any])
+:canonical: boardwalkd.server.AuthLoginApiWebsocketHandler.write_to_client_by_id
+:classmethod:
+
+```{autodoc2-docstring} boardwalkd.server.AuthLoginApiWebsocketHandler.write_to_client_by_id
+```
+
+````
+
+`````
+
+`````{py:class} AuthApiDenied(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.AuthApiDenied
+
+Bases: {py:obj}`boardwalkd.server.APIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.AuthApiDenied
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.AuthApiDenied.__init__
+```
+
+````{py:method} get()
+:canonical: boardwalkd.server.AuthApiDenied.get
+
+```{autodoc2-docstring} boardwalkd.server.AuthApiDenied.get
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceCatchApiHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.WorkspaceCatchApiHandler
+
+Bases: {py:obj}`boardwalkd.server.APIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceCatchApiHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceCatchApiHandler.__init__
+```
+
+````{py:method} post(workspace: str)
+:canonical: boardwalkd.server.WorkspaceCatchApiHandler.post
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceCatchApiHandler.post
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceDetailsApiHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.WorkspaceDetailsApiHandler
+
+Bases: {py:obj}`boardwalkd.server.APIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceDetailsApiHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceDetailsApiHandler.__init__
+```
+
+````{py:method} get(workspace: str)
+:canonical: boardwalkd.server.WorkspaceDetailsApiHandler.get
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceDetailsApiHandler.get
+```
+
+````
+
+````{py:method} post(workspace: str)
+:canonical: boardwalkd.server.WorkspaceDetailsApiHandler.post
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceDetailsApiHandler.post
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceHeartbeatApiHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.WorkspaceHeartbeatApiHandler
+
+Bases: {py:obj}`boardwalkd.server.APIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceHeartbeatApiHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceHeartbeatApiHandler.__init__
+```
+
+````{py:method} post(workspace: str)
+:canonical: boardwalkd.server.WorkspaceHeartbeatApiHandler.post
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceHeartbeatApiHandler.post
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceEventApiHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.WorkspaceEventApiHandler
+
+Bases: {py:obj}`boardwalkd.server.APIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceEventApiHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceEventApiHandler.__init__
+```
+
+````{py:method} post(workspace: str)
+:canonical: boardwalkd.server.WorkspaceEventApiHandler.post
+:async:
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceEventApiHandler.post
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceMutexApiHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.WorkspaceMutexApiHandler
+
+Bases: {py:obj}`boardwalkd.server.APIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceMutexApiHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceMutexApiHandler.__init__
+```
+
+````{py:method} post(workspace: str)
+:canonical: boardwalkd.server.WorkspaceMutexApiHandler.post
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceMutexApiHandler.post
+```
+
+````
+
+````{py:method} delete(workspace: str)
+:canonical: boardwalkd.server.WorkspaceMutexApiHandler.delete
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceMutexApiHandler.delete
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceSemaphoresApiHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs: typing.Any)
+:canonical: boardwalkd.server.WorkspaceSemaphoresApiHandler
+
+Bases: {py:obj}`boardwalkd.server.APIBaseHandler`
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceSemaphoresApiHandler
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceSemaphoresApiHandler.__init__
+```
+
+````{py:method} get(workspace: str)
+:canonical: boardwalkd.server.WorkspaceSemaphoresApiHandler.get
+
+```{autodoc2-docstring} boardwalkd.server.WorkspaceSemaphoresApiHandler.get
+```
+
+````
+
+`````
+
+````{py:function} log_request(handler: tornado.web.RequestHandler)
+:canonical: boardwalkd.server.log_request
+
+```{autodoc2-docstring} boardwalkd.server.log_request
+```
+````
+
+````{py:function} internal_workspace_event(workspace: str, event: boardwalkd.protocol.WorkspaceEvent)
+:canonical: boardwalkd.server.internal_workspace_event
+
+```{autodoc2-docstring} boardwalkd.server.internal_workspace_event
+```
+````
+
+````{py:function} make_app(auth_expire_days: float, auth_method: str, develop: bool, host_header_pattern: re.Pattern[str], owner: str, slack_error_webhook_url: str, slack_webhook_url: str, url: str) -> tornado.web.Application
+:canonical: boardwalkd.server.make_app
+
+```{autodoc2-docstring} boardwalkd.server.make_app
+```
+````
+
+````{py:function} run(auth_expire_days: float, auth_method: str, develop: bool, host_header_pattern: re.Pattern[str], owner: str, port_number: int | None, tls_crt_path: str | None, tls_key_path: str | None, slack_app_token: str | None, slack_bot_token: str | None, tls_port_number: int | None, slack_error_webhook_url: str, slack_webhook_url: str, slack_slash_command_prefix: str, url: str)
+:canonical: boardwalkd.server.run
+:async:
+
+```{autodoc2-docstring} boardwalkd.server.run
+```
+````
diff --git a/docs/source/apidocs/boardwalkd/boardwalkd.slack.md b/docs/source/apidocs/boardwalkd/boardwalkd.slack.md
new file mode 100644
index 0000000..e7e6bde
--- /dev/null
+++ b/docs/source/apidocs/boardwalkd/boardwalkd.slack.md
@@ -0,0 +1,207 @@
+# {py:mod}`boardwalkd.slack`
+
+```{py:module} boardwalkd.slack
+```
+
+```{autodoc2-docstring} boardwalkd.slack
+:allowtitles:
+```
+
+## Module Contents
+
+### Functions
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`_count_of_workspaces_caught `
+ - ```{autodoc2-docstring} boardwalkd.slack._count_of_workspaces_caught
+ :summary:
+ ```
+* - {py:obj}`_list_active_workspaces `
+ - ```{autodoc2-docstring} boardwalkd.slack._list_active_workspaces
+ :summary:
+ ```
+* - {py:obj}`_list_inactive_workspaces `
+ - ```{autodoc2-docstring} boardwalkd.slack._list_inactive_workspaces
+ :summary:
+ ```
+* - {py:obj}`hello_command `
+ - ```{autodoc2-docstring} boardwalkd.slack.hello_command
+ :summary:
+ ```
+* - {py:obj}`catch_release_workspaces `
+ - ```{autodoc2-docstring} boardwalkd.slack.catch_release_workspaces
+ :summary:
+ ```
+* - {py:obj}`modal_catch_release_view_submission_event `
+ - ```{autodoc2-docstring} boardwalkd.slack.modal_catch_release_view_submission_event
+ :summary:
+ ```
+* - {py:obj}`command_list_active_workspaces `
+ - ```{autodoc2-docstring} boardwalkd.slack.command_list_active_workspaces
+ :summary:
+ ```
+* - {py:obj}`app_home_opened `
+ - ```{autodoc2-docstring} boardwalkd.slack.app_home_opened
+ :summary:
+ ```
+* - {py:obj}`app_home_workspace_details `
+ - ```{autodoc2-docstring} boardwalkd.slack.app_home_workspace_details
+ :summary:
+ ```
+* - {py:obj}`_modal_about_boardwalk `
+ - ```{autodoc2-docstring} boardwalkd.slack._modal_about_boardwalk
+ :summary:
+ ```
+* - {py:obj}`action_app_home_overflow_menu_event_handler `
+ - ```{autodoc2-docstring} boardwalkd.slack.action_app_home_overflow_menu_event_handler
+ :summary:
+ ```
+* - {py:obj}`dummy_slack_acknowledgement_handler `
+ - ```{autodoc2-docstring} boardwalkd.slack.dummy_slack_acknowledgement_handler
+ :summary:
+ ```
+* - {py:obj}`auth_boardwalk `
+ - ```{autodoc2-docstring} boardwalkd.slack.auth_boardwalk
+ :summary:
+ ```
+* - {py:obj}`connect `
+ - ```{autodoc2-docstring} boardwalkd.slack.connect
+ :summary:
+ ```
+````
+
+### Data
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`app `
+ - ```{autodoc2-docstring} boardwalkd.slack.app
+ :summary:
+ ```
+````
+
+### API
+
+````{py:data} app
+:canonical: boardwalkd.slack.app
+:value: >
+ 'AsyncApp(...)'
+
+```{autodoc2-docstring} boardwalkd.slack.app
+```
+
+````
+
+````{py:function} _count_of_workspaces_caught() -> int
+:canonical: boardwalkd.slack._count_of_workspaces_caught
+
+```{autodoc2-docstring} boardwalkd.slack._count_of_workspaces_caught
+```
+````
+
+````{py:function} _list_active_workspaces(last_seen_seconds: int = 10, _sorted: bool = True) -> list[str]
+:canonical: boardwalkd.slack._list_active_workspaces
+
+```{autodoc2-docstring} boardwalkd.slack._list_active_workspaces
+```
+````
+
+````{py:function} _list_inactive_workspaces(last_seen_seconds: int = 10) -> list[str]
+:canonical: boardwalkd.slack._list_inactive_workspaces
+
+```{autodoc2-docstring} boardwalkd.slack._list_inactive_workspaces
+```
+````
+
+````{py:function} hello_command(ack: slack_bolt.async_app.AsyncAck, body: dict[str, typing.Any], client: slack_sdk.web.async_client.AsyncWebClient) -> None
+:canonical: boardwalkd.slack.hello_command
+:async:
+
+```{autodoc2-docstring} boardwalkd.slack.hello_command
+```
+````
+
+````{py:function} catch_release_workspaces(ack: slack_bolt.async_app.AsyncAck, body: dict[str, typing.Any], client: slack_sdk.web.async_client.AsyncWebClient)
+:canonical: boardwalkd.slack.catch_release_workspaces
+:async:
+
+```{autodoc2-docstring} boardwalkd.slack.catch_release_workspaces
+```
+````
+
+````{py:function} modal_catch_release_view_submission_event(ack: slack_bolt.async_app.AsyncAck, client: slack_sdk.web.async_client.AsyncWebClient, context: slack_bolt.async_app.AsyncBoltContext, logger: logging.Logger, payload: dict[str, typing.Any])
+:canonical: boardwalkd.slack.modal_catch_release_view_submission_event
+:async:
+
+```{autodoc2-docstring} boardwalkd.slack.modal_catch_release_view_submission_event
+```
+````
+
+````{py:function} command_list_active_workspaces(ack: slack_bolt.async_app.AsyncAck, body: dict[str, typing.Any], client: slack_sdk.web.async_client.AsyncWebClient) -> None
+:canonical: boardwalkd.slack.command_list_active_workspaces
+:async:
+
+```{autodoc2-docstring} boardwalkd.slack.command_list_active_workspaces
+```
+````
+
+````{py:function} app_home_opened(ack: slack_bolt.async_app.AsyncAck, client: slack_sdk.web.async_client.AsyncWebClient, logger: logging.Logger, context: slack_bolt.async_app.AsyncBoltContext)
+:canonical: boardwalkd.slack.app_home_opened
+:async:
+
+```{autodoc2-docstring} boardwalkd.slack.app_home_opened
+```
+````
+
+````{py:function} app_home_workspace_details(ack: slack_bolt.async_app.AsyncAck, logger: logging.Logger, client: slack_sdk.web.async_client.AsyncWebClient, context: slack_bolt.async_app.AsyncBoltContext, payload: dict[str, typing.Any]) -> None
+:canonical: boardwalkd.slack.app_home_workspace_details
+:async:
+
+```{autodoc2-docstring} boardwalkd.slack.app_home_workspace_details
+```
+````
+
+````{py:function} _modal_about_boardwalk(trigger_id: str, client: slack_sdk.web.async_client.AsyncWebClient)
+:canonical: boardwalkd.slack._modal_about_boardwalk
+:async:
+
+```{autodoc2-docstring} boardwalkd.slack._modal_about_boardwalk
+```
+````
+
+````{py:function} action_app_home_overflow_menu_event_handler(ack: slack_bolt.async_app.AsyncAck, body: dict[str, typing.Any], client: slack_sdk.web.async_client.AsyncWebClient, payload) -> None
+:canonical: boardwalkd.slack.action_app_home_overflow_menu_event_handler
+:async:
+
+```{autodoc2-docstring} boardwalkd.slack.action_app_home_overflow_menu_event_handler
+```
+````
+
+````{py:function} dummy_slack_acknowledgement_handler(ack: slack_bolt.async_app.AsyncAck)
+:canonical: boardwalkd.slack.dummy_slack_acknowledgement_handler
+:async:
+
+```{autodoc2-docstring} boardwalkd.slack.dummy_slack_acknowledgement_handler
+```
+````
+
+````{py:function} auth_boardwalk(client: slack_sdk.web.async_client.AsyncWebClient, context: slack_bolt.async_app.AsyncBoltContext, payload: dict[str, typing.Any], next: collections.abc.Callable[[], collections.abc.Awaitable]) -> None
+:canonical: boardwalkd.slack.auth_boardwalk
+:async:
+
+```{autodoc2-docstring} boardwalkd.slack.auth_boardwalk
+```
+````
+
+````{py:function} connect() -> None
+:canonical: boardwalkd.slack.connect
+:async:
+
+```{autodoc2-docstring} boardwalkd.slack.connect
+```
+````
diff --git a/docs/source/apidocs/boardwalkd/boardwalkd.state.md b/docs/source/apidocs/boardwalkd/boardwalkd.state.md
new file mode 100644
index 0000000..35bf84d
--- /dev/null
+++ b/docs/source/apidocs/boardwalkd/boardwalkd.state.md
@@ -0,0 +1,305 @@
+# {py:mod}`boardwalkd.state`
+
+```{py:module} boardwalkd.state
+```
+
+```{autodoc2-docstring} boardwalkd.state
+:allowtitles:
+```
+
+## Module Contents
+
+### Classes
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`StateBaseModel `
+ - ```{autodoc2-docstring} boardwalkd.state.StateBaseModel
+ :summary:
+ ```
+* - {py:obj}`User `
+ - ```{autodoc2-docstring} boardwalkd.state.User
+ :summary:
+ ```
+* - {py:obj}`WorkspaceState `
+ - ```{autodoc2-docstring} boardwalkd.state.WorkspaceState
+ :summary:
+ ```
+* - {py:obj}`State `
+ - ```{autodoc2-docstring} boardwalkd.state.State
+ :summary:
+ ```
+````
+
+### Functions
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`load_state `
+ - ```{autodoc2-docstring} boardwalkd.state.load_state
+ :summary:
+ ```
+````
+
+### Data
+
+````{list-table}
+:class: autosummary longtable
+:align: left
+
+* - {py:obj}`statefile_dir_path `
+ - ```{autodoc2-docstring} boardwalkd.state.statefile_dir_path
+ :summary:
+ ```
+* - {py:obj}`statefile_path `
+ - ```{autodoc2-docstring} boardwalkd.state.statefile_path
+ :summary:
+ ```
+* - {py:obj}`valid_user_roles `
+ - ```{autodoc2-docstring} boardwalkd.state.valid_user_roles
+ :summary:
+ ```
+````
+
+### API
+
+````{py:data} statefile_dir_path
+:canonical: boardwalkd.state.statefile_dir_path
+:value: >
+ 'joinpath(...)'
+
+```{autodoc2-docstring} boardwalkd.state.statefile_dir_path
+```
+
+````
+
+````{py:data} statefile_path
+:canonical: boardwalkd.state.statefile_path
+:value: >
+ 'joinpath(...)'
+
+```{autodoc2-docstring} boardwalkd.state.statefile_path
+```
+
+````
+
+````{py:data} valid_user_roles
+:canonical: boardwalkd.state.valid_user_roles
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalkd.state.valid_user_roles
+```
+
+````
+
+````{py:class} StateBaseModel(/, **data: typing.Any)
+:canonical: boardwalkd.state.StateBaseModel
+
+Bases: {py:obj}`pydantic.BaseModel`
+
+```{autodoc2-docstring} boardwalkd.state.StateBaseModel
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.state.StateBaseModel.__init__
+```
+
+````
+
+`````{py:class} User(/, **data: typing.Any)
+:canonical: boardwalkd.state.User
+
+Bases: {py:obj}`boardwalkd.state.StateBaseModel`
+
+```{autodoc2-docstring} boardwalkd.state.User
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.state.User.__init__
+```
+
+````{py:attribute} enabled
+:canonical: boardwalkd.state.User.enabled
+:type: bool
+:value: >
+ True
+
+```{autodoc2-docstring} boardwalkd.state.User.enabled
+```
+
+````
+
+````{py:attribute} email
+:canonical: boardwalkd.state.User.email
+:type: pydantic.EmailStr
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalkd.state.User.email
+```
+
+````
+
+````{py:attribute} roles
+:canonical: boardwalkd.state.User.roles
+:type: set[str]
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalkd.state.User.roles
+```
+
+````
+
+````{py:method} validate_roles(input_roles: set[str])
+:canonical: boardwalkd.state.User.validate_roles
+:classmethod:
+
+```{autodoc2-docstring} boardwalkd.state.User.validate_roles
+```
+
+````
+
+`````
+
+`````{py:class} WorkspaceState(/, **data: typing.Any)
+:canonical: boardwalkd.state.WorkspaceState
+
+Bases: {py:obj}`boardwalkd.state.StateBaseModel`
+
+```{autodoc2-docstring} boardwalkd.state.WorkspaceState
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.state.WorkspaceState.__init__
+```
+
+````{py:attribute} details
+:canonical: boardwalkd.state.WorkspaceState.details
+:type: boardwalkd.protocol.WorkspaceDetails
+:value: >
+ 'WorkspaceDetails(...)'
+
+```{autodoc2-docstring} boardwalkd.state.WorkspaceState.details
+```
+
+````
+
+````{py:attribute} last_seen
+:canonical: boardwalkd.state.WorkspaceState.last_seen
+:type: datetime.datetime | None
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalkd.state.WorkspaceState.last_seen
+```
+
+````
+
+````{py:attribute} _max_workspace_events
+:canonical: boardwalkd.state.WorkspaceState._max_workspace_events
+:type: int
+:value: >
+ 64
+
+```{autodoc2-docstring} boardwalkd.state.WorkspaceState._max_workspace_events
+```
+
+````
+
+````{py:attribute} events
+:canonical: boardwalkd.state.WorkspaceState.events
+:type: collections.deque[boardwalkd.protocol.WorkspaceEvent]
+:value: >
+ 'deque(...)'
+
+```{autodoc2-docstring} boardwalkd.state.WorkspaceState.events
+```
+
+````
+
+````{py:attribute} semaphores
+:canonical: boardwalkd.state.WorkspaceState.semaphores
+:type: boardwalkd.protocol.WorkspaceSemaphores
+:value: >
+ 'WorkspaceSemaphores(...)'
+
+```{autodoc2-docstring} boardwalkd.state.WorkspaceState.semaphores
+```
+
+````
+
+````{py:method} validate_events(input_events: collections.deque[boardwalkd.protocol.WorkspaceEvent]) -> collections.deque[boardwalkd.protocol.WorkspaceEvent]
+:canonical: boardwalkd.state.WorkspaceState.validate_events
+:classmethod:
+
+```{autodoc2-docstring} boardwalkd.state.WorkspaceState.validate_events
+```
+
+````
+
+`````
+
+`````{py:class} State(/, **data: typing.Any)
+:canonical: boardwalkd.state.State
+
+Bases: {py:obj}`boardwalkd.state.StateBaseModel`
+
+```{autodoc2-docstring} boardwalkd.state.State
+```
+
+```{rubric} Initialization
+```
+
+```{autodoc2-docstring} boardwalkd.state.State.__init__
+```
+
+````{py:attribute} workspaces
+:canonical: boardwalkd.state.State.workspaces
+:type: dict[str, boardwalkd.state.WorkspaceState]
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalkd.state.State.workspaces
+```
+
+````
+
+````{py:attribute} users
+:canonical: boardwalkd.state.State.users
+:type: dict[str, boardwalkd.state.User]
+:value: >
+ None
+
+```{autodoc2-docstring} boardwalkd.state.State.users
+```
+
+````
+
+````{py:method} flush()
+:canonical: boardwalkd.state.State.flush
+
+```{autodoc2-docstring} boardwalkd.state.State.flush
+```
+
+````
+
+`````
+
+````{py:function} load_state() -> boardwalkd.state.State
+:canonical: boardwalkd.state.load_state
+
+```{autodoc2-docstring} boardwalkd.state.load_state
+```
+````
diff --git a/docs/source/apidocs/index.rst b/docs/source/apidocs/index.rst
new file mode 100644
index 0000000..9a746e0
--- /dev/null
+++ b/docs/source/apidocs/index.rst
@@ -0,0 +1,12 @@
+Auto-generated API
+==================
+
+This section contains auto-generated API reference documentation [#f1]_.
+
+.. toctree::
+ :titlesonly:
+
+ boardwalk/boardwalk
+ boardwalkd/boardwalkd
+
+.. [#f1] Created with `sphinx-autodoc2 `_
diff --git a/docs/source/cli_helpdocs/boardwalk/boardwalk.md b/docs/source/cli_helpdocs/boardwalk/boardwalk.md
new file mode 100644
index 0000000..dc787e5
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalk/boardwalk.md
@@ -0,0 +1,33 @@
+# `boardwalk`
+
+
+
+
+
+ Usage: boardwalk [OPTIONS] COMMAND [ARGS]...
+
+ Boardwalk is a linear remote execution workflow engine built on top of Ansible. See the README.md @
+ https://github.com/Backblaze/boardwalk for more info
+ To see more info about any subcommand, do `boardwalk <subcommand> --help`
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --verbose -v INTEGER RANGE [0<=x<=5] Whether or not output messages should be verbose. Additional -v's ā
+ā increases the verbosity ā
+ā [env var: BOARDWALK_VERBOSITY] ā
+ā [default: 0; 0<=x<=5] ā
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+āā Commands āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā catch Catch workflow in active workspace ā
+ā check Runs workflow in check mode. Equivalent to run --check ā
+ā init Inits local workspace state by getting host facts ā
+ā login Login to the API ā
+ā release Removes catch from active workspace ā
+ā run Runs workflow jobs ā
+ā version Prints the boardwalk module version number and exits ā
+ā workspace Subcommand group for working with workspaces ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalk/boardwalk_catch.md b/docs/source/cli_helpdocs/boardwalk/boardwalk_catch.md
new file mode 100644
index 0000000..884c0aa
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalk/boardwalk_catch.md
@@ -0,0 +1,18 @@
+# `boardwalk catch`
+
+
+
+
+
+ Usage: boardwalk catch [OPTIONS]
+
+ Creates 'catch' in the active workspace. Workflows will stop at the next host. Catch remains in place until
+ released
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalk/boardwalk_check.md b/docs/source/cli_helpdocs/boardwalk/boardwalk_check.md
new file mode 100644
index 0000000..1392a1e
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalk/boardwalk_check.md
@@ -0,0 +1,32 @@
+# `boardwalk check`
+
+
+
+
+
+ Usage: boardwalk check [OPTIONS]
+
+ Runs workflow in check mode. Equivalent to run --check
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --sort-hosts -s [shuffle|s|ascending|a|descend Overrides the workspace's ā
+ā ing|d|] default sort ordering. May be ā
+ā specified with first letter ā
+ā --server-connect/--no-server-cā¦ -sc/-nsc Whether or not connect to the ā
+ā configured boardwalkd server, ā
+ā if any. It may be dangerous to ā
+ā run workflows without ā
+ā connecting to the server ā
+ā [default: server-connect] ā
+ā --limit -l TEXT An Ansible pattern to limit ā
+ā hosts by. Defaults to no limit ā
+ā --ask-become-pass/--no-ask-becā¦ -K/-nK Whether or not ask for a become ā
+ā password. The ā
+ā ANSIBLE_BECOME_ASK_PASS env var ā
+ā can also set this ā
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalk/boardwalk_init.md b/docs/source/cli_helpdocs/boardwalk/boardwalk_init.md
new file mode 100644
index 0000000..3f61ce5
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalk/boardwalk_init.md
@@ -0,0 +1,23 @@
+# `boardwalk init`
+
+
+
+
+
+ Usage: boardwalk init [OPTIONS]
+
+ Inits the workspace state with host data. Gathers Ansible facts for hosts matching the workspaces host
+ pattern. OK to run multiple times; hosts are only added or updated, never removed by this operation. Use
+ `boardwalk workspace reset` to clear existing state if needed
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --limit -l TEXT An Ansible pattern to limit hosts by. Defaults to no limit ā
+ā --retry/--no-retry -r/-nr Retry getting state for hosts that were unreachable/failed on the last ā
+ā attempt ā
+ā [default: no-retry] ā
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalk/boardwalk_login.md b/docs/source/cli_helpdocs/boardwalk/boardwalk_login.md
new file mode 100644
index 0000000..0b7286b
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalk/boardwalk_login.md
@@ -0,0 +1,17 @@
+# `boardwalk login`
+
+
+
+
+
+ Usage: boardwalk login [OPTIONS]
+
+ Login to the API
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalk/boardwalk_release.md b/docs/source/cli_helpdocs/boardwalk/boardwalk_release.md
new file mode 100644
index 0000000..6e415fd
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalk/boardwalk_release.md
@@ -0,0 +1,17 @@
+# `boardwalk release`
+
+
+
+
+
+ Usage: boardwalk release [OPTIONS]
+
+ Removes catch from active workspace. Any running workflow will resume if it was caught
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalk/boardwalk_run.md b/docs/source/cli_helpdocs/boardwalk/boardwalk_run.md
new file mode 100644
index 0000000..4fd4a87
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalk/boardwalk_run.md
@@ -0,0 +1,40 @@
+# `boardwalk run`
+
+
+
+
+
+ Usage: boardwalk run [OPTIONS]
+
+ Runs workflow jobs defined in the Boardwalkfile.py
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --ask-become-pass/--no-ask-becā¦ -K/-nK Whether or not ask for a become ā
+ā password. The ā
+ā ANSIBLE_BECOME_ASK_PASS env var ā
+ā can also set this ā
+ā [default: no-ask-become-pass] ā
+ā --check/--no-check -C/-nC Whether or not to run Ansible ā
+ā in --check/-C mode ā
+ā [default: no-check] ā
+ā --limit -l TEXT An Ansible pattern to limit ā
+ā hosts by. Defaults to no limit ā
+ā --server-connect/--no-server-cā¦ -sc/-nsc Whether or not connect to the ā
+ā configured boardwalkd server, ā
+ā if any. It may be dangerous to ā
+ā run workflows without ā
+ā connecting to the server ā
+ā [default: server-connect] ā
+ā --sort-hosts -s [shuffle|s|ascending|a|descend Overrides the workspace's ā
+ā ing|d|] default sort ordering. May be ā
+ā specified with first letter ā
+ā --stomp-locks/--no-stomp-locks Whether or not to ignore and ā
+ā override existing host locks. ā
+ā Probably dangerous ā
+ā [default: no-stomp-locks] ā
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalk/boardwalk_version.md b/docs/source/cli_helpdocs/boardwalk/boardwalk_version.md
new file mode 100644
index 0000000..5d42cc6
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalk/boardwalk_version.md
@@ -0,0 +1,17 @@
+# `boardwalk version`
+
+
+
+
+
+ Usage: boardwalk version [OPTIONS]
+
+ Prints the boardwalk module version number and exits
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace.md b/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace.md
new file mode 100644
index 0000000..15220bb
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace.md
@@ -0,0 +1,22 @@
+# `boardwalk workspace`
+
+
+
+
+
+ Usage: boardwalk workspace [OPTIONS] COMMAND [ARGS]...
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+āā Commands āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā dump Prints the active workspace's state to stdout as JSON ā
+ā list Lists available workspaces from the Boardwalkfile.py ā
+ā reset Resets active workspace ā
+ā show Displays the active workspace ā
+ā use Sets the active workspace ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_dump.md b/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_dump.md
new file mode 100644
index 0000000..2d9ed56
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_dump.md
@@ -0,0 +1,17 @@
+# `boardwalk workspace dump`
+
+
+
+
+
+ Usage: boardwalk workspace dump [OPTIONS]
+
+ Prints the active workspace's state to stdout as JSON
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_list.md b/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_list.md
new file mode 100644
index 0000000..618a2cb
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_list.md
@@ -0,0 +1,17 @@
+# `boardwalk workspace list`
+
+
+
+
+
+ Usage: boardwalk workspace list [OPTIONS]
+
+ Lists available workspaces from the Boardwalkfile.py
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_reset.md b/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_reset.md
new file mode 100644
index 0000000..4d4483a
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_reset.md
@@ -0,0 +1,18 @@
+# `boardwalk workspace reset`
+
+
+
+
+
+ Usage: boardwalk workspace reset [OPTIONS]
+
+ Resets/clears the active workspace state
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --yes Confirm the action without prompting. ā
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_show.md b/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_show.md
new file mode 100644
index 0000000..933e4cb
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_show.md
@@ -0,0 +1,17 @@
+# `boardwalk workspace show`
+
+
+
+
+
+ Usage: boardwalk workspace show [OPTIONS]
+
+ Displays the active workspace
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_use.md b/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_use.md
new file mode 100644
index 0000000..279de8e
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_use.md
@@ -0,0 +1,15 @@
+# `boardwalk workspace use`
+
+
+
+
+
+ Usage: boardwalk workspace use [OPTIONS] WORKSPACE_NAME
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalk/index.md b/docs/source/cli_helpdocs/boardwalk/index.md
new file mode 100644
index 0000000..cf7a416
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalk/index.md
@@ -0,0 +1,22 @@
+# `boardwalk`
+
+This section contains auto-generated CLI manual pages for `boardwalk`.
+
+```{toctree}
+:titlesonly:
+
+boardwalk.md
+boardwalk_catch.md
+boardwalk_check.md
+boardwalk_init.md
+boardwalk_login.md
+boardwalk_release.md
+boardwalk_run.md
+boardwalk_version.md
+boardwalk_workspace.md
+boardwalk_workspace_dump.md
+boardwalk_workspace_list.md
+boardwalk_workspace_reset.md
+boardwalk_workspace_show.md
+boardwalk_workspace_use.md
+```
\ No newline at end of file
diff --git a/docs/source/cli_helpdocs/boardwalkd/boardwalkd.md b/docs/source/cli_helpdocs/boardwalkd/boardwalkd.md
new file mode 100644
index 0000000..053f8e3
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalkd/boardwalkd.md
@@ -0,0 +1,23 @@
+# `boardwalkd`
+
+
+
+
+
+ Usage: boardwalkd [OPTIONS] COMMAND [ARGS]...
+
+ Boardwalkd is the server component of Boardwalk. See the README.md @ https://github.com/Backblaze/boardwalk
+ for more info
+ To see more info about any subcommand, do `boardwalkd <subcommand> --help`
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+āā Commands āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā serve Runs the server ā
+ā version Prints the boardwalk module version number and exits ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalkd/boardwalkd_serve.md b/docs/source/cli_helpdocs/boardwalkd/boardwalkd_serve.md
new file mode 100644
index 0000000..902ee32
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalkd/boardwalkd_serve.md
@@ -0,0 +1,98 @@
+# `boardwalkd serve`
+
+
+
+
+
+ Usage: boardwalkd serve [OPTIONS]
+
+ Runs the server
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --auth-expire-days FLOAT The number of days login tokens and user API ā
+ā keys are valid before they expire ā
+ā [default: 14] ā
+ā --auth-method [anonymous|google_oauth] Enables an authentication method for the web ā
+ā UI. The API always requires authentication, ā
+ā however without this option configured a ā
+ā predictable anonymous user will be used. The ā
+ā method is supplied as a string argument. The ā
+ā BOARDWALK_SECRET environment variable must be ā
+ā set for any method to work except for ā
+ā 'anonymous'; it is the key used to sign ā
+ā secure strings, such as auth cookies and API ā
+ā keys ā
+ā Available auth methods: ā
+ā anonymous ā
+ā All requests are performed as an 'anonymous' ā
+ā default user ā
+ā google_oauth ā
+ā Uses Google Oauth2 to identify users by their ā
+ā Google account email address. ā
+ā BOARDWALKD_GOOGLE_OAUTH_CLIENT_ID and ā
+ā BOARDWALKD_GOOGLE_OAUTH_SECRET environment ā
+ā variables must be set. The authorized ā
+ā redirect URI should be ā
+ā https://<hostname>/auth/login ā
+ā [default: anonymous] ā
+ā --develop/--no-develop Runs the server in development mode with ā
+ā auto-reloading and tracebacks ā
+ā [default: no-develop] ā
+ā * --host-header-pattern TEXT A valid python regex pattern to match ā
+ā accepted Host header values. This prevents ā
+ā DNS rebinding attacks when the pattern is ā
+ā appropriately scoped Requests reaching the ā
+ā server that don't match this pattern will ā
+ā return a 404 ā
+ā [required] ā
+ā --owner TEXT A default admin user. Every time the server ā
+ā starts up, this user will be enabled and ā
+ā added to the admin role. This option must be ā
+ā supplied when --auth-method is anything other ā
+ā than 'anonymous'. The purpose of the owner is ā
+ā to have an initial admin user available at ā
+ā first start and to avoid lock-outs ā
+ā --port INTEGER The non-TLS port number the server binds to. ā
+ā --port and/or --tls-port must be configured ā
+ā --slack-webhook-url TEXT A Slack webhook URL to broadcast all key ā
+ā events to ā
+ā [env var: BOARDWALKD_SLACK_WEBHOOK_URL] ā
+ā --slack-error-webhook-url TEXT A Slack webhook URL to broadcast error events ā
+ā to. If defined, errors will not be sent to ā
+ā the URL defined by --slack-webhook-url ā
+ā [env var: BOARDWALKD_SLACK_ERROR_WEBHOOK_URL] ā
+ā --slack-app-token TEXT A Slack App Token for the Slack App this ā
+ā Boardwalkd instance is to connect to. If ā
+ā specified, --slack-bot-token must also be ā
+ā provided. ā
+ā [env var: BOARDWALKD_SLACK_APP_TOKEN] ā
+ā --slack-bot-token TEXT A Slack OAuth Bot Token for the Slack App ā
+ā this Boardwalkd instance is to connect to. ā
+ā [env var: BOARDWALKD_SLACK_BOT_TOKEN] ā
+ā --slack-slash-command-prefix TEXT The prefix to use in front of Boardwalk slash ā
+ā commands in Slack (e.g., /PREFIX-version). ā
+ā Needs to match the prefix supplied in the ā
+ā Slack App configuration. ā
+ā [env var: ā
+ā BOARDWALKD_SLACK_SLASH_COMMAND_PREFIX] ā
+ā [default: brdwlk] ā
+ā --tls-crt PATH Path to TLS certificate chain file for use ā
+ā along with --tls-port ā
+ā --tls-key PATH Path to TLS key file for use along with ā
+ā --tls-port ā
+ā --tls-port INTEGER The TLS port number the server binds to. When ā
+ā configured, the --url option must have an ā
+ā https:// scheme. When --tls-port is ā
+ā configured, --tls-crt and --tls-key must also ā
+ā be supplied ā
+ā * --url TEXT The base URL where the server can be reached. ā
+ā UI Requests that do not match the scheme or ā
+ā host:port of this URL will automatically be ā
+ā redirected ā
+ā [required] ā
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalkd/boardwalkd_version.md b/docs/source/cli_helpdocs/boardwalkd/boardwalkd_version.md
new file mode 100644
index 0000000..7b7e109
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalkd/boardwalkd_version.md
@@ -0,0 +1,17 @@
+# `boardwalkd version`
+
+
+
+
+
+ Usage: boardwalkd version [OPTIONS]
+
+ Prints the boardwalk module version number and exits
+
+āā Options āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
+ā --help Show this message and exit. ā
+ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ
+
+
+
+
diff --git a/docs/source/cli_helpdocs/boardwalkd/index.md b/docs/source/cli_helpdocs/boardwalkd/index.md
new file mode 100644
index 0000000..1cb6dea
--- /dev/null
+++ b/docs/source/cli_helpdocs/boardwalkd/index.md
@@ -0,0 +1,11 @@
+# `boardwalkd`
+
+This section contains auto-generated CLI manual pages for `boardwalkd`.
+
+```{toctree}
+:titlesonly:
+
+boardwalkd.md
+boardwalkd_serve.md
+boardwalkd_version.md
+```
\ No newline at end of file
diff --git a/docs/source/cli_helpdocs/index.md b/docs/source/cli_helpdocs/index.md
new file mode 100644
index 0000000..5c85aae
--- /dev/null
+++ b/docs/source/cli_helpdocs/index.md
@@ -0,0 +1,12 @@
+# Command-line help reference
+
+This section contains auto-generated CLI manual pages.[^1]
+
+```{toctree}
+:titlesonly:
+
+boardwalk/index.md
+boardwalkd/index.md
+```
+
+[^1]: Auto-generated via the script at `docs/build_cli_help_pages.sh`.
\ No newline at end of file
diff --git a/docs/source/conf.py b/docs/source/conf.py
new file mode 100644
index 0000000..3565d0e
--- /dev/null
+++ b/docs/source/conf.py
@@ -0,0 +1,140 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# For the full list of built-in configuration values, see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+from datetime import UTC, datetime
+from importlib.metadata import version as lib_version
+
+# -- Project information -----------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
+
+project = "Boardwalk"
+copyright = f"{datetime.now(tz=UTC).year}, Backblaze"
+author = "Backblaze"
+release = f"{lib_version("boardwalk")}"
+
+
+# -- General configuration ---------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
+
+extensions = [
+ "sphinx.ext.duration",
+ "sphinx.ext.intersphinx",
+ "sphinx.ext.doctest",
+ "sphinx.ext.autosummary",
+ "sphinx.ext.napoleon",
+ "autodoc2",
+ "myst_parser",
+ "sphinx_copybutton",
+]
+
+exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
+
+nitpicky = True
+nitpick_ignore = [
+ # This does anchor correctly when testing the rendered page.
+ ("myst", "the-boardwalkfile"),
+ # I think these are just by virtue of the fact we have these behind an `if TYPE_CHECKING:` line? Need to (eventually) figure these out.
+ ("py:class", "boardwalk.ansible.AnsibleFacts"),
+ ("py:class", "boardwalk.ansible.AnsibleTasksType"),
+ ("py:class", "boardwalk.ansible.InventoryData"),
+ ("py:class", "boardwalk.ansible.InventoryHostVars"),
+ ("py:class", "boardwalk.ansible.HostVarsType"),
+]
+nitpick_ignore_regex = [
+ # slack_sdk and slack_bolt don't use Sphinx
+ ("py:class", "slack_bolt.*"),
+ ("py:class", "slack_sdk.*"),
+ # Neither does pydantic
+ ("py:class", "pydantic.*"),
+ ("py:obj", "pydantic.*"),
+ # TODO: Pretty sure we need to update some type references, here; ignoring these for now
+ ("py:class", "ansible_runner.*"),
+]
+
+suppress_warnings = [
+ # Can Sphinx have a more granular suppression than just ignore _everything_?
+ "image.not_readable",
+]
+
+templates_path = ["_templates"]
+
+intersphinx_mapping = {
+ "python": ("https://docs.python.org/3/", None),
+ "tornado": ("https://www.tornadoweb.org/en/stable/", None),
+ "click": ("https://click.palletsprojects.com/en/stable/", None),
+ "ansible_runner": ("https://ansible.readthedocs.io/projects/runner/en/latest/", None),
+}
+
+# -- sphinx-autodoc2 configuration ---------------------------------------------------
+# https://sphinx-autodoc2.readthedocs.io/en/stable/config.html
+
+autodoc2_index_template = """Auto-generated API
+==================
+
+This section contains auto-generated API reference documentation [#f1]_.
+
+.. toctree::
+ :titlesonly:
+{% for package in top_level %}
+ {{ package }}
+{%- endfor %}
+
+.. [#f1] Created with `sphinx-autodoc2 `_
+
+""" # The blank line above lets us avoid a blank line at the end of the generated file.
+
+autodoc2_packages = [
+ {"path": "../../src/boardwalk", "module": "boardwalk"},
+ {"path": "../../src/boardwalkd", "module": "boardwalkd"},
+]
+
+autodoc2_render_plugin = "myst"
+
+# -- Options for HTML output -------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
+
+html_theme = "sphinx_book_theme"
+html_extra_path = [
+ "_img/",
+]
+html_static_path = ["_static"]
+html_logo = "_img/src/boardwalkd/static/boardwalk_icon.jpg"
+# html_favicon = "_static/logo-square.svg"
+html_title = ""
+html_theme_options = {
+ "home_page_in_toc": True,
+ "logo": {
+ "alt_text": "Boardwalk documentation - Home",
+ "text": "Boardwalk, a linear Ansible workflow engine",
+ },
+ "repository_branch": "main",
+ "repository_url": "https://github.com/Backblaze/boardwalk/",
+ "path_to_docs": "docs",
+ "use_edit_page_button": True,
+ "use_issues_button": True,
+ "use_repository_button": True,
+ "use_source_button": True,
+}
+html_last_updated_fmt = ""
+
+# -- Options for MyST Configuration -------------------------------------------------
+# https://myst-parser.readthedocs.io/en/latest/syntax/optional.html
+# myst_gfm_only = True
+myst_enable_extensions = [
+ "amsmath",
+ "attrs_inline",
+ "colon_fence",
+ "deflist",
+ "dollarmath",
+ "fieldlist",
+ "html_admonition",
+ "html_image",
+ "linkify",
+ "replacements",
+ "smartquotes",
+ "strikethrough",
+ "substitution",
+ "tasklist",
+]
diff --git a/docs/source/index.md b/docs/source/index.md
new file mode 100644
index 0000000..7dd796c
--- /dev/null
+++ b/docs/source/index.md
@@ -0,0 +1,32 @@
+-------
+# Using GitHub flavored Markdown here, as we're including portions of the README.md, which is used on GitHub.
+gfm_only: True
+-------
+
+```{include} ../../README.md
+:end-before: GitHub-Table-of-Contents_Before
+```
+
+```{toctree}
+:includehidden:
+:maxdepth: 1
+:caption: General
+
+overview.md
+```
+
+```{toctree}
+:includehidden:
+:maxdepth: 1
+:caption: Command-line applications
+
+cli_helpdocs/index.md
+```
+
+```{toctree}
+:includehidden:
+:maxdepth: 1
+:caption: API Reference
+
+apidocs/index.rst
+```
\ No newline at end of file
diff --git a/docs/source/overview.md b/docs/source/overview.md
new file mode 100644
index 0000000..2336cd4
--- /dev/null
+++ b/docs/source/overview.md
@@ -0,0 +1,10 @@
+-------
+# Using GitHub flavored Markdown here, as we're including portions of the README.md, which is used on GitHub.
+gfm_only: True
+-------
+
+# Overview
+
+```{include} ../../README.md
+:start-after: GitHub-Table-of-Contents_After -->
+```
diff --git a/poetry.lock b/poetry.lock
index 84555ae..c4bc771 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,5 +1,23 @@
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
+[[package]]
+name = "accessible-pygments"
+version = "0.0.5"
+description = "A collection of accessible pygments styles"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "accessible_pygments-0.0.5-py3-none-any.whl", hash = "sha256:88ae3211e68a1d0b011504b2ffc1691feafce124b845bd072ab6f9f66f34d4b7"},
+ {file = "accessible_pygments-0.0.5.tar.gz", hash = "sha256:40918d3e6a2b619ad424cb91e556bd3bd8865443d9f22f1dcdf79e33c8046872"},
+]
+
+[package.dependencies]
+pygments = ">=1.5"
+
+[package.extras]
+dev = ["pillow", "pkginfo (>=1.10)", "playwright", "pre-commit", "setuptools", "twine (>=5.0)"]
+tests = ["hypothesis", "pytest"]
+
[[package]]
name = "aiohappyeyeballs"
version = "2.4.3"
@@ -136,6 +154,17 @@ files = [
[package.dependencies]
frozenlist = ">=1.1.0"
+[[package]]
+name = "alabaster"
+version = "1.0.0"
+description = "A light, configurable Sphinx theme"
+optional = false
+python-versions = ">=3.10"
+files = [
+ {file = "alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b"},
+ {file = "alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e"},
+]
+
[[package]]
name = "annotated-types"
version = "0.7.0"
@@ -184,6 +213,17 @@ doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)",
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21.0b1)"]
trio = ["trio (>=0.26.1)"]
+[[package]]
+name = "astroid"
+version = "3.3.5"
+description = "An abstract syntax tree for Python with inference support."
+optional = false
+python-versions = ">=3.9.0"
+files = [
+ {file = "astroid-3.3.5-py3-none-any.whl", hash = "sha256:a9d1c946ada25098d790e079ba2a1b112157278f3fb7e718ae6a9252f5835dc8"},
+ {file = "astroid-3.3.5.tar.gz", hash = "sha256:5cfc40ae9f68311075d27ef68a4841bdc5cc7f6cf86671b49f00607d30188e2d"},
+]
+
[[package]]
name = "attrs"
version = "24.2.0"
@@ -203,6 +243,41 @@ docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphi
tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"]
+[[package]]
+name = "babel"
+version = "2.16.0"
+description = "Internationalization utilities"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"},
+ {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"},
+]
+
+[package.extras]
+dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
+
+[[package]]
+name = "beautifulsoup4"
+version = "4.12.3"
+description = "Screen-scraping library"
+optional = false
+python-versions = ">=3.6.0"
+files = [
+ {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"},
+ {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"},
+]
+
+[package.dependencies]
+soupsieve = ">1.2"
+
+[package.extras]
+cchardet = ["cchardet"]
+chardet = ["chardet"]
+charset-normalizer = ["charset-normalizer"]
+html5lib = ["html5lib"]
+lxml = ["lxml"]
+
[[package]]
name = "boltons"
version = "21.0.0"
@@ -761,6 +836,17 @@ protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4
[package.extras]
grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"]
+[[package]]
+name = "h11"
+version = "0.14.0"
+description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
+ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
+]
+
[[package]]
name = "idna"
version = "3.10"
@@ -775,6 +861,17 @@ files = [
[package.extras]
all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
+[[package]]
+name = "imagesize"
+version = "1.4.1"
+description = "Getting image size from png/jpeg/jpeg2000/gif file"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"},
+ {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"},
+]
+
[[package]]
name = "importlib-metadata"
version = "7.1.0"
@@ -805,6 +902,23 @@ files = [
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
]
+[[package]]
+name = "jinja2"
+version = "3.1.4"
+description = "A very fast and expressive template engine."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
+ {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
+]
+
+[package.dependencies]
+MarkupSafe = ">=2.0"
+
+[package.extras]
+i18n = ["Babel (>=2.7)"]
+
[[package]]
name = "jsonschema"
version = "4.23.0"
@@ -840,6 +954,26 @@ files = [
[package.dependencies]
referencing = ">=0.31.0"
+[[package]]
+name = "linkify-it-py"
+version = "2.0.3"
+description = "Links recognition library with FULL unicode support."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "linkify-it-py-2.0.3.tar.gz", hash = "sha256:68cda27e162e9215c17d786649d1da0021a451bdc436ef9e0fa0ba5234b9b048"},
+ {file = "linkify_it_py-2.0.3-py3-none-any.whl", hash = "sha256:6bcbc417b0ac14323382aef5c5192c0075bf8a9d6b41820a2b66371eac6b6d79"},
+]
+
+[package.dependencies]
+uc-micro-py = "*"
+
+[package.extras]
+benchmark = ["pytest", "pytest-benchmark"]
+dev = ["black", "flake8", "isort", "pre-commit", "pyproject-flake8"]
+doc = ["myst-parser", "sphinx", "sphinx-book-theme"]
+test = ["coverage", "pytest", "pytest-cov"]
+
[[package]]
name = "lockfile"
version = "0.12.2"
@@ -893,6 +1027,95 @@ profiling = ["gprof2dot"]
rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
+[[package]]
+name = "markupsafe"
+version = "3.0.2"
+description = "Safely add untrusted strings to HTML/XML markup."
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"},
+ {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"},
+]
+
+[[package]]
+name = "mdit-py-plugins"
+version = "0.4.2"
+description = "Collection of plugins for markdown-it-py"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636"},
+ {file = "mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5"},
+]
+
+[package.dependencies]
+markdown-it-py = ">=1.0.0,<4.0.0"
+
+[package.extras]
+code-style = ["pre-commit"]
+rtd = ["myst-parser", "sphinx-book-theme"]
+testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
+
[[package]]
name = "mdurl"
version = "0.1.2"
@@ -1005,6 +1228,33 @@ files = [
{file = "multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a"},
]
+[[package]]
+name = "myst-parser"
+version = "4.0.0"
+description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser,"
+optional = false
+python-versions = ">=3.10"
+files = [
+ {file = "myst_parser-4.0.0-py3-none-any.whl", hash = "sha256:b9317997552424448c6096c2558872fdb6f81d3ecb3a40ce84a7518798f3f28d"},
+ {file = "myst_parser-4.0.0.tar.gz", hash = "sha256:851c9dfb44e36e56d15d05e72f02b80da21a9e0d07cba96baf5e2d476bb91531"},
+]
+
+[package.dependencies]
+docutils = ">=0.19,<0.22"
+jinja2 = "*"
+linkify-it-py = {version = ">=2.0,<3.0", optional = true, markers = "extra == \"linkify\""}
+markdown-it-py = ">=3.0,<4.0"
+mdit-py-plugins = ">=0.4.1,<1.0"
+pyyaml = "*"
+sphinx = ">=7,<9"
+
+[package.extras]
+code-style = ["pre-commit (>=3.0,<4.0)"]
+linkify = ["linkify-it-py (>=2.0,<3.0)"]
+rtd = ["ipython", "sphinx (>=7)", "sphinx-autodoc2 (>=0.5.0,<0.6.0)", "sphinx-book-theme (>=1.1,<2.0)", "sphinx-copybutton", "sphinx-design", "sphinx-pyscript", "sphinx-tippy (>=0.4.3)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.9.0,<0.10.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"]
+testing = ["beautifulsoup4", "coverage[toml]", "defusedxml", "pytest (>=8,<9)", "pytest-cov", "pytest-param-files (>=0.6.0,<0.7.0)", "pytest-regressions", "sphinx-pytest"]
+testing-docutils = ["pygments", "pytest (>=8,<9)", "pytest-param-files (>=0.6.0,<0.7.0)"]
+
[[package]]
name = "nodeenv"
version = "1.9.1"
@@ -1479,6 +1729,33 @@ files = [
[package.dependencies]
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
+[[package]]
+name = "pydata-sphinx-theme"
+version = "0.16.0"
+description = "Bootstrap-based Sphinx theme from the PyData community"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "pydata_sphinx_theme-0.16.0-py3-none-any.whl", hash = "sha256:18c810ee4e67e05281e371e156c1fb5bb0fa1f2747240461b225272f7d8d57d8"},
+ {file = "pydata_sphinx_theme-0.16.0.tar.gz", hash = "sha256:721dd26e05fa8b992d66ef545536e6cbe0110afb9865820a08894af1ad6f7707"},
+]
+
+[package.dependencies]
+accessible-pygments = "*"
+Babel = "*"
+beautifulsoup4 = "*"
+docutils = "!=0.17.0"
+pygments = ">=2.7"
+sphinx = ">=6.1"
+typing-extensions = "*"
+
+[package.extras]
+a11y = ["pytest-playwright"]
+dev = ["pandoc", "pre-commit", "pydata-sphinx-theme[doc,test]", "pyyaml", "sphinx-theme-builder[cli]", "tox"]
+doc = ["ablog (>=0.11.8)", "colorama", "graphviz", "ipykernel", "ipyleaflet", "ipywidgets", "jupyter_sphinx", "jupyterlite-sphinx", "linkify-it-py", "matplotlib", "myst-parser", "nbsphinx", "numpy", "numpydoc", "pandas", "plotly", "rich", "sphinx-autoapi (>=3.0.0)", "sphinx-copybutton", "sphinx-design", "sphinx-favicon (>=1.0.1)", "sphinx-sitemap", "sphinx-togglebutton", "sphinxcontrib-youtube (>=1.4.1)", "sphinxext-rediraffe", "xarray"]
+i18n = ["Babel", "jinja2"]
+test = ["pytest", "pytest-cov", "pytest-regressions", "sphinx[test]"]
+
[[package]]
name = "pygments"
version = "2.18.0"
@@ -1533,23 +1810,26 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments
[[package]]
name = "python-daemon"
-version = "3.0.1"
+version = "3.1.0"
description = "Library to implement a well-behaved Unix daemon process."
optional = false
-python-versions = ">=3"
+python-versions = ">=3.7"
files = [
- {file = "python-daemon-3.0.1.tar.gz", hash = "sha256:6c57452372f7eaff40934a1c03ad1826bf5e793558e87fef49131e6464b4dae5"},
- {file = "python_daemon-3.0.1-py3-none-any.whl", hash = "sha256:42bb848a3260a027fa71ad47ecd959e471327cb34da5965962edd5926229f341"},
+ {file = "python_daemon-3.1.0-py3-none-any.whl", hash = "sha256:a66b5896f0aed5807a25c6128268eb496488b1f9c6927c487710049ba16be32a"},
+ {file = "python_daemon-3.1.0.tar.gz", hash = "sha256:fdb621d7e5f46e74b4de1ad6b0fff6e69cd91b4f219de1476190ebdd0f4781df"},
]
[package.dependencies]
-docutils = "*"
lockfile = ">=0.10"
setuptools = ">=62.4.0"
[package.extras]
-devel = ["coverage", "docutils", "isort", "testscenarios (>=0.4)", "testtools", "twine"]
-test = ["coverage", "docutils", "testscenarios (>=0.4)", "testtools"]
+build = ["build", "changelog-chug", "docutils", "python-daemon[doc]", "wheel"]
+devel = ["python-daemon[dist,test]"]
+dist = ["python-daemon[build]", "twine"]
+doc = ["Sphinx (>=4.4,<5.0)"]
+static-analysis = ["isort (>=5.13,<6.0)", "pip-check", "pycodestyle (>=2.12,<3.0)", "pydocstyle (>=6.3,<7.0)", "pyupgrade (>=3.17,<4.0)"]
+test = ["coverage", "python-daemon[build,static-analysis]", "testscenarios (>=0.4)", "testtools"]
[[package]]
name = "pyyaml"
@@ -1667,116 +1947,136 @@ pygments = ">=2.13.0,<3.0.0"
[package.extras]
jupyter = ["ipywidgets (>=7.5.1,<9)"]
+[[package]]
+name = "rich-click"
+version = "1.8.3"
+description = "Format click help output nicely with rich"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "rich_click-1.8.3-py3-none-any.whl", hash = "sha256:636d9c040d31c5eee242201b5bf4f2d358bfae4db14bb22ec1cafa717cfd02cd"},
+ {file = "rich_click-1.8.3.tar.gz", hash = "sha256:6d75bdfa7aa9ed2c467789a0688bc6da23fbe3a143e19aa6ad3f8bac113d2ab3"},
+]
+
+[package.dependencies]
+click = ">=7"
+rich = ">=10.7"
+typing-extensions = "*"
+
+[package.extras]
+dev = ["mypy", "packaging", "pre-commit", "pytest", "pytest-cov", "rich-codex", "ruff", "types-setuptools"]
+docs = ["markdown-include", "mkdocs", "mkdocs-glightbox", "mkdocs-material-extensions", "mkdocs-material[imaging] (>=9.5.18,<9.6.0)", "mkdocs-rss-plugin", "mkdocstrings[python]", "rich-codex"]
+
[[package]]
name = "rpds-py"
-version = "0.20.0"
+version = "0.20.1"
description = "Python bindings to Rust's persistent data structures (rpds)"
optional = false
python-versions = ">=3.8"
files = [
- {file = "rpds_py-0.20.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3ad0fda1635f8439cde85c700f964b23ed5fc2d28016b32b9ee5fe30da5c84e2"},
- {file = "rpds_py-0.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9bb4a0d90fdb03437c109a17eade42dfbf6190408f29b2744114d11586611d6f"},
- {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6377e647bbfd0a0b159fe557f2c6c602c159fc752fa316572f012fc0bf67150"},
- {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb851b7df9dda52dc1415ebee12362047ce771fc36914586b2e9fcbd7d293b3e"},
- {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e0f80b739e5a8f54837be5d5c924483996b603d5502bfff79bf33da06164ee2"},
- {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a8c94dad2e45324fc74dce25e1645d4d14df9a4e54a30fa0ae8bad9a63928e3"},
- {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8e604fe73ba048c06085beaf51147eaec7df856824bfe7b98657cf436623daf"},
- {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:df3de6b7726b52966edf29663e57306b23ef775faf0ac01a3e9f4012a24a4140"},
- {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf258ede5bc22a45c8e726b29835b9303c285ab46fc7c3a4cc770736b5304c9f"},
- {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:55fea87029cded5df854ca7e192ec7bdb7ecd1d9a3f63d5c4eb09148acf4a7ce"},
- {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ae94bd0b2f02c28e199e9bc51485d0c5601f58780636185660f86bf80c89af94"},
- {file = "rpds_py-0.20.0-cp310-none-win32.whl", hash = "sha256:28527c685f237c05445efec62426d285e47a58fb05ba0090a4340b73ecda6dee"},
- {file = "rpds_py-0.20.0-cp310-none-win_amd64.whl", hash = "sha256:238a2d5b1cad28cdc6ed15faf93a998336eb041c4e440dd7f902528b8891b399"},
- {file = "rpds_py-0.20.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489"},
- {file = "rpds_py-0.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318"},
- {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db"},
- {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:758406267907b3781beee0f0edfe4a179fbd97c0be2e9b1154d7f0a1279cf8e5"},
- {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3d61339e9f84a3f0767b1995adfb171a0d00a1185192718a17af6e124728e0f5"},
- {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1259c7b3705ac0a0bd38197565a5d603218591d3f6cee6e614e380b6ba61c6f6"},
- {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209"},
- {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7e60cb630f674a31f0368ed32b2a6b4331b8350d67de53c0359992444b116dd3"},
- {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dbe982f38565bb50cb7fb061ebf762c2f254ca3d8c20d4006878766e84266272"},
- {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:514b3293b64187172bc77c8fb0cdae26981618021053b30d8371c3a902d4d5ad"},
- {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d0a26ffe9d4dd35e4dfdd1e71f46401cff0181c75ac174711ccff0459135fa58"},
- {file = "rpds_py-0.20.0-cp311-none-win32.whl", hash = "sha256:89c19a494bf3ad08c1da49445cc5d13d8fefc265f48ee7e7556839acdacf69d0"},
- {file = "rpds_py-0.20.0-cp311-none-win_amd64.whl", hash = "sha256:c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c"},
- {file = "rpds_py-0.20.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a84ab91cbe7aab97f7446652d0ed37d35b68a465aeef8fc41932a9d7eee2c1a6"},
- {file = "rpds_py-0.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:56e27147a5a4c2c21633ff8475d185734c0e4befd1c989b5b95a5d0db699b21b"},
- {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2580b0c34583b85efec8c5c5ec9edf2dfe817330cc882ee972ae650e7b5ef739"},
- {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b80d4a7900cf6b66bb9cee5c352b2d708e29e5a37fe9bf784fa97fc11504bf6c"},
- {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50eccbf054e62a7b2209b28dc7a22d6254860209d6753e6b78cfaeb0075d7bee"},
- {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:49a8063ea4296b3a7e81a5dfb8f7b2d73f0b1c20c2af401fb0cdf22e14711a96"},
- {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea438162a9fcbee3ecf36c23e6c68237479f89f962f82dae83dc15feeceb37e4"},
- {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18d7585c463087bddcfa74c2ba267339f14f2515158ac4db30b1f9cbdb62c8ef"},
- {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d4c7d1a051eeb39f5c9547e82ea27cbcc28338482242e3e0b7768033cb083821"},
- {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4df1e3b3bec320790f699890d41c59d250f6beda159ea3c44c3f5bac1976940"},
- {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2cf126d33a91ee6eedc7f3197b53e87a2acdac63602c0f03a02dd69e4b138174"},
- {file = "rpds_py-0.20.0-cp312-none-win32.whl", hash = "sha256:8bc7690f7caee50b04a79bf017a8d020c1f48c2a1077ffe172abec59870f1139"},
- {file = "rpds_py-0.20.0-cp312-none-win_amd64.whl", hash = "sha256:0e13e6952ef264c40587d510ad676a988df19adea20444c2b295e536457bc585"},
- {file = "rpds_py-0.20.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:aa9a0521aeca7d4941499a73ad7d4f8ffa3d1affc50b9ea11d992cd7eff18a29"},
- {file = "rpds_py-0.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1f1d51eccb7e6c32ae89243cb352389228ea62f89cd80823ea7dd1b98e0b91"},
- {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a86a9b96070674fc88b6f9f71a97d2c1d3e5165574615d1f9168ecba4cecb24"},
- {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6c8ef2ebf76df43f5750b46851ed1cdf8f109d7787ca40035fe19fbdc1acc5a7"},
- {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b74b25f024b421d5859d156750ea9a65651793d51b76a2e9238c05c9d5f203a9"},
- {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57eb94a8c16ab08fef6404301c38318e2c5a32216bf5de453e2714c964c125c8"},
- {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1940dae14e715e2e02dfd5b0f64a52e8374a517a1e531ad9412319dc3ac7879"},
- {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d20277fd62e1b992a50c43f13fbe13277a31f8c9f70d59759c88f644d66c619f"},
- {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:06db23d43f26478303e954c34c75182356ca9aa7797d22c5345b16871ab9c45c"},
- {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b2a5db5397d82fa847e4c624b0c98fe59d2d9b7cf0ce6de09e4d2e80f8f5b3f2"},
- {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5a35df9f5548fd79cb2f52d27182108c3e6641a4feb0f39067911bf2adaa3e57"},
- {file = "rpds_py-0.20.0-cp313-none-win32.whl", hash = "sha256:fd2d84f40633bc475ef2d5490b9c19543fbf18596dcb1b291e3a12ea5d722f7a"},
- {file = "rpds_py-0.20.0-cp313-none-win_amd64.whl", hash = "sha256:9bc2d153989e3216b0559251b0c260cfd168ec78b1fac33dd485750a228db5a2"},
- {file = "rpds_py-0.20.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:f2fbf7db2012d4876fb0d66b5b9ba6591197b0f165db8d99371d976546472a24"},
- {file = "rpds_py-0.20.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1e5f3cd7397c8f86c8cc72d5a791071431c108edd79872cdd96e00abd8497d29"},
- {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce9845054c13696f7af7f2b353e6b4f676dab1b4b215d7fe5e05c6f8bb06f965"},
- {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c3e130fd0ec56cb76eb49ef52faead8ff09d13f4527e9b0c400307ff72b408e1"},
- {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b16aa0107ecb512b568244ef461f27697164d9a68d8b35090e9b0c1c8b27752"},
- {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7f429242aae2947246587d2964fad750b79e8c233a2367f71b554e9447949c"},
- {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af0fc424a5842a11e28956e69395fbbeab2c97c42253169d87e90aac2886d751"},
- {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b8c00a3b1e70c1d3891f0db1b05292747f0dbcfb49c43f9244d04c70fbc40eb8"},
- {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:40ce74fc86ee4645d0a225498d091d8bc61f39b709ebef8204cb8b5a464d3c0e"},
- {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4fe84294c7019456e56d93e8ababdad5a329cd25975be749c3f5f558abb48253"},
- {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:338ca4539aad4ce70a656e5187a3a31c5204f261aef9f6ab50e50bcdffaf050a"},
- {file = "rpds_py-0.20.0-cp38-none-win32.whl", hash = "sha256:54b43a2b07db18314669092bb2de584524d1ef414588780261e31e85846c26a5"},
- {file = "rpds_py-0.20.0-cp38-none-win_amd64.whl", hash = "sha256:a1862d2d7ce1674cffa6d186d53ca95c6e17ed2b06b3f4c476173565c862d232"},
- {file = "rpds_py-0.20.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3fde368e9140312b6e8b6c09fb9f8c8c2f00999d1823403ae90cc00480221b22"},
- {file = "rpds_py-0.20.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9824fb430c9cf9af743cf7aaf6707bf14323fb51ee74425c380f4c846ea70789"},
- {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11ef6ce74616342888b69878d45e9f779b95d4bd48b382a229fe624a409b72c5"},
- {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c52d3f2f82b763a24ef52f5d24358553e8403ce05f893b5347098014f2d9eff2"},
- {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d35cef91e59ebbeaa45214861874bc6f19eb35de96db73e467a8358d701a96c"},
- {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d72278a30111e5b5525c1dd96120d9e958464316f55adb030433ea905866f4de"},
- {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4c29cbbba378759ac5786730d1c3cb4ec6f8ababf5c42a9ce303dc4b3d08cda"},
- {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6632f2d04f15d1bd6fe0eedd3b86d9061b836ddca4c03d5cf5c7e9e6b7c14580"},
- {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d0b67d87bb45ed1cd020e8fbf2307d449b68abc45402fe1a4ac9e46c3c8b192b"},
- {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ec31a99ca63bf3cd7f1a5ac9fe95c5e2d060d3c768a09bc1d16e235840861420"},
- {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22e6c9976e38f4d8c4a63bd8a8edac5307dffd3ee7e6026d97f3cc3a2dc02a0b"},
- {file = "rpds_py-0.20.0-cp39-none-win32.whl", hash = "sha256:569b3ea770c2717b730b61998b6c54996adee3cef69fc28d444f3e7920313cf7"},
- {file = "rpds_py-0.20.0-cp39-none-win_amd64.whl", hash = "sha256:e6900ecdd50ce0facf703f7a00df12374b74bbc8ad9fe0f6559947fb20f82364"},
- {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:617c7357272c67696fd052811e352ac54ed1d9b49ab370261a80d3b6ce385045"},
- {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9426133526f69fcaba6e42146b4e12d6bc6c839b8b555097020e2b78ce908dcc"},
- {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deb62214c42a261cb3eb04d474f7155279c1a8a8c30ac89b7dcb1721d92c3c02"},
- {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcaeb7b57f1a1e071ebd748984359fef83ecb026325b9d4ca847c95bc7311c92"},
- {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d454b8749b4bd70dd0a79f428731ee263fa6995f83ccb8bada706e8d1d3ff89d"},
- {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d807dc2051abe041b6649681dce568f8e10668e3c1c6543ebae58f2d7e617855"},
- {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3c20f0ddeb6e29126d45f89206b8291352b8c5b44384e78a6499d68b52ae511"},
- {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b7f19250ceef892adf27f0399b9e5afad019288e9be756d6919cb58892129f51"},
- {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4f1ed4749a08379555cebf4650453f14452eaa9c43d0a95c49db50c18b7da075"},
- {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:dcedf0b42bcb4cfff4101d7771a10532415a6106062f005ab97d1d0ab5681c60"},
- {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:39ed0d010457a78f54090fafb5d108501b5aa5604cc22408fc1c0c77eac14344"},
- {file = "rpds_py-0.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:bb273176be34a746bdac0b0d7e4e2c467323d13640b736c4c477881a3220a989"},
- {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f918a1a130a6dfe1d7fe0f105064141342e7dd1611f2e6a21cd2f5c8cb1cfb3e"},
- {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f60012a73aa396be721558caa3a6fd49b3dd0033d1675c6d59c4502e870fcf0c"},
- {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d2b1ad682a3dfda2a4e8ad8572f3100f95fad98cb99faf37ff0ddfe9cbf9d03"},
- {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:614fdafe9f5f19c63ea02817fa4861c606a59a604a77c8cdef5aa01d28b97921"},
- {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa518bcd7600c584bf42e6617ee8132869e877db2f76bcdc281ec6a4113a53ab"},
- {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0475242f447cc6cb8a9dd486d68b2ef7fbee84427124c232bff5f63b1fe11e5"},
- {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90a4cd061914a60bd51c68bcb4357086991bd0bb93d8aa66a6da7701370708f"},
- {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:def7400461c3a3f26e49078302e1c1b38f6752342c77e3cf72ce91ca69fb1bc1"},
- {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:65794e4048ee837494aea3c21a28ad5fc080994dfba5b036cf84de37f7ad5074"},
- {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:faefcc78f53a88f3076b7f8be0a8f8d35133a3ecf7f3770895c25f8813460f08"},
- {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:5b4f105deeffa28bbcdff6c49b34e74903139afa690e35d2d9e3c2c2fba18cec"},
- {file = "rpds_py-0.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fdfc3a892927458d98f3d55428ae46b921d1f7543b89382fdb483f5640daaec8"},
- {file = "rpds_py-0.20.0.tar.gz", hash = "sha256:d72a210824facfdaf8768cf2d7ca25a042c30320b3020de2fa04640920d4e121"},
+ {file = "rpds_py-0.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a649dfd735fff086e8a9d0503a9f0c7d01b7912a333c7ae77e1515c08c146dad"},
+ {file = "rpds_py-0.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f16bc1334853e91ddaaa1217045dd7be166170beec337576818461268a3de67f"},
+ {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14511a539afee6f9ab492b543060c7491c99924314977a55c98bfa2ee29ce78c"},
+ {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3ccb8ac2d3c71cda472b75af42818981bdacf48d2e21c36331b50b4f16930163"},
+ {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c142b88039b92e7e0cb2552e8967077e3179b22359e945574f5e2764c3953dcf"},
+ {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f19169781dddae7478a32301b499b2858bc52fc45a112955e798ee307e294977"},
+ {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13c56de6518e14b9bf6edde23c4c39dac5b48dcf04160ea7bce8fca8397cdf86"},
+ {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:925d176a549f4832c6f69fa6026071294ab5910e82a0fe6c6228fce17b0706bd"},
+ {file = "rpds_py-0.20.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:78f0b6877bfce7a3d1ff150391354a410c55d3cdce386f862926a4958ad5ab7e"},
+ {file = "rpds_py-0.20.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3dd645e2b0dcb0fd05bf58e2e54c13875847687d0b71941ad2e757e5d89d4356"},
+ {file = "rpds_py-0.20.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4f676e21db2f8c72ff0936f895271e7a700aa1f8d31b40e4e43442ba94973899"},
+ {file = "rpds_py-0.20.1-cp310-none-win32.whl", hash = "sha256:648386ddd1e19b4a6abab69139b002bc49ebf065b596119f8f37c38e9ecee8ff"},
+ {file = "rpds_py-0.20.1-cp310-none-win_amd64.whl", hash = "sha256:d9ecb51120de61e4604650666d1f2b68444d46ae18fd492245a08f53ad2b7711"},
+ {file = "rpds_py-0.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:762703bdd2b30983c1d9e62b4c88664df4a8a4d5ec0e9253b0231171f18f6d75"},
+ {file = "rpds_py-0.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0b581f47257a9fce535c4567782a8976002d6b8afa2c39ff616edf87cbeff712"},
+ {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:842c19a6ce894493563c3bd00d81d5100e8e57d70209e84d5491940fdb8b9e3a"},
+ {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42cbde7789f5c0bcd6816cb29808e36c01b960fb5d29f11e052215aa85497c93"},
+ {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c8e9340ce5a52f95fa7d3b552b35c7e8f3874d74a03a8a69279fd5fca5dc751"},
+ {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ba6f89cac95c0900d932c9efb7f0fb6ca47f6687feec41abcb1bd5e2bd45535"},
+ {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a916087371afd9648e1962e67403c53f9c49ca47b9680adbeef79da3a7811b0"},
+ {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:200a23239781f46149e6a415f1e870c5ef1e712939fe8fa63035cd053ac2638e"},
+ {file = "rpds_py-0.20.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:58b1d5dd591973d426cbb2da5e27ba0339209832b2f3315928c9790e13f159e8"},
+ {file = "rpds_py-0.20.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6b73c67850ca7cae0f6c56f71e356d7e9fa25958d3e18a64927c2d930859b8e4"},
+ {file = "rpds_py-0.20.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d8761c3c891cc51e90bc9926d6d2f59b27beaf86c74622c8979380a29cc23ac3"},
+ {file = "rpds_py-0.20.1-cp311-none-win32.whl", hash = "sha256:cd945871335a639275eee904caef90041568ce3b42f402c6959b460d25ae8732"},
+ {file = "rpds_py-0.20.1-cp311-none-win_amd64.whl", hash = "sha256:7e21b7031e17c6b0e445f42ccc77f79a97e2687023c5746bfb7a9e45e0921b84"},
+ {file = "rpds_py-0.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:36785be22066966a27348444b40389f8444671630063edfb1a2eb04318721e17"},
+ {file = "rpds_py-0.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:142c0a5124d9bd0e2976089484af5c74f47bd3298f2ed651ef54ea728d2ea42c"},
+ {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbddc10776ca7ebf2a299c41a4dde8ea0d8e3547bfd731cb87af2e8f5bf8962d"},
+ {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:15a842bb369e00295392e7ce192de9dcbf136954614124a667f9f9f17d6a216f"},
+ {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be5ef2f1fc586a7372bfc355986226484e06d1dc4f9402539872c8bb99e34b01"},
+ {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbcf360c9e3399b056a238523146ea77eeb2a596ce263b8814c900263e46031a"},
+ {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecd27a66740ffd621d20b9a2f2b5ee4129a56e27bfb9458a3bcc2e45794c96cb"},
+ {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0b937b2a1988f184a3e9e577adaa8aede21ec0b38320d6009e02bd026db04fa"},
+ {file = "rpds_py-0.20.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6889469bfdc1eddf489729b471303739bf04555bb151fe8875931f8564309afc"},
+ {file = "rpds_py-0.20.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:19b73643c802f4eaf13d97f7855d0fb527fbc92ab7013c4ad0e13a6ae0ed23bd"},
+ {file = "rpds_py-0.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3c6afcf2338e7f374e8edc765c79fbcb4061d02b15dd5f8f314a4af2bdc7feb5"},
+ {file = "rpds_py-0.20.1-cp312-none-win32.whl", hash = "sha256:dc73505153798c6f74854aba69cc75953888cf9866465196889c7cdd351e720c"},
+ {file = "rpds_py-0.20.1-cp312-none-win_amd64.whl", hash = "sha256:8bbe951244a838a51289ee53a6bae3a07f26d4e179b96fc7ddd3301caf0518eb"},
+ {file = "rpds_py-0.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:6ca91093a4a8da4afae7fe6a222c3b53ee4eef433ebfee4d54978a103435159e"},
+ {file = "rpds_py-0.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b9c2fe36d1f758b28121bef29ed1dee9b7a2453e997528e7d1ac99b94892527c"},
+ {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f009c69bc8c53db5dfab72ac760895dc1f2bc1b62ab7408b253c8d1ec52459fc"},
+ {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6740a3e8d43a32629bb9b009017ea5b9e713b7210ba48ac8d4cb6d99d86c8ee8"},
+ {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:32b922e13d4c0080d03e7b62991ad7f5007d9cd74e239c4b16bc85ae8b70252d"},
+ {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe00a9057d100e69b4ae4a094203a708d65b0f345ed546fdef86498bf5390982"},
+ {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49fe9b04b6fa685bd39237d45fad89ba19e9163a1ccaa16611a812e682913496"},
+ {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aa7ac11e294304e615b43f8c441fee5d40094275ed7311f3420d805fde9b07b4"},
+ {file = "rpds_py-0.20.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aa97af1558a9bef4025f8f5d8c60d712e0a3b13a2fe875511defc6ee77a1ab7"},
+ {file = "rpds_py-0.20.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:483b29f6f7ffa6af845107d4efe2e3fa8fb2693de8657bc1849f674296ff6a5a"},
+ {file = "rpds_py-0.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:37fe0f12aebb6a0e3e17bb4cd356b1286d2d18d2e93b2d39fe647138458b4bcb"},
+ {file = "rpds_py-0.20.1-cp313-none-win32.whl", hash = "sha256:a624cc00ef2158e04188df5e3016385b9353638139a06fb77057b3498f794782"},
+ {file = "rpds_py-0.20.1-cp313-none-win_amd64.whl", hash = "sha256:b71b8666eeea69d6363248822078c075bac6ed135faa9216aa85f295ff009b1e"},
+ {file = "rpds_py-0.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:5b48e790e0355865197ad0aca8cde3d8ede347831e1959e158369eb3493d2191"},
+ {file = "rpds_py-0.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3e310838a5801795207c66c73ea903deda321e6146d6f282e85fa7e3e4854804"},
+ {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2249280b870e6a42c0d972339e9cc22ee98730a99cd7f2f727549af80dd5a963"},
+ {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e79059d67bea28b53d255c1437b25391653263f0e69cd7dec170d778fdbca95e"},
+ {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b431c777c9653e569986ecf69ff4a5dba281cded16043d348bf9ba505486f36"},
+ {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da584ff96ec95e97925174eb8237e32f626e7a1a97888cdd27ee2f1f24dd0ad8"},
+ {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02a0629ec053fc013808a85178524e3cb63a61dbc35b22499870194a63578fb9"},
+ {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fbf15aff64a163db29a91ed0868af181d6f68ec1a3a7d5afcfe4501252840bad"},
+ {file = "rpds_py-0.20.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:07924c1b938798797d60c6308fa8ad3b3f0201802f82e4a2c41bb3fafb44cc28"},
+ {file = "rpds_py-0.20.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4a5a844f68776a7715ecb30843b453f07ac89bad393431efbf7accca3ef599c1"},
+ {file = "rpds_py-0.20.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:518d2ca43c358929bf08f9079b617f1c2ca6e8848f83c1225c88caeac46e6cbc"},
+ {file = "rpds_py-0.20.1-cp38-none-win32.whl", hash = "sha256:3aea7eed3e55119635a74bbeb80b35e776bafccb70d97e8ff838816c124539f1"},
+ {file = "rpds_py-0.20.1-cp38-none-win_amd64.whl", hash = "sha256:7dca7081e9a0c3b6490a145593f6fe3173a94197f2cb9891183ef75e9d64c425"},
+ {file = "rpds_py-0.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b41b6321805c472f66990c2849e152aff7bc359eb92f781e3f606609eac877ad"},
+ {file = "rpds_py-0.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a90c373ea2975519b58dece25853dbcb9779b05cc46b4819cb1917e3b3215b6"},
+ {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16d4477bcb9fbbd7b5b0e4a5d9b493e42026c0bf1f06f723a9353f5153e75d30"},
+ {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84b8382a90539910b53a6307f7c35697bc7e6ffb25d9c1d4e998a13e842a5e83"},
+ {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4888e117dd41b9d34194d9e31631af70d3d526efc363085e3089ab1a62c32ed1"},
+ {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5265505b3d61a0f56618c9b941dc54dc334dc6e660f1592d112cd103d914a6db"},
+ {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e75ba609dba23f2c95b776efb9dd3f0b78a76a151e96f96cc5b6b1b0004de66f"},
+ {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1791ff70bc975b098fe6ecf04356a10e9e2bd7dc21fa7351c1742fdeb9b4966f"},
+ {file = "rpds_py-0.20.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d126b52e4a473d40232ec2052a8b232270ed1f8c9571aaf33f73a14cc298c24f"},
+ {file = "rpds_py-0.20.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c14937af98c4cc362a1d4374806204dd51b1e12dded1ae30645c298e5a5c4cb1"},
+ {file = "rpds_py-0.20.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3d089d0b88996df627693639d123c8158cff41c0651f646cd8fd292c7da90eaf"},
+ {file = "rpds_py-0.20.1-cp39-none-win32.whl", hash = "sha256:653647b8838cf83b2e7e6a0364f49af96deec64d2a6578324db58380cff82aca"},
+ {file = "rpds_py-0.20.1-cp39-none-win_amd64.whl", hash = "sha256:fa41a64ac5b08b292906e248549ab48b69c5428f3987b09689ab2441f267d04d"},
+ {file = "rpds_py-0.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7a07ced2b22f0cf0b55a6a510078174c31b6d8544f3bc00c2bcee52b3d613f74"},
+ {file = "rpds_py-0.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:68cb0a499f2c4a088fd2f521453e22ed3527154136a855c62e148b7883b99f9a"},
+ {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa3060d885657abc549b2a0f8e1b79699290e5d83845141717c6c90c2df38311"},
+ {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:95f3b65d2392e1c5cec27cff08fdc0080270d5a1a4b2ea1d51d5f4a2620ff08d"},
+ {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2cc3712a4b0b76a1d45a9302dd2f53ff339614b1c29603a911318f2357b04dd2"},
+ {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d4eea0761e37485c9b81400437adb11c40e13ef513375bbd6973e34100aeb06"},
+ {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f5179583d7a6cdb981151dd349786cbc318bab54963a192692d945dd3f6435d"},
+ {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fbb0ffc754490aff6dabbf28064be47f0f9ca0b9755976f945214965b3ace7e"},
+ {file = "rpds_py-0.20.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a94e52537a0e0a85429eda9e49f272ada715506d3b2431f64b8a3e34eb5f3e75"},
+ {file = "rpds_py-0.20.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:92b68b79c0da2a980b1c4197e56ac3dd0c8a149b4603747c4378914a68706979"},
+ {file = "rpds_py-0.20.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:93da1d3db08a827eda74356f9f58884adb254e59b6664f64cc04cdff2cc19b0d"},
+ {file = "rpds_py-0.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:754bbed1a4ca48479e9d4182a561d001bbf81543876cdded6f695ec3d465846b"},
+ {file = "rpds_py-0.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ca449520e7484534a2a44faf629362cae62b660601432d04c482283c47eaebab"},
+ {file = "rpds_py-0.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:9c4cb04a16b0f199a8c9bf807269b2f63b7b5b11425e4a6bd44bd6961d28282c"},
+ {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb63804105143c7e24cee7db89e37cb3f3941f8e80c4379a0b355c52a52b6780"},
+ {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:55cd1fa4ecfa6d9f14fbd97ac24803e6f73e897c738f771a9fe038f2f11ff07c"},
+ {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f8f741b6292c86059ed175d80eefa80997125b7c478fb8769fd9ac8943a16c0"},
+ {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fc212779bf8411667234b3cdd34d53de6c2b8b8b958e1e12cb473a5f367c338"},
+ {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ad56edabcdb428c2e33bbf24f255fe2b43253b7d13a2cdbf05de955217313e6"},
+ {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0a3a1e9ee9728b2c1734f65d6a1d376c6f2f6fdcc13bb007a08cc4b1ff576dc5"},
+ {file = "rpds_py-0.20.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e13de156137b7095442b288e72f33503a469aa1980ed856b43c353ac86390519"},
+ {file = "rpds_py-0.20.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:07f59760ef99f31422c49038964b31c4dfcfeb5d2384ebfc71058a7c9adae2d2"},
+ {file = "rpds_py-0.20.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:59240685e7da61fb78f65a9f07f8108e36a83317c53f7b276b4175dc44151684"},
+ {file = "rpds_py-0.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:83cba698cfb3c2c5a7c3c6bac12fe6c6a51aae69513726be6411076185a8b24a"},
+ {file = "rpds_py-0.20.1.tar.gz", hash = "sha256:e1791c4aabd117653530dccd24108fa03cc6baf21f58b950d0a73c3b3b29a350"},
]
[[package]]
@@ -1876,16 +2176,16 @@ files = [
[[package]]
name = "semgrep"
-version = "1.93.0"
+version = "1.94.0"
description = "Lightweight static analysis for many languages. Find bug variants with patterns that look like source code."
optional = false
python-versions = ">=3.8"
files = [
- {file = "semgrep-1.93.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-any.whl", hash = "sha256:41c3df47c84e2ef064becad233bf619d98824f46787109a7e247fa1266429732"},
- {file = "semgrep-1.93.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-macosx_10_14_x86_64.whl", hash = "sha256:40ae350c75fa7b8ea949f815b1afc9709449a5a2cc9659c79e1f983a400342db"},
- {file = "semgrep-1.93.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-macosx_11_0_arm64.whl", hash = "sha256:d021e4513fcff7a60cdc4541c443212b5a8165d1e8f49abd8661ab685607dd34"},
- {file = "semgrep-1.93.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-musllinux_1_0_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cde7d4c42a579359f37f3ef19cc04f91886903381ba3cff6ce0d90ea3ca80676"},
- {file = "semgrep-1.93.0.tar.gz", hash = "sha256:b97fd47b303ca1ba6f85a1b50428093b987126d8e4aa7422e5acdcc3787c6628"},
+ {file = "semgrep-1.94.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-any.whl", hash = "sha256:c0ab9e7084419db7f61a60e32ef59c01e723c7d43ff7b40a974b51f3d81beafe"},
+ {file = "semgrep-1.94.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-macosx_10_14_x86_64.whl", hash = "sha256:121ff5116310c5cb58d31712e971a3ecd7605c26b6b5b54e3537f6b3676190c0"},
+ {file = "semgrep-1.94.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-macosx_11_0_arm64.whl", hash = "sha256:c91fd31a58665ff1e5ac6dbbcfb7ce4929eb86d9226ce51dcb24cd69cdd0aee8"},
+ {file = "semgrep-1.94.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-musllinux_1_0_aarch64.manylinux2014_aarch64.whl", hash = "sha256:191b881dbb4329c68602550cc4119eb9e06576f96ad435b3f6195adb248381dc"},
+ {file = "semgrep-1.94.0.tar.gz", hash = "sha256:ebe1515b49972cc9cc9ed1973780ce899fe2ece4779a51036f0bfab3235d32a8"},
]
[package.dependencies]
@@ -1914,33 +2214,33 @@ wcmatch = ">=8.3,<9.0"
[[package]]
name = "setuptools"
-version = "75.2.0"
+version = "75.3.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false
python-versions = ">=3.8"
files = [
- {file = "setuptools-75.2.0-py3-none-any.whl", hash = "sha256:a7fcb66f68b4d9e8e66b42f9876150a3371558f98fa32222ffaa5bced76406f8"},
- {file = "setuptools-75.2.0.tar.gz", hash = "sha256:753bb6ebf1f465a1912e19ed1d41f403a79173a9acf66a42e7e6aec45c3c16ec"},
+ {file = "setuptools-75.3.0-py3-none-any.whl", hash = "sha256:f2504966861356aa38616760c0f66568e535562374995367b4e69c7143cf6bcd"},
+ {file = "setuptools-75.3.0.tar.gz", hash = "sha256:fba5dd4d766e97be1b1681d98712680ae8f2f26d7881245f2ce9e40714f1a686"},
]
[package.extras]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"]
-core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
+core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
cover = ["pytest-cov"]
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
enabler = ["pytest-enabler (>=2.2)"]
-test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
-type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11.*)", "pytest-mypy"]
+test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
+type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.12.*)", "pytest-mypy"]
[[package]]
name = "slack-bolt"
-version = "1.21.1"
+version = "1.21.2"
description = "The Bolt Framework for Python"
optional = false
python-versions = ">=3.6"
files = [
- {file = "slack_bolt-1.21.1-py2.py3-none-any.whl", hash = "sha256:feb3c97ed7c388318d6e007a9c1b50dd88b0d59e64ff1f8c4e770db30e890ec8"},
- {file = "slack_bolt-1.21.1.tar.gz", hash = "sha256:f0f1e7223f0e5621a768d1efce470058619b4f4eacbec405625c8c813e489c20"},
+ {file = "slack_bolt-1.21.2-py2.py3-none-any.whl", hash = "sha256:6860fc8693ca543b653c5d49a09b8b542f5fb7a02638342a7ddd18d8bc6f3ba0"},
+ {file = "slack_bolt-1.21.2.tar.gz", hash = "sha256:05ac2d454adfddfc629fb63c7a3723bd1432a24373119368bc81f2f52b029cbf"},
]
[package.dependencies]
@@ -1948,13 +2248,13 @@ slack-sdk = ">=3.33.1,<4"
[[package]]
name = "slack-sdk"
-version = "3.33.1"
+version = "3.33.3"
description = "The Slack API Platform SDK for Python"
optional = false
python-versions = ">=3.6"
files = [
- {file = "slack_sdk-3.33.1-py2.py3-none-any.whl", hash = "sha256:ef93beec3ce9c8f64da02fd487598a05ec4bc9c92ceed58f122dbe632691cbe2"},
- {file = "slack_sdk-3.33.1.tar.gz", hash = "sha256:e328bb661d95db5f66b993b1d64288ac7c72201a745b4c7cf8848dafb7b74e40"},
+ {file = "slack_sdk-3.33.3-py2.py3-none-any.whl", hash = "sha256:0515fb93cd03b18de61f876a8304c4c3cef4dd3c2a3bad62d7394d2eb5a3c8e6"},
+ {file = "slack_sdk-3.33.3.tar.gz", hash = "sha256:4cc44c9ffe4bb28a01fbe3264c2f466c783b893a4eca62026ab845ec7c176ff1"},
]
[package.extras]
@@ -1971,6 +2271,254 @@ files = [
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
]
+[[package]]
+name = "snowballstemmer"
+version = "2.2.0"
+description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
+optional = false
+python-versions = "*"
+files = [
+ {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"},
+ {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"},
+]
+
+[[package]]
+name = "soupsieve"
+version = "2.6"
+description = "A modern CSS selector implementation for Beautiful Soup."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"},
+ {file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"},
+]
+
+[[package]]
+name = "sphinx"
+version = "8.1.3"
+description = "Python documentation generator"
+optional = false
+python-versions = ">=3.10"
+files = [
+ {file = "sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2"},
+ {file = "sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927"},
+]
+
+[package.dependencies]
+alabaster = ">=0.7.14"
+babel = ">=2.13"
+colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""}
+docutils = ">=0.20,<0.22"
+imagesize = ">=1.3"
+Jinja2 = ">=3.1"
+packaging = ">=23.0"
+Pygments = ">=2.17"
+requests = ">=2.30.0"
+snowballstemmer = ">=2.2"
+sphinxcontrib-applehelp = ">=1.0.7"
+sphinxcontrib-devhelp = ">=1.0.6"
+sphinxcontrib-htmlhelp = ">=2.0.6"
+sphinxcontrib-jsmath = ">=1.0.1"
+sphinxcontrib-qthelp = ">=1.0.6"
+sphinxcontrib-serializinghtml = ">=1.1.9"
+
+[package.extras]
+docs = ["sphinxcontrib-websupport"]
+lint = ["flake8 (>=6.0)", "mypy (==1.11.1)", "pyright (==1.1.384)", "pytest (>=6.0)", "ruff (==0.6.9)", "sphinx-lint (>=0.9)", "tomli (>=2)", "types-Pillow (==10.2.0.20240822)", "types-Pygments (==2.18.0.20240506)", "types-colorama (==0.4.15.20240311)", "types-defusedxml (==0.7.0.20240218)", "types-docutils (==0.21.0.20241005)", "types-requests (==2.32.0.20240914)", "types-urllib3 (==1.26.25.14)"]
+test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=8.0)", "setuptools (>=70.0)", "typing_extensions (>=4.9)"]
+
+[[package]]
+name = "sphinx-autobuild"
+version = "2024.10.3"
+description = "Rebuild Sphinx documentation on changes, with hot reloading in the browser."
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "sphinx_autobuild-2024.10.3-py3-none-any.whl", hash = "sha256:158e16c36f9d633e613c9aaf81c19b0fc458ca78b112533b20dafcda430d60fa"},
+ {file = "sphinx_autobuild-2024.10.3.tar.gz", hash = "sha256:248150f8f333e825107b6d4b86113ab28fa51750e5f9ae63b59dc339be951fb1"},
+]
+
+[package.dependencies]
+colorama = ">=0.4.6"
+sphinx = "*"
+starlette = ">=0.35"
+uvicorn = ">=0.25"
+watchfiles = ">=0.20"
+websockets = ">=11"
+
+[package.extras]
+test = ["httpx", "pytest (>=6)"]
+
+[[package]]
+name = "sphinx-autodoc2"
+version = "0.5.0"
+description = "Analyse a python project and create documentation for it."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "sphinx_autodoc2-0.5.0-py3-none-any.whl", hash = "sha256:e867013b1512f9d6d7e6f6799f8b537d6884462acd118ef361f3f619a60b5c9e"},
+ {file = "sphinx_autodoc2-0.5.0.tar.gz", hash = "sha256:7d76044aa81d6af74447080182b6868c7eb066874edc835e8ddf810735b6565a"},
+]
+
+[package.dependencies]
+astroid = ">=2.7,<4"
+typing-extensions = "*"
+
+[package.extras]
+cli = ["typer[all]"]
+docs = ["furo", "myst-parser", "sphinx (>=4.0.0)"]
+sphinx = ["sphinx (>=4.0.0)"]
+testing = ["pytest", "pytest-cov", "pytest-regressions", "sphinx (>=4.0.0,<7)"]
+
+[[package]]
+name = "sphinx-book-theme"
+version = "1.1.3"
+description = "A clean book theme for scientific explanations and documentation with Sphinx"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "sphinx_book_theme-1.1.3-py3-none-any.whl", hash = "sha256:a554a9a7ac3881979a87a2b10f633aa2a5706e72218a10f71be38b3c9e831ae9"},
+ {file = "sphinx_book_theme-1.1.3.tar.gz", hash = "sha256:1f25483b1846cb3d353a6bc61b3b45b031f4acf845665d7da90e01ae0aef5b4d"},
+]
+
+[package.dependencies]
+pydata-sphinx-theme = ">=0.15.2"
+sphinx = ">=5"
+
+[package.extras]
+code-style = ["pre-commit"]
+doc = ["ablog", "folium", "ipywidgets", "matplotlib", "myst-nb", "nbclient", "numpy", "numpydoc", "pandas", "plotly", "sphinx-copybutton", "sphinx-design", "sphinx-examples", "sphinx-tabs", "sphinx-thebe", "sphinx-togglebutton", "sphinxcontrib-bibtex", "sphinxcontrib-youtube", "sphinxext-opengraph"]
+test = ["beautifulsoup4", "coverage", "defusedxml", "myst-nb", "pytest", "pytest-cov", "pytest-regressions", "sphinx_thebe"]
+
+[[package]]
+name = "sphinx-copybutton"
+version = "0.5.2"
+description = "Add a copy button to each of your code cells."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd"},
+ {file = "sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e"},
+]
+
+[package.dependencies]
+sphinx = ">=1.8"
+
+[package.extras]
+code-style = ["pre-commit (==2.12.1)"]
+rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"]
+
+[[package]]
+name = "sphinxcontrib-applehelp"
+version = "2.0.0"
+description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"},
+ {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"},
+]
+
+[package.extras]
+lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
+standalone = ["Sphinx (>=5)"]
+test = ["pytest"]
+
+[[package]]
+name = "sphinxcontrib-devhelp"
+version = "2.0.0"
+description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"},
+ {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"},
+]
+
+[package.extras]
+lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
+standalone = ["Sphinx (>=5)"]
+test = ["pytest"]
+
+[[package]]
+name = "sphinxcontrib-htmlhelp"
+version = "2.1.0"
+description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"},
+ {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"},
+]
+
+[package.extras]
+lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
+standalone = ["Sphinx (>=5)"]
+test = ["html5lib", "pytest"]
+
+[[package]]
+name = "sphinxcontrib-jsmath"
+version = "1.0.1"
+description = "A sphinx extension which renders display math in HTML via JavaScript"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"},
+ {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"},
+]
+
+[package.extras]
+test = ["flake8", "mypy", "pytest"]
+
+[[package]]
+name = "sphinxcontrib-qthelp"
+version = "2.0.0"
+description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"},
+ {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"},
+]
+
+[package.extras]
+lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
+standalone = ["Sphinx (>=5)"]
+test = ["defusedxml (>=0.7.1)", "pytest"]
+
+[[package]]
+name = "sphinxcontrib-serializinghtml"
+version = "2.0.0"
+description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"},
+ {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"},
+]
+
+[package.extras]
+lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
+standalone = ["Sphinx (>=5)"]
+test = ["pytest"]
+
+[[package]]
+name = "starlette"
+version = "0.41.2"
+description = "The little ASGI library that shines."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "starlette-0.41.2-py3-none-any.whl", hash = "sha256:fbc189474b4731cf30fcef52f18a8d070e3f3b46c6a04c97579e85e6ffca942d"},
+ {file = "starlette-0.41.2.tar.gz", hash = "sha256:9834fd799d1a87fd346deb76158668cfa0b0d56f85caefe8268e2d97c3468b62"},
+]
+
+[package.dependencies]
+anyio = ">=3.4.0,<5"
+
+[package.extras]
+full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"]
+
[[package]]
name = "tomli"
version = "2.0.2"
@@ -2013,6 +2561,20 @@ files = [
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
]
+[[package]]
+name = "uc-micro-py"
+version = "1.0.3"
+description = "Micro subset of unicode data files for linkify-it-py projects."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "uc-micro-py-1.0.3.tar.gz", hash = "sha256:d321b92cff673ec58027c04015fcaa8bb1e005478643ff4a500882eaab88c48a"},
+ {file = "uc_micro_py-1.0.3-py3-none-any.whl", hash = "sha256:db1dffff340817673d7b466ec86114a9dc0e9d4d9b5ba229d9d60e5c12600cd5"},
+]
+
+[package.extras]
+test = ["coverage", "pytest", "pytest-cov"]
+
[[package]]
name = "urllib3"
version = "2.2.3"
@@ -2030,6 +2592,119 @@ h2 = ["h2 (>=4,<5)"]
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
zstd = ["zstandard (>=0.18.0)"]
+[[package]]
+name = "uvicorn"
+version = "0.32.0"
+description = "The lightning-fast ASGI server."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "uvicorn-0.32.0-py3-none-any.whl", hash = "sha256:60b8f3a5ac027dcd31448f411ced12b5ef452c646f76f02f8cc3f25d8d26fd82"},
+ {file = "uvicorn-0.32.0.tar.gz", hash = "sha256:f78b36b143c16f54ccdb8190d0a26b5f1901fe5a3c777e1ab29f26391af8551e"},
+]
+
+[package.dependencies]
+click = ">=7.0"
+h11 = ">=0.8"
+
+[package.extras]
+standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
+
+[[package]]
+name = "watchfiles"
+version = "0.24.0"
+description = "Simple, modern and high performance file watching and code reload in python."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "watchfiles-0.24.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:083dc77dbdeef09fa44bb0f4d1df571d2e12d8a8f985dccde71ac3ac9ac067a0"},
+ {file = "watchfiles-0.24.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e94e98c7cb94cfa6e071d401ea3342767f28eb5a06a58fafdc0d2a4974f4f35c"},
+ {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82ae557a8c037c42a6ef26c494d0631cacca040934b101d001100ed93d43f361"},
+ {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:acbfa31e315a8f14fe33e3542cbcafc55703b8f5dcbb7c1eecd30f141df50db3"},
+ {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b74fdffce9dfcf2dc296dec8743e5b0332d15df19ae464f0e249aa871fc1c571"},
+ {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:449f43f49c8ddca87c6b3980c9284cab6bd1f5c9d9a2b00012adaaccd5e7decd"},
+ {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4abf4ad269856618f82dee296ac66b0cd1d71450fc3c98532d93798e73399b7a"},
+ {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f895d785eb6164678ff4bb5cc60c5996b3ee6df3edb28dcdeba86a13ea0465e"},
+ {file = "watchfiles-0.24.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ae3e208b31be8ce7f4c2c0034f33406dd24fbce3467f77223d10cd86778471c"},
+ {file = "watchfiles-0.24.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2efec17819b0046dde35d13fb8ac7a3ad877af41ae4640f4109d9154ed30a188"},
+ {file = "watchfiles-0.24.0-cp310-none-win32.whl", hash = "sha256:6bdcfa3cd6fdbdd1a068a52820f46a815401cbc2cb187dd006cb076675e7b735"},
+ {file = "watchfiles-0.24.0-cp310-none-win_amd64.whl", hash = "sha256:54ca90a9ae6597ae6dc00e7ed0a040ef723f84ec517d3e7ce13e63e4bc82fa04"},
+ {file = "watchfiles-0.24.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:bdcd5538e27f188dd3c804b4a8d5f52a7fc7f87e7fd6b374b8e36a4ca03db428"},
+ {file = "watchfiles-0.24.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2dadf8a8014fde6addfd3c379e6ed1a981c8f0a48292d662e27cabfe4239c83c"},
+ {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6509ed3f467b79d95fc62a98229f79b1a60d1b93f101e1c61d10c95a46a84f43"},
+ {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8360f7314a070c30e4c976b183d1d8d1585a4a50c5cb603f431cebcbb4f66327"},
+ {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:316449aefacf40147a9efaf3bd7c9bdd35aaba9ac5d708bd1eb5763c9a02bef5"},
+ {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73bde715f940bea845a95247ea3e5eb17769ba1010efdc938ffcb967c634fa61"},
+ {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3770e260b18e7f4e576edca4c0a639f704088602e0bc921c5c2e721e3acb8d15"},
+ {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa0fd7248cf533c259e59dc593a60973a73e881162b1a2f73360547132742823"},
+ {file = "watchfiles-0.24.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d7a2e3b7f5703ffbd500dabdefcbc9eafeff4b9444bbdd5d83d79eedf8428fab"},
+ {file = "watchfiles-0.24.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d831ee0a50946d24a53821819b2327d5751b0c938b12c0653ea5be7dea9c82ec"},
+ {file = "watchfiles-0.24.0-cp311-none-win32.whl", hash = "sha256:49d617df841a63b4445790a254013aea2120357ccacbed00253f9c2b5dc24e2d"},
+ {file = "watchfiles-0.24.0-cp311-none-win_amd64.whl", hash = "sha256:d3dcb774e3568477275cc76554b5a565024b8ba3a0322f77c246bc7111c5bb9c"},
+ {file = "watchfiles-0.24.0-cp311-none-win_arm64.whl", hash = "sha256:9301c689051a4857d5b10777da23fafb8e8e921bcf3abe6448a058d27fb67633"},
+ {file = "watchfiles-0.24.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7211b463695d1e995ca3feb38b69227e46dbd03947172585ecb0588f19b0d87a"},
+ {file = "watchfiles-0.24.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4b8693502d1967b00f2fb82fc1e744df128ba22f530e15b763c8d82baee15370"},
+ {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdab9555053399318b953a1fe1f586e945bc8d635ce9d05e617fd9fe3a4687d6"},
+ {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:34e19e56d68b0dad5cff62273107cf5d9fbaf9d75c46277aa5d803b3ef8a9e9b"},
+ {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:41face41f036fee09eba33a5b53a73e9a43d5cb2c53dad8e61fa6c9f91b5a51e"},
+ {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5148c2f1ea043db13ce9b0c28456e18ecc8f14f41325aa624314095b6aa2e9ea"},
+ {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e4bd963a935aaf40b625c2499f3f4f6bbd0c3776f6d3bc7c853d04824ff1c9f"},
+ {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c79d7719d027b7a42817c5d96461a99b6a49979c143839fc37aa5748c322f234"},
+ {file = "watchfiles-0.24.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:32aa53a9a63b7f01ed32e316e354e81e9da0e6267435c7243bf8ae0f10b428ef"},
+ {file = "watchfiles-0.24.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ce72dba6a20e39a0c628258b5c308779b8697f7676c254a845715e2a1039b968"},
+ {file = "watchfiles-0.24.0-cp312-none-win32.whl", hash = "sha256:d9018153cf57fc302a2a34cb7564870b859ed9a732d16b41a9b5cb2ebed2d444"},
+ {file = "watchfiles-0.24.0-cp312-none-win_amd64.whl", hash = "sha256:551ec3ee2a3ac9cbcf48a4ec76e42c2ef938a7e905a35b42a1267fa4b1645896"},
+ {file = "watchfiles-0.24.0-cp312-none-win_arm64.whl", hash = "sha256:b52a65e4ea43c6d149c5f8ddb0bef8d4a1e779b77591a458a893eb416624a418"},
+ {file = "watchfiles-0.24.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3d2e3ab79a1771c530233cadfd277fcc762656d50836c77abb2e5e72b88e3a48"},
+ {file = "watchfiles-0.24.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:327763da824817b38ad125dcd97595f942d720d32d879f6c4ddf843e3da3fe90"},
+ {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd82010f8ab451dabe36054a1622870166a67cf3fce894f68895db6f74bbdc94"},
+ {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d64ba08db72e5dfd5c33be1e1e687d5e4fcce09219e8aee893a4862034081d4e"},
+ {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1cf1f6dd7825053f3d98f6d33f6464ebdd9ee95acd74ba2c34e183086900a827"},
+ {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43e3e37c15a8b6fe00c1bce2473cfa8eb3484bbeecf3aefbf259227e487a03df"},
+ {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88bcd4d0fe1d8ff43675360a72def210ebad3f3f72cabfeac08d825d2639b4ab"},
+ {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:999928c6434372fde16c8f27143d3e97201160b48a614071261701615a2a156f"},
+ {file = "watchfiles-0.24.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:30bbd525c3262fd9f4b1865cb8d88e21161366561cd7c9e1194819e0a33ea86b"},
+ {file = "watchfiles-0.24.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:edf71b01dec9f766fb285b73930f95f730bb0943500ba0566ae234b5c1618c18"},
+ {file = "watchfiles-0.24.0-cp313-none-win32.whl", hash = "sha256:f4c96283fca3ee09fb044f02156d9570d156698bc3734252175a38f0e8975f07"},
+ {file = "watchfiles-0.24.0-cp313-none-win_amd64.whl", hash = "sha256:a974231b4fdd1bb7f62064a0565a6b107d27d21d9acb50c484d2cdba515b9366"},
+ {file = "watchfiles-0.24.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:ee82c98bed9d97cd2f53bdb035e619309a098ea53ce525833e26b93f673bc318"},
+ {file = "watchfiles-0.24.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fd92bbaa2ecdb7864b7600dcdb6f2f1db6e0346ed425fbd01085be04c63f0b05"},
+ {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f83df90191d67af5a831da3a33dd7628b02a95450e168785586ed51e6d28943c"},
+ {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fca9433a45f18b7c779d2bae7beeec4f740d28b788b117a48368d95a3233ed83"},
+ {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b995bfa6bf01a9e09b884077a6d37070464b529d8682d7691c2d3b540d357a0c"},
+ {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed9aba6e01ff6f2e8285e5aa4154e2970068fe0fc0998c4380d0e6278222269b"},
+ {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5171ef898299c657685306d8e1478a45e9303ddcd8ac5fed5bd52ad4ae0b69b"},
+ {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4933a508d2f78099162da473841c652ad0de892719043d3f07cc83b33dfd9d91"},
+ {file = "watchfiles-0.24.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:95cf3b95ea665ab03f5a54765fa41abf0529dbaf372c3b83d91ad2cfa695779b"},
+ {file = "watchfiles-0.24.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:01def80eb62bd5db99a798d5e1f5f940ca0a05986dcfae21d833af7a46f7ee22"},
+ {file = "watchfiles-0.24.0-cp38-none-win32.whl", hash = "sha256:4d28cea3c976499475f5b7a2fec6b3a36208656963c1a856d328aeae056fc5c1"},
+ {file = "watchfiles-0.24.0-cp38-none-win_amd64.whl", hash = "sha256:21ab23fdc1208086d99ad3f69c231ba265628014d4aed31d4e8746bd59e88cd1"},
+ {file = "watchfiles-0.24.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b665caeeda58625c3946ad7308fbd88a086ee51ccb706307e5b1fa91556ac886"},
+ {file = "watchfiles-0.24.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5c51749f3e4e269231510da426ce4a44beb98db2dce9097225c338f815b05d4f"},
+ {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b2509f08761f29a0fdad35f7e1638b8ab1adfa2666d41b794090361fb8b855"},
+ {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a60e2bf9dc6afe7f743e7c9b149d1fdd6dbf35153c78fe3a14ae1a9aee3d98b"},
+ {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f7d9b87c4c55e3ea8881dfcbf6d61ea6775fffed1fedffaa60bd047d3c08c430"},
+ {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:78470906a6be5199524641f538bd2c56bb809cd4bf29a566a75051610bc982c3"},
+ {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:07cdef0c84c03375f4e24642ef8d8178e533596b229d32d2bbd69e5128ede02a"},
+ {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d337193bbf3e45171c8025e291530fb7548a93c45253897cd764a6a71c937ed9"},
+ {file = "watchfiles-0.24.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ec39698c45b11d9694a1b635a70946a5bad066b593af863460a8e600f0dff1ca"},
+ {file = "watchfiles-0.24.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e28d91ef48eab0afb939fa446d8ebe77e2f7593f5f463fd2bb2b14132f95b6e"},
+ {file = "watchfiles-0.24.0-cp39-none-win32.whl", hash = "sha256:7138eff8baa883aeaa074359daabb8b6c1e73ffe69d5accdc907d62e50b1c0da"},
+ {file = "watchfiles-0.24.0-cp39-none-win_amd64.whl", hash = "sha256:b3ef2c69c655db63deb96b3c3e587084612f9b1fa983df5e0c3379d41307467f"},
+ {file = "watchfiles-0.24.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:632676574429bee8c26be8af52af20e0c718cc7f5f67f3fb658c71928ccd4f7f"},
+ {file = "watchfiles-0.24.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:a2a9891723a735d3e2540651184be6fd5b96880c08ffe1a98bae5017e65b544b"},
+ {file = "watchfiles-0.24.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7fa2bc0efef3e209a8199fd111b8969fe9db9c711acc46636686331eda7dd4"},
+ {file = "watchfiles-0.24.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01550ccf1d0aed6ea375ef259706af76ad009ef5b0203a3a4cce0f6024f9b68a"},
+ {file = "watchfiles-0.24.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:96619302d4374de5e2345b2b622dc481257a99431277662c30f606f3e22f42be"},
+ {file = "watchfiles-0.24.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:85d5f0c7771dcc7a26c7a27145059b6bb0ce06e4e751ed76cdf123d7039b60b5"},
+ {file = "watchfiles-0.24.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:951088d12d339690a92cef2ec5d3cfd957692834c72ffd570ea76a6790222777"},
+ {file = "watchfiles-0.24.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49fb58bcaa343fedc6a9e91f90195b20ccb3135447dc9e4e2570c3a39565853e"},
+ {file = "watchfiles-0.24.0.tar.gz", hash = "sha256:afb72325b74fa7a428c009c1b8be4b4d7c2afedafb2982827ef2156646df2fe1"},
+]
+
+[package.dependencies]
+anyio = ">=3.0.0"
+
[[package]]
name = "wcmatch"
version = "8.5.2"
@@ -2044,6 +2719,101 @@ files = [
[package.dependencies]
bracex = ">=2.1.1"
+[[package]]
+name = "websockets"
+version = "13.1"
+description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "websockets-13.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f48c749857f8fb598fb890a75f540e3221d0976ed0bf879cf3c7eef34151acee"},
+ {file = "websockets-13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7e72ce6bda6fb9409cc1e8164dd41d7c91466fb599eb047cfda72fe758a34a7"},
+ {file = "websockets-13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f779498eeec470295a2b1a5d97aa1bc9814ecd25e1eb637bd9d1c73a327387f6"},
+ {file = "websockets-13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676df3fe46956fbb0437d8800cd5f2b6d41143b6e7e842e60554398432cf29b"},
+ {file = "websockets-13.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7affedeb43a70351bb811dadf49493c9cfd1ed94c9c70095fd177e9cc1541fa"},
+ {file = "websockets-13.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1971e62d2caa443e57588e1d82d15f663b29ff9dfe7446d9964a4b6f12c1e700"},
+ {file = "websockets-13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5f2e75431f8dc4a47f31565a6e1355fb4f2ecaa99d6b89737527ea917066e26c"},
+ {file = "websockets-13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58cf7e75dbf7e566088b07e36ea2e3e2bd5676e22216e4cad108d4df4a7402a0"},
+ {file = "websockets-13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c90d6dec6be2c7d03378a574de87af9b1efea77d0c52a8301dd831ece938452f"},
+ {file = "websockets-13.1-cp310-cp310-win32.whl", hash = "sha256:730f42125ccb14602f455155084f978bd9e8e57e89b569b4d7f0f0c17a448ffe"},
+ {file = "websockets-13.1-cp310-cp310-win_amd64.whl", hash = "sha256:5993260f483d05a9737073be197371940c01b257cc45ae3f1d5d7adb371b266a"},
+ {file = "websockets-13.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:61fc0dfcda609cda0fc9fe7977694c0c59cf9d749fbb17f4e9483929e3c48a19"},
+ {file = "websockets-13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ceec59f59d092c5007e815def4ebb80c2de330e9588e101cf8bd94c143ec78a5"},
+ {file = "websockets-13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1dca61c6db1166c48b95198c0b7d9c990b30c756fc2923cc66f68d17dc558fd"},
+ {file = "websockets-13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:308e20f22c2c77f3f39caca508e765f8725020b84aa963474e18c59accbf4c02"},
+ {file = "websockets-13.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d516c325e6540e8a57b94abefc3459d7dab8ce52ac75c96cad5549e187e3a7"},
+ {file = "websockets-13.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87c6e35319b46b99e168eb98472d6c7d8634ee37750d7693656dc766395df096"},
+ {file = "websockets-13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5f9fee94ebafbc3117c30be1844ed01a3b177bb6e39088bc6b2fa1dc15572084"},
+ {file = "websockets-13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7c1e90228c2f5cdde263253fa5db63e6653f1c00e7ec64108065a0b9713fa1b3"},
+ {file = "websockets-13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6548f29b0e401eea2b967b2fdc1c7c7b5ebb3eeb470ed23a54cd45ef078a0db9"},
+ {file = "websockets-13.1-cp311-cp311-win32.whl", hash = "sha256:c11d4d16e133f6df8916cc5b7e3e96ee4c44c936717d684a94f48f82edb7c92f"},
+ {file = "websockets-13.1-cp311-cp311-win_amd64.whl", hash = "sha256:d04f13a1d75cb2b8382bdc16ae6fa58c97337253826dfe136195b7f89f661557"},
+ {file = "websockets-13.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9d75baf00138f80b48f1eac72ad1535aac0b6461265a0bcad391fc5aba875cfc"},
+ {file = "websockets-13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9b6f347deb3dcfbfde1c20baa21c2ac0751afaa73e64e5b693bb2b848efeaa49"},
+ {file = "websockets-13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de58647e3f9c42f13f90ac7e5f58900c80a39019848c5547bc691693098ae1bd"},
+ {file = "websockets-13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1b54689e38d1279a51d11e3467dd2f3a50f5f2e879012ce8f2d6943f00e83f0"},
+ {file = "websockets-13.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf1781ef73c073e6b0f90af841aaf98501f975d306bbf6221683dd594ccc52b6"},
+ {file = "websockets-13.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d23b88b9388ed85c6faf0e74d8dec4f4d3baf3ecf20a65a47b836d56260d4b9"},
+ {file = "websockets-13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3c78383585f47ccb0fcf186dcb8a43f5438bd7d8f47d69e0b56f71bf431a0a68"},
+ {file = "websockets-13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d6d300f8ec35c24025ceb9b9019ae9040c1ab2f01cddc2bcc0b518af31c75c14"},
+ {file = "websockets-13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a9dcaf8b0cc72a392760bb8755922c03e17a5a54e08cca58e8b74f6902b433cf"},
+ {file = "websockets-13.1-cp312-cp312-win32.whl", hash = "sha256:2f85cf4f2a1ba8f602298a853cec8526c2ca42a9a4b947ec236eaedb8f2dc80c"},
+ {file = "websockets-13.1-cp312-cp312-win_amd64.whl", hash = "sha256:38377f8b0cdeee97c552d20cf1865695fcd56aba155ad1b4ca8779a5b6ef4ac3"},
+ {file = "websockets-13.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a9ab1e71d3d2e54a0aa646ab6d4eebfaa5f416fe78dfe4da2839525dc5d765c6"},
+ {file = "websockets-13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b9d7439d7fab4dce00570bb906875734df13d9faa4b48e261c440a5fec6d9708"},
+ {file = "websockets-13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:327b74e915cf13c5931334c61e1a41040e365d380f812513a255aa804b183418"},
+ {file = "websockets-13.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:325b1ccdbf5e5725fdcb1b0e9ad4d2545056479d0eee392c291c1bf76206435a"},
+ {file = "websockets-13.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:346bee67a65f189e0e33f520f253d5147ab76ae42493804319b5716e46dddf0f"},
+ {file = "websockets-13.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91a0fa841646320ec0d3accdff5b757b06e2e5c86ba32af2e0815c96c7a603c5"},
+ {file = "websockets-13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:18503d2c5f3943e93819238bf20df71982d193f73dcecd26c94514f417f6b135"},
+ {file = "websockets-13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a9cd1af7e18e5221d2878378fbc287a14cd527fdd5939ed56a18df8a31136bb2"},
+ {file = "websockets-13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:70c5be9f416aa72aab7a2a76c90ae0a4fe2755c1816c153c1a2bcc3333ce4ce6"},
+ {file = "websockets-13.1-cp313-cp313-win32.whl", hash = "sha256:624459daabeb310d3815b276c1adef475b3e6804abaf2d9d2c061c319f7f187d"},
+ {file = "websockets-13.1-cp313-cp313-win_amd64.whl", hash = "sha256:c518e84bb59c2baae725accd355c8dc517b4a3ed8db88b4bc93c78dae2974bf2"},
+ {file = "websockets-13.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c7934fd0e920e70468e676fe7f1b7261c1efa0d6c037c6722278ca0228ad9d0d"},
+ {file = "websockets-13.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:149e622dc48c10ccc3d2760e5f36753db9cacf3ad7bc7bbbfd7d9c819e286f23"},
+ {file = "websockets-13.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a569eb1b05d72f9bce2ebd28a1ce2054311b66677fcd46cf36204ad23acead8c"},
+ {file = "websockets-13.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95df24ca1e1bd93bbca51d94dd049a984609687cb2fb08a7f2c56ac84e9816ea"},
+ {file = "websockets-13.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8dbb1bf0c0a4ae8b40bdc9be7f644e2f3fb4e8a9aca7145bfa510d4a374eeb7"},
+ {file = "websockets-13.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:035233b7531fb92a76beefcbf479504db8c72eb3bff41da55aecce3a0f729e54"},
+ {file = "websockets-13.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:e4450fc83a3df53dec45922b576e91e94f5578d06436871dce3a6be38e40f5db"},
+ {file = "websockets-13.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:463e1c6ec853202dd3657f156123d6b4dad0c546ea2e2e38be2b3f7c5b8e7295"},
+ {file = "websockets-13.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6d6855bbe70119872c05107e38fbc7f96b1d8cb047d95c2c50869a46c65a8e96"},
+ {file = "websockets-13.1-cp38-cp38-win32.whl", hash = "sha256:204e5107f43095012b00f1451374693267adbb832d29966a01ecc4ce1db26faf"},
+ {file = "websockets-13.1-cp38-cp38-win_amd64.whl", hash = "sha256:485307243237328c022bc908b90e4457d0daa8b5cf4b3723fd3c4a8012fce4c6"},
+ {file = "websockets-13.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9b37c184f8b976f0c0a231a5f3d6efe10807d41ccbe4488df8c74174805eea7d"},
+ {file = "websockets-13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:163e7277e1a0bd9fb3c8842a71661ad19c6aa7bb3d6678dc7f89b17fbcc4aeb7"},
+ {file = "websockets-13.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4b889dbd1342820cc210ba44307cf75ae5f2f96226c0038094455a96e64fb07a"},
+ {file = "websockets-13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:586a356928692c1fed0eca68b4d1c2cbbd1ca2acf2ac7e7ebd3b9052582deefa"},
+ {file = "websockets-13.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7bd6abf1e070a6b72bfeb71049d6ad286852e285f146682bf30d0296f5fbadfa"},
+ {file = "websockets-13.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2aad13a200e5934f5a6767492fb07151e1de1d6079c003ab31e1823733ae79"},
+ {file = "websockets-13.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:df01aea34b6e9e33572c35cd16bae5a47785e7d5c8cb2b54b2acdb9678315a17"},
+ {file = "websockets-13.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e54affdeb21026329fb0744ad187cf812f7d3c2aa702a5edb562b325191fcab6"},
+ {file = "websockets-13.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9ef8aa8bdbac47f4968a5d66462a2a0935d044bf35c0e5a8af152d58516dbeb5"},
+ {file = "websockets-13.1-cp39-cp39-win32.whl", hash = "sha256:deeb929efe52bed518f6eb2ddc00cc496366a14c726005726ad62c2dd9017a3c"},
+ {file = "websockets-13.1-cp39-cp39-win_amd64.whl", hash = "sha256:7c65ffa900e7cc958cd088b9a9157a8141c991f8c53d11087e6fb7277a03f81d"},
+ {file = "websockets-13.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5dd6da9bec02735931fccec99d97c29f47cc61f644264eb995ad6c0c27667238"},
+ {file = "websockets-13.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:2510c09d8e8df777177ee3d40cd35450dc169a81e747455cc4197e63f7e7bfe5"},
+ {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1c3cf67185543730888b20682fb186fc8d0fa6f07ccc3ef4390831ab4b388d9"},
+ {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcc03c8b72267e97b49149e4863d57c2d77f13fae12066622dc78fe322490fe6"},
+ {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:004280a140f220c812e65f36944a9ca92d766b6cc4560be652a0a3883a79ed8a"},
+ {file = "websockets-13.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e2620453c075abeb0daa949a292e19f56de518988e079c36478bacf9546ced23"},
+ {file = "websockets-13.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9156c45750b37337f7b0b00e6248991a047be4aa44554c9886fe6bdd605aab3b"},
+ {file = "websockets-13.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:80c421e07973a89fbdd93e6f2003c17d20b69010458d3a8e37fb47874bd67d51"},
+ {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82d0ba76371769d6a4e56f7e83bb8e81846d17a6190971e38b5de108bde9b0d7"},
+ {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9875a0143f07d74dc5e1ded1c4581f0d9f7ab86c78994e2ed9e95050073c94d"},
+ {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a11e38ad8922c7961447f35c7b17bffa15de4d17c70abd07bfbe12d6faa3e027"},
+ {file = "websockets-13.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4059f790b6ae8768471cddb65d3c4fe4792b0ab48e154c9f0a04cefaabcd5978"},
+ {file = "websockets-13.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:25c35bf84bf7c7369d247f0b8cfa157f989862c49104c5cf85cb5436a641d93e"},
+ {file = "websockets-13.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:83f91d8a9bb404b8c2c41a707ac7f7f75b9442a0a876df295de27251a856ad09"},
+ {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a43cfdcddd07f4ca2b1afb459824dd3c6d53a51410636a2c7fc97b9a8cf4842"},
+ {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48a2ef1381632a2f0cb4efeff34efa97901c9fbc118e01951ad7cfc10601a9bb"},
+ {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:459bf774c754c35dbb487360b12c5727adab887f1622b8aed5755880a21c4a20"},
+ {file = "websockets-13.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:95858ca14a9f6fa8413d29e0a585b31b278388aa775b8a81fa24830123874678"},
+ {file = "websockets-13.1-py3-none-any.whl", hash = "sha256:a9a396a6ad26130cdae92ae10c36af09d9bfe6cafe69670fd3b6da9b07b4044f"},
+ {file = "websockets-13.1.tar.gz", hash = "sha256:a3b3366087c1bc0a2795111edcadddb8b3b59509d5db5d7ea3fdd69f954a8878"},
+]
+
[[package]]
name = "win32-setctime"
version = "1.1.0"
@@ -2139,93 +2909,93 @@ files = [
[[package]]
name = "yarl"
-version = "1.16.0"
+version = "1.17.1"
description = "Yet another URL library"
optional = false
python-versions = ">=3.9"
files = [
- {file = "yarl-1.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:32468f41242d72b87ab793a86d92f885355bcf35b3355aa650bfa846a5c60058"},
- {file = "yarl-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:234f3a3032b505b90e65b5bc6652c2329ea7ea8855d8de61e1642b74b4ee65d2"},
- {file = "yarl-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a0296040e5cddf074c7f5af4a60f3fc42c0237440df7bcf5183be5f6c802ed5"},
- {file = "yarl-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de6c14dd7c7c0badba48157474ea1f03ebee991530ba742d381b28d4f314d6f3"},
- {file = "yarl-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b140e532fe0266003c936d017c1ac301e72ee4a3fd51784574c05f53718a55d8"},
- {file = "yarl-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:019f5d58093402aa8f6661e60fd82a28746ad6d156f6c5336a70a39bd7b162b9"},
- {file = "yarl-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c42998fd1cbeb53cd985bff0e4bc25fbe55fd6eb3a545a724c1012d69d5ec84"},
- {file = "yarl-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c7c30fb38c300fe8140df30a046a01769105e4cf4282567a29b5cdb635b66c4"},
- {file = "yarl-1.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e49e0fd86c295e743fd5be69b8b0712f70a686bc79a16e5268386c2defacaade"},
- {file = "yarl-1.16.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:b9ca7b9147eb1365c8bab03c003baa1300599575effad765e0b07dd3501ea9af"},
- {file = "yarl-1.16.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:27e11db3f1e6a51081a981509f75617b09810529de508a181319193d320bc5c7"},
- {file = "yarl-1.16.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8994c42f4ca25df5380ddf59f315c518c81df6a68fed5bb0c159c6cb6b92f120"},
- {file = "yarl-1.16.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:542fa8e09a581bcdcbb30607c7224beff3fdfb598c798ccd28a8184ffc18b7eb"},
- {file = "yarl-1.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2bd6a51010c7284d191b79d3b56e51a87d8e1c03b0902362945f15c3d50ed46b"},
- {file = "yarl-1.16.0-cp310-cp310-win32.whl", hash = "sha256:178ccb856e265174a79f59721031060f885aca428983e75c06f78aa24b91d929"},
- {file = "yarl-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe8bba2545427418efc1929c5c42852bdb4143eb8d0a46b09de88d1fe99258e7"},
- {file = "yarl-1.16.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d8643975a0080f361639787415a038bfc32d29208a4bf6b783ab3075a20b1ef3"},
- {file = "yarl-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:676d96bafc8c2d0039cea0cd3fd44cee7aa88b8185551a2bb93354668e8315c2"},
- {file = "yarl-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d9525f03269e64310416dbe6c68d3b23e5d34aaa8f47193a1c45ac568cecbc49"},
- {file = "yarl-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b37d5ec034e668b22cf0ce1074d6c21fd2a08b90d11b1b73139b750a8b0dd97"},
- {file = "yarl-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f32c4cb7386b41936894685f6e093c8dfaf0960124d91fe0ec29fe439e201d0"},
- {file = "yarl-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b8e265a0545637492a7e12fd7038370d66c9375a61d88c5567d0e044ded9202"},
- {file = "yarl-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:789a3423f28a5fff46fbd04e339863c169ece97c827b44de16e1a7a42bc915d2"},
- {file = "yarl-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1d1f45e3e8d37c804dca99ab3cf4ab3ed2e7a62cd82542924b14c0a4f46d243"},
- {file = "yarl-1.16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:621280719c4c5dad4c1391160a9b88925bb8b0ff6a7d5af3224643024871675f"},
- {file = "yarl-1.16.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ed097b26f18a1f5ff05f661dc36528c5f6735ba4ce8c9645e83b064665131349"},
- {file = "yarl-1.16.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2f1fe2b2e3ee418862f5ebc0c0083c97f6f6625781382f828f6d4e9b614eba9b"},
- {file = "yarl-1.16.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:87dd10bc0618991c66cee0cc65fa74a45f4ecb13bceec3c62d78ad2e42b27a16"},
- {file = "yarl-1.16.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:4199db024b58a8abb2cfcedac7b1292c3ad421684571aeb622a02f242280e8d6"},
- {file = "yarl-1.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:99a9dcd4b71dd5f5f949737ab3f356cfc058c709b4f49833aeffedc2652dac56"},
- {file = "yarl-1.16.0-cp311-cp311-win32.whl", hash = "sha256:a9394c65ae0ed95679717d391c862dece9afacd8fa311683fc8b4362ce8a410c"},
- {file = "yarl-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:5b9101f528ae0f8f65ac9d64dda2bb0627de8a50344b2f582779f32fda747c1d"},
- {file = "yarl-1.16.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:4ffb7c129707dd76ced0a4a4128ff452cecf0b0e929f2668ea05a371d9e5c104"},
- {file = "yarl-1.16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1a5e9d8ce1185723419c487758d81ac2bde693711947032cce600ca7c9cda7d6"},
- {file = "yarl-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d743e3118b2640cef7768ea955378c3536482d95550222f908f392167fe62059"},
- {file = "yarl-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26768342f256e6e3c37533bf9433f5f15f3e59e3c14b2409098291b3efaceacb"},
- {file = "yarl-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1b0796168b953bca6600c5f97f5ed407479889a36ad7d17183366260f29a6b9"},
- {file = "yarl-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:858728086914f3a407aa7979cab743bbda1fe2bdf39ffcd991469a370dd7414d"},
- {file = "yarl-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5570e6d47bcb03215baf4c9ad7bf7c013e56285d9d35013541f9ac2b372593e7"},
- {file = "yarl-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66ea8311422a7ba1fc79b4c42c2baa10566469fe5a78500d4e7754d6e6db8724"},
- {file = "yarl-1.16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:649bddcedee692ee8a9b7b6e38582cb4062dc4253de9711568e5620d8707c2a3"},
- {file = "yarl-1.16.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3a91654adb7643cb21b46f04244c5a315a440dcad63213033826549fa2435f71"},
- {file = "yarl-1.16.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b439cae82034ade094526a8f692b9a2b5ee936452de5e4c5f0f6c48df23f8604"},
- {file = "yarl-1.16.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:571f781ae8ac463ce30bacebfaef2c6581543776d5970b2372fbe31d7bf31a07"},
- {file = "yarl-1.16.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:aa7943f04f36d6cafc0cf53ea89824ac2c37acbdb4b316a654176ab8ffd0f968"},
- {file = "yarl-1.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1a5cf32539373ff39d97723e39a9283a7277cbf1224f7aef0c56c9598b6486c3"},
- {file = "yarl-1.16.0-cp312-cp312-win32.whl", hash = "sha256:a5b6c09b9b4253d6a208b0f4a2f9206e511ec68dce9198e0fbec4f160137aa67"},
- {file = "yarl-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:1208ca14eed2fda324042adf8d6c0adf4a31522fa95e0929027cd487875f0240"},
- {file = "yarl-1.16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5ace0177520bd4caa99295a9b6fb831d0e9a57d8e0501a22ffaa61b4c024283"},
- {file = "yarl-1.16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7118bdb5e3ed81acaa2095cba7ec02a0fe74b52a16ab9f9ac8e28e53ee299732"},
- {file = "yarl-1.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38fec8a2a94c58bd47c9a50a45d321ab2285ad133adefbbadf3012c054b7e656"},
- {file = "yarl-1.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8791d66d81ee45866a7bb15a517b01a2bcf583a18ebf5d72a84e6064c417e64b"},
- {file = "yarl-1.16.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cf936ba67bc6c734f3aa1c01391da74ab7fc046a9f8bbfa230b8393b90cf472"},
- {file = "yarl-1.16.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1aab176dd55b59f77a63b27cffaca67d29987d91a5b615cbead41331e6b7428"},
- {file = "yarl-1.16.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:995d0759004c08abd5d1b81300a91d18c8577c6389300bed1c7c11675105a44d"},
- {file = "yarl-1.16.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1bc22e00edeb068f71967ab99081e9406cd56dbed864fc3a8259442999d71552"},
- {file = "yarl-1.16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:35b4f7842154176523e0a63c9b871168c69b98065d05a4f637fce342a6a2693a"},
- {file = "yarl-1.16.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:7ace71c4b7a0c41f317ae24be62bb61e9d80838d38acb20e70697c625e71f120"},
- {file = "yarl-1.16.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8f639e3f5795a6568aa4f7d2ac6057c757dcd187593679f035adbf12b892bb00"},
- {file = "yarl-1.16.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:e8be3aff14f0120ad049121322b107f8a759be76a6a62138322d4c8a337a9e2c"},
- {file = "yarl-1.16.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:122d8e7986043d0549e9eb23c7fd23be078be4b70c9eb42a20052b3d3149c6f2"},
- {file = "yarl-1.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0fd9c227990f609c165f56b46107d0bc34553fe0387818c42c02f77974402c36"},
- {file = "yarl-1.16.0-cp313-cp313-win32.whl", hash = "sha256:595ca5e943baed31d56b33b34736461a371c6ea0038d3baec399949dd628560b"},
- {file = "yarl-1.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:921b81b8d78f0e60242fb3db615ea3f368827a76af095d5a69f1c3366db3f596"},
- {file = "yarl-1.16.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab2b2ac232110a1fdb0d3ffcd087783edd3d4a6ced432a1bf75caf7b7be70916"},
- {file = "yarl-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7f8713717a09acbfee7c47bfc5777e685539fefdd34fa72faf504c8be2f3df4e"},
- {file = "yarl-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cdcffe1dbcb4477d2b4202f63cd972d5baa155ff5a3d9e35801c46a415b7f71a"},
- {file = "yarl-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a91217208306d82357c67daeef5162a41a28c8352dab7e16daa82e3718852a7"},
- {file = "yarl-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ab3ed42c78275477ea8e917491365e9a9b69bb615cb46169020bd0aa5e2d6d3"},
- {file = "yarl-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:707ae579ccb3262dfaef093e202b4c3fb23c3810e8df544b1111bd2401fd7b09"},
- {file = "yarl-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad7a852d1cd0b8d8b37fc9d7f8581152add917a98cfe2ea6e241878795f917ae"},
- {file = "yarl-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3f1cc3d3d4dc574bebc9b387f6875e228ace5748a7c24f49d8f01ac1bc6c31b"},
- {file = "yarl-1.16.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5ff96da263740779b0893d02b718293cc03400c3a208fc8d8cd79d9b0993e532"},
- {file = "yarl-1.16.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:3d375a19ba2bfe320b6d873f3fb165313b002cef8b7cc0a368ad8b8a57453837"},
- {file = "yarl-1.16.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:62c7da0ad93a07da048b500514ca47b759459ec41924143e2ddb5d7e20fd3db5"},
- {file = "yarl-1.16.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:147b0fcd0ee33b4b5f6edfea80452d80e419e51b9a3f7a96ce98eaee145c1581"},
- {file = "yarl-1.16.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:504e1fe1cc4f170195320eb033d2b0ccf5c6114ce5bf2f617535c01699479bca"},
- {file = "yarl-1.16.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:bdcf667a5dec12a48f669e485d70c54189f0639c2157b538a4cffd24a853624f"},
- {file = "yarl-1.16.0-cp39-cp39-win32.whl", hash = "sha256:e9951afe6557c75a71045148890052cb942689ee4c9ec29f5436240e1fcc73b7"},
- {file = "yarl-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:7d7aaa8ff95d0840e289423e7dc35696c2b058d635f945bf05b5cd633146b027"},
- {file = "yarl-1.16.0-py3-none-any.whl", hash = "sha256:e6980a558d8461230c457218bd6c92dfc1d10205548215c2c21d79dc8d0a96f3"},
- {file = "yarl-1.16.0.tar.gz", hash = "sha256:b6f687ced5510a9a2474bbae96a4352e5ace5fa34dc44a217b0537fec1db00b4"},
+ {file = "yarl-1.17.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1794853124e2f663f0ea54efb0340b457f08d40a1cef78edfa086576179c91"},
+ {file = "yarl-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fbea1751729afe607d84acfd01efd95e3b31db148a181a441984ce9b3d3469da"},
+ {file = "yarl-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8ee427208c675f1b6e344a1f89376a9613fc30b52646a04ac0c1f6587c7e46ec"},
+ {file = "yarl-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b74ff4767d3ef47ffe0cd1d89379dc4d828d4873e5528976ced3b44fe5b0a21"},
+ {file = "yarl-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:62a91aefff3d11bf60e5956d340eb507a983a7ec802b19072bb989ce120cd948"},
+ {file = "yarl-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:846dd2e1243407133d3195d2d7e4ceefcaa5f5bf7278f0a9bda00967e6326b04"},
+ {file = "yarl-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e844be8d536afa129366d9af76ed7cb8dfefec99f5f1c9e4f8ae542279a6dc3"},
+ {file = "yarl-1.17.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc7c92c1baa629cb03ecb0c3d12564f172218fb1739f54bf5f3881844daadc6d"},
+ {file = "yarl-1.17.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ae3476e934b9d714aa8000d2e4c01eb2590eee10b9d8cd03e7983ad65dfbfcba"},
+ {file = "yarl-1.17.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c7e177c619342e407415d4f35dec63d2d134d951e24b5166afcdfd1362828e17"},
+ {file = "yarl-1.17.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64cc6e97f14cf8a275d79c5002281f3040c12e2e4220623b5759ea7f9868d6a5"},
+ {file = "yarl-1.17.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:84c063af19ef5130084db70ada40ce63a84f6c1ef4d3dbc34e5e8c4febb20822"},
+ {file = "yarl-1.17.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:482c122b72e3c5ec98f11457aeb436ae4aecca75de19b3d1de7cf88bc40db82f"},
+ {file = "yarl-1.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:380e6c38ef692b8fd5a0f6d1fa8774d81ebc08cfbd624b1bca62a4d4af2f9931"},
+ {file = "yarl-1.17.1-cp310-cp310-win32.whl", hash = "sha256:16bca6678a83657dd48df84b51bd56a6c6bd401853aef6d09dc2506a78484c7b"},
+ {file = "yarl-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:561c87fea99545ef7d692403c110b2f99dced6dff93056d6e04384ad3bc46243"},
+ {file = "yarl-1.17.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cbad927ea8ed814622305d842c93412cb47bd39a496ed0f96bfd42b922b4a217"},
+ {file = "yarl-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fca4b4307ebe9c3ec77a084da3a9d1999d164693d16492ca2b64594340999988"},
+ {file = "yarl-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff5c6771c7e3511a06555afa317879b7db8d640137ba55d6ab0d0c50425cab75"},
+ {file = "yarl-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b29beab10211a746f9846baa39275e80034e065460d99eb51e45c9a9495bcca"},
+ {file = "yarl-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a52a1ffdd824fb1835272e125385c32fd8b17fbdefeedcb4d543cc23b332d74"},
+ {file = "yarl-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:58c8e9620eb82a189c6c40cb6b59b4e35b2ee68b1f2afa6597732a2b467d7e8f"},
+ {file = "yarl-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d216e5d9b8749563c7f2c6f7a0831057ec844c68b4c11cb10fc62d4fd373c26d"},
+ {file = "yarl-1.17.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:881764d610e3269964fc4bb3c19bb6fce55422828e152b885609ec176b41cf11"},
+ {file = "yarl-1.17.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8c79e9d7e3d8a32d4824250a9c6401194fb4c2ad9a0cec8f6a96e09a582c2cc0"},
+ {file = "yarl-1.17.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:299f11b44d8d3a588234adbe01112126010bd96d9139c3ba7b3badd9829261c3"},
+ {file = "yarl-1.17.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:cc7d768260f4ba4ea01741c1b5fe3d3a6c70eb91c87f4c8761bbcce5181beafe"},
+ {file = "yarl-1.17.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:de599af166970d6a61accde358ec9ded821234cbbc8c6413acfec06056b8e860"},
+ {file = "yarl-1.17.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2b24ec55fad43e476905eceaf14f41f6478780b870eda5d08b4d6de9a60b65b4"},
+ {file = "yarl-1.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9fb815155aac6bfa8d86184079652c9715c812d506b22cfa369196ef4e99d1b4"},
+ {file = "yarl-1.17.1-cp311-cp311-win32.whl", hash = "sha256:7615058aabad54416ddac99ade09a5510cf77039a3b903e94e8922f25ed203d7"},
+ {file = "yarl-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:14bc88baa44e1f84164a392827b5defb4fa8e56b93fecac3d15315e7c8e5d8b3"},
+ {file = "yarl-1.17.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:327828786da2006085a4d1feb2594de6f6d26f8af48b81eb1ae950c788d97f61"},
+ {file = "yarl-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cc353841428d56b683a123a813e6a686e07026d6b1c5757970a877195f880c2d"},
+ {file = "yarl-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c73df5b6e8fabe2ddb74876fb82d9dd44cbace0ca12e8861ce9155ad3c886139"},
+ {file = "yarl-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bdff5e0995522706c53078f531fb586f56de9c4c81c243865dd5c66c132c3b5"},
+ {file = "yarl-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:06157fb3c58f2736a5e47c8fcbe1afc8b5de6fb28b14d25574af9e62150fcaac"},
+ {file = "yarl-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1654ec814b18be1af2c857aa9000de7a601400bd4c9ca24629b18486c2e35463"},
+ {file = "yarl-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f6595c852ca544aaeeb32d357e62c9c780eac69dcd34e40cae7b55bc4fb1147"},
+ {file = "yarl-1.17.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:459e81c2fb920b5f5df744262d1498ec2c8081acdcfe18181da44c50f51312f7"},
+ {file = "yarl-1.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7e48cdb8226644e2fbd0bdb0a0f87906a3db07087f4de77a1b1b1ccfd9e93685"},
+ {file = "yarl-1.17.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d9b6b28a57feb51605d6ae5e61a9044a31742db557a3b851a74c13bc61de5172"},
+ {file = "yarl-1.17.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e594b22688d5747b06e957f1ef822060cb5cb35b493066e33ceac0cf882188b7"},
+ {file = "yarl-1.17.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5f236cb5999ccd23a0ab1bd219cfe0ee3e1c1b65aaf6dd3320e972f7ec3a39da"},
+ {file = "yarl-1.17.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a2a64e62c7a0edd07c1c917b0586655f3362d2c2d37d474db1a509efb96fea1c"},
+ {file = "yarl-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d0eea830b591dbc68e030c86a9569826145df485b2b4554874b07fea1275a199"},
+ {file = "yarl-1.17.1-cp312-cp312-win32.whl", hash = "sha256:46ddf6e0b975cd680eb83318aa1d321cb2bf8d288d50f1754526230fcf59ba96"},
+ {file = "yarl-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:117ed8b3732528a1e41af3aa6d4e08483c2f0f2e3d3d7dca7cf538b3516d93df"},
+ {file = "yarl-1.17.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5d1d42556b063d579cae59e37a38c61f4402b47d70c29f0ef15cee1acaa64488"},
+ {file = "yarl-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c0167540094838ee9093ef6cc2c69d0074bbf84a432b4995835e8e5a0d984374"},
+ {file = "yarl-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2f0a6423295a0d282d00e8701fe763eeefba8037e984ad5de44aa349002562ac"},
+ {file = "yarl-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5b078134f48552c4d9527db2f7da0b5359abd49393cdf9794017baec7506170"},
+ {file = "yarl-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d401f07261dc5aa36c2e4efc308548f6ae943bfff20fcadb0a07517a26b196d8"},
+ {file = "yarl-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5f1ac7359e17efe0b6e5fec21de34145caef22b260e978336f325d5c84e6938"},
+ {file = "yarl-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f63d176a81555984e91f2c84c2a574a61cab7111cc907e176f0f01538e9ff6e"},
+ {file = "yarl-1.17.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e275792097c9f7e80741c36de3b61917aebecc08a67ae62899b074566ff8556"},
+ {file = "yarl-1.17.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:81713b70bea5c1386dc2f32a8f0dab4148a2928c7495c808c541ee0aae614d67"},
+ {file = "yarl-1.17.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:aa46dce75078fceaf7cecac5817422febb4355fbdda440db55206e3bd288cfb8"},
+ {file = "yarl-1.17.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1ce36ded585f45b1e9bb36d0ae94765c6608b43bd2e7f5f88079f7a85c61a4d3"},
+ {file = "yarl-1.17.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:2d374d70fdc36f5863b84e54775452f68639bc862918602d028f89310a034ab0"},
+ {file = "yarl-1.17.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:2d9f0606baaec5dd54cb99667fcf85183a7477f3766fbddbe3f385e7fc253299"},
+ {file = "yarl-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b0341e6d9a0c0e3cdc65857ef518bb05b410dbd70d749a0d33ac0f39e81a4258"},
+ {file = "yarl-1.17.1-cp313-cp313-win32.whl", hash = "sha256:2e7ba4c9377e48fb7b20dedbd473cbcbc13e72e1826917c185157a137dac9df2"},
+ {file = "yarl-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:949681f68e0e3c25377462be4b658500e85ca24323d9619fdc41f68d46a1ffda"},
+ {file = "yarl-1.17.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8994b29c462de9a8fce2d591028b986dbbe1b32f3ad600b2d3e1c482c93abad6"},
+ {file = "yarl-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f9cbfbc5faca235fbdf531b93aa0f9f005ec7d267d9d738761a4d42b744ea159"},
+ {file = "yarl-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b40d1bf6e6f74f7c0a567a9e5e778bbd4699d1d3d2c0fe46f4b717eef9e96b95"},
+ {file = "yarl-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5efe0661b9fcd6246f27957f6ae1c0eb29bc60552820f01e970b4996e016004"},
+ {file = "yarl-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5c4804e4039f487e942c13381e6c27b4b4e66066d94ef1fae3f6ba8b953f383"},
+ {file = "yarl-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5d6a6c9602fd4598fa07e0389e19fe199ae96449008d8304bf5d47cb745462e"},
+ {file = "yarl-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f4c9156c4d1eb490fe374fb294deeb7bc7eaccda50e23775b2354b6a6739934"},
+ {file = "yarl-1.17.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6324274b4e0e2fa1b3eccb25997b1c9ed134ff61d296448ab8269f5ac068c4c"},
+ {file = "yarl-1.17.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d8a8b74d843c2638f3864a17d97a4acda58e40d3e44b6303b8cc3d3c44ae2d29"},
+ {file = "yarl-1.17.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:7fac95714b09da9278a0b52e492466f773cfe37651cf467a83a1b659be24bf71"},
+ {file = "yarl-1.17.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c180ac742a083e109c1a18151f4dd8675f32679985a1c750d2ff806796165b55"},
+ {file = "yarl-1.17.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:578d00c9b7fccfa1745a44f4eddfdc99d723d157dad26764538fbdda37209857"},
+ {file = "yarl-1.17.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:1a3b91c44efa29e6c8ef8a9a2b583347998e2ba52c5d8280dbd5919c02dfc3b5"},
+ {file = "yarl-1.17.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a7ac5b4984c468ce4f4a553df281450df0a34aefae02e58d77a0847be8d1e11f"},
+ {file = "yarl-1.17.1-cp39-cp39-win32.whl", hash = "sha256:7294e38f9aa2e9f05f765b28ffdc5d81378508ce6dadbe93f6d464a8c9594473"},
+ {file = "yarl-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:eb6dce402734575e1a8cc0bb1509afca508a400a57ce13d306ea2c663bad1138"},
+ {file = "yarl-1.17.1-py3-none-any.whl", hash = "sha256:f1790a4b1e8e8e028c391175433b9c8122c39b46e1663228158e61e6f915bf06"},
+ {file = "yarl-1.17.1.tar.gz", hash = "sha256:067a63fcfda82da6b198fa73079b1ca40b7c9b7994995b6ee38acda728b64d47"},
]
[package.dependencies]
@@ -2255,4 +3025,4 @@ type = ["pytest-mypy"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.11,<4"
-content-hash = "9e8161320447d7b61416abfb1d60fbeabb713f65f34b927863cf4d2f317af01c"
+content-hash = "22b76834a04979694d69649155d47363ebf62ac7bf26263f7ad575594a03c77f"
diff --git a/pyproject.toml b/pyproject.toml
index d1c4b3f..6ee5362 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,9 +6,12 @@ build-backend = "poetry.core.masonry.api"
name = "boardwalk"
requires-python = ">=3.11"
+# -- Package and dependencies, configured with Poetry -------------------------
+# https://python-poetry.org/docs/
+
[tool.poetry]
name = "boardwalk"
-version = "0.8.23"
+version = "0.8.24"
description = "Boardwalk is a linear Ansible workflow engine"
readme = "README.md"
authors = [
@@ -56,6 +59,18 @@ ruff = "^0.6.4"
pytest = "^8.1.1"
anyio = "^4.6.2.post1"
+[tool.poetry.group.docs]
+optional = true
+
+[tool.poetry.group.docs.dependencies]
+rich-click = "^1.8.3"
+sphinx = "^8.1.3"
+sphinx-book-theme = "^1.1.3"
+myst-parser = {extras = ["linkify"], version = "^4.0.0"}
+sphinx-autobuild = "^2024.10.3"
+sphinx-autodoc2 = "^0.5.0"
+sphinx-copybutton = "^0.5.2"
+
[tool.poetry.scripts]
boardwalk = "boardwalk.cli:cli"
boardwalkd = "boardwalkd.cli:cli"
@@ -66,13 +81,14 @@ filterwarnings = [
'ignore:::pydantic.*:',
]
+# -- Configuration for Ruff ---------------------------------------------------
+# https://docs.astral.sh/ruff/
+
[tool.ruff]
line-length = 120
-
extend-exclude = [
"typings/*",
]
-
lint.extend-select = [
"I", # isort (import sorting)
"W", # pycodestyle warnings
@@ -80,6 +96,7 @@ lint.extend-select = [
"DTZ", # flake8-datetimez
]
+# -- Typechecking (currently pyright) -----------------------------------------
[tool.pyright]
exclude = [
"build/",
diff --git a/src/boardwalk/cli.py b/src/boardwalk/cli.py
index 6a8d207..581bd54 100755
--- a/src/boardwalk/cli.py
+++ b/src/boardwalk/cli.py
@@ -74,7 +74,8 @@ def cli(ctx: click.Context, verbose: int):
ctx.obj["VERBOSITY"] = verbose
logger.remove()
logger.add(sys.stdout, level=loglevel)
- logger.info(f"Log level is {loglevel}")
+ if verbose > 0:
+ logger.info(f"Log level is {loglevel}")
signal.signal(signal.SIGINT, handle_signal)
signal.signal(signal.SIGHUP, handle_signal)
From c09f39f9140a5342295b1863360f2b07ab844c3f Mon Sep 17 00:00:00 2001
From: Alex Sullivan <115666116+asullivan-blze@users.noreply.github.com>
Date: Thu, 7 Nov 2024 14:37:05 -0800
Subject: [PATCH 2/6] Fix incorrect -- for Python 3.11 -- syntax for f-string
in docs/conf.py.
This was an issue caused by the fact that my local development environment is running,
surprise surprise, Python 3.12, and the Actions workflows are running 3.11. PEP 701,
implemented in Python 3.12, makes it so the following pattern would function as expected.
```python
release = f"{lib_version("boardwalk")}"
```
https://docs.python.org/3/whatsnew/3.12.html#pep-701-syntactic-formalization-of-f-strings
As a note discovered while researching this issue, Python 3.13 is now released; as such,
eventually -- not in this PR, which is effectively just documentation -- the minimum
Python version will be shifted to 3.12.
---
.github/workflows/sphinx.yml | 11 --
docs/source/conf.py | 2 +-
poetry.lock | 215 ++++++++++++++++-------------------
3 files changed, 102 insertions(+), 126 deletions(-)
diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml
index dd84095..9bb9ed6 100644
--- a/.github/workflows/sphinx.yml
+++ b/.github/workflows/sphinx.yml
@@ -29,17 +29,6 @@ jobs:
- name: Check out repository
uses: actions/checkout@v4
- # Manually triggered debugging; see: https://github.com/mxschmitt/action-tmate?tab=readme-ov-file#manually-triggered-debug
- - name: Setup tmate session
- uses: mxschmitt/action-tmate@v3
- # Need to run this always in the development; cause this is in a PR, it doesn't allow manual workflows to be triggered?
- # if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
- with:
- # Starts the tmate session, prints connection details, then resumes the workflow
- detached: true
- # Requires the initiating user's SSH key to be provided
- limit-access-to-actor: true
-
- name: Set up python
id: setup-python
uses: actions/setup-python@v5.3.0
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 3565d0e..4ca22fc 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -12,7 +12,7 @@
project = "Boardwalk"
copyright = f"{datetime.now(tz=UTC).year}, Backblaze"
author = "Backblaze"
-release = f"{lib_version("boardwalk")}"
+release = f"{lib_version('boardwalk')}"
# -- General configuration ---------------------------------------------------
diff --git a/poetry.lock b/poetry.lock
index c4bc771..ca339e7 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -687,13 +687,13 @@ test = ["pytest (>=6)"]
[[package]]
name = "face"
-version = "22.0.0"
+version = "24.0.0"
description = "A command-line application framework (and CLI parser). Friendly for users, full-featured for developers."
optional = false
python-versions = "*"
files = [
- {file = "face-22.0.0-py3-none-any.whl", hash = "sha256:344fe31562d0f6f444a45982418f3793d4b14f9abb98ccca1509d22e0a3e7e35"},
- {file = "face-22.0.0.tar.gz", hash = "sha256:d5d692f90bc8f5987b636e47e36384b9bbda499aaf0a77aa0b0bbe834c76923d"},
+ {file = "face-24.0.0-py3-none-any.whl", hash = "sha256:0e2c17b426fa4639a4e77d1de9580f74a98f4869ba4c7c8c175b810611622cd3"},
+ {file = "face-24.0.0.tar.gz", hash = "sha256:611e29a01ac5970f0077f9c577e746d48c082588b411b33a0dd55c4d872949f6"},
]
[package.dependencies]
@@ -1969,114 +1969,101 @@ docs = ["markdown-include", "mkdocs", "mkdocs-glightbox", "mkdocs-material-exten
[[package]]
name = "rpds-py"
-version = "0.20.1"
+version = "0.21.0"
description = "Python bindings to Rust's persistent data structures (rpds)"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.9"
files = [
- {file = "rpds_py-0.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a649dfd735fff086e8a9d0503a9f0c7d01b7912a333c7ae77e1515c08c146dad"},
- {file = "rpds_py-0.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f16bc1334853e91ddaaa1217045dd7be166170beec337576818461268a3de67f"},
- {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14511a539afee6f9ab492b543060c7491c99924314977a55c98bfa2ee29ce78c"},
- {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3ccb8ac2d3c71cda472b75af42818981bdacf48d2e21c36331b50b4f16930163"},
- {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c142b88039b92e7e0cb2552e8967077e3179b22359e945574f5e2764c3953dcf"},
- {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f19169781dddae7478a32301b499b2858bc52fc45a112955e798ee307e294977"},
- {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13c56de6518e14b9bf6edde23c4c39dac5b48dcf04160ea7bce8fca8397cdf86"},
- {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:925d176a549f4832c6f69fa6026071294ab5910e82a0fe6c6228fce17b0706bd"},
- {file = "rpds_py-0.20.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:78f0b6877bfce7a3d1ff150391354a410c55d3cdce386f862926a4958ad5ab7e"},
- {file = "rpds_py-0.20.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3dd645e2b0dcb0fd05bf58e2e54c13875847687d0b71941ad2e757e5d89d4356"},
- {file = "rpds_py-0.20.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4f676e21db2f8c72ff0936f895271e7a700aa1f8d31b40e4e43442ba94973899"},
- {file = "rpds_py-0.20.1-cp310-none-win32.whl", hash = "sha256:648386ddd1e19b4a6abab69139b002bc49ebf065b596119f8f37c38e9ecee8ff"},
- {file = "rpds_py-0.20.1-cp310-none-win_amd64.whl", hash = "sha256:d9ecb51120de61e4604650666d1f2b68444d46ae18fd492245a08f53ad2b7711"},
- {file = "rpds_py-0.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:762703bdd2b30983c1d9e62b4c88664df4a8a4d5ec0e9253b0231171f18f6d75"},
- {file = "rpds_py-0.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0b581f47257a9fce535c4567782a8976002d6b8afa2c39ff616edf87cbeff712"},
- {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:842c19a6ce894493563c3bd00d81d5100e8e57d70209e84d5491940fdb8b9e3a"},
- {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42cbde7789f5c0bcd6816cb29808e36c01b960fb5d29f11e052215aa85497c93"},
- {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c8e9340ce5a52f95fa7d3b552b35c7e8f3874d74a03a8a69279fd5fca5dc751"},
- {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ba6f89cac95c0900d932c9efb7f0fb6ca47f6687feec41abcb1bd5e2bd45535"},
- {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a916087371afd9648e1962e67403c53f9c49ca47b9680adbeef79da3a7811b0"},
- {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:200a23239781f46149e6a415f1e870c5ef1e712939fe8fa63035cd053ac2638e"},
- {file = "rpds_py-0.20.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:58b1d5dd591973d426cbb2da5e27ba0339209832b2f3315928c9790e13f159e8"},
- {file = "rpds_py-0.20.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6b73c67850ca7cae0f6c56f71e356d7e9fa25958d3e18a64927c2d930859b8e4"},
- {file = "rpds_py-0.20.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d8761c3c891cc51e90bc9926d6d2f59b27beaf86c74622c8979380a29cc23ac3"},
- {file = "rpds_py-0.20.1-cp311-none-win32.whl", hash = "sha256:cd945871335a639275eee904caef90041568ce3b42f402c6959b460d25ae8732"},
- {file = "rpds_py-0.20.1-cp311-none-win_amd64.whl", hash = "sha256:7e21b7031e17c6b0e445f42ccc77f79a97e2687023c5746bfb7a9e45e0921b84"},
- {file = "rpds_py-0.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:36785be22066966a27348444b40389f8444671630063edfb1a2eb04318721e17"},
- {file = "rpds_py-0.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:142c0a5124d9bd0e2976089484af5c74f47bd3298f2ed651ef54ea728d2ea42c"},
- {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbddc10776ca7ebf2a299c41a4dde8ea0d8e3547bfd731cb87af2e8f5bf8962d"},
- {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:15a842bb369e00295392e7ce192de9dcbf136954614124a667f9f9f17d6a216f"},
- {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be5ef2f1fc586a7372bfc355986226484e06d1dc4f9402539872c8bb99e34b01"},
- {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbcf360c9e3399b056a238523146ea77eeb2a596ce263b8814c900263e46031a"},
- {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecd27a66740ffd621d20b9a2f2b5ee4129a56e27bfb9458a3bcc2e45794c96cb"},
- {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0b937b2a1988f184a3e9e577adaa8aede21ec0b38320d6009e02bd026db04fa"},
- {file = "rpds_py-0.20.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6889469bfdc1eddf489729b471303739bf04555bb151fe8875931f8564309afc"},
- {file = "rpds_py-0.20.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:19b73643c802f4eaf13d97f7855d0fb527fbc92ab7013c4ad0e13a6ae0ed23bd"},
- {file = "rpds_py-0.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3c6afcf2338e7f374e8edc765c79fbcb4061d02b15dd5f8f314a4af2bdc7feb5"},
- {file = "rpds_py-0.20.1-cp312-none-win32.whl", hash = "sha256:dc73505153798c6f74854aba69cc75953888cf9866465196889c7cdd351e720c"},
- {file = "rpds_py-0.20.1-cp312-none-win_amd64.whl", hash = "sha256:8bbe951244a838a51289ee53a6bae3a07f26d4e179b96fc7ddd3301caf0518eb"},
- {file = "rpds_py-0.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:6ca91093a4a8da4afae7fe6a222c3b53ee4eef433ebfee4d54978a103435159e"},
- {file = "rpds_py-0.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b9c2fe36d1f758b28121bef29ed1dee9b7a2453e997528e7d1ac99b94892527c"},
- {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f009c69bc8c53db5dfab72ac760895dc1f2bc1b62ab7408b253c8d1ec52459fc"},
- {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6740a3e8d43a32629bb9b009017ea5b9e713b7210ba48ac8d4cb6d99d86c8ee8"},
- {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:32b922e13d4c0080d03e7b62991ad7f5007d9cd74e239c4b16bc85ae8b70252d"},
- {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe00a9057d100e69b4ae4a094203a708d65b0f345ed546fdef86498bf5390982"},
- {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49fe9b04b6fa685bd39237d45fad89ba19e9163a1ccaa16611a812e682913496"},
- {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aa7ac11e294304e615b43f8c441fee5d40094275ed7311f3420d805fde9b07b4"},
- {file = "rpds_py-0.20.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aa97af1558a9bef4025f8f5d8c60d712e0a3b13a2fe875511defc6ee77a1ab7"},
- {file = "rpds_py-0.20.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:483b29f6f7ffa6af845107d4efe2e3fa8fb2693de8657bc1849f674296ff6a5a"},
- {file = "rpds_py-0.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:37fe0f12aebb6a0e3e17bb4cd356b1286d2d18d2e93b2d39fe647138458b4bcb"},
- {file = "rpds_py-0.20.1-cp313-none-win32.whl", hash = "sha256:a624cc00ef2158e04188df5e3016385b9353638139a06fb77057b3498f794782"},
- {file = "rpds_py-0.20.1-cp313-none-win_amd64.whl", hash = "sha256:b71b8666eeea69d6363248822078c075bac6ed135faa9216aa85f295ff009b1e"},
- {file = "rpds_py-0.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:5b48e790e0355865197ad0aca8cde3d8ede347831e1959e158369eb3493d2191"},
- {file = "rpds_py-0.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3e310838a5801795207c66c73ea903deda321e6146d6f282e85fa7e3e4854804"},
- {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2249280b870e6a42c0d972339e9cc22ee98730a99cd7f2f727549af80dd5a963"},
- {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e79059d67bea28b53d255c1437b25391653263f0e69cd7dec170d778fdbca95e"},
- {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b431c777c9653e569986ecf69ff4a5dba281cded16043d348bf9ba505486f36"},
- {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da584ff96ec95e97925174eb8237e32f626e7a1a97888cdd27ee2f1f24dd0ad8"},
- {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02a0629ec053fc013808a85178524e3cb63a61dbc35b22499870194a63578fb9"},
- {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fbf15aff64a163db29a91ed0868af181d6f68ec1a3a7d5afcfe4501252840bad"},
- {file = "rpds_py-0.20.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:07924c1b938798797d60c6308fa8ad3b3f0201802f82e4a2c41bb3fafb44cc28"},
- {file = "rpds_py-0.20.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4a5a844f68776a7715ecb30843b453f07ac89bad393431efbf7accca3ef599c1"},
- {file = "rpds_py-0.20.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:518d2ca43c358929bf08f9079b617f1c2ca6e8848f83c1225c88caeac46e6cbc"},
- {file = "rpds_py-0.20.1-cp38-none-win32.whl", hash = "sha256:3aea7eed3e55119635a74bbeb80b35e776bafccb70d97e8ff838816c124539f1"},
- {file = "rpds_py-0.20.1-cp38-none-win_amd64.whl", hash = "sha256:7dca7081e9a0c3b6490a145593f6fe3173a94197f2cb9891183ef75e9d64c425"},
- {file = "rpds_py-0.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b41b6321805c472f66990c2849e152aff7bc359eb92f781e3f606609eac877ad"},
- {file = "rpds_py-0.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a90c373ea2975519b58dece25853dbcb9779b05cc46b4819cb1917e3b3215b6"},
- {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16d4477bcb9fbbd7b5b0e4a5d9b493e42026c0bf1f06f723a9353f5153e75d30"},
- {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84b8382a90539910b53a6307f7c35697bc7e6ffb25d9c1d4e998a13e842a5e83"},
- {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4888e117dd41b9d34194d9e31631af70d3d526efc363085e3089ab1a62c32ed1"},
- {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5265505b3d61a0f56618c9b941dc54dc334dc6e660f1592d112cd103d914a6db"},
- {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e75ba609dba23f2c95b776efb9dd3f0b78a76a151e96f96cc5b6b1b0004de66f"},
- {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1791ff70bc975b098fe6ecf04356a10e9e2bd7dc21fa7351c1742fdeb9b4966f"},
- {file = "rpds_py-0.20.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d126b52e4a473d40232ec2052a8b232270ed1f8c9571aaf33f73a14cc298c24f"},
- {file = "rpds_py-0.20.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c14937af98c4cc362a1d4374806204dd51b1e12dded1ae30645c298e5a5c4cb1"},
- {file = "rpds_py-0.20.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3d089d0b88996df627693639d123c8158cff41c0651f646cd8fd292c7da90eaf"},
- {file = "rpds_py-0.20.1-cp39-none-win32.whl", hash = "sha256:653647b8838cf83b2e7e6a0364f49af96deec64d2a6578324db58380cff82aca"},
- {file = "rpds_py-0.20.1-cp39-none-win_amd64.whl", hash = "sha256:fa41a64ac5b08b292906e248549ab48b69c5428f3987b09689ab2441f267d04d"},
- {file = "rpds_py-0.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7a07ced2b22f0cf0b55a6a510078174c31b6d8544f3bc00c2bcee52b3d613f74"},
- {file = "rpds_py-0.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:68cb0a499f2c4a088fd2f521453e22ed3527154136a855c62e148b7883b99f9a"},
- {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa3060d885657abc549b2a0f8e1b79699290e5d83845141717c6c90c2df38311"},
- {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:95f3b65d2392e1c5cec27cff08fdc0080270d5a1a4b2ea1d51d5f4a2620ff08d"},
- {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2cc3712a4b0b76a1d45a9302dd2f53ff339614b1c29603a911318f2357b04dd2"},
- {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d4eea0761e37485c9b81400437adb11c40e13ef513375bbd6973e34100aeb06"},
- {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f5179583d7a6cdb981151dd349786cbc318bab54963a192692d945dd3f6435d"},
- {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fbb0ffc754490aff6dabbf28064be47f0f9ca0b9755976f945214965b3ace7e"},
- {file = "rpds_py-0.20.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a94e52537a0e0a85429eda9e49f272ada715506d3b2431f64b8a3e34eb5f3e75"},
- {file = "rpds_py-0.20.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:92b68b79c0da2a980b1c4197e56ac3dd0c8a149b4603747c4378914a68706979"},
- {file = "rpds_py-0.20.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:93da1d3db08a827eda74356f9f58884adb254e59b6664f64cc04cdff2cc19b0d"},
- {file = "rpds_py-0.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:754bbed1a4ca48479e9d4182a561d001bbf81543876cdded6f695ec3d465846b"},
- {file = "rpds_py-0.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ca449520e7484534a2a44faf629362cae62b660601432d04c482283c47eaebab"},
- {file = "rpds_py-0.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:9c4cb04a16b0f199a8c9bf807269b2f63b7b5b11425e4a6bd44bd6961d28282c"},
- {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb63804105143c7e24cee7db89e37cb3f3941f8e80c4379a0b355c52a52b6780"},
- {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:55cd1fa4ecfa6d9f14fbd97ac24803e6f73e897c738f771a9fe038f2f11ff07c"},
- {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f8f741b6292c86059ed175d80eefa80997125b7c478fb8769fd9ac8943a16c0"},
- {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fc212779bf8411667234b3cdd34d53de6c2b8b8b958e1e12cb473a5f367c338"},
- {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ad56edabcdb428c2e33bbf24f255fe2b43253b7d13a2cdbf05de955217313e6"},
- {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0a3a1e9ee9728b2c1734f65d6a1d376c6f2f6fdcc13bb007a08cc4b1ff576dc5"},
- {file = "rpds_py-0.20.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e13de156137b7095442b288e72f33503a469aa1980ed856b43c353ac86390519"},
- {file = "rpds_py-0.20.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:07f59760ef99f31422c49038964b31c4dfcfeb5d2384ebfc71058a7c9adae2d2"},
- {file = "rpds_py-0.20.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:59240685e7da61fb78f65a9f07f8108e36a83317c53f7b276b4175dc44151684"},
- {file = "rpds_py-0.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:83cba698cfb3c2c5a7c3c6bac12fe6c6a51aae69513726be6411076185a8b24a"},
- {file = "rpds_py-0.20.1.tar.gz", hash = "sha256:e1791c4aabd117653530dccd24108fa03cc6baf21f58b950d0a73c3b3b29a350"},
+ {file = "rpds_py-0.21.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a017f813f24b9df929674d0332a374d40d7f0162b326562daae8066b502d0590"},
+ {file = "rpds_py-0.21.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:20cc1ed0bcc86d8e1a7e968cce15be45178fd16e2ff656a243145e0b439bd250"},
+ {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad116dda078d0bc4886cb7840e19811562acdc7a8e296ea6ec37e70326c1b41c"},
+ {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:808f1ac7cf3b44f81c9475475ceb221f982ef548e44e024ad5f9e7060649540e"},
+ {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de552f4a1916e520f2703ec474d2b4d3f86d41f353e7680b597512ffe7eac5d0"},
+ {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:efec946f331349dfc4ae9d0e034c263ddde19414fe5128580f512619abed05f1"},
+ {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b80b4690bbff51a034bfde9c9f6bf9357f0a8c61f548942b80f7b66356508bf5"},
+ {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:085ed25baac88953d4283e5b5bd094b155075bb40d07c29c4f073e10623f9f2e"},
+ {file = "rpds_py-0.21.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:daa8efac2a1273eed2354397a51216ae1e198ecbce9036fba4e7610b308b6153"},
+ {file = "rpds_py-0.21.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:95a5bad1ac8a5c77b4e658671642e4af3707f095d2b78a1fdd08af0dfb647624"},
+ {file = "rpds_py-0.21.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3e53861b29a13d5b70116ea4230b5f0f3547b2c222c5daa090eb7c9c82d7f664"},
+ {file = "rpds_py-0.21.0-cp310-none-win32.whl", hash = "sha256:ea3a6ac4d74820c98fcc9da4a57847ad2cc36475a8bd9683f32ab6d47a2bd682"},
+ {file = "rpds_py-0.21.0-cp310-none-win_amd64.whl", hash = "sha256:b8f107395f2f1d151181880b69a2869c69e87ec079c49c0016ab96860b6acbe5"},
+ {file = "rpds_py-0.21.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5555db3e618a77034954b9dc547eae94166391a98eb867905ec8fcbce1308d95"},
+ {file = "rpds_py-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:97ef67d9bbc3e15584c2f3c74bcf064af36336c10d2e21a2131e123ce0f924c9"},
+ {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ab2c2a26d2f69cdf833174f4d9d86118edc781ad9a8fa13970b527bf8236027"},
+ {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4e8921a259f54bfbc755c5bbd60c82bb2339ae0324163f32868f63f0ebb873d9"},
+ {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a7ff941004d74d55a47f916afc38494bd1cfd4b53c482b77c03147c91ac0ac3"},
+ {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5145282a7cd2ac16ea0dc46b82167754d5e103a05614b724457cffe614f25bd8"},
+ {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de609a6f1b682f70bb7163da745ee815d8f230d97276db049ab447767466a09d"},
+ {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:40c91c6e34cf016fa8e6b59d75e3dbe354830777fcfd74c58b279dceb7975b75"},
+ {file = "rpds_py-0.21.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d2132377f9deef0c4db89e65e8bb28644ff75a18df5293e132a8d67748397b9f"},
+ {file = "rpds_py-0.21.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0a9e0759e7be10109645a9fddaaad0619d58c9bf30a3f248a2ea57a7c417173a"},
+ {file = "rpds_py-0.21.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9e20da3957bdf7824afdd4b6eeb29510e83e026473e04952dca565170cd1ecc8"},
+ {file = "rpds_py-0.21.0-cp311-none-win32.whl", hash = "sha256:f71009b0d5e94c0e86533c0b27ed7cacc1239cb51c178fd239c3cfefefb0400a"},
+ {file = "rpds_py-0.21.0-cp311-none-win_amd64.whl", hash = "sha256:e168afe6bf6ab7ab46c8c375606298784ecbe3ba31c0980b7dcbb9631dcba97e"},
+ {file = "rpds_py-0.21.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:30b912c965b2aa76ba5168fd610087bad7fcde47f0a8367ee8f1876086ee6d1d"},
+ {file = "rpds_py-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ca9989d5d9b1b300bc18e1801c67b9f6d2c66b8fd9621b36072ed1df2c977f72"},
+ {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f54e7106f0001244a5f4cf810ba8d3f9c542e2730821b16e969d6887b664266"},
+ {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fed5dfefdf384d6fe975cc026886aece4f292feaf69d0eeb716cfd3c5a4dd8be"},
+ {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:590ef88db231c9c1eece44dcfefd7515d8bf0d986d64d0caf06a81998a9e8cab"},
+ {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f983e4c2f603c95dde63df633eec42955508eefd8d0f0e6d236d31a044c882d7"},
+ {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b229ce052ddf1a01c67d68166c19cb004fb3612424921b81c46e7ea7ccf7c3bf"},
+ {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ebf64e281a06c904a7636781d2e973d1f0926a5b8b480ac658dc0f556e7779f4"},
+ {file = "rpds_py-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:998a8080c4495e4f72132f3d66ff91f5997d799e86cec6ee05342f8f3cda7dca"},
+ {file = "rpds_py-0.21.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:98486337f7b4f3c324ab402e83453e25bb844f44418c066623db88e4c56b7c7b"},
+ {file = "rpds_py-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a78d8b634c9df7f8d175451cfeac3810a702ccb85f98ec95797fa98b942cea11"},
+ {file = "rpds_py-0.21.0-cp312-none-win32.whl", hash = "sha256:a58ce66847711c4aa2ecfcfaff04cb0327f907fead8945ffc47d9407f41ff952"},
+ {file = "rpds_py-0.21.0-cp312-none-win_amd64.whl", hash = "sha256:e860f065cc4ea6f256d6f411aba4b1251255366e48e972f8a347cf88077b24fd"},
+ {file = "rpds_py-0.21.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ee4eafd77cc98d355a0d02f263efc0d3ae3ce4a7c24740010a8b4012bbb24937"},
+ {file = "rpds_py-0.21.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:688c93b77e468d72579351a84b95f976bd7b3e84aa6686be6497045ba84be560"},
+ {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c38dbf31c57032667dd5a2f0568ccde66e868e8f78d5a0d27dcc56d70f3fcd3b"},
+ {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2d6129137f43f7fa02d41542ffff4871d4aefa724a5fe38e2c31a4e0fd343fb0"},
+ {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520ed8b99b0bf86a176271f6fe23024323862ac674b1ce5b02a72bfeff3fff44"},
+ {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaeb25ccfb9b9014a10eaf70904ebf3f79faaa8e60e99e19eef9f478651b9b74"},
+ {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af04ac89c738e0f0f1b913918024c3eab6e3ace989518ea838807177d38a2e94"},
+ {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b9b76e2afd585803c53c5b29e992ecd183f68285b62fe2668383a18e74abe7a3"},
+ {file = "rpds_py-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5afb5efde74c54724e1a01118c6e5c15e54e642c42a1ba588ab1f03544ac8c7a"},
+ {file = "rpds_py-0.21.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:52c041802a6efa625ea18027a0723676a778869481d16803481ef6cc02ea8cb3"},
+ {file = "rpds_py-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee1e4fc267b437bb89990b2f2abf6c25765b89b72dd4a11e21934df449e0c976"},
+ {file = "rpds_py-0.21.0-cp313-none-win32.whl", hash = "sha256:0c025820b78817db6a76413fff6866790786c38f95ea3f3d3c93dbb73b632202"},
+ {file = "rpds_py-0.21.0-cp313-none-win_amd64.whl", hash = "sha256:320c808df533695326610a1b6a0a6e98f033e49de55d7dc36a13c8a30cfa756e"},
+ {file = "rpds_py-0.21.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:2c51d99c30091f72a3c5d126fad26236c3f75716b8b5e5cf8effb18889ced928"},
+ {file = "rpds_py-0.21.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cbd7504a10b0955ea287114f003b7ad62330c9e65ba012c6223dba646f6ffd05"},
+ {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dcc4949be728ede49e6244eabd04064336012b37f5c2200e8ec8eb2988b209c"},
+ {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f414da5c51bf350e4b7960644617c130140423882305f7574b6cf65a3081cecb"},
+ {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9afe42102b40007f588666bc7de82451e10c6788f6f70984629db193849dced1"},
+ {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b929c2bb6e29ab31f12a1117c39f7e6d6450419ab7464a4ea9b0b417174f044"},
+ {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8404b3717da03cbf773a1d275d01fec84ea007754ed380f63dfc24fb76ce4592"},
+ {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e12bb09678f38b7597b8346983d2323a6482dcd59e423d9448108c1be37cac9d"},
+ {file = "rpds_py-0.21.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:58a0e345be4b18e6b8501d3b0aa540dad90caeed814c515e5206bb2ec26736fd"},
+ {file = "rpds_py-0.21.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c3761f62fcfccf0864cc4665b6e7c3f0c626f0380b41b8bd1ce322103fa3ef87"},
+ {file = "rpds_py-0.21.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c2b2f71c6ad6c2e4fc9ed9401080badd1469fa9889657ec3abea42a3d6b2e1ed"},
+ {file = "rpds_py-0.21.0-cp39-none-win32.whl", hash = "sha256:b21747f79f360e790525e6f6438c7569ddbfb1b3197b9e65043f25c3c9b489d8"},
+ {file = "rpds_py-0.21.0-cp39-none-win_amd64.whl", hash = "sha256:0626238a43152918f9e72ede9a3b6ccc9e299adc8ade0d67c5e142d564c9a83d"},
+ {file = "rpds_py-0.21.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6b4ef7725386dc0762857097f6b7266a6cdd62bfd209664da6712cb26acef035"},
+ {file = "rpds_py-0.21.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:6bc0e697d4d79ab1aacbf20ee5f0df80359ecf55db33ff41481cf3e24f206919"},
+ {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da52d62a96e61c1c444f3998c434e8b263c384f6d68aca8274d2e08d1906325c"},
+ {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:98e4fe5db40db87ce1c65031463a760ec7906ab230ad2249b4572c2fc3ef1f9f"},
+ {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30bdc973f10d28e0337f71d202ff29345320f8bc49a31c90e6c257e1ccef4333"},
+ {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:faa5e8496c530f9c71f2b4e1c49758b06e5f4055e17144906245c99fa6d45356"},
+ {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32eb88c30b6a4f0605508023b7141d043a79b14acb3b969aa0b4f99b25bc7d4a"},
+ {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a89a8ce9e4e75aeb7fa5d8ad0f3fecdee813802592f4f46a15754dcb2fd6b061"},
+ {file = "rpds_py-0.21.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:241e6c125568493f553c3d0fdbb38c74babf54b45cef86439d4cd97ff8feb34d"},
+ {file = "rpds_py-0.21.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:3b766a9f57663396e4f34f5140b3595b233a7b146e94777b97a8413a1da1be18"},
+ {file = "rpds_py-0.21.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:af4a644bf890f56e41e74be7d34e9511e4954894d544ec6b8efe1e21a1a8da6c"},
+ {file = "rpds_py-0.21.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3e30a69a706e8ea20444b98a49f386c17b26f860aa9245329bab0851ed100677"},
+ {file = "rpds_py-0.21.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:031819f906bb146561af051c7cef4ba2003d28cff07efacef59da973ff7969ba"},
+ {file = "rpds_py-0.21.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b876f2bc27ab5954e2fd88890c071bd0ed18b9c50f6ec3de3c50a5ece612f7a6"},
+ {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc5695c321e518d9f03b7ea6abb5ea3af4567766f9852ad1560f501b17588c7b"},
+ {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b4de1da871b5c0fd5537b26a6fc6814c3cc05cabe0c941db6e9044ffbb12f04a"},
+ {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:878f6fea96621fda5303a2867887686d7a198d9e0f8a40be100a63f5d60c88c9"},
+ {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8eeec67590e94189f434c6d11c426892e396ae59e4801d17a93ac96b8c02a6c"},
+ {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ff2eba7f6c0cb523d7e9cff0903f2fe1feff8f0b2ceb6bd71c0e20a4dcee271"},
+ {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a429b99337062877d7875e4ff1a51fe788424d522bd64a8c0a20ef3021fdb6ed"},
+ {file = "rpds_py-0.21.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:d167e4dbbdac48bd58893c7e446684ad5d425b407f9336e04ab52e8b9194e2ed"},
+ {file = "rpds_py-0.21.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:4eb2de8a147ffe0626bfdc275fc6563aa7bf4b6db59cf0d44f0ccd6ca625a24e"},
+ {file = "rpds_py-0.21.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e78868e98f34f34a88e23ee9ccaeeec460e4eaf6db16d51d7a9b883e5e785a5e"},
+ {file = "rpds_py-0.21.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4991ca61656e3160cdaca4851151fd3f4a92e9eba5c7a530ab030d6aee96ec89"},
+ {file = "rpds_py-0.21.0.tar.gz", hash = "sha256:ed6378c9d66d0de903763e7706383d60c33829581f0adff47b6535f1802fa6db"},
]
[[package]]
@@ -2176,16 +2163,16 @@ files = [
[[package]]
name = "semgrep"
-version = "1.94.0"
+version = "1.96.0"
description = "Lightweight static analysis for many languages. Find bug variants with patterns that look like source code."
optional = false
python-versions = ">=3.8"
files = [
- {file = "semgrep-1.94.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-any.whl", hash = "sha256:c0ab9e7084419db7f61a60e32ef59c01e723c7d43ff7b40a974b51f3d81beafe"},
- {file = "semgrep-1.94.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-macosx_10_14_x86_64.whl", hash = "sha256:121ff5116310c5cb58d31712e971a3ecd7605c26b6b5b54e3537f6b3676190c0"},
- {file = "semgrep-1.94.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-macosx_11_0_arm64.whl", hash = "sha256:c91fd31a58665ff1e5ac6dbbcfb7ce4929eb86d9226ce51dcb24cd69cdd0aee8"},
- {file = "semgrep-1.94.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-musllinux_1_0_aarch64.manylinux2014_aarch64.whl", hash = "sha256:191b881dbb4329c68602550cc4119eb9e06576f96ad435b3f6195adb248381dc"},
- {file = "semgrep-1.94.0.tar.gz", hash = "sha256:ebe1515b49972cc9cc9ed1973780ce899fe2ece4779a51036f0bfab3235d32a8"},
+ {file = "semgrep-1.96.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-any.whl", hash = "sha256:b55c70f4a8c1aaa8040e4ecb2d36f358f8c1320da6470b5b55ef78110901604a"},
+ {file = "semgrep-1.96.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-macosx_10_14_x86_64.whl", hash = "sha256:255298c471cd5fda18f762fadafcfbf3c9b82333afea706837a14eea9e679c9d"},
+ {file = "semgrep-1.96.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-macosx_11_0_arm64.whl", hash = "sha256:177c43375f19876cbdc159734defa4840f537f7d653c30f3b5efceb2a4e5a067"},
+ {file = "semgrep-1.96.0-cp38.cp39.cp310.cp311.py37.py38.py39.py310.py311-none-musllinux_1_0_aarch64.manylinux2014_aarch64.whl", hash = "sha256:735d72d39eeb03202ce14d7c18e1d23526dbf265e47c3b11ec3cfe7c745083bc"},
+ {file = "semgrep-1.96.0.tar.gz", hash = "sha256:4785bda32d259400ec2f9186a51b0dbc49e0bd09baaa7c672e12277cc90994b5"},
]
[package.dependencies]
From 1144161dba5b965f07e54705decc606480059842 Mon Sep 17 00:00:00 2001
From: Alex Sullivan <115666116+asullivan-blze@users.noreply.github.com>
Date: Thu, 7 Nov 2024 17:14:21 -0800
Subject: [PATCH 3/6] Reorder Installation section; add version/build info; fix
and unsilence MyST warning
---
.github/workflows/sphinx.yml | 6 --
README.md | 129 ++++++++++++++++----------------
docs/source/_templates/.gitkeep | 0
docs/source/conf.py | 25 +++++--
docs/source/index.md | 5 +-
docs/source/installation.md | 11 +++
docs/source/overview.md | 2 +-
7 files changed, 101 insertions(+), 77 deletions(-)
create mode 100644 docs/source/_templates/.gitkeep
create mode 100644 docs/source/installation.md
diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml
index 9bb9ed6..63eb38d 100644
--- a/.github/workflows/sphinx.yml
+++ b/.github/workflows/sphinx.yml
@@ -8,12 +8,6 @@ on:
tags:
- 'v*.*.*'
workflow_dispatch:
- inputs:
- debug_enabled:
- type: boolean
- description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
- required: false
- default: false
jobs:
build:
diff --git a/README.md b/README.md
index eedfb31..883a86e 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ stopping and resuming long-running Ansible workflows easy and efficient.
updates.__ š„
-
+
# Table of Contents
- [Motivation & Goals](#motivation--goals)
- [Open-Source License](#open-source-license)
@@ -33,11 +33,11 @@ updates.__ š„
- [Remote State](#remote-state)
- [Usage](#usage)
- [Installation](#installation)
- - [The `Boardwalkfile.py`](#the-boardwalkfile)
+ - [The `Boardwalkfile.py`](#the-boardwalkfilepy)
- [Command-line Interface](#environment-variables)
- [`boardwalkd` Server](#boardwalkd-server)
-
+
# Motivation & Goals
@@ -75,6 +75,64 @@ interface used by [AWX](https://github.com/ansible/awx).
own secret management system, because Ansible already has solutions to those
areas.
+# Installation
+
+
+We recommend installing `boardwalk` in a [`pipx`](https://pipx.pypa.io/stable/)
+environment, to ensure that your system or user pip packages are not affected by
+Boardwalk's dependencies. Refer to `pipx`'s documentation for how to install it,
+and then execute the following commands:
+```sh
+# Boardwalk depends on `ansible` in order to run.
+pipx install ansible>=6.5.0
+# Inject Boardwalk into the environment so it can use Ansible. Optionally,
+# appending an @ allows for installing specific commits,
+# branches, or tags.
+pipx inject ansible git+ssh://git@github.com/Backblaze/boardwalk.git
+```
+
+__Note__:
+Boardwalk should be designed to be compatible with the current stable Python3
+release, minus 1 minor version. So, if the current stable version is `3.22.x`,
+Boardwalk should work with `3.21.x`. Consider using
+[`pyenv`](https://github.com/pyenv/pyenv) to maintain fresh python environment.
+
+## Shell Completion
+
+To enable shell completion for `boardwalk` and `boardwalkd`, the following set
+of commands will generate the completion script and add them to your shell (a
+shell restart will be needed):
+
+### Bash
+```bash
+_BOARDWALK_COMPLETE=bash_source boardwalk > ~/.boardwalk-complete.bash
+_BOARDWALKD_COMPLETE=bash_source boardwalkd > ~/.boardwalkd-complete.bash
+echo '. ~/.boardwalk-complete.bash' >> ~/.bashrc
+echo '. ~/.boardwalkd-complete.bash' >> ~/.bashrc
+```
+
+### Zsh
+```zsh
+_BOARDWALK_COMPLETE=zsh_source boardwalk > ~/.boardwalk-complete.zsh
+_BOARDWALKD_COMPLETE=zsh_source boardwalkd > ~/.boardwalkd-complete.zsh
+echo '. ~/.boardwalk-complete.zsh' >> ~/.zshrc
+echo '. ~/.boardwalkd-complete.zsh' >> ~/.zshrc
+```
+
+### Fish
+```sh
+_BOARDWALK_COMPLETE=fish_source boardwalk > ~/.config/fish/completions/boardwalk.fish
+_BOARDWALKD_COMPLETE=fish_source boardwalkd > ~/.config/fish/completions/boardwalkd.fish
+```
+
+## Container Install
+
+Boardwalk may be built as a container image by running `make container`.
+
+The entrypoint is simply `python -m` so either `boardwalk` or `boardwalkd`
+must be specified as the command when running.
+
+
# Open-Source License
Boardwalk is open source, licensed under the terms of the [MIT license](https://github.com/Backblaze/boardwalk/blob/main/LICENSE).
@@ -93,7 +151,7 @@ Workspaces define isolated configurations and state for working on projects with
Boardwalk. They define the Ansible host pattern Boardwalk should target, the
Workflow Boardwalk will use, and some essential configuration options.
-Workspaces are defined in the [Boardwalkfile.py](#the-boardwalkfile). The
+Workspaces are defined in the [Boardwalkfile.py](#the-boardwalkfilepy). The
active Workspace is selected with `boardwalk workspace use `.
## Workflow
@@ -105,7 +163,7 @@ purpose of a Workflow is to mutate a host from one state to another. Typically
Workflows depend upon some Ansible fact(s) having changed after the Workflow has
completed all of its Jobs.
-Workflows are defined in the [Boardwalkfile.py](#the-boardwalkfile).
+Workflows are defined in the [Boardwalkfile.py](#the-boardwalkfilepy).
Workflows can be dry-run with `boardwalk check`, which runs Ansible in `--check`
mode. Workflows are run with `boardwalk run`.
@@ -116,7 +174,7 @@ that are run against hosts. They accept options that can be passed into them and
used in tasks. They define preconditions that a host must meet before a Workflow
will run against it.
-Jobs are defined in the [Boardwalkfile.py](#the-boardwalkfile).
+Jobs are defined in the [Boardwalkfile.py](#the-boardwalkfilepy).
### Job Preconditions
@@ -165,63 +223,8 @@ Boardwalk.
# Usage
-## Installation
-
-We recommend installing `boardwalk` in a [`pipx`](https://pipx.pypa.io/stable/)
-environment, to ensure that your system or user pip packages are not affected by
-Boardwalk's dependencies. Refer to `pipx`'s documentation for how to install it,
-and then execute the following commands:
-```sh
-# Boardwalk depends on `ansible` in order to run.
-pipx install ansible>=6.5.0
-# Inject Boardwalk into the environment so it can use Ansible. Optionally,
-# appending an @ allows for installing specific commits,
-# branches, or tags.
-pipx inject ansible git+ssh://git@github.com/Backblaze/boardwalk.git
-```
-
-__Note__:
-Boardwalk should be designed to be compatible with the current stable Python3
-release, minus 1 minor version. So, if the current stable version is `3.22.x`,
-Boardwalk should work with `3.21.x`. Consider using
-[`pyenv`](https://github.com/pyenv/pyenv) to maintain fresh python environment.
-
-### Shell Completion
-
-To enable shell completion for `boardwalk` and `boardwalkd`, the following set
-of commands will generate the completion script and add them to your shell (a
-shell restart will be needed):
-
-#### Bash
-```bash
-_BOARDWALK_COMPLETE=bash_source boardwalk > ~/.boardwalk-complete.bash
-_BOARDWALKD_COMPLETE=bash_source boardwalkd > ~/.boardwalkd-complete.bash
-echo '. ~/.boardwalk-complete.bash' >> ~/.bashrc
-echo '. ~/.boardwalkd-complete.bash' >> ~/.bashrc
-```
-
-#### Zsh
-```zsh
-_BOARDWALK_COMPLETE=zsh_source boardwalk > ~/.boardwalk-complete.zsh
-_BOARDWALKD_COMPLETE=zsh_source boardwalkd > ~/.boardwalkd-complete.zsh
-echo '. ~/.boardwalk-complete.zsh' >> ~/.zshrc
-echo '. ~/.boardwalkd-complete.zsh' >> ~/.zshrc
-```
-
-#### Fish
-```sh
-_BOARDWALK_COMPLETE=fish_source boardwalk > ~/.config/fish/completions/boardwalk.fish
-_BOARDWALKD_COMPLETE=fish_source boardwalkd > ~/.config/fish/completions/boardwalkd.fish
-```
-
-### Container Install
-
-Boardwalk may be built as a container image by running `make container`.
-
-The entrypoint is simply `python -m` so either `boardwalk` or `boardwalkd`
-must be specified as the command when running.
-
-## The `Boardwalkfile`
+(the-boardwalkfilepy)=
+## The `Boardwalkfile.py`
Boardwalk is both a python library and command-line tool. The `boardwalk`
command-line tool expects a file called `Boardwalkfile.py` to exist in the
diff --git a/docs/source/_templates/.gitkeep b/docs/source/_templates/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 4ca22fc..c23f44e 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -3,16 +3,30 @@
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
+import subprocess
from datetime import UTC, datetime
from importlib.metadata import version as lib_version
+# -- Helper functions -----------------------------------------------------
+
+
+def get_git_revision_hash() -> str:
+ return subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii").strip()
+
+
+def get_git_revision_short_hash() -> str:
+ return subprocess.check_output(["git", "rev-parse", "--short", "HEAD"]).decode("ascii").strip()
+
+
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
project = "Boardwalk"
copyright = f"{datetime.now(tz=UTC).year}, Backblaze"
author = "Backblaze"
-release = f"{lib_version('boardwalk')}"
+VERSION: str = lib_version("boardwalk")
+release = f"v{VERSION}"
+version = VERSION
# -- General configuration ---------------------------------------------------
@@ -33,8 +47,6 @@
nitpicky = True
nitpick_ignore = [
- # This does anchor correctly when testing the rendered page.
- ("myst", "the-boardwalkfile"),
# I think these are just by virtue of the fact we have these behind an `if TYPE_CHECKING:` line? Need to (eventually) figure these out.
("py:class", "boardwalk.ansible.AnsibleFacts"),
("py:class", "boardwalk.ansible.AnsibleTasksType"),
@@ -102,12 +114,15 @@
html_static_path = ["_static"]
html_logo = "_img/src/boardwalkd/static/boardwalk_icon.jpg"
# html_favicon = "_static/logo-square.svg"
-html_title = ""
+html_title = f"Boardwalk v{VERSION} ({get_git_revision_short_hash()})"
html_theme_options = {
+ "extra_footer": f"""
+ Documentation generated with commit {get_git_revision_short_hash()}
+ """,
"home_page_in_toc": True,
"logo": {
"alt_text": "Boardwalk documentation - Home",
- "text": "Boardwalk, a linear Ansible workflow engine",
+ "text": f"Boardwalk, a linear Ansible workflow engine
v{VERSION}",
},
"repository_branch": "main",
"repository_url": "https://github.com/Backblaze/boardwalk/",
diff --git a/docs/source/index.md b/docs/source/index.md
index 7dd796c..b95a90f 100644
--- a/docs/source/index.md
+++ b/docs/source/index.md
@@ -4,7 +4,7 @@ gfm_only: True
-------
```{include} ../../README.md
-:end-before: GitHub-Table-of-Contents_Before
+:end-before:
```
```{toctree}
@@ -13,6 +13,7 @@ gfm_only: True
:caption: General
overview.md
+installation.md
```
```{toctree}
@@ -29,4 +30,4 @@ cli_helpdocs/index.md
:caption: API Reference
apidocs/index.rst
-```
\ No newline at end of file
+```
diff --git a/docs/source/installation.md b/docs/source/installation.md
new file mode 100644
index 0000000..338df10
--- /dev/null
+++ b/docs/source/installation.md
@@ -0,0 +1,11 @@
+-------
+# Using GitHub flavored Markdown here, as we're including portions of the README.md, which is used on GitHub.
+gfm_only: True
+-------
+
+# Installation
+
+```{include} ../../README.md
+:start-after:
+:end-before:
+```
diff --git a/docs/source/overview.md b/docs/source/overview.md
index 2336cd4..01b1843 100644
--- a/docs/source/overview.md
+++ b/docs/source/overview.md
@@ -6,5 +6,5 @@ gfm_only: True
# Overview
```{include} ../../README.md
-:start-after: GitHub-Table-of-Contents_After -->
+:start-after:
```
From 453948dff5bf15d233f053e5875a6c69deed48cf Mon Sep 17 00:00:00 2001
From: Alex Sullivan <115666116+asullivan-blze@users.noreply.github.com>
Date: Fri, 8 Nov 2024 11:46:19 -0800
Subject: [PATCH 4/6] - Lowers the HTML build artifact retention to 14 days -
Cleans up code bits used during development - Removes the Git SHA from the
generated page footer; we still have the short SHA and the version in the
page heading, so nothing is really missing by not including this.
---
.github/workflows/sphinx.yml | 26 +++++++++++---------------
docs/source/conf.py | 20 ++++++--------------
2 files changed, 17 insertions(+), 29 deletions(-)
diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml
index 63eb38d..b821c7d 100644
--- a/.github/workflows/sphinx.yml
+++ b/.github/workflows/sphinx.yml
@@ -1,13 +1,13 @@
name: "Sphinx: Render docs"
on:
- pull_request:
+ pull_request: {}
push:
branches:
- main
tags:
- 'v*.*.*'
- workflow_dispatch:
+ workflow_dispatch: {}
jobs:
build:
@@ -70,20 +70,16 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: html-docs
- path: docs/build/
+ # Lower default retention -- the artifacts can be rebuilt from source, if needed
+ retention-days: 14
+ # Don't include the doctrees subdir; it's just pickled data Sphinx generates to make the HTML
+ path: |
+ docs/build/
+ !docs/build/doctrees
- # - name: Deploy main branch docs to gh-pages branch
- # uses: peaceiris/actions-gh-pages@v4
- # if: github.ref == 'refs/heads/main'
- # with:
- # github_token: ${{ secrets.GITHUB_TOKEN }}
- # publish_dir: docs/build/
-
- # Since it doesn't seem GHActions supports `or`, using this as an intermediate testing step.
- # The above will remain once we merge this workflow back into the main repo.
- - name: Deploy testing docs to gh-pages branch
+ - name: Deploy documentation to the gh-pages branch for publishing
uses: peaceiris/actions-gh-pages@v4
- if: github.ref == 'refs/heads/dev'
+ if: github.ref == 'refs/heads/main'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
- publish_dir: docs/build/
+ publish_dir: docs/build/html
diff --git a/docs/source/conf.py b/docs/source/conf.py
index c23f44e..8c90eab 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -7,17 +7,6 @@
from datetime import UTC, datetime
from importlib.metadata import version as lib_version
-# -- Helper functions -----------------------------------------------------
-
-
-def get_git_revision_hash() -> str:
- return subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii").strip()
-
-
-def get_git_revision_short_hash() -> str:
- return subprocess.check_output(["git", "rev-parse", "--short", "HEAD"]).decode("ascii").strip()
-
-
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
@@ -28,6 +17,12 @@ def get_git_revision_short_hash() -> str:
release = f"v{VERSION}"
version = VERSION
+# -- Helper functions -----------------------------------------------------
+
+
+def get_git_revision_short_hash() -> str:
+ return subprocess.check_output(["git", "rev-parse", "--short", "HEAD"]).decode("ascii").strip()
+
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
@@ -116,9 +111,6 @@ def get_git_revision_short_hash() -> str:
# html_favicon = "_static/logo-square.svg"
html_title = f"Boardwalk v{VERSION} ({get_git_revision_short_hash()})"
html_theme_options = {
- "extra_footer": f"""
- Documentation generated with commit {get_git_revision_short_hash()}
- """,
"home_page_in_toc": True,
"logo": {
"alt_text": "Boardwalk documentation - Home",
From 80bdbe6d87a32861c17974864896f5c1c902774c Mon Sep 17 00:00:00 2001
From: Alex Sullivan <115666116+asullivan-blze@users.noreply.github.com>
Date: Fri, 8 Nov 2024 13:20:32 -0800
Subject: [PATCH 5/6] Remove development artifact from GH action which wasn't
eventually used
---
.github/dependabot.yml | 5 -----
docs/requirements.txt | 8 --------
2 files changed, 13 deletions(-)
delete mode 100644 docs/requirements.txt
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index af35054..2a21467 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -8,11 +8,6 @@ updates:
directory: "/"
schedule:
interval: "daily"
- # Keep the requirements.txt for Sphinx builds in `/docs` up to date, also.
- - package-ecosystem: "pip"
- directory: "/docs"
- schedule:
- interval: "daily"
# For keeping workflows up-to-date.
- package-ecosystem: "github-actions"
directory: "/"
diff --git a/docs/requirements.txt b/docs/requirements.txt
deleted file mode 100644
index db831ac..0000000
--- a/docs/requirements.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-# Requirements file for the GitHub ammaraskar/sphinx-action, which builds Sphinx
-# documentation
-
-sphinx-autobuild >= 2024.10.3
-sphinx-autodoc2 >= 0.5.0, < 1.0
-sphinx-book-theme >= 1.1.3, < 2.0
-sphinx-copybutton >= 0.5.2, < 1.0
-myst-parser [linkify] >= 4.0.0, < 5.0
From 7d610408ccf0a5c765778f00dd9a7f134b0637a6 Mon Sep 17 00:00:00 2001
From: Alex Sullivan <115666116+asullivan-blze@users.noreply.github.com>
Date: Tue, 12 Nov 2024 17:10:53 -0800
Subject: [PATCH 6/6] Auto-generate automatic documentation at document
build-time
There's little reason to include the files that would get built and/or rebuilt by Sphinx. Avoids bloated diffs.
---
.github/workflows/sphinx.yml | 85 --
.gitignore | 2 +
Makefile | 3 +-
README.md | 3 +-
docs/Makefile | 18 +-
docs/build_cli_help_pages.sh | 10 +-
.../apidocs/boardwalk/boardwalk.__main__.md | 8 -
.../apidocs/boardwalk/boardwalk.ansible.md | 144 ---
.../boardwalk/boardwalk.app_exceptions.md | 36 -
.../source/apidocs/boardwalk/boardwalk.cli.md | 75 --
.../apidocs/boardwalk/boardwalk.cli_catch.md | 42 -
.../apidocs/boardwalk/boardwalk.cli_init.md | 53 -
.../apidocs/boardwalk/boardwalk.cli_login.md | 31 -
.../apidocs/boardwalk/boardwalk.cli_run.md | 289 -----
.../boardwalk/boardwalk.cli_workspace.md | 97 --
.../apidocs/boardwalk/boardwalk.host.md | 211 ----
.../apidocs/boardwalk/boardwalk.manifest.md | 610 ----------
docs/source/apidocs/boardwalk/boardwalk.md | 29 -
.../apidocs/boardwalk/boardwalk.state.md | 186 ---
.../apidocs/boardwalk/boardwalk.utils.md | 31 -
.../apidocs/boardwalkd/boardwalkd.__main__.md | 8 -
.../boardwalkd/boardwalkd.broadcast.md | 32 -
.../apidocs/boardwalkd/boardwalkd.cli.md | 76 --
docs/source/apidocs/boardwalkd/boardwalkd.md | 23 -
.../apidocs/boardwalkd/boardwalkd.protocol.md | 554 ---------
.../apidocs/boardwalkd/boardwalkd.server.md | 1005 -----------------
.../apidocs/boardwalkd/boardwalkd.slack.md | 207 ----
.../apidocs/boardwalkd/boardwalkd.state.md | 305 -----
docs/source/apidocs/index.rst | 12 -
.../cli_helpdocs/boardwalk/boardwalk.md | 33 -
.../cli_helpdocs/boardwalk/boardwalk_catch.md | 18 -
.../cli_helpdocs/boardwalk/boardwalk_check.md | 32 -
.../cli_helpdocs/boardwalk/boardwalk_init.md | 23 -
.../cli_helpdocs/boardwalk/boardwalk_login.md | 17 -
.../boardwalk/boardwalk_release.md | 17 -
.../cli_helpdocs/boardwalk/boardwalk_run.md | 40 -
.../boardwalk/boardwalk_version.md | 17 -
.../boardwalk/boardwalk_workspace.md | 22 -
.../boardwalk/boardwalk_workspace_dump.md | 17 -
.../boardwalk/boardwalk_workspace_list.md | 17 -
.../boardwalk/boardwalk_workspace_reset.md | 18 -
.../boardwalk/boardwalk_workspace_show.md | 17 -
.../boardwalk/boardwalk_workspace_use.md | 15 -
docs/source/cli_helpdocs/boardwalk/index.md | 34 +-
.../cli_helpdocs/boardwalkd/boardwalkd.md | 23 -
.../boardwalkd/boardwalkd_serve.md | 98 --
.../boardwalkd/boardwalkd_version.md | 17 -
docs/source/cli_helpdocs/boardwalkd/index.md | 12 +-
docs/source/cli_helpdocs/index.md | 6 +-
docs/source/conf.py | 5 +-
docs/source/index.md | 2 +-
51 files changed, 66 insertions(+), 4619 deletions(-)
delete mode 100644 .github/workflows/sphinx.yml
delete mode 100644 docs/source/apidocs/boardwalk/boardwalk.__main__.md
delete mode 100644 docs/source/apidocs/boardwalk/boardwalk.ansible.md
delete mode 100644 docs/source/apidocs/boardwalk/boardwalk.app_exceptions.md
delete mode 100644 docs/source/apidocs/boardwalk/boardwalk.cli.md
delete mode 100644 docs/source/apidocs/boardwalk/boardwalk.cli_catch.md
delete mode 100644 docs/source/apidocs/boardwalk/boardwalk.cli_init.md
delete mode 100644 docs/source/apidocs/boardwalk/boardwalk.cli_login.md
delete mode 100644 docs/source/apidocs/boardwalk/boardwalk.cli_run.md
delete mode 100644 docs/source/apidocs/boardwalk/boardwalk.cli_workspace.md
delete mode 100644 docs/source/apidocs/boardwalk/boardwalk.host.md
delete mode 100644 docs/source/apidocs/boardwalk/boardwalk.manifest.md
delete mode 100644 docs/source/apidocs/boardwalk/boardwalk.md
delete mode 100644 docs/source/apidocs/boardwalk/boardwalk.state.md
delete mode 100644 docs/source/apidocs/boardwalk/boardwalk.utils.md
delete mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.__main__.md
delete mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.broadcast.md
delete mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.cli.md
delete mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.md
delete mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.protocol.md
delete mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.server.md
delete mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.slack.md
delete mode 100644 docs/source/apidocs/boardwalkd/boardwalkd.state.md
delete mode 100644 docs/source/apidocs/index.rst
delete mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk.md
delete mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_catch.md
delete mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_check.md
delete mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_init.md
delete mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_login.md
delete mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_release.md
delete mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_run.md
delete mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_version.md
delete mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_workspace.md
delete mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_dump.md
delete mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_list.md
delete mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_reset.md
delete mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_show.md
delete mode 100644 docs/source/cli_helpdocs/boardwalk/boardwalk_workspace_use.md
delete mode 100644 docs/source/cli_helpdocs/boardwalkd/boardwalkd.md
delete mode 100644 docs/source/cli_helpdocs/boardwalkd/boardwalkd_serve.md
delete mode 100644 docs/source/cli_helpdocs/boardwalkd/boardwalkd_version.md
diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml
deleted file mode 100644
index b821c7d..0000000
--- a/.github/workflows/sphinx.yml
+++ /dev/null
@@ -1,85 +0,0 @@
-name: "Sphinx: Render docs"
-
-on:
- pull_request: {}
- push:
- branches:
- - main
- tags:
- - 'v*.*.*'
- workflow_dispatch: {}
-
-jobs:
- build:
- runs-on: ubuntu-latest
- concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- permissions:
- contents: write
- steps:
- #----------------------------------------------
- # check-out repo and set-up python
- #----------------------------------------------
- - name: Check out repository
- uses: actions/checkout@v4
-
- - name: Set up python
- id: setup-python
- uses: actions/setup-python@v5.3.0
- with:
- python-version: '3.11'
-
- #----------------------------------------------
- # Install and configure Poetry, or restore from cache
- #----------------------------------------------
- - name: Load cached Poetry installation
- id: cached-poetry
- uses: actions/cache@v4.1.2
- with:
- path: ~/.local # the path depends on the OS
- key: poetry-docs-0 # increment to reset cache
-
- - name: Install Poetry
- if: steps.cached-poetry.outputs.cache-hit != 'true'
- uses: snok/install-poetry@v1
- with:
- virtualenvs-create: true
- virtualenvs-in-project: true
- installer-parallel: true
-
- #----------------------------------------------
- # load cached venv if cache exists
- #----------------------------------------------
- - name: Load cached venv
- id: cached-poetry-dependencies
- uses: actions/cache@v4.1.2
- with:
- path: .venv
- key: boardwalk-docs-venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
-
- #----------------------------------------------
- # install your root project, if required
- #----------------------------------------------
- - name: Install project, with dependencies foor building documentation
- run: poetry install --no-interaction --with=docs --sync
-
- - name: Run 'make docs', to build documentation
- run: poetry run make docs
-
- - name: Upload artifacts
- uses: actions/upload-artifact@v4
- with:
- name: html-docs
- # Lower default retention -- the artifacts can be rebuilt from source, if needed
- retention-days: 14
- # Don't include the doctrees subdir; it's just pickled data Sphinx generates to make the HTML
- path: |
- docs/build/
- !docs/build/doctrees
-
- - name: Deploy documentation to the gh-pages branch for publishing
- uses: peaceiris/actions-gh-pages@v4
- if: github.ref == 'refs/heads/main'
- with:
- github_token: ${{ secrets.GITHUB_TOKEN }}
- publish_dir: docs/build/html
diff --git a/.gitignore b/.gitignore
index 12af726..0beaa84 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,5 @@ __pycache__/
*.egg-info/
build/
dist/
+# Contains files which are automatically generated by the documentation build process.
+docs/source/_autogenerated
diff --git a/Makefile b/Makefile
index 7ab6159..a7aa6b0 100644
--- a/Makefile
+++ b/Makefile
@@ -11,8 +11,9 @@ container:
clean:
set -o pipefail
- @echo '[.] Removing built packages ...'
+ @echo '[.] Removing built packages and documentation ...'
rm -rf dist/
+ make --directory=./docs/ clean
@echo '[.] Cleaning __pycache__ directories ...'
find . -type d -name '__pycache__' | xargs rm -rf
diff --git a/README.md b/README.md
index 883a86e..1e5d18e 100644
--- a/README.md
+++ b/README.md
@@ -23,6 +23,7 @@ updates.__ š„
# Table of Contents
- [Motivation & Goals](#motivation--goals)
+- [Installation](#installation)
- [Open-Source License](#open-source-license)
- [Contributing](#contributing)
- [Concepts](#concepts)
@@ -32,7 +33,6 @@ updates.__ š„
- [Local State](#local-state)
- [Remote State](#remote-state)
- [Usage](#usage)
- - [Installation](#installation)
- [The `Boardwalkfile.py`](#the-boardwalkfilepy)
- [Command-line Interface](#environment-variables)
- [`boardwalkd` Server](#boardwalkd-server)
@@ -223,7 +223,6 @@ Boardwalk.
# Usage
-(the-boardwalkfilepy)=
## The `Boardwalkfile.py`
Boardwalk is both a python library and command-line tool. The `boardwalk`
diff --git a/docs/Makefile b/docs/Makefile
index c99ffc2..2e53837 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -9,14 +9,28 @@ SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
+.PHONY: help Makefile
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
-.PHONY: help Makefile
+
+# Define some build targets manually, since we also have the auto-generated documentation to handle
+.PHONY: clean
+clean:
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+ -rm -r source/_autogenerated
+
+.PHONY: generate_cli_help_page_sources
+generate_cli_help_page_sources:
+ ./build_cli_help_pages.sh
+
+.PHONY: html
+html: generate_cli_help_page_sources
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
-livehtml:
+livehtml: generate_cli_help_page_sources
sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs/build_cli_help_pages.sh b/docs/build_cli_help_pages.sh
index 7ce4220..b5f3351 100755
--- a/docs/build_cli_help_pages.sh
+++ b/docs/build_cli_help_pages.sh
@@ -30,6 +30,11 @@ GET_PAGE_NAME() {
echo '`'"$1"'`'
}
+AUTO_GEN_DIR=source/_autogenerated/cli_helpdocs
+mkdir -p "$AUTO_GEN_DIR"
+mkdir -p "$AUTO_GEN_DIR/boardwalk"
+mkdir -p "$AUTO_GEN_DIR/boardwalkd"
+
for cmd in "${commands[@]}"; do
# Define regular expression patterns for 'boardwalk' and 'boardwalkd', so we
# can sort them into the correct subdirectories. Note that we need to use
@@ -47,8 +52,9 @@ for cmd in "${commands[@]}"; do
echo "[!] Skipping generation for $cmd; is this a boardwalk or boardwalkd command?"
continue
fi
- FILENAME=./source/cli_helpdocs/$SUBDIR/$(echo "$cmd" | tr ' ' _).md
- echo "[+] Generating doc page for $FILENAME"
+ FILENAME=$AUTO_GEN_DIR/$SUBDIR/$(echo "$cmd" | tr ' ' _).md
+ echo "[+] Generating doc page for $cmd"
+ touch "$FILENAME"
{
echo "# $(GET_PAGE_NAME "$cmd")"
echo ""
diff --git a/docs/source/apidocs/boardwalk/boardwalk.__main__.md b/docs/source/apidocs/boardwalk/boardwalk.__main__.md
deleted file mode 100644
index 2c9c9d2..0000000
--- a/docs/source/apidocs/boardwalk/boardwalk.__main__.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# {py:mod}`boardwalk.__main__`
-
-```{py:module} boardwalk.__main__
-```
-
-```{autodoc2-docstring} boardwalk.__main__
-:allowtitles:
-```
diff --git a/docs/source/apidocs/boardwalk/boardwalk.ansible.md b/docs/source/apidocs/boardwalk/boardwalk.ansible.md
deleted file mode 100644
index 32c2cd6..0000000
--- a/docs/source/apidocs/boardwalk/boardwalk.ansible.md
+++ /dev/null
@@ -1,144 +0,0 @@
-# {py:mod}`boardwalk.ansible`
-
-```{py:module} boardwalk.ansible
-```
-
-```{autodoc2-docstring} boardwalk.ansible
-:allowtitles:
-```
-
-## Module Contents
-
-### Functions
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`ansible_runner_cancel_callback `
- - ```{autodoc2-docstring} boardwalk.ansible.ansible_runner_cancel_callback
- :summary:
- ```
-* - {py:obj}`ansible_runner_errors_to_output `
- - ```{autodoc2-docstring} boardwalk.ansible.ansible_runner_errors_to_output
- :summary:
- ```
-* - {py:obj}`ansible_runner_run_tasks `
- - ```{autodoc2-docstring} boardwalk.ansible.ansible_runner_run_tasks
- :summary:
- ```
-* - {py:obj}`ansible_inventory `
- - ```{autodoc2-docstring} boardwalk.ansible.ansible_inventory
- :summary:
- ```
-````
-
-### API
-
-````{py:function} ansible_runner_cancel_callback(ws: boardwalk.manifest.Workspace)
-:canonical: boardwalk.ansible.ansible_runner_cancel_callback
-
-```{autodoc2-docstring} boardwalk.ansible.ansible_runner_cancel_callback
-```
-````
-
-````{py:function} ansible_runner_errors_to_output(runner: ansible_runner.Runner, include_msg: bool = True) -> str
-:canonical: boardwalk.ansible.ansible_runner_errors_to_output
-
-```{autodoc2-docstring} boardwalk.ansible.ansible_runner_errors_to_output
-```
-````
-
-````{py:function} ansible_runner_run_tasks(hosts: str, invocation_msg: str, job_type: boardwalk.manifest.JobTypes, tasks: boardwalk.ansible.AnsibleTasksType, become: bool = False, become_password: str | None = None, check: bool = False, gather_facts: bool = True, limit: str | None = None, quiet: bool = True, timeout: int | None = None, verbosity: int = 0, extra_vars: dict = {}) -> ansible_runner.Runner
-:canonical: boardwalk.ansible.ansible_runner_run_tasks
-
-```{autodoc2-docstring} boardwalk.ansible.ansible_runner_run_tasks
-```
-````
-
-````{py:function} ansible_inventory() -> boardwalk.ansible.InventoryData
-:canonical: boardwalk.ansible.ansible_inventory
-
-```{autodoc2-docstring} boardwalk.ansible.ansible_inventory
-```
-````
-
-````{py:exception} AnsibleRunnerBaseException(message: str, runner_msg: str, runner: ansible_runner.Runner)
-:canonical: boardwalk.ansible.AnsibleRunnerBaseException
-
-Bases: {py:obj}`Exception`
-
-```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerBaseException
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerBaseException.__init__
-```
-
-````
-
-````{py:exception} AnsibleRunnerGeneralError(message: str, runner_msg: str, runner: ansible_runner.Runner)
-:canonical: boardwalk.ansible.AnsibleRunnerGeneralError
-
-Bases: {py:obj}`boardwalk.ansible.AnsibleRunnerBaseException`
-
-```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerGeneralError
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerGeneralError.__init__
-```
-
-````
-
-````{py:exception} AnsibleRunError(message: str, runner_msg: str, runner: ansible_runner.Runner)
-:canonical: boardwalk.ansible.AnsibleRunError
-
-Bases: {py:obj}`boardwalk.ansible.AnsibleRunnerBaseException`
-
-```{autodoc2-docstring} boardwalk.ansible.AnsibleRunError
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.ansible.AnsibleRunError.__init__
-```
-
-````
-
-````{py:exception} AnsibleRunnerUnreachableHost(message: str, runner_msg: str, runner: ansible_runner.Runner)
-:canonical: boardwalk.ansible.AnsibleRunnerUnreachableHost
-
-Bases: {py:obj}`boardwalk.ansible.AnsibleRunnerBaseException`
-
-```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerUnreachableHost
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerUnreachableHost.__init__
-```
-
-````
-
-````{py:exception} AnsibleRunnerFailedHost(message: str, runner_msg: str, runner: ansible_runner.Runner)
-:canonical: boardwalk.ansible.AnsibleRunnerFailedHost
-
-Bases: {py:obj}`boardwalk.ansible.AnsibleRunnerBaseException`
-
-```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerFailedHost
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.ansible.AnsibleRunnerFailedHost.__init__
-```
-
-````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.app_exceptions.md b/docs/source/apidocs/boardwalk/boardwalk.app_exceptions.md
deleted file mode 100644
index 23c03eb..0000000
--- a/docs/source/apidocs/boardwalk/boardwalk.app_exceptions.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# {py:mod}`boardwalk.app_exceptions`
-
-```{py:module} boardwalk.app_exceptions
-```
-
-```{autodoc2-docstring} boardwalk.app_exceptions
-:allowtitles:
-```
-
-## Module Contents
-
-### API
-
-`````{py:exception} BoardwalkException(message: str)
-:canonical: boardwalk.app_exceptions.BoardwalkException
-
-Bases: {py:obj}`click.ClickException`
-
-```{autodoc2-docstring} boardwalk.app_exceptions.BoardwalkException
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.app_exceptions.BoardwalkException.__init__
-```
-
-````{py:method} show(file: typing.IO[str] | None = None) -> None
-:canonical: boardwalk.app_exceptions.BoardwalkException.show
-
-```{autodoc2-docstring} boardwalk.app_exceptions.BoardwalkException.show
-```
-
-````
-
-`````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.cli.md b/docs/source/apidocs/boardwalk/boardwalk.cli.md
deleted file mode 100644
index b693e4e..0000000
--- a/docs/source/apidocs/boardwalk/boardwalk.cli.md
+++ /dev/null
@@ -1,75 +0,0 @@
-# {py:mod}`boardwalk.cli`
-
-```{py:module} boardwalk.cli
-```
-
-```{autodoc2-docstring} boardwalk.cli
-:allowtitles:
-```
-
-## Module Contents
-
-### Functions
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`handle_signal `
- - ```{autodoc2-docstring} boardwalk.cli.handle_signal
- :summary:
- ```
-* - {py:obj}`cli `
- - ```{autodoc2-docstring} boardwalk.cli.cli
- :summary:
- ```
-* - {py:obj}`version `
- - ```{autodoc2-docstring} boardwalk.cli.version
- :summary:
- ```
-````
-
-### Data
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`terminating `
- - ```{autodoc2-docstring} boardwalk.cli.terminating
- :summary:
- ```
-````
-
-### API
-
-````{py:data} terminating
-:canonical: boardwalk.cli.terminating
-:value: >
- False
-
-```{autodoc2-docstring} boardwalk.cli.terminating
-```
-
-````
-
-````{py:function} handle_signal(sig: int, frame: typing.Any)
-:canonical: boardwalk.cli.handle_signal
-
-```{autodoc2-docstring} boardwalk.cli.handle_signal
-```
-````
-
-````{py:function} cli(ctx: click.Context, verbose: int)
-:canonical: boardwalk.cli.cli
-
-```{autodoc2-docstring} boardwalk.cli.cli
-```
-````
-
-````{py:function} version()
-:canonical: boardwalk.cli.version
-
-```{autodoc2-docstring} boardwalk.cli.version
-```
-````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.cli_catch.md b/docs/source/apidocs/boardwalk/boardwalk.cli_catch.md
deleted file mode 100644
index 0d7af96..0000000
--- a/docs/source/apidocs/boardwalk/boardwalk.cli_catch.md
+++ /dev/null
@@ -1,42 +0,0 @@
-# {py:mod}`boardwalk.cli_catch`
-
-```{py:module} boardwalk.cli_catch
-```
-
-```{autodoc2-docstring} boardwalk.cli_catch
-:allowtitles:
-```
-
-## Module Contents
-
-### Functions
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`catch `
- - ```{autodoc2-docstring} boardwalk.cli_catch.catch
- :summary:
- ```
-* - {py:obj}`release `
- - ```{autodoc2-docstring} boardwalk.cli_catch.release
- :summary:
- ```
-````
-
-### API
-
-````{py:function} catch()
-:canonical: boardwalk.cli_catch.catch
-
-```{autodoc2-docstring} boardwalk.cli_catch.catch
-```
-````
-
-````{py:function} release()
-:canonical: boardwalk.cli_catch.release
-
-```{autodoc2-docstring} boardwalk.cli_catch.release
-```
-````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.cli_init.md b/docs/source/apidocs/boardwalk/boardwalk.cli_init.md
deleted file mode 100644
index 2bc9fb0..0000000
--- a/docs/source/apidocs/boardwalk/boardwalk.cli_init.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# {py:mod}`boardwalk.cli_init`
-
-```{py:module} boardwalk.cli_init
-```
-
-```{autodoc2-docstring} boardwalk.cli_init
-:allowtitles:
-```
-
-## Module Contents
-
-### Functions
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`init `
- - ```{autodoc2-docstring} boardwalk.cli_init.init
- :summary:
- ```
-* - {py:obj}`add_gathered_facts_to_state `
- - ```{autodoc2-docstring} boardwalk.cli_init.add_gathered_facts_to_state
- :summary:
- ```
-* - {py:obj}`handle_failed_init_hosts `
- - ```{autodoc2-docstring} boardwalk.cli_init.handle_failed_init_hosts
- :summary:
- ```
-````
-
-### API
-
-````{py:function} init(ctx: click.Context, limit: str, retry: bool)
-:canonical: boardwalk.cli_init.init
-
-```{autodoc2-docstring} boardwalk.cli_init.init
-```
-````
-
-````{py:function} add_gathered_facts_to_state(event: ansible_runner.RunnerEvent, ws: boardwalk.manifest.Workspace)
-:canonical: boardwalk.cli_init.add_gathered_facts_to_state
-
-```{autodoc2-docstring} boardwalk.cli_init.add_gathered_facts_to_state
-```
-````
-
-````{py:function} handle_failed_init_hosts(event: ansible_runner.RunnerEvent, retry_file_path: pathlib.Path)
-:canonical: boardwalk.cli_init.handle_failed_init_hosts
-
-```{autodoc2-docstring} boardwalk.cli_init.handle_failed_init_hosts
-```
-````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.cli_login.md b/docs/source/apidocs/boardwalk/boardwalk.cli_login.md
deleted file mode 100644
index 906cc41..0000000
--- a/docs/source/apidocs/boardwalk/boardwalk.cli_login.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# {py:mod}`boardwalk.cli_login`
-
-```{py:module} boardwalk.cli_login
-```
-
-```{autodoc2-docstring} boardwalk.cli_login
-:allowtitles:
-```
-
-## Module Contents
-
-### Functions
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`login `
- - ```{autodoc2-docstring} boardwalk.cli_login.login
- :summary:
- ```
-````
-
-### API
-
-````{py:function} login()
-:canonical: boardwalk.cli_login.login
-
-```{autodoc2-docstring} boardwalk.cli_login.login
-```
-````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.cli_run.md b/docs/source/apidocs/boardwalk/boardwalk.cli_run.md
deleted file mode 100644
index 488349e..0000000
--- a/docs/source/apidocs/boardwalk/boardwalk.cli_run.md
+++ /dev/null
@@ -1,289 +0,0 @@
-# {py:mod}`boardwalk.cli_run`
-
-```{py:module} boardwalk.cli_run
-```
-
-```{autodoc2-docstring} boardwalk.cli_run
-:allowtitles:
-```
-
-## Module Contents
-
-### Functions
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`run `
- - ```{autodoc2-docstring} boardwalk.cli_run.run
- :summary:
- ```
-* - {py:obj}`check `
- - ```{autodoc2-docstring} boardwalk.cli_run.check
- :summary:
- ```
-* - {py:obj}`run_workflow `
- - ```{autodoc2-docstring} boardwalk.cli_run.run_workflow
- :summary:
- ```
-* - {py:obj}`run_failure_mode_handler `
- - ```{autodoc2-docstring} boardwalk.cli_run.run_failure_mode_handler
- :summary:
- ```
-* - {py:obj}`filter_hosts_by_limit `
- - ```{autodoc2-docstring} boardwalk.cli_run.filter_hosts_by_limit
- :summary:
- ```
-* - {py:obj}`sort_host_list `
- - ```{autodoc2-docstring} boardwalk.cli_run.sort_host_list
- :summary:
- ```
-* - {py:obj}`check_host_preconditions_locally `
- - ```{autodoc2-docstring} boardwalk.cli_run.check_host_preconditions_locally
- :summary:
- ```
-* - {py:obj}`handle_workflow_catch `
- - ```{autodoc2-docstring} boardwalk.cli_run.handle_workflow_catch
- :summary:
- ```
-* - {py:obj}`lock_remote_host `
- - ```{autodoc2-docstring} boardwalk.cli_run.lock_remote_host
- :summary:
- ```
-* - {py:obj}`bootstrap_with_server `
- - ```{autodoc2-docstring} boardwalk.cli_run.bootstrap_with_server
- :summary:
- ```
-* - {py:obj}`update_host_facts_in_local_state `
- - ```{autodoc2-docstring} boardwalk.cli_run.update_host_facts_in_local_state
- :summary:
- ```
-* - {py:obj}`directly_confirm_host_preconditions `
- - ```{autodoc2-docstring} boardwalk.cli_run.directly_confirm_host_preconditions
- :summary:
- ```
-* - {py:obj}`execute_workflow_jobs `
- - ```{autodoc2-docstring} boardwalk.cli_run.execute_workflow_jobs
- :summary:
- ```
-* - {py:obj}`execute_host_workflow `
- - ```{autodoc2-docstring} boardwalk.cli_run.execute_host_workflow
- :summary:
- ```
-````
-
-### Data
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`become_password `
- - ```{autodoc2-docstring} boardwalk.cli_run.become_password
- :summary:
- ```
-* - {py:obj}`boardwalkd_client `
- - ```{autodoc2-docstring} boardwalk.cli_run.boardwalkd_client
- :summary:
- ```
-* - {py:obj}`boardwalkd_send_broadcasts `
- - ```{autodoc2-docstring} boardwalk.cli_run.boardwalkd_send_broadcasts
- :summary:
- ```
-* - {py:obj}`_check_mode `
- - ```{autodoc2-docstring} boardwalk.cli_run._check_mode
- :summary:
- ```
-* - {py:obj}`_stomp_locks `
- - ```{autodoc2-docstring} boardwalk.cli_run._stomp_locks
- :summary:
- ```
-````
-
-### API
-
-````{py:data} become_password
-:canonical: boardwalk.cli_run.become_password
-:type: str | None
-:value: >
- None
-
-```{autodoc2-docstring} boardwalk.cli_run.become_password
-```
-
-````
-
-````{py:data} boardwalkd_client
-:canonical: boardwalk.cli_run.boardwalkd_client
-:type: boardwalkd.protocol.WorkspaceClient | None
-:value: >
- None
-
-```{autodoc2-docstring} boardwalk.cli_run.boardwalkd_client
-```
-
-````
-
-````{py:data} boardwalkd_send_broadcasts
-:canonical: boardwalk.cli_run.boardwalkd_send_broadcasts
-:type: bool
-:value: >
- False
-
-```{autodoc2-docstring} boardwalk.cli_run.boardwalkd_send_broadcasts
-```
-
-````
-
-````{py:data} _check_mode
-:canonical: boardwalk.cli_run._check_mode
-:type: bool
-:value: >
- True
-
-```{autodoc2-docstring} boardwalk.cli_run._check_mode
-```
-
-````
-
-````{py:data} _stomp_locks
-:canonical: boardwalk.cli_run._stomp_locks
-:type: bool
-:value: >
- False
-
-```{autodoc2-docstring} boardwalk.cli_run._stomp_locks
-```
-
-````
-
-````{py:function} run(ctx: click.Context, ask_become_pass: bool, check: bool, limit: str, server_connect: bool, sort_hosts: str, stomp_locks: bool)
-:canonical: boardwalk.cli_run.run
-
-```{autodoc2-docstring} boardwalk.cli_run.run
-```
-````
-
-````{py:function} check(ctx: click.Context, ask_become_pass: bool, limit: str, server_connect: bool, sort_hosts: str)
-:canonical: boardwalk.cli_run.check
-
-```{autodoc2-docstring} boardwalk.cli_run.check
-```
-````
-
-````{py:function} run_workflow(hosts: list[boardwalk.host.Host], inventory_vars: boardwalk.ansible.HostVarsType, workspace: boardwalk.manifest.Workspace, verbosity: int)
-:canonical: boardwalk.cli_run.run_workflow
-
-```{autodoc2-docstring} boardwalk.cli_run.run_workflow
-```
-````
-
-````{py:function} run_failure_mode_handler(exception: Exception, hostname: str, workspace: boardwalk.manifest.Workspace)
-:canonical: boardwalk.cli_run.run_failure_mode_handler
-
-```{autodoc2-docstring} boardwalk.cli_run.run_failure_mode_handler
-```
-````
-
-````{py:function} filter_hosts_by_limit(workspace: boardwalk.manifest.Workspace, hosts: collections.abc.ItemsView[str, boardwalk.host.Host], pattern: str) -> list[boardwalk.host.Host]
-:canonical: boardwalk.cli_run.filter_hosts_by_limit
-
-```{autodoc2-docstring} boardwalk.cli_run.filter_hosts_by_limit
-```
-````
-
-````{py:function} sort_host_list(hosts: list[boardwalk.host.Host], sort_method: str)
-:canonical: boardwalk.cli_run.sort_host_list
-
-```{autodoc2-docstring} boardwalk.cli_run.sort_host_list
-```
-````
-
-````{py:function} check_host_preconditions_locally(hosts: list[boardwalk.host.Host], inventory_vars: boardwalk.ansible.HostVarsType, workspace: boardwalk.manifest.Workspace) -> list[boardwalk.host.Host]
-:canonical: boardwalk.cli_run.check_host_preconditions_locally
-
-```{autodoc2-docstring} boardwalk.cli_run.check_host_preconditions_locally
-```
-````
-
-````{py:function} handle_workflow_catch(workspace: boardwalk.manifest.Workspace, hostname: str)
-:canonical: boardwalk.cli_run.handle_workflow_catch
-
-```{autodoc2-docstring} boardwalk.cli_run.handle_workflow_catch
-```
-````
-
-````{py:function} lock_remote_host(host: boardwalk.host.Host)
-:canonical: boardwalk.cli_run.lock_remote_host
-
-```{autodoc2-docstring} boardwalk.cli_run.lock_remote_host
-```
-````
-
-````{py:function} bootstrap_with_server(workspace: boardwalk.manifest.Workspace, ctx: click.Context)
-:canonical: boardwalk.cli_run.bootstrap_with_server
-
-```{autodoc2-docstring} boardwalk.cli_run.bootstrap_with_server
-```
-````
-
-````{py:function} update_host_facts_in_local_state(host: boardwalk.host.Host, workspace: boardwalk.manifest.Workspace)
-:canonical: boardwalk.cli_run.update_host_facts_in_local_state
-
-```{autodoc2-docstring} boardwalk.cli_run.update_host_facts_in_local_state
-```
-````
-
-````{py:function} directly_confirm_host_preconditions(host: boardwalk.host.Host, inventory_vars: boardwalk.ansible.InventoryHostVars, workspace: boardwalk.manifest.Workspace) -> bool
-:canonical: boardwalk.cli_run.directly_confirm_host_preconditions
-
-```{autodoc2-docstring} boardwalk.cli_run.directly_confirm_host_preconditions
-```
-````
-
-````{py:function} execute_workflow_jobs(host: boardwalk.host.Host, workspace: boardwalk.manifest.Workspace, job_kind: str, verbosity: int)
-:canonical: boardwalk.cli_run.execute_workflow_jobs
-
-```{autodoc2-docstring} boardwalk.cli_run.execute_workflow_jobs
-```
-````
-
-````{py:function} execute_host_workflow(host: boardwalk.host.Host, workspace: boardwalk.manifest.Workspace, verbosity: int)
-:canonical: boardwalk.cli_run.execute_host_workflow
-
-```{autodoc2-docstring} boardwalk.cli_run.execute_host_workflow
-```
-````
-
-````{py:exception} NoHostsMatched()
-:canonical: boardwalk.cli_run.NoHostsMatched
-
-Bases: {py:obj}`Exception`
-
-```{autodoc2-docstring} boardwalk.cli_run.NoHostsMatched
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.cli_run.NoHostsMatched.__init__
-```
-
-````
-
-````{py:exception} HostPreConditionsUnmet()
-:canonical: boardwalk.cli_run.HostPreConditionsUnmet
-
-Bases: {py:obj}`Exception`
-
-```{autodoc2-docstring} boardwalk.cli_run.HostPreConditionsUnmet
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.cli_run.HostPreConditionsUnmet.__init__
-```
-
-````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.cli_workspace.md b/docs/source/apidocs/boardwalk/boardwalk.cli_workspace.md
deleted file mode 100644
index 0969251..0000000
--- a/docs/source/apidocs/boardwalk/boardwalk.cli_workspace.md
+++ /dev/null
@@ -1,97 +0,0 @@
-# {py:mod}`boardwalk.cli_workspace`
-
-```{py:module} boardwalk.cli_workspace
-```
-
-```{autodoc2-docstring} boardwalk.cli_workspace
-:allowtitles:
-```
-
-## Module Contents
-
-### Functions
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`workspace `
- - ```{autodoc2-docstring} boardwalk.cli_workspace.workspace
- :summary:
- ```
-* - {py:obj}`workspace_show `
- - ```{autodoc2-docstring} boardwalk.cli_workspace.workspace_show
- :summary:
- ```
-* - {py:obj}`workspace_use_completion `
- - ```{autodoc2-docstring} boardwalk.cli_workspace.workspace_use_completion
- :summary:
- ```
-* - {py:obj}`workspace_use `
- - ```{autodoc2-docstring} boardwalk.cli_workspace.workspace_use
- :summary:
- ```
-* - {py:obj}`workspace_list `
- - ```{autodoc2-docstring} boardwalk.cli_workspace.workspace_list
- :summary:
- ```
-* - {py:obj}`workspace_reset `
- - ```{autodoc2-docstring} boardwalk.cli_workspace.workspace_reset
- :summary:
- ```
-* - {py:obj}`workspace_dump `
- - ```{autodoc2-docstring} boardwalk.cli_workspace.workspace_dump
- :summary:
- ```
-````
-
-### API
-
-````{py:function} workspace()
-:canonical: boardwalk.cli_workspace.workspace
-
-```{autodoc2-docstring} boardwalk.cli_workspace.workspace
-```
-````
-
-````{py:function} workspace_show()
-:canonical: boardwalk.cli_workspace.workspace_show
-
-```{autodoc2-docstring} boardwalk.cli_workspace.workspace_show
-```
-````
-
-````{py:function} workspace_use_completion(ctx, param, incomplete)
-:canonical: boardwalk.cli_workspace.workspace_use_completion
-
-```{autodoc2-docstring} boardwalk.cli_workspace.workspace_use_completion
-```
-````
-
-````{py:function} workspace_use(workspace_name: str)
-:canonical: boardwalk.cli_workspace.workspace_use
-
-```{autodoc2-docstring} boardwalk.cli_workspace.workspace_use
-```
-````
-
-````{py:function} workspace_list()
-:canonical: boardwalk.cli_workspace.workspace_list
-
-```{autodoc2-docstring} boardwalk.cli_workspace.workspace_list
-```
-````
-
-````{py:function} workspace_reset()
-:canonical: boardwalk.cli_workspace.workspace_reset
-
-```{autodoc2-docstring} boardwalk.cli_workspace.workspace_reset
-```
-````
-
-````{py:function} workspace_dump()
-:canonical: boardwalk.cli_workspace.workspace_dump
-
-```{autodoc2-docstring} boardwalk.cli_workspace.workspace_dump
-```
-````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.host.md b/docs/source/apidocs/boardwalk/boardwalk.host.md
deleted file mode 100644
index 1d72ed0..0000000
--- a/docs/source/apidocs/boardwalk/boardwalk.host.md
+++ /dev/null
@@ -1,211 +0,0 @@
-# {py:mod}`boardwalk.host`
-
-```{py:module} boardwalk.host
-```
-
-```{autodoc2-docstring} boardwalk.host
-:allowtitles:
-```
-
-## Module Contents
-
-### Classes
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`Host `
- - ```{autodoc2-docstring} boardwalk.host.Host
- :summary:
- ```
-````
-
-### API
-
-`````{py:class} Host(/, **data: typing.Any)
-:canonical: boardwalk.host.Host
-
-Bases: {py:obj}`pydantic.BaseModel`
-
-```{autodoc2-docstring} boardwalk.host.Host
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.host.Host.__init__
-```
-
-````{py:attribute} ansible_facts
-:canonical: boardwalk.host.Host.ansible_facts
-:type: dict[str, typing.Any]
-:value: >
- None
-
-```{autodoc2-docstring} boardwalk.host.Host.ansible_facts
-```
-
-````
-
-````{py:attribute} name
-:canonical: boardwalk.host.Host.name
-:type: str
-:value: >
- None
-
-```{autodoc2-docstring} boardwalk.host.Host.name
-```
-
-````
-
-````{py:attribute} meta
-:canonical: boardwalk.host.Host.meta
-:type: dict[str, str | int | bool]
-:value: >
- None
-
-```{autodoc2-docstring} boardwalk.host.Host.meta
-```
-
-````
-
-````{py:attribute} remote_mutex_path
-:canonical: boardwalk.host.Host.remote_mutex_path
-:type: str
-:value: >
- '/opt/boardwalk.mutex'
-
-```{autodoc2-docstring} boardwalk.host.Host.remote_mutex_path
-```
-
-````
-
-````{py:attribute} remote_alert_msg
-:canonical: boardwalk.host.Host.remote_alert_msg
-:type: str
-:value: >
- 'ALERT: Boardwalk is running a workflow against this host. Services may be interrupted'
-
-```{autodoc2-docstring} boardwalk.host.Host.remote_alert_msg
-```
-
-````
-
-````{py:attribute} remote_alert_string_formatted
-:canonical: boardwalk.host.Host.remote_alert_string_formatted
-:type: str
-:value: >
- None
-
-```{autodoc2-docstring} boardwalk.host.Host.remote_alert_string_formatted
-```
-
-````
-
-````{py:attribute} remote_alert_motd
-:canonical: boardwalk.host.Host.remote_alert_motd
-:type: str
-:value: >
- None
-
-```{autodoc2-docstring} boardwalk.host.Host.remote_alert_motd
-```
-
-````
-
-````{py:attribute} remote_alert_motd_path
-:canonical: boardwalk.host.Host.remote_alert_motd_path
-:type: str
-:value: >
- '/etc/update-motd.d/99-boardwalk-alert'
-
-```{autodoc2-docstring} boardwalk.host.Host.remote_alert_motd_path
-```
-
-````
-
-````{py:attribute} remote_alert_wall_cmd
-:canonical: boardwalk.host.Host.remote_alert_wall_cmd
-:type: str
-:value: >
- None
-
-```{autodoc2-docstring} boardwalk.host.Host.remote_alert_wall_cmd
-```
-
-````
-
-````{py:method} ansible_run(invocation_msg: str, tasks: boardwalk.ansible.AnsibleTasksType, job_type: boardwalk.manifest.JobTypes, verbosity: int = 0, become: bool = False, become_password: str | None = None, check: bool = False, gather_facts: bool = True, quiet: bool = True, extra_vars: dict = {}) -> ansible_runner.Runner
-:canonical: boardwalk.host.Host.ansible_run
-
-```{autodoc2-docstring} boardwalk.host.Host.ansible_run
-```
-
-````
-
-````{py:method} is_locked() -> str | bool
-:canonical: boardwalk.host.Host.is_locked
-
-```{autodoc2-docstring} boardwalk.host.Host.is_locked
-```
-
-````
-
-````{py:method} lock(become_password: str | None = None, check: bool = False, stomp_existing_locks: bool = False)
-:canonical: boardwalk.host.Host.lock
-
-```{autodoc2-docstring} boardwalk.host.Host.lock
-```
-
-````
-
-````{py:method} release(become_password: str | None = None, check: bool = False) -> None
-:canonical: boardwalk.host.Host.release
-
-```{autodoc2-docstring} boardwalk.host.Host.release
-```
-
-````
-
-````{py:method} gather_facts() -> dict[str, typing.Any]
-:canonical: boardwalk.host.Host.gather_facts
-
-```{autodoc2-docstring} boardwalk.host.Host.gather_facts
-```
-
-````
-
-````{py:method} get_remote_state() -> boardwalk.state.RemoteStateModel
-:canonical: boardwalk.host.Host.get_remote_state
-
-```{autodoc2-docstring} boardwalk.host.Host.get_remote_state
-```
-
-````
-
-````{py:method} set_remote_state(remote_state_obj: boardwalk.state.RemoteStateModel, become_password: str | None = None, check: bool = False)
-:canonical: boardwalk.host.Host.set_remote_state
-
-```{autodoc2-docstring} boardwalk.host.Host.set_remote_state
-```
-
-````
-
-`````
-
-````{py:exception} RemoteHostLocked(message: str)
-:canonical: boardwalk.host.RemoteHostLocked
-
-Bases: {py:obj}`boardwalk.app_exceptions.BoardwalkException`
-
-```{autodoc2-docstring} boardwalk.host.RemoteHostLocked
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.host.RemoteHostLocked.__init__
-```
-
-````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.manifest.md b/docs/source/apidocs/boardwalk/boardwalk.manifest.md
deleted file mode 100644
index dc4f498..0000000
--- a/docs/source/apidocs/boardwalk/boardwalk.manifest.md
+++ /dev/null
@@ -1,610 +0,0 @@
-# {py:mod}`boardwalk.manifest`
-
-```{py:module} boardwalk.manifest
-```
-
-```{autodoc2-docstring} boardwalk.manifest
-:allowtitles:
-```
-
-## Module Contents
-
-### Classes
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`JobTypes `
- -
-* - {py:obj}`BaseJob `
- - ```{autodoc2-docstring} boardwalk.manifest.BaseJob
- :summary:
- ```
-* - {py:obj}`TaskJob `
- - ```{autodoc2-docstring} boardwalk.manifest.TaskJob
- :summary:
- ```
-* - {py:obj}`Job `
- - ```{autodoc2-docstring} boardwalk.manifest.Job
- :summary:
- ```
-* - {py:obj}`PlaybookJob `
- - ```{autodoc2-docstring} boardwalk.manifest.PlaybookJob
- :summary:
- ```
-* - {py:obj}`WorkflowConfig `
- - ```{autodoc2-docstring} boardwalk.manifest.WorkflowConfig
- :summary:
- ```
-* - {py:obj}`Workflow `
- - ```{autodoc2-docstring} boardwalk.manifest.Workflow
- :summary:
- ```
-* - {py:obj}`WorkspaceConfig `
- - ```{autodoc2-docstring} boardwalk.manifest.WorkspaceConfig
- :summary:
- ```
-* - {py:obj}`Workspace `
- - ```{autodoc2-docstring} boardwalk.manifest.Workspace
- :summary:
- ```
-````
-
-### Functions
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`get_ws `
- - ```{autodoc2-docstring} boardwalk.manifest.get_ws
- :summary:
- ```
-* - {py:obj}`get_boardwalkd_url `
- - ```{autodoc2-docstring} boardwalk.manifest.get_boardwalkd_url
- :summary:
- ```
-* - {py:obj}`path `
- - ```{autodoc2-docstring} boardwalk.manifest.path
- :summary:
- ```
-````
-
-### Data
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`workspaces_dir `
- - ```{autodoc2-docstring} boardwalk.manifest.workspaces_dir
- :summary:
- ```
-* - {py:obj}`active_workspace_file `
- - ```{autodoc2-docstring} boardwalk.manifest.active_workspace_file
- :summary:
- ```
-````
-
-### API
-
-````{py:data} workspaces_dir
-:canonical: boardwalk.manifest.workspaces_dir
-:value: >
- 'joinpath(...)'
-
-```{autodoc2-docstring} boardwalk.manifest.workspaces_dir
-```
-
-````
-
-````{py:data} active_workspace_file
-:canonical: boardwalk.manifest.active_workspace_file
-:value: >
- 'joinpath(...)'
-
-```{autodoc2-docstring} boardwalk.manifest.active_workspace_file
-```
-
-````
-
-````{py:exception} DuplicateManifestClass()
-:canonical: boardwalk.manifest.DuplicateManifestClass
-
-Bases: {py:obj}`Exception`
-
-```{autodoc2-docstring} boardwalk.manifest.DuplicateManifestClass
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.manifest.DuplicateManifestClass.__init__
-```
-
-````
-
-````{py:exception} ManifestNotFound()
-:canonical: boardwalk.manifest.ManifestNotFound
-
-Bases: {py:obj}`Exception`
-
-```{autodoc2-docstring} boardwalk.manifest.ManifestNotFound
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.manifest.ManifestNotFound.__init__
-```
-
-````
-
-`````{py:exception} NoActiveWorkspace()
-:canonical: boardwalk.manifest.NoActiveWorkspace
-
-Bases: {py:obj}`Exception`
-
-```{autodoc2-docstring} boardwalk.manifest.NoActiveWorkspace
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.manifest.NoActiveWorkspace.__init__
-```
-
-````{py:attribute} message
-:canonical: boardwalk.manifest.NoActiveWorkspace.message
-:value: >
- 'No workspace selected. Use `boardwalk workspace list` to list workspaces and `boardwalk workspace us...'
-
-```{autodoc2-docstring} boardwalk.manifest.NoActiveWorkspace.message
-```
-
-````
-
-`````
-
-````{py:exception} WorkspaceNotFound()
-:canonical: boardwalk.manifest.WorkspaceNotFound
-
-Bases: {py:obj}`Exception`
-
-```{autodoc2-docstring} boardwalk.manifest.WorkspaceNotFound
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.manifest.WorkspaceNotFound.__init__
-```
-
-````
-
-````{py:function} get_ws() -> Workspace
-:canonical: boardwalk.manifest.get_ws
-
-```{autodoc2-docstring} boardwalk.manifest.get_ws
-```
-````
-
-````{py:function} get_boardwalkd_url() -> str
-:canonical: boardwalk.manifest.get_boardwalkd_url
-
-```{autodoc2-docstring} boardwalk.manifest.get_boardwalkd_url
-```
-````
-
-`````{py:class} JobTypes(*args, **kwds)
-:canonical: boardwalk.manifest.JobTypes
-
-Bases: {py:obj}`enum.Enum`
-
-````{py:attribute} TASK
-:canonical: boardwalk.manifest.JobTypes.TASK
-:value: >
- 1
-
-```{autodoc2-docstring} boardwalk.manifest.JobTypes.TASK
-```
-
-````
-
-````{py:attribute} PLAYBOOK
-:canonical: boardwalk.manifest.JobTypes.PLAYBOOK
-:value: >
- 2
-
-```{autodoc2-docstring} boardwalk.manifest.JobTypes.PLAYBOOK
-```
-
-````
-
-`````
-
-`````{py:class} BaseJob(options: dict[str, typing.Any] = dict())
-:canonical: boardwalk.manifest.BaseJob
-
-```{autodoc2-docstring} boardwalk.manifest.BaseJob
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.manifest.BaseJob.__init__
-```
-
-````{py:attribute} options
-:canonical: boardwalk.manifest.BaseJob.options
-:value: >
- None
-
-```{autodoc2-docstring} boardwalk.manifest.BaseJob.options
-```
-
-````
-
-````{py:method} required_options() -> tuple[str]
-:canonical: boardwalk.manifest.BaseJob.required_options
-
-```{autodoc2-docstring} boardwalk.manifest.BaseJob.required_options
-```
-
-````
-
-````{py:method} preconditions(facts: boardwalk.ansible.AnsibleFacts, inventory_vars: boardwalk.ansible.InventoryHostVars) -> bool
-:canonical: boardwalk.manifest.BaseJob.preconditions
-
-```{autodoc2-docstring} boardwalk.manifest.BaseJob.preconditions
-```
-
-````
-
-````{py:method} _required_options() -> tuple[str]
-:canonical: boardwalk.manifest.BaseJob._required_options
-
-```{autodoc2-docstring} boardwalk.manifest.BaseJob._required_options
-```
-
-````
-
-````{py:method} _check_options(options: dict[str, typing.Any])
-:canonical: boardwalk.manifest.BaseJob._check_options
-
-```{autodoc2-docstring} boardwalk.manifest.BaseJob._check_options
-```
-
-````
-
-`````
-
-`````{py:class} TaskJob(options: dict[str, typing.Any] = dict())
-:canonical: boardwalk.manifest.TaskJob
-
-Bases: {py:obj}`boardwalk.manifest.BaseJob`
-
-```{autodoc2-docstring} boardwalk.manifest.TaskJob
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.manifest.TaskJob.__init__
-```
-
-````{py:method} tasks() -> boardwalk.ansible.AnsibleTasksType
-:canonical: boardwalk.manifest.TaskJob.tasks
-
-```{autodoc2-docstring} boardwalk.manifest.TaskJob.tasks
-```
-
-````
-
-`````
-
-````{py:class} Job(options: dict[str, typing.Any] = dict())
-:canonical: boardwalk.manifest.Job
-
-Bases: {py:obj}`boardwalk.manifest.TaskJob`
-
-```{autodoc2-docstring} boardwalk.manifest.Job
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.manifest.Job.__init__
-```
-
-````
-
-`````{py:class} PlaybookJob(options: dict[str, typing.Any] = dict())
-:canonical: boardwalk.manifest.PlaybookJob
-
-Bases: {py:obj}`boardwalk.manifest.BaseJob`
-
-```{autodoc2-docstring} boardwalk.manifest.PlaybookJob
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.manifest.PlaybookJob.__init__
-```
-
-````{py:method} tasks() -> boardwalk.ansible.AnsibleTasksType
-:canonical: boardwalk.manifest.PlaybookJob.tasks
-
-```{autodoc2-docstring} boardwalk.manifest.PlaybookJob.tasks
-```
-
-````
-
-````{py:method} playbooks() -> boardwalk.ansible.AnsibleTasksType
-:canonical: boardwalk.manifest.PlaybookJob.playbooks
-
-```{autodoc2-docstring} boardwalk.manifest.PlaybookJob.playbooks
-```
-
-````
-
-`````
-
-````{py:class} WorkflowConfig(always_retry_failed_hosts: bool = True)
-:canonical: boardwalk.manifest.WorkflowConfig
-
-```{autodoc2-docstring} boardwalk.manifest.WorkflowConfig
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.manifest.WorkflowConfig.__init__
-```
-
-````
-
-`````{py:class} Workflow()
-:canonical: boardwalk.manifest.Workflow
-
-Bases: {py:obj}`abc.ABC`
-
-```{autodoc2-docstring} boardwalk.manifest.Workflow
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.manifest.Workflow.__init__
-```
-
-````{py:method} config() -> boardwalk.manifest.WorkflowConfig
-:canonical: boardwalk.manifest.Workflow.config
-
-```{autodoc2-docstring} boardwalk.manifest.Workflow.config
-```
-
-````
-
-````{py:method} jobs()
-:canonical: boardwalk.manifest.Workflow.jobs
-:abstractmethod:
-
-```{autodoc2-docstring} boardwalk.manifest.Workflow.jobs
-```
-
-````
-
-````{py:method} exit_jobs() -> boardwalk.manifest.TaskJob | boardwalk.manifest.PlaybookJob | tuple[boardwalk.manifest.TaskJob | boardwalk.manifest.PlaybookJob, ...]
-:canonical: boardwalk.manifest.Workflow.exit_jobs
-
-```{autodoc2-docstring} boardwalk.manifest.Workflow.exit_jobs
-```
-
-````
-
-`````
-
-`````{py:class} WorkspaceConfig(host_pattern: str, workflow: boardwalk.manifest.Workflow, default_sort_order: str = 'shuffle', require_limit: bool = False)
-:canonical: boardwalk.manifest.WorkspaceConfig
-
-```{autodoc2-docstring} boardwalk.manifest.WorkspaceConfig
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.manifest.WorkspaceConfig.__init__
-```
-
-````{py:attribute} valid_sort_orders
-:canonical: boardwalk.manifest.WorkspaceConfig.valid_sort_orders
-:value: >
- ['ascending', 'descending', 'shuffle']
-
-```{autodoc2-docstring} boardwalk.manifest.WorkspaceConfig.valid_sort_orders
-```
-
-````
-
-````{py:property} default_sort_order
-:canonical: boardwalk.manifest.WorkspaceConfig.default_sort_order
-:type: str
-
-```{autodoc2-docstring} boardwalk.manifest.WorkspaceConfig.default_sort_order
-```
-
-````
-
-````{py:method} _is_valid_sort_order(value: str)
-:canonical: boardwalk.manifest.WorkspaceConfig._is_valid_sort_order
-
-```{autodoc2-docstring} boardwalk.manifest.WorkspaceConfig._is_valid_sort_order
-```
-
-````
-
-`````
-
-`````{py:class} Workspace()
-:canonical: boardwalk.manifest.Workspace
-
-Bases: {py:obj}`abc.ABC`
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace.__init__
-```
-
-````{py:attribute} _initialized
-:canonical: boardwalk.manifest.Workspace._initialized
-:type: bool
-:value: >
- False
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace._initialized
-```
-
-````
-
-````{py:attribute} _instance
-:canonical: boardwalk.manifest.Workspace._instance
-:type: boardwalk.manifest.Workspace | None
-:value: >
- None
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace._instance
-```
-
-````
-
-````{py:method} __new__()
-:canonical: boardwalk.manifest.Workspace.__new__
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace.__new__
-```
-
-````
-
-````{py:method} assert_host_pattern_unchanged() -> None
-:canonical: boardwalk.manifest.Workspace.assert_host_pattern_unchanged
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace.assert_host_pattern_unchanged
-```
-
-````
-
-````{py:method} config() -> boardwalk.manifest.WorkspaceConfig
-:canonical: boardwalk.manifest.Workspace.config
-:abstractmethod:
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace.config
-```
-
-````
-
-````{py:method} flush()
-:canonical: boardwalk.manifest.Workspace.flush
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace.flush
-```
-
-````
-
-````{py:method} reset()
-:canonical: boardwalk.manifest.Workspace.reset
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace.reset
-```
-
-````
-
-````{py:method} mutex()
-:canonical: boardwalk.manifest.Workspace.mutex
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace.mutex
-```
-
-````
-
-````{py:method} has_mutex()
-:canonical: boardwalk.manifest.Workspace.has_mutex
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace.has_mutex
-```
-
-````
-
-````{py:method} unmutex()
-:canonical: boardwalk.manifest.Workspace.unmutex
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace.unmutex
-```
-
-````
-
-````{py:method} catch()
-:canonical: boardwalk.manifest.Workspace.catch
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace.catch
-```
-
-````
-
-````{py:method} caught()
-:canonical: boardwalk.manifest.Workspace.caught
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace.caught
-```
-
-````
-
-````{py:method} release()
-:canonical: boardwalk.manifest.Workspace.release
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace.release
-```
-
-````
-
-````{py:method} use(name: str)
-:canonical: boardwalk.manifest.Workspace.use
-:staticmethod:
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace.use
-```
-
-````
-
-````{py:method} exists(name: str) -> bool
-:canonical: boardwalk.manifest.Workspace.exists
-:staticmethod:
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace.exists
-```
-
-````
-
-````{py:method} fetch_subclass(name: str) -> collections.abc.Callable[..., boardwalk.manifest.Workspace]
-:canonical: boardwalk.manifest.Workspace.fetch_subclass
-:staticmethod:
-
-```{autodoc2-docstring} boardwalk.manifest.Workspace.fetch_subclass
-```
-
-````
-
-`````
-
-````{py:function} path(file_path: str) -> str
-:canonical: boardwalk.manifest.path
-
-```{autodoc2-docstring} boardwalk.manifest.path
-```
-````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.md b/docs/source/apidocs/boardwalk/boardwalk.md
deleted file mode 100644
index 2fc7be8..0000000
--- a/docs/source/apidocs/boardwalk/boardwalk.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# {py:mod}`boardwalk`
-
-```{py:module} boardwalk
-```
-
-```{autodoc2-docstring} boardwalk
-:allowtitles:
-```
-
-## Submodules
-
-```{toctree}
-:titlesonly:
-:maxdepth: 1
-
-boardwalk.ansible
-boardwalk.manifest
-boardwalk.cli_login
-boardwalk.cli_catch
-boardwalk.host
-boardwalk.app_exceptions
-boardwalk.cli_init
-boardwalk.cli_run
-boardwalk.cli
-boardwalk.utils
-boardwalk.cli_workspace
-boardwalk.__main__
-boardwalk.state
-```
diff --git a/docs/source/apidocs/boardwalk/boardwalk.state.md b/docs/source/apidocs/boardwalk/boardwalk.state.md
deleted file mode 100644
index 5a6eaef..0000000
--- a/docs/source/apidocs/boardwalk/boardwalk.state.md
+++ /dev/null
@@ -1,186 +0,0 @@
-# {py:mod}`boardwalk.state`
-
-```{py:module} boardwalk.state
-```
-
-```{autodoc2-docstring} boardwalk.state
-:allowtitles:
-```
-
-## Module Contents
-
-### Classes
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`StateBaseModel `
- - ```{autodoc2-docstring} boardwalk.state.StateBaseModel
- :summary:
- ```
-* - {py:obj}`LocalState `
- - ```{autodoc2-docstring} boardwalk.state.LocalState
- :summary:
- ```
-* - {py:obj}`RemoteStateWorkflow `
- - ```{autodoc2-docstring} boardwalk.state.RemoteStateWorkflow
- :summary:
- ```
-* - {py:obj}`RemoteStateWorkspace `
- - ```{autodoc2-docstring} boardwalk.state.RemoteStateWorkspace
- :summary:
- ```
-* - {py:obj}`RemoteStateModel `
- - ```{autodoc2-docstring} boardwalk.state.RemoteStateModel
- :summary:
- ```
-````
-
-### API
-
-````{py:class} StateBaseModel(/, **data: typing.Any)
-:canonical: boardwalk.state.StateBaseModel
-
-Bases: {py:obj}`pydantic.BaseModel`
-
-```{autodoc2-docstring} boardwalk.state.StateBaseModel
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.state.StateBaseModel.__init__
-```
-
-````
-
-`````{py:class} LocalState(/, **data: typing.Any)
-:canonical: boardwalk.state.LocalState
-
-Bases: {py:obj}`boardwalk.state.StateBaseModel`
-
-```{autodoc2-docstring} boardwalk.state.LocalState
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.state.LocalState.__init__
-```
-
-````{py:attribute} host_pattern
-:canonical: boardwalk.state.LocalState.host_pattern
-:type: str
-:value: >
- None
-
-```{autodoc2-docstring} boardwalk.state.LocalState.host_pattern
-```
-
-````
-
-````{py:attribute} hosts
-:canonical: boardwalk.state.LocalState.hosts
-:type: dict[str, boardwalk.host.Host]
-:value: >
- None
-
-```{autodoc2-docstring} boardwalk.state.LocalState.hosts
-```
-
-````
-
-`````
-
-`````{py:class} RemoteStateWorkflow(/, **data: typing.Any)
-:canonical: boardwalk.state.RemoteStateWorkflow
-
-Bases: {py:obj}`boardwalk.state.StateBaseModel`
-
-```{autodoc2-docstring} boardwalk.state.RemoteStateWorkflow
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.state.RemoteStateWorkflow.__init__
-```
-
-````{py:attribute} started
-:canonical: boardwalk.state.RemoteStateWorkflow.started
-:type: bool
-:value: >
- False
-
-```{autodoc2-docstring} boardwalk.state.RemoteStateWorkflow.started
-```
-
-````
-
-````{py:attribute} succeeded
-:canonical: boardwalk.state.RemoteStateWorkflow.succeeded
-:type: bool
-:value: >
- False
-
-```{autodoc2-docstring} boardwalk.state.RemoteStateWorkflow.succeeded
-```
-
-````
-
-`````
-
-`````{py:class} RemoteStateWorkspace(/, **data: typing.Any)
-:canonical: boardwalk.state.RemoteStateWorkspace
-
-Bases: {py:obj}`boardwalk.state.StateBaseModel`
-
-```{autodoc2-docstring} boardwalk.state.RemoteStateWorkspace
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.state.RemoteStateWorkspace.__init__
-```
-
-````{py:attribute} workflow
-:canonical: boardwalk.state.RemoteStateWorkspace.workflow
-:type: boardwalk.state.RemoteStateWorkflow
-:value: >
- None
-
-```{autodoc2-docstring} boardwalk.state.RemoteStateWorkspace.workflow
-```
-
-````
-
-`````
-
-`````{py:class} RemoteStateModel(/, **data: typing.Any)
-:canonical: boardwalk.state.RemoteStateModel
-
-Bases: {py:obj}`boardwalk.state.StateBaseModel`
-
-```{autodoc2-docstring} boardwalk.state.RemoteStateModel
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalk.state.RemoteStateModel.__init__
-```
-
-````{py:attribute} workspaces
-:canonical: boardwalk.state.RemoteStateModel.workspaces
-:type: dict[str, boardwalk.state.RemoteStateWorkspace]
-:value: >
- None
-
-```{autodoc2-docstring} boardwalk.state.RemoteStateModel.workspaces
-```
-
-````
-
-`````
diff --git a/docs/source/apidocs/boardwalk/boardwalk.utils.md b/docs/source/apidocs/boardwalk/boardwalk.utils.md
deleted file mode 100644
index d4951e3..0000000
--- a/docs/source/apidocs/boardwalk/boardwalk.utils.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# {py:mod}`boardwalk.utils`
-
-```{py:module} boardwalk.utils
-```
-
-```{autodoc2-docstring} boardwalk.utils
-:allowtitles:
-```
-
-## Module Contents
-
-### Functions
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`strtobool `
- - ```{autodoc2-docstring} boardwalk.utils.strtobool
- :summary:
- ```
-````
-
-### API
-
-````{py:function} strtobool(val: str) -> bool
-:canonical: boardwalk.utils.strtobool
-
-```{autodoc2-docstring} boardwalk.utils.strtobool
-```
-````
diff --git a/docs/source/apidocs/boardwalkd/boardwalkd.__main__.md b/docs/source/apidocs/boardwalkd/boardwalkd.__main__.md
deleted file mode 100644
index ea70e29..0000000
--- a/docs/source/apidocs/boardwalkd/boardwalkd.__main__.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# {py:mod}`boardwalkd.__main__`
-
-```{py:module} boardwalkd.__main__
-```
-
-```{autodoc2-docstring} boardwalkd.__main__
-:allowtitles:
-```
diff --git a/docs/source/apidocs/boardwalkd/boardwalkd.broadcast.md b/docs/source/apidocs/boardwalkd/boardwalkd.broadcast.md
deleted file mode 100644
index f20c618..0000000
--- a/docs/source/apidocs/boardwalkd/boardwalkd.broadcast.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# {py:mod}`boardwalkd.broadcast`
-
-```{py:module} boardwalkd.broadcast
-```
-
-```{autodoc2-docstring} boardwalkd.broadcast
-:allowtitles:
-```
-
-## Module Contents
-
-### Functions
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`handle_slack_broadcast `
- - ```{autodoc2-docstring} boardwalkd.broadcast.handle_slack_broadcast
- :summary:
- ```
-````
-
-### API
-
-````{py:function} handle_slack_broadcast(event: boardwalkd.protocol.WorkspaceEvent, workspace: str, webhook_url: str | None, error_webhook_url: str | None, server_url: str)
-:canonical: boardwalkd.broadcast.handle_slack_broadcast
-:async:
-
-```{autodoc2-docstring} boardwalkd.broadcast.handle_slack_broadcast
-```
-````
diff --git a/docs/source/apidocs/boardwalkd/boardwalkd.cli.md b/docs/source/apidocs/boardwalkd/boardwalkd.cli.md
deleted file mode 100644
index 7b7aa96..0000000
--- a/docs/source/apidocs/boardwalkd/boardwalkd.cli.md
+++ /dev/null
@@ -1,76 +0,0 @@
-# {py:mod}`boardwalkd.cli`
-
-```{py:module} boardwalkd.cli
-```
-
-```{autodoc2-docstring} boardwalkd.cli
-:allowtitles:
-```
-
-## Module Contents
-
-### Functions
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`cli `
- - ```{autodoc2-docstring} boardwalkd.cli.cli
- :summary:
- ```
-* - {py:obj}`serve `
- - ```{autodoc2-docstring} boardwalkd.cli.serve
- :summary:
- ```
-* - {py:obj}`version `
- - ```{autodoc2-docstring} boardwalkd.cli.version
- :summary:
- ```
-````
-
-### Data
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`CONTEXT_SETTINGS `
- - ```{autodoc2-docstring} boardwalkd.cli.CONTEXT_SETTINGS
- :summary:
- ```
-````
-
-### API
-
-````{py:data} CONTEXT_SETTINGS
-:canonical: boardwalkd.cli.CONTEXT_SETTINGS
-:type: dict
-:value: >
- 'dict(...)'
-
-```{autodoc2-docstring} boardwalkd.cli.CONTEXT_SETTINGS
-```
-
-````
-
-````{py:function} cli()
-:canonical: boardwalkd.cli.cli
-
-```{autodoc2-docstring} boardwalkd.cli.cli
-```
-````
-
-````{py:function} serve(auth_expire_days: float, auth_method: str, develop: bool, host_header_pattern: str, owner: str | None, port: int | None, slack_error_webhook_url: str, slack_webhook_url: str, slack_app_token: str | None, slack_bot_token: str | None, slack_slash_command_prefix: str, tls_crt: str | None, tls_key: str | None, tls_port: int | None, url: str)
-:canonical: boardwalkd.cli.serve
-
-```{autodoc2-docstring} boardwalkd.cli.serve
-```
-````
-
-````{py:function} version()
-:canonical: boardwalkd.cli.version
-
-```{autodoc2-docstring} boardwalkd.cli.version
-```
-````
diff --git a/docs/source/apidocs/boardwalkd/boardwalkd.md b/docs/source/apidocs/boardwalkd/boardwalkd.md
deleted file mode 100644
index f1847e5..0000000
--- a/docs/source/apidocs/boardwalkd/boardwalkd.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# {py:mod}`boardwalkd`
-
-```{py:module} boardwalkd
-```
-
-```{autodoc2-docstring} boardwalkd
-:allowtitles:
-```
-
-## Submodules
-
-```{toctree}
-:titlesonly:
-:maxdepth: 1
-
-boardwalkd.server
-boardwalkd.protocol
-boardwalkd.cli
-boardwalkd.broadcast
-boardwalkd.__main__
-boardwalkd.slack
-boardwalkd.state
-```
diff --git a/docs/source/apidocs/boardwalkd/boardwalkd.protocol.md b/docs/source/apidocs/boardwalkd/boardwalkd.protocol.md
deleted file mode 100644
index 1f1babe..0000000
--- a/docs/source/apidocs/boardwalkd/boardwalkd.protocol.md
+++ /dev/null
@@ -1,554 +0,0 @@
-# {py:mod}`boardwalkd.protocol`
-
-```{py:module} boardwalkd.protocol
-```
-
-```{autodoc2-docstring} boardwalkd.protocol
-:allowtitles:
-```
-
-## Module Contents
-
-### Classes
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`ProtocolBaseModel `
- - ```{autodoc2-docstring} boardwalkd.protocol.ProtocolBaseModel
- :summary:
- ```
-* - {py:obj}`ApiLoginMessage `
- - ```{autodoc2-docstring} boardwalkd.protocol.ApiLoginMessage
- :summary:
- ```
-* - {py:obj}`WorkspaceDetails `
- - ```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails
- :summary:
- ```
-* - {py:obj}`WorkspaceEvent `
- - ```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent
- :summary:
- ```
-* - {py:obj}`WorkspaceSemaphores `
- - ```{autodoc2-docstring} boardwalkd.protocol.WorkspaceSemaphores
- :summary:
- ```
-* - {py:obj}`Client `
- - ```{autodoc2-docstring} boardwalkd.protocol.Client
- :summary:
- ```
-* - {py:obj}`WorkspaceClient `
- - ```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient
- :summary:
- ```
-````
-
-### API
-
-````{py:class} ProtocolBaseModel(/, **data: typing.Any)
-:canonical: boardwalkd.protocol.ProtocolBaseModel
-
-Bases: {py:obj}`pydantic.BaseModel`
-
-```{autodoc2-docstring} boardwalkd.protocol.ProtocolBaseModel
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalkd.protocol.ProtocolBaseModel.__init__
-```
-
-````
-
-`````{py:class} ApiLoginMessage(/, **data: typing.Any)
-:canonical: boardwalkd.protocol.ApiLoginMessage
-
-Bases: {py:obj}`boardwalkd.protocol.ProtocolBaseModel`
-
-```{autodoc2-docstring} boardwalkd.protocol.ApiLoginMessage
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalkd.protocol.ApiLoginMessage.__init__
-```
-
-````{py:attribute} login_url
-:canonical: boardwalkd.protocol.ApiLoginMessage.login_url
-:type: str
-:value:
-
-```{autodoc2-docstring} boardwalkd.protocol.ApiLoginMessage.login_url
-```
-
-````
-
-````{py:attribute} token
-:canonical: boardwalkd.protocol.ApiLoginMessage.token
-:type: str
-:value:
-
-```{autodoc2-docstring} boardwalkd.protocol.ApiLoginMessage.token
-```
-
-````
-
-`````
-
-`````{py:class} WorkspaceDetails(/, **data: typing.Any)
-:canonical: boardwalkd.protocol.WorkspaceDetails
-
-Bases: {py:obj}`boardwalkd.protocol.ProtocolBaseModel`
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails.__init__
-```
-
-````{py:attribute} host_pattern
-:canonical: boardwalkd.protocol.WorkspaceDetails.host_pattern
-:type: str
-:value:
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails.host_pattern
-```
-
-````
-
-````{py:attribute} workflow
-:canonical: boardwalkd.protocol.WorkspaceDetails.workflow
-:type: str
-:value:
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails.workflow
-```
-
-````
-
-````{py:attribute} worker_command
-:canonical: boardwalkd.protocol.WorkspaceDetails.worker_command
-:type: str
-:value:
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails.worker_command
-```
-
-````
-
-````{py:attribute} worker_hostname
-:canonical: boardwalkd.protocol.WorkspaceDetails.worker_hostname
-:type: str
-:value:
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails.worker_hostname
-```
-
-````
-
-````{py:attribute} worker_limit
-:canonical: boardwalkd.protocol.WorkspaceDetails.worker_limit
-:type: str
-:value:
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails.worker_limit
-```
-
-````
-
-````{py:attribute} worker_username
-:canonical: boardwalkd.protocol.WorkspaceDetails.worker_username
-:type: str
-:value:
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceDetails.worker_username
-```
-
-````
-
-`````
-
-`````{py:class} WorkspaceEvent(**kwargs: str)
-:canonical: boardwalkd.protocol.WorkspaceEvent
-
-Bases: {py:obj}`boardwalkd.protocol.ProtocolBaseModel`
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent.__init__
-```
-
-````{py:attribute} message
-:canonical: boardwalkd.protocol.WorkspaceEvent.message
-:type: str
-:value: >
- None
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent.message
-```
-
-````
-
-````{py:attribute} severity
-:canonical: boardwalkd.protocol.WorkspaceEvent.severity
-:type: str
-:value: >
- None
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent.severity
-```
-
-````
-
-````{py:attribute} create_time
-:canonical: boardwalkd.protocol.WorkspaceEvent.create_time
-:type: datetime.datetime | None
-:value: >
- None
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent.create_time
-```
-
-````
-
-````{py:attribute} received_time
-:canonical: boardwalkd.protocol.WorkspaceEvent.received_time
-:type: datetime.datetime | None
-:value: >
- None
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent.received_time
-```
-
-````
-
-````{py:method} severity_level(v: str)
-:canonical: boardwalkd.protocol.WorkspaceEvent.severity_level
-:classmethod:
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceEvent.severity_level
-```
-
-````
-
-`````
-
-`````{py:class} WorkspaceSemaphores(/, **data: typing.Any)
-:canonical: boardwalkd.protocol.WorkspaceSemaphores
-
-Bases: {py:obj}`boardwalkd.protocol.ProtocolBaseModel`
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceSemaphores
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceSemaphores.__init__
-```
-
-````{py:attribute} caught
-:canonical: boardwalkd.protocol.WorkspaceSemaphores.caught
-:type: bool
-:value: >
- False
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceSemaphores.caught
-```
-
-````
-
-````{py:attribute} has_mutex
-:canonical: boardwalkd.protocol.WorkspaceSemaphores.has_mutex
-:type: bool
-:value: >
- False
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceSemaphores.has_mutex
-```
-
-````
-
-`````
-
-````{py:exception} WorkspaceNotFound()
-:canonical: boardwalkd.protocol.WorkspaceNotFound
-
-Bases: {py:obj}`Exception`
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceNotFound
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceNotFound.__init__
-```
-
-````
-
-````{py:exception} WorkspaceHasMutex()
-:canonical: boardwalkd.protocol.WorkspaceHasMutex
-
-Bases: {py:obj}`Exception`
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceHasMutex
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceHasMutex.__init__
-```
-
-````
-
-`````{py:class} Client(url: str)
-:canonical: boardwalkd.protocol.Client
-
-```{autodoc2-docstring} boardwalkd.protocol.Client
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.__init__
-```
-
-````{py:method} get_api_token() -> str
-:canonical: boardwalkd.protocol.Client.get_api_token
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.get_api_token
-```
-
-````
-
-````{py:method} api_login()
-:canonical: boardwalkd.protocol.Client.api_login
-:async:
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.api_login
-```
-
-````
-
-````{py:method} authenticated_request(path: str, method: str = 'GET', body: bytes | str | None = None, auto_login_prompt: bool = True) -> tornado.httpclient.HTTPResponse
-:canonical: boardwalkd.protocol.Client.authenticated_request
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.authenticated_request
-```
-
-````
-
-````{py:method} workspace_delete_mutex(workspace_name: str)
-:canonical: boardwalkd.protocol.Client.workspace_delete_mutex
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_delete_mutex
-```
-
-````
-
-````{py:method} workspace_get_details(workspace_name: str) -> boardwalkd.protocol.WorkspaceDetails
-:canonical: boardwalkd.protocol.Client.workspace_get_details
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_get_details
-```
-
-````
-
-````{py:method} workspace_post_catch(workspace_name: str)
-:canonical: boardwalkd.protocol.Client.workspace_post_catch
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_post_catch
-```
-
-````
-
-````{py:method} workspace_post_details(workspace_name: str, workspace_details: boardwalkd.protocol.WorkspaceDetails)
-:canonical: boardwalkd.protocol.Client.workspace_post_details
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_post_details
-```
-
-````
-
-````{py:method} workspace_post_heartbeat(workspace_name: str)
-:canonical: boardwalkd.protocol.Client.workspace_post_heartbeat
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_post_heartbeat
-```
-
-````
-
-````{py:method} workspace_heartbeat_keepalive(workspace_name: str, quit: threading.Event) -> None
-:canonical: boardwalkd.protocol.Client.workspace_heartbeat_keepalive
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_heartbeat_keepalive
-```
-
-````
-
-````{py:method} workspace_heartbeat_keepalive_connect(workspace_name: str) -> threading.Event
-:canonical: boardwalkd.protocol.Client.workspace_heartbeat_keepalive_connect
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_heartbeat_keepalive_connect
-```
-
-````
-
-````{py:method} workspace_post_event(workspace_name: str, workspace_event: boardwalkd.protocol.WorkspaceEvent, broadcast: bool = False)
-:canonical: boardwalkd.protocol.Client.workspace_post_event
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_post_event
-```
-
-````
-
-````{py:method} workspace_queue_event(workspace_name: str, workspace_event: boardwalkd.protocol.WorkspaceEvent, broadcast: bool = False)
-:canonical: boardwalkd.protocol.Client.workspace_queue_event
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_queue_event
-```
-
-````
-
-````{py:method} flush_event_queue()
-:canonical: boardwalkd.protocol.Client.flush_event_queue
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.flush_event_queue
-```
-
-````
-
-````{py:method} workspace_post_mutex(workspace_name: str)
-:canonical: boardwalkd.protocol.Client.workspace_post_mutex
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_post_mutex
-```
-
-````
-
-````{py:method} workspace_get_semaphores(workspace_name: str) -> boardwalkd.protocol.WorkspaceSemaphores
-:canonical: boardwalkd.protocol.Client.workspace_get_semaphores
-
-```{autodoc2-docstring} boardwalkd.protocol.Client.workspace_get_semaphores
-```
-
-````
-
-`````
-
-`````{py:class} WorkspaceClient(url: str, workspace_name: str)
-:canonical: boardwalkd.protocol.WorkspaceClient
-
-Bases: {py:obj}`boardwalkd.protocol.Client`
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient
-```
-
-```{rubric} Initialization
-```
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.__init__
-```
-
-````{py:method} get_semaphores() -> boardwalkd.protocol.WorkspaceSemaphores
-:canonical: boardwalkd.protocol.WorkspaceClient.get_semaphores
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.get_semaphores
-```
-
-````
-
-````{py:method} has_mutex() -> bool
-:canonical: boardwalkd.protocol.WorkspaceClient.has_mutex
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.has_mutex
-```
-
-````
-
-````{py:method} post_catch()
-:canonical: boardwalkd.protocol.WorkspaceClient.post_catch
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.post_catch
-```
-
-````
-
-````{py:method} caught() -> bool
-:canonical: boardwalkd.protocol.WorkspaceClient.caught
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.caught
-```
-
-````
-
-````{py:method} heartbeat_keepalive_connect()
-:canonical: boardwalkd.protocol.WorkspaceClient.heartbeat_keepalive_connect
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.heartbeat_keepalive_connect
-```
-
-````
-
-````{py:method} mutex()
-:canonical: boardwalkd.protocol.WorkspaceClient.mutex
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.mutex
-```
-
-````
-
-````{py:method} post_details(workspace_details: boardwalkd.protocol.WorkspaceDetails)
-:canonical: boardwalkd.protocol.WorkspaceClient.post_details
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.post_details
-```
-
-````
-
-````{py:method} post_heartbeat()
-:canonical: boardwalkd.protocol.WorkspaceClient.post_heartbeat
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.post_heartbeat
-```
-
-````
-
-````{py:method} post_event(workspace_event: boardwalkd.protocol.WorkspaceEvent, broadcast: bool = False)
-:canonical: boardwalkd.protocol.WorkspaceClient.post_event
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.post_event
-```
-
-````
-
-````{py:method} queue_event(workspace_event: boardwalkd.protocol.WorkspaceEvent, broadcast: bool = False)
-:canonical: boardwalkd.protocol.WorkspaceClient.queue_event
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.queue_event
-```
-
-````
-
-````{py:method} unmutex()
-:canonical: boardwalkd.protocol.WorkspaceClient.unmutex
-
-```{autodoc2-docstring} boardwalkd.protocol.WorkspaceClient.unmutex
-```
-
-````
-
-`````
diff --git a/docs/source/apidocs/boardwalkd/boardwalkd.server.md b/docs/source/apidocs/boardwalkd/boardwalkd.server.md
deleted file mode 100644
index 1f93a9c..0000000
--- a/docs/source/apidocs/boardwalkd/boardwalkd.server.md
+++ /dev/null
@@ -1,1005 +0,0 @@
-# {py:mod}`boardwalkd.server`
-
-```{py:module} boardwalkd.server
-```
-
-```{autodoc2-docstring} boardwalkd.server
-:allowtitles:
-```
-
-## Module Contents
-
-### Classes
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`UIBaseHandler `
- - ```{autodoc2-docstring} boardwalkd.server.UIBaseHandler
- :summary:
- ```
-* - {py:obj}`AdminUIBaseHandler `
- - ```{autodoc2-docstring} boardwalkd.server.AdminUIBaseHandler
- :summary:
- ```
-* - {py:obj}`AdminHandler `
- - ```{autodoc2-docstring} boardwalkd.server.AdminHandler
- :summary:
- ```
-* - {py:obj}`UserEnableHandler `
- - ```{autodoc2-docstring} boardwalkd.server.UserEnableHandler
- :summary:
- ```
-* - {py:obj}`UserRoleHandler `
- - ```{autodoc2-docstring} boardwalkd.server.UserRoleHandler
- :summary:
- ```
-* - {py:obj}`AnonymousLoginHandler `
- - ```{autodoc2-docstring} boardwalkd.server.AnonymousLoginHandler
- :summary:
- ```
-* - {py:obj}`GoogleOAuth2LoginHandler `
- - ```{autodoc2-docstring} boardwalkd.server.GoogleOAuth2LoginHandler
- :summary:
- ```
-* - {py:obj}`IndexHandler `
- - ```{autodoc2-docstring} boardwalkd.server.IndexHandler
- :summary:
- ```
-* - {py:obj}`WorkspaceCatchHandler `
- - ```{autodoc2-docstring} boardwalkd.server.WorkspaceCatchHandler
- :summary:
- ```
-* - {py:obj}`WorkspaceEventsHandler `
- - ```{autodoc2-docstring} boardwalkd.server.WorkspaceEventsHandler
- :summary:
- ```
-* - {py:obj}`WorkspaceEventsTableHandler `
- - ```{autodoc2-docstring} boardwalkd.server.WorkspaceEventsTableHandler
- :summary:
- ```
-* - {py:obj}`WorkspaceMutexHandler `
- - ```{autodoc2-docstring} boardwalkd.server.WorkspaceMutexHandler
- :summary:
- ```
-* - {py:obj}`WorkspaceDeleteHandler `
- - ```{autodoc2-docstring} boardwalkd.server.WorkspaceDeleteHandler
- :summary:
- ```
-* - {py:obj}`WorkspacesHandler `
- - ```{autodoc2-docstring} boardwalkd.server.WorkspacesHandler
- :summary:
- ```
-* - {py:obj}`APIBaseHandler `
- - ```{autodoc2-docstring} boardwalkd.server.APIBaseHandler
- :summary:
- ```
-* - {py:obj}`AuthLoginApiHandler `
- - ```{autodoc2-docstring} boardwalkd.server.AuthLoginApiHandler
- :summary:
- ```
-* - {py:obj}`AuthLoginApiWebsocketHandler `
- - ```{autodoc2-docstring} boardwalkd.server.AuthLoginApiWebsocketHandler
- :summary:
- ```
-* - {py:obj}`AuthApiDenied `
- - ```{autodoc2-docstring} boardwalkd.server.AuthApiDenied
- :summary:
- ```
-* - {py:obj}`WorkspaceCatchApiHandler `
- - ```{autodoc2-docstring} boardwalkd.server.WorkspaceCatchApiHandler
- :summary:
- ```
-* - {py:obj}`WorkspaceDetailsApiHandler `
- - ```{autodoc2-docstring} boardwalkd.server.WorkspaceDetailsApiHandler
- :summary:
- ```
-* - {py:obj}`WorkspaceHeartbeatApiHandler `
- - ```{autodoc2-docstring} boardwalkd.server.WorkspaceHeartbeatApiHandler
- :summary:
- ```
-* - {py:obj}`WorkspaceEventApiHandler `
- - ```{autodoc2-docstring} boardwalkd.server.WorkspaceEventApiHandler
- :summary:
- ```
-* - {py:obj}`WorkspaceMutexApiHandler `
- - ```{autodoc2-docstring} boardwalkd.server.WorkspaceMutexApiHandler
- :summary:
- ```
-* - {py:obj}`WorkspaceSemaphoresApiHandler `
- - ```{autodoc2-docstring} boardwalkd.server.WorkspaceSemaphoresApiHandler
- :summary:
- ```
-````
-
-### Functions
-
-````{list-table}
-:class: autosummary longtable
-:align: left
-
-* - {py:obj}`ui_method_sha256 `
- - ```{autodoc2-docstring} boardwalkd.server.ui_method_sha256
- :summary:
- ```
-* - {py:obj}`ui_method_secondsdelta