diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 60f9533c..4a5bb8d9 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -6,7 +6,7 @@ name: Build Python package and docs
on:
push:
tags-ignore:
- - "*"
+ - '**'
pull_request:
paths:
- doc/**
@@ -20,19 +20,11 @@ on:
jobs:
build:
- runs-on: ubuntu-20.04
- strategy:
- matrix:
- python-version: [3.8, 3.9]
-
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v1
- with:
- python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
pip install poetry
diff --git a/.github/workflows/publish-ide-docs.yml b/.github/workflows/publish-ide-docs.yml
index a467adcf..15a4db00 100644
--- a/.github/workflows/publish-ide-docs.yml
+++ b/.github/workflows/publish-ide-docs.yml
@@ -7,7 +7,7 @@ on:
jobs:
publish_ide_docs:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
- name: Ubuntu packages
run: |
@@ -17,7 +17,7 @@ jobs:
with:
submodules: recursive
- name: Set up Python 3.8
- uses: actions/setup-python@v1
+ uses: actions/setup-python@v4
with:
python-version: 3.8
- name: Install dependencies
@@ -25,8 +25,8 @@ jobs:
pip install poetry
poetry run python -m pip install --upgrade pip
poetry run python -m pip install --upgrade setuptools
- poetry install
- - uses: actions/setup-node@v1
+ poetry install --only=doc
+ - uses: actions/setup-node@v3
with:
node-version: '14.x'
registry-url: 'https://registry.npmjs.org'
diff --git a/.github/workflows/release-to-pypi.yml b/.github/workflows/release-to-pypi.yml
deleted file mode 100644
index 1187f061..00000000
--- a/.github/workflows/release-to-pypi.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-name: Release to PyPI
-
-on:
- release:
- types: [published]
-
-jobs:
- build_and_publish:
- runs-on: ubuntu-22.04
- steps:
- - uses: actions/checkout@v3
- - run: pipx run poetry build
- - run: pipx run poetry publish
- env:
- POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_TOKEN }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 00000000..d5d3a2f2
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,45 @@
+on:
+ push:
+ tags:
+ - 'v3.*'
+
+name: Create release on GitHub and PyPI
+
+permissions:
+ contents: write
+
+jobs:
+ create_release:
+ name: Create release on GitHub
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+ with:
+ submodules: true
+ fetch-depth: 0
+ - name: Get tag
+ run: echo "GITHUB_TAG=${GITHUB_REF#*refs/tags/}" >> $GITHUB_ENV
+ - name: Create release
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ tag: ${{ github.ref_name }}
+ run: |
+ if [[ "${{ contains(env.GITHUB_TAG, 'a') || contains(env.GITHUB_TAG, 'b') || contains(env.GITHUB_TAG, 'c') }}" == "true" ]]; then
+ PRERELEASE_FLAG="--prerelease"
+ else
+ PRERELEASE_FLAG=""
+ fi
+ gh release create "$tag" \
+ --repo="$GITHUB_REPOSITORY" \
+ --title="${tag#v}" \
+ -F CHANGELOG.md \
+ $PRERELEASE_FLAG
+ build_and_publish:
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v3
+ - run: pipx run poetry build
+ - run: pipx run poetry publish
+ env:
+ POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_TOKEN }}
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
deleted file mode 100644
index 5eb9bef9..00000000
--- a/.readthedocs.yaml
+++ /dev/null
@@ -1,22 +0,0 @@
-# .readthedocs.yaml
-# Read the Docs configuration file
-# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
-#
-# Settings in the readthedocs online dashboard will be ignored.
-
-# Required
-version: 2
-
-# Build documentation in the doc/main directory with Sphinx
-sphinx:
- configuration: doc/main/conf.py
-
-# Build your docs in additional formats such as PDF
-formats:
- - pdf
-
-# Set the version of Python and requirements required to build the docs
-python:
- version: 3.8
- install:
- - requirements: rtd-requirements.txt
diff --git a/.readthedocs.yml b/.readthedocs.yml
new file mode 100644
index 00000000..f868fca4
--- /dev/null
+++ b/.readthedocs.yml
@@ -0,0 +1,24 @@
+# .readthedocs.yaml
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+build:
+ os: "ubuntu-22.04"
+ tools:
+ python: "3.10"
+ jobs:
+ post_create_environment:
+ - pip install poetry
+ post_install:
+ - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install --only=doc
+
+# Build documentation in the doc/main/ directory with Sphinx
+sphinx:
+ configuration: doc/main/conf.py
+
+# Optionally build your docs in additional formats such as PDF
+formats:
+ - pdf
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index b6d82275..fdeaed32 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -4,7 +4,8 @@
// List of extensions which should be recommended for users of this workspace.
"recommendations": [
- "ms-python.python"
+ "ms-python.python",
+ "ms-python.black-formatter"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": [
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 4ccb1bd8..04b39b75 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -4,14 +4,14 @@
},
"python.defaultInterpreterPath": ".venv/bin/python",
"python.autoComplete.extraPaths": ["jedi/src"],
- "python.formatting.provider": "black",
+ "python.formatting.provider": "none",
"python.linting.pylintEnabled": false,
"python.linting.flake8Enabled": true,
"python.linting.pycodestyleEnabled": false,
"python.linting.enabled": true,
"[python]": {
"editor.formatOnSave": true,
- "editor.defaultFormatter": "ms-python.python"
+ "editor.defaultFormatter": "ms-python.black-formatter"
},
"python.languageServer": "Pylance",
"python.testing.pytestArgs": [
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d36a31d4..0d78e740 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,106 @@
## Unreleased
+## 3.5.0- 2024-04-11
+
+### Changed
+- Bump version to 3.5.0 without additional changes.
+
+## 3.5.0b2 - 2024-04-05
+
+### Added
+
+- Added `pybricks.pupdevices.Remote.disconnect` method.
+- Added blocks for `up`, `ready` and `stationary` for IMUs.
+- Added `last` and `chr` parameters to `read_input_byte` and add blocks.
+- Added block for the `in` operation.
+- Add double ternary block.
+
+## 3.5.0b1 - 2024-03-11
+
+### Added
+
+- Added `XboxController.rumble` method.
+- Added block icons for `hub.system.set_stop_button` and `hub.system.shutdown`.
+- Added program stop block (`raise SystemExit`).
+
+## 3.4.1 - 2024-03-11
+
+### Fixed
+
+- Fixed Read The Docs virtual environment workflow.
+
+## 3.4.0 - 2024-03-11
+
+### Changed
+
+- Update list block screenshots to match implementation.
+
+## 3.4.0b5 - 2024-03-05
+
+### Changed
+
+- Updates for v3.4.0b3 firmware (out of sync with docs).
+- Changed `hub.button` to `hub.buttons` on single button hubs. Access via
+ `hub.button` will keep working in the firmware for backwards compatibility.
+
+## 3.4.0b4 - 2024-02-14
+
+### Added
+
+- Added `pybricks.iodevices.XboxController` class.
+
+### Changed
+
+- Changed `buttons.pressed` return type to set.
+
+## 3.4.0b3 - 2024-01-30
+
+### Added
+
+- Added `pybricks.robotics.Car` class.
+
+### Changed
+
+- Changed `pybricks.robotics.DriveBase` icon to two wheels instead of steering
+ wheel, which will be used for the new car class.
+
+## 3.4.0b2 - 2023-11-28
+
+### Changed
+- Include first batch of block coding images.
+
+## 3.3.0 - 2023-11-24
+
+### Changed
+- Bump beta version to release version with no further changes.
+
+## 3.3.0c1 - 2023-11-20
+
+### Added
+- Enabled tilt and orientation config for `MoveHub()`.
+- Documented `Motor.close()`
+
+## Fixed
+- Fixed missing awaitable for `Remote.light` and LWP3 writes.
+
+## 3.3.0b9 - 2023-10-26
+
+### Changed
+- Changed the beta feature for using the hub's gyro. Gyro control can now be
+ toggled using `use_gyro` instead of using a separate `GyroDriveBase` class.
+- Documentation updates to match firmware 3.3.0b5--3.3.0b9 updates.
+
+### Added
+- Added `set` to `ubuiltins` module.
+- Basic multitasking docs.
+- Awaitable keyword for awaitable methods and functions.
+
+## 3.3.0b5 - 2023-05-16
+
+### Added
+- Documented new `hub.ble` methods.
+
## 3.3.0b4 - 2023-04-21
### Added
@@ -76,7 +176,7 @@
## 3.2.0b1-r1 - 2022-06-09
-## Added
+### Added
- Added `__init__.py` to `pybricks` package.
## 3.2.0b1 - 2022-06-02
@@ -147,7 +247,7 @@ not correspond to Pybricks firmware version numbers.**
## 1.3.2 - 2021-04-26
-## Changed
+### Changed
- Theme style fixes.
- Example code fixes
- Match doc version to firmware version.
diff --git a/doc/common/_static/css/blocks.css b/doc/common/_static/css/blocks.css
new file mode 100644
index 00000000..4bff7f71
--- /dev/null
+++ b/doc/common/_static/css/blocks.css
@@ -0,0 +1,3 @@
+.block-image {
+ margin-top: 10px;
+}
diff --git a/doc/common/conf.py b/doc/common/conf.py
index 89f1fab2..9d3173f8 100644
--- a/doc/common/conf.py
+++ b/doc/common/conf.py
@@ -57,6 +57,7 @@
"sphinx.ext.todo",
"sphinx.ext.mathjax",
# Custom Pybricks extensions
+ "blockimg",
"color",
"classlink",
"requirements",
@@ -145,13 +146,10 @@
# -- Options for HTML output ----------------------------------------------
-if ON_RTD:
- html_theme = "default"
-else:
- import sphinx_rtd_theme
+import sphinx_rtd_theme
- html_theme = "sphinx_rtd_theme"
- html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
+html_theme = "sphinx_rtd_theme"
+html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
html_context = {
"disclaimer": _DISCLAIMER,
@@ -321,10 +319,11 @@ def on_missing_reference(
app.builder, node["refdoc"], "signaltypes", "numbers", contnode
)
- # References with special characters can't exist, so we have to supress
+ # References with special characters can't exist, so we have to suppress
# warnings when Sphinx tries to cross reference units like deg/s. For
# consistency, we also treat units without special characters this way.
for unit in [
+ "dBm",
"deg",
"deg/s",
"deg/s²",
@@ -342,13 +341,16 @@ def on_missing_reference(
"Ω",
"N",
]:
-
- # If they match on raw source, we are dealing with argument types.
- if unit == contnode.rawsource:
- # Return as-is to suppress missing cross reference warning. We
- # could make this more fancy by returning an xref node that links
- # to the signals page.
- return contnode
+ try:
+ # If they match on raw source, we are dealing with argument types.
+ if unit == contnode.rawsource:
+ # Return as-is to suppress missing cross reference warning. We
+ # could make this more fancy by returning an xref node that links
+ # to the signals page.
+ return contnode
+
+ except AttributeError:
+ pass
# Return types are denoted as "int: deg"
try:
diff --git a/doc/common/extensions/blockimg.py b/doc/common/extensions/blockimg.py
new file mode 100644
index 00000000..02152d35
--- /dev/null
+++ b/doc/common/extensions/blockimg.py
@@ -0,0 +1,59 @@
+import xml.etree.ElementTree as ET
+
+from docutils.parsers.rst import directives
+from docutils.parsers.rst.directives.images import Image
+from docutils.nodes import image, paragraph
+from pathlib import Path
+
+SPHINX_IMAGE_PATH = "blockimg"
+
+SVG_SCALE = 0.9
+
+
+def get_svg_size(file_path):
+ tree = ET.parse(file_path)
+ root = tree.getroot()
+
+ width = root.attrib.get("width")
+ height = root.attrib.get("height")
+
+ return float(width), float(height)
+
+
+# Global variable to store the app object
+app = None
+
+
+class BlockImageDirective(Image):
+ option_spec = Image.option_spec.copy()
+ option_spec["stack"] = directives.flag
+
+ def run(self):
+ # Adjust the image path
+ file_name = self.arguments[0] + ".svg"
+ self.arguments[0] = "/" + SPHINX_IMAGE_PATH + "/" + file_name
+ path = Path(app.srcdir) / SPHINX_IMAGE_PATH / file_name
+
+ # Set it to the scaled SVG size unless width explicitly set.
+ if self.options.get("width") is None:
+ width, height = get_svg_size(path)
+ self.options["width"] = str(round(width * SVG_SCALE)) + "px"
+ self.options["height"] = str(round(height * SVG_SCALE)) + "px"
+
+ # Call the parent class's run method
+ nodes = super().run()
+
+ # Wrap each image node in a paragraph node
+ for i, node in enumerate(nodes):
+ if isinstance(node, image):
+ if "stack" not in self.options:
+ node["classes"].append("block-image")
+ nodes[i] = paragraph("", "", node)
+
+ return nodes
+
+
+def setup(apparg):
+ global app
+ app = apparg
+ app.add_directive("blockimg", BlockImageDirective)
diff --git a/doc/common/extensions/requirements-static.py b/doc/common/extensions/requirements-static.py
index 3162a3ea..2c2c796b 100644
--- a/doc/common/extensions/requirements-static.py
+++ b/doc/common/extensions/requirements-static.py
@@ -14,6 +14,7 @@
"pybricks-iodevices",
"stm32-extra",
"stm32-float",
+ "pybricks-frozen",
}
# Large feature set.
@@ -23,20 +24,26 @@
HUB_FEATURES = {
"movehub": {"movehub"} | FEATURES_SMALL,
"cityhub": {"cityhub"} | FEATURES_MEDIUM,
- "technichub": {"technichub", "gyro"} | FEATURES_MEDIUM,
- "primehub": {"primehub", "inventorhub", "light-matrix", "gyro"} | FEATURES_LARGE,
- "inventorhub": {"primehub", "inventorhub", "light-matrix", "gyro"} | FEATURES_LARGE,
- "essentialhub": {"essentialhub", "gyro"} | FEATURES_LARGE,
+ "technichub": {"technichub", "gyro", "xbox-controller"} | FEATURES_MEDIUM,
+ "primehub": {"primehub", "inventorhub", "light-matrix", "gyro", "xbox-controller"}
+ | FEATURES_LARGE,
+ "inventorhub": {
+ "primehub",
+ "inventorhub",
+ "light-matrix",
+ "gyro",
+ "xbox-controller",
+ }
+ | FEATURES_LARGE,
+ "essentialhub": {"essentialhub", "gyro", "xbox-controller"} | FEATURES_LARGE,
}
class PybricksRequirementsStaticDirective(Directive):
-
required_arguments = 0
optional_arguments = 10
def run(self):
-
# Copy required resources to static
# CC BY-SA 4.0 via https://stackoverflow.com/a/63728208
env = self.state.document.settings.env
diff --git a/doc/main/blockimg/LICENSE b/doc/main/blockimg/LICENSE
new file mode 100644
index 00000000..decfb181
--- /dev/null
+++ b/doc/main/blockimg/LICENSE
@@ -0,0 +1 @@
+Copyright (c) 2024 The Pybricks Authors - All rights reserved
diff --git a/doc/main/blockimg/pybricks_blockBatteryMeasure_CityHub_battery.current.svg b/doc/main/blockimg/pybricks_blockBatteryMeasure_CityHub_battery.current.svg
new file mode 100644
index 00000000..f0734db7
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBatteryMeasure_CityHub_battery.current.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBatteryMeasure_CityHub_battery.voltage.svg b/doc/main/blockimg/pybricks_blockBatteryMeasure_CityHub_battery.voltage.svg
new file mode 100644
index 00000000..dfe3a601
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBatteryMeasure_CityHub_battery.voltage.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBatteryMeasure_EssentialHub_battery.current.svg b/doc/main/blockimg/pybricks_blockBatteryMeasure_EssentialHub_battery.current.svg
new file mode 100644
index 00000000..ccb3cae8
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBatteryMeasure_EssentialHub_battery.current.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBatteryMeasure_EssentialHub_battery.voltage.svg b/doc/main/blockimg/pybricks_blockBatteryMeasure_EssentialHub_battery.voltage.svg
new file mode 100644
index 00000000..2e1648ad
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBatteryMeasure_EssentialHub_battery.voltage.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBatteryMeasure_InventorHub_battery.current.svg b/doc/main/blockimg/pybricks_blockBatteryMeasure_InventorHub_battery.current.svg
new file mode 100644
index 00000000..20abbe76
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBatteryMeasure_InventorHub_battery.current.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBatteryMeasure_InventorHub_battery.voltage.svg b/doc/main/blockimg/pybricks_blockBatteryMeasure_InventorHub_battery.voltage.svg
new file mode 100644
index 00000000..c228b2cd
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBatteryMeasure_InventorHub_battery.voltage.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBatteryMeasure_MoveHub_battery.current.svg b/doc/main/blockimg/pybricks_blockBatteryMeasure_MoveHub_battery.current.svg
new file mode 100644
index 00000000..039f8a5c
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBatteryMeasure_MoveHub_battery.current.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBatteryMeasure_MoveHub_battery.voltage.svg b/doc/main/blockimg/pybricks_blockBatteryMeasure_MoveHub_battery.voltage.svg
new file mode 100644
index 00000000..5bf539d5
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBatteryMeasure_MoveHub_battery.voltage.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBatteryMeasure_PrimeHub_battery.current.svg b/doc/main/blockimg/pybricks_blockBatteryMeasure_PrimeHub_battery.current.svg
new file mode 100644
index 00000000..a3ec4ae9
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBatteryMeasure_PrimeHub_battery.current.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBatteryMeasure_PrimeHub_battery.voltage.svg b/doc/main/blockimg/pybricks_blockBatteryMeasure_PrimeHub_battery.voltage.svg
new file mode 100644
index 00000000..c99ed243
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBatteryMeasure_PrimeHub_battery.voltage.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBatteryMeasure_TechnicHub_battery.current.svg b/doc/main/blockimg/pybricks_blockBatteryMeasure_TechnicHub_battery.current.svg
new file mode 100644
index 00000000..39d86276
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBatteryMeasure_TechnicHub_battery.current.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBatteryMeasure_TechnicHub_battery.voltage.svg b/doc/main/blockimg/pybricks_blockBatteryMeasure_TechnicHub_battery.voltage.svg
new file mode 100644
index 00000000..4d914a6f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBatteryMeasure_TechnicHub_battery.voltage.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBleBroadcast_CityHub.svg b/doc/main/blockimg/pybricks_blockBleBroadcast_CityHub.svg
new file mode 100644
index 00000000..71084ee3
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBleBroadcast_CityHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBleBroadcast_EssentialHub.svg b/doc/main/blockimg/pybricks_blockBleBroadcast_EssentialHub.svg
new file mode 100644
index 00000000..2264d6ee
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBleBroadcast_EssentialHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBleBroadcast_PrimeHub.svg b/doc/main/blockimg/pybricks_blockBleBroadcast_PrimeHub.svg
new file mode 100644
index 00000000..9ec3011a
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBleBroadcast_PrimeHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBleBroadcast_TechnicHub.svg b/doc/main/blockimg/pybricks_blockBleBroadcast_TechnicHub.svg
new file mode 100644
index 00000000..db4e4478
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBleBroadcast_TechnicHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBleObserve_CityHub.svg b/doc/main/blockimg/pybricks_blockBleObserve_CityHub.svg
new file mode 100644
index 00000000..c9fa5034
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBleObserve_CityHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBleObserve_EssentialHub.svg b/doc/main/blockimg/pybricks_blockBleObserve_EssentialHub.svg
new file mode 100644
index 00000000..51a03941
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBleObserve_EssentialHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBleObserve_PrimeHub.svg b/doc/main/blockimg/pybricks_blockBleObserve_PrimeHub.svg
new file mode 100644
index 00000000..76936f57
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBleObserve_PrimeHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockBleObserve_TechnicHub.svg b/doc/main/blockimg/pybricks_blockBleObserve_TechnicHub.svg
new file mode 100644
index 00000000..b4f37d3a
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockBleObserve_TechnicHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockButtonIsPressed_CityHub.svg b/doc/main/blockimg/pybricks_blockButtonIsPressed_CityHub.svg
new file mode 100644
index 00000000..2a5bc73a
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockButtonIsPressed_CityHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockButtonIsPressed_EssentialHub.svg b/doc/main/blockimg/pybricks_blockButtonIsPressed_EssentialHub.svg
new file mode 100644
index 00000000..c74dec66
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockButtonIsPressed_EssentialHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockButtonIsPressed_PrimeHub.svg b/doc/main/blockimg/pybricks_blockButtonIsPressed_PrimeHub.svg
new file mode 100644
index 00000000..03ec6f81
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockButtonIsPressed_PrimeHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockButtonIsPressed_Remote.svg b/doc/main/blockimg/pybricks_blockButtonIsPressed_Remote.svg
new file mode 100644
index 00000000..07db1a75
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockButtonIsPressed_Remote.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockButtonIsPressed_TechnicHub.svg b/doc/main/blockimg/pybricks_blockButtonIsPressed_TechnicHub.svg
new file mode 100644
index 00000000..84f05420
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockButtonIsPressed_TechnicHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockButtonIsPressed_XboxController.svg b/doc/main/blockimg/pybricks_blockButtonIsPressed_XboxController.svg
new file mode 100644
index 00000000..195fe4ba
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockButtonIsPressed_XboxController.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockCarDrive_car_drive_at_power.svg b/doc/main/blockimg/pybricks_blockCarDrive_car_drive_at_power.svg
new file mode 100644
index 00000000..03c00b4d
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockCarDrive_car_drive_at_power.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockCarDrive_car_drive_at_speed.svg b/doc/main/blockimg/pybricks_blockCarDrive_car_drive_at_speed.svg
new file mode 100644
index 00000000..861ef410
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockCarDrive_car_drive_at_speed.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockCarSteer.svg b/doc/main/blockimg/pybricks_blockCarSteer.svg
new file mode 100644
index 00000000..958536e4
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockCarSteer.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockColor_ColorDistanceSensor_color.svg b/doc/main/blockimg/pybricks_blockColor_ColorDistanceSensor_color.svg
new file mode 100644
index 00000000..1e70c202
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockColor_ColorDistanceSensor_color.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockColor_ColorDistanceSensor_hsv.svg b/doc/main/blockimg/pybricks_blockColor_ColorDistanceSensor_hsv.svg
new file mode 100644
index 00000000..ab021ef2
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockColor_ColorDistanceSensor_hsv.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockColor_ColorSensor_color.svg b/doc/main/blockimg/pybricks_blockColor_ColorSensor_color.svg
new file mode 100644
index 00000000..31244014
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockColor_ColorSensor_color.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockColor_ColorSensor_hsv.svg b/doc/main/blockimg/pybricks_blockColor_ColorSensor_hsv.svg
new file mode 100644
index 00000000..998ab1c9
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockColor_ColorSensor_hsv.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockComment.svg b/doc/main/blockimg/pybricks_blockComment.svg
new file mode 100644
index 00000000..9eef89d8
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockComment.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDistance_ColorDistanceSensor.svg b/doc/main/blockimg/pybricks_blockDistance_ColorDistanceSensor.svg
new file mode 100644
index 00000000..893f203f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDistance_ColorDistanceSensor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockDistance_ForceSensor.svg b/doc/main/blockimg/pybricks_blockDistance_ForceSensor.svg
new file mode 100644
index 00000000..546c72bb
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDistance_ForceSensor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockDistance_InfraredSensor.svg b/doc/main/blockimg/pybricks_blockDistance_InfraredSensor.svg
new file mode 100644
index 00000000..613157c7
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDistance_InfraredSensor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockDistance_UltrasonicSensor.svg b/doc/main/blockimg/pybricks_blockDistance_UltrasonicSensor.svg
new file mode 100644
index 00000000..dc7a48c7
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDistance_UltrasonicSensor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseConfigure_drivebase_straight_acceleration.svg b/doc/main/blockimg/pybricks_blockDriveBaseConfigure_drivebase_straight_acceleration.svg
new file mode 100644
index 00000000..0629f9e5
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseConfigure_drivebase_straight_acceleration.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseConfigure_drivebase_straight_speed.svg b/doc/main/blockimg/pybricks_blockDriveBaseConfigure_drivebase_straight_speed.svg
new file mode 100644
index 00000000..0bd4ecf3
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseConfigure_drivebase_straight_speed.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseConfigure_drivebase_turn_acceleration.svg b/doc/main/blockimg/pybricks_blockDriveBaseConfigure_drivebase_turn_acceleration.svg
new file mode 100644
index 00000000..1c06fa81
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseConfigure_drivebase_turn_acceleration.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseConfigure_drivebase_turn_rate.svg b/doc/main/blockimg/pybricks_blockDriveBaseConfigure_drivebase_turn_rate.svg
new file mode 100644
index 00000000..7b6e68de
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseConfigure_drivebase_turn_rate.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseDrive_drivebase_drive_curve.svg b/doc/main/blockimg/pybricks_blockDriveBaseDrive_drivebase_drive_curve.svg
new file mode 100644
index 00000000..db9b753c
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseDrive_drivebase_drive_curve.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseDrive_drivebase_drive_forever.svg b/doc/main/blockimg/pybricks_blockDriveBaseDrive_drivebase_drive_forever.svg
new file mode 100644
index 00000000..c11eab5f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseDrive_drivebase_drive_forever.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseDrive_drivebase_drive_straight.svg b/doc/main/blockimg/pybricks_blockDriveBaseDrive_drivebase_drive_straight.svg
new file mode 100644
index 00000000..c4063f60
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseDrive_drivebase_drive_straight.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseDrive_drivebase_drive_turn.svg b/doc/main/blockimg/pybricks_blockDriveBaseDrive_drivebase_drive_turn.svg
new file mode 100644
index 00000000..545cddb3
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseDrive_drivebase_drive_turn.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseMeasure_drivebase_get_angle.svg b/doc/main/blockimg/pybricks_blockDriveBaseMeasure_drivebase_get_angle.svg
new file mode 100644
index 00000000..2f0b21e6
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseMeasure_drivebase_get_angle.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseMeasure_drivebase_get_distance.svg b/doc/main/blockimg/pybricks_blockDriveBaseMeasure_drivebase_get_distance.svg
new file mode 100644
index 00000000..494fa607
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseMeasure_drivebase_get_distance.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseMeasure_drivebase_get_speed.svg b/doc/main/blockimg/pybricks_blockDriveBaseMeasure_drivebase_get_speed.svg
new file mode 100644
index 00000000..fb7bcaec
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseMeasure_drivebase_get_speed.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseMeasure_drivebase_get_turn_rate.svg b/doc/main/blockimg/pybricks_blockDriveBaseMeasure_drivebase_get_turn_rate.svg
new file mode 100644
index 00000000..2077dc1f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseMeasure_drivebase_get_turn_rate.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseStop_brake.svg b/doc/main/blockimg/pybricks_blockDriveBaseStop_brake.svg
new file mode 100644
index 00000000..d6806058
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseStop_brake.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseStop_coast.svg b/doc/main/blockimg/pybricks_blockDriveBaseStop_coast.svg
new file mode 100644
index 00000000..81dca857
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseStop_coast.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseStop_hold.svg b/doc/main/blockimg/pybricks_blockDriveBaseStop_hold.svg
new file mode 100644
index 00000000..c815f3e6
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseStop_hold.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockDriveBaseUseGyro.svg b/doc/main/blockimg/pybricks_blockDriveBaseUseGyro.svg
new file mode 100644
index 00000000..827d4b76
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockDriveBaseUseGyro.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockFlowBreakContinue_break.svg b/doc/main/blockimg/pybricks_blockFlowBreakContinue_break.svg
new file mode 100644
index 00000000..612553e7
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockFlowBreakContinue_break.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockFlowBreakContinue_continue.svg b/doc/main/blockimg/pybricks_blockFlowBreakContinue_continue.svg
new file mode 100644
index 00000000..b577ae88
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockFlowBreakContinue_continue.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockFlowForEach_loop_for.svg b/doc/main/blockimg/pybricks_blockFlowForEach_loop_for.svg
new file mode 100644
index 00000000..58a462c9
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockFlowForEach_loop_for.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockFlowForEach_loop_for_list.svg b/doc/main/blockimg/pybricks_blockFlowForEach_loop_for_list.svg
new file mode 100644
index 00000000..ee834295
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockFlowForEach_loop_for_list.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockFlowForEach_loop_for_range.svg b/doc/main/blockimg/pybricks_blockFlowForEach_loop_for_range.svg
new file mode 100644
index 00000000..ed8ec4b5
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockFlowForEach_loop_for_range.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockFlowRepeat.svg b/doc/main/blockimg/pybricks_blockFlowRepeat.svg
new file mode 100644
index 00000000..74531fd0
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockFlowRepeat.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockFlowWhile_until.svg b/doc/main/blockimg/pybricks_blockFlowWhile_until.svg
new file mode 100644
index 00000000..11938b3c
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockFlowWhile_until.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockFlowWhile_while.svg b/doc/main/blockimg/pybricks_blockFlowWhile_while.svg
new file mode 100644
index 00000000..6b21e4b9
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockFlowWhile_while.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockForce_ForceSensor.svg b/doc/main/blockimg/pybricks_blockForce_ForceSensor.svg
new file mode 100644
index 00000000..2ce5b585
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockForce_ForceSensor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockGamepadRumble_default.svg b/doc/main/blockimg/pybricks_blockGamepadRumble_default.svg
new file mode 100644
index 00000000..4ffee226
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockGamepadRumble_default.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockGamepadRumble_default_with_list.svg b/doc/main/blockimg/pybricks_blockGamepadRumble_default_with_list.svg
new file mode 100644
index 00000000..5bdbc927
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockGamepadRumble_default_with_list.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockGamepadRumble_with_options.svg b/doc/main/blockimg/pybricks_blockGamepadRumble_with_options.svg
new file mode 100644
index 00000000..d649829f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockGamepadRumble_with_options.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockGlobalSetup.svg b/doc/main/blockimg/pybricks_blockGlobalSetup.svg
new file mode 100644
index 00000000..e0171762
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockGlobalSetup.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockGlobalStart.svg b/doc/main/blockimg/pybricks_blockGlobalStart.svg
new file mode 100644
index 00000000..0f282947
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockGlobalStart.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockHubShutdown_CityHub.svg b/doc/main/blockimg/pybricks_blockHubShutdown_CityHub.svg
new file mode 100644
index 00000000..ece5aaf7
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubShutdown_CityHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubShutdown_EssentialHub.svg b/doc/main/blockimg/pybricks_blockHubShutdown_EssentialHub.svg
new file mode 100644
index 00000000..703ee970
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubShutdown_EssentialHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubShutdown_InventorHub.svg b/doc/main/blockimg/pybricks_blockHubShutdown_InventorHub.svg
new file mode 100644
index 00000000..ae42dd92
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubShutdown_InventorHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubShutdown_MoveHub.svg b/doc/main/blockimg/pybricks_blockHubShutdown_MoveHub.svg
new file mode 100644
index 00000000..85860ceb
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubShutdown_MoveHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubShutdown_PrimeHub.svg b/doc/main/blockimg/pybricks_blockHubShutdown_PrimeHub.svg
new file mode 100644
index 00000000..7b21239e
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubShutdown_PrimeHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubShutdown_TechnicHub.svg b/doc/main/blockimg/pybricks_blockHubShutdown_TechnicHub.svg
new file mode 100644
index 00000000..e4fe215c
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubShutdown_TechnicHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubStopButton_CityHub.svg b/doc/main/blockimg/pybricks_blockHubStopButton_CityHub.svg
new file mode 100644
index 00000000..c55dd5e1
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubStopButton_CityHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubStopButton_CityHub_none.svg b/doc/main/blockimg/pybricks_blockHubStopButton_CityHub_none.svg
new file mode 100644
index 00000000..1899cfcf
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubStopButton_CityHub_none.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubStopButton_EssentialHub.svg b/doc/main/blockimg/pybricks_blockHubStopButton_EssentialHub.svg
new file mode 100644
index 00000000..837b777d
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubStopButton_EssentialHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubStopButton_EssentialHub_none.svg b/doc/main/blockimg/pybricks_blockHubStopButton_EssentialHub_none.svg
new file mode 100644
index 00000000..32709d96
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubStopButton_EssentialHub_none.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubStopButton_InventorHub.svg b/doc/main/blockimg/pybricks_blockHubStopButton_InventorHub.svg
new file mode 100644
index 00000000..321be19d
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubStopButton_InventorHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubStopButton_InventorHub_none.svg b/doc/main/blockimg/pybricks_blockHubStopButton_InventorHub_none.svg
new file mode 100644
index 00000000..0c0a92a4
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubStopButton_InventorHub_none.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubStopButton_MoveHub.svg b/doc/main/blockimg/pybricks_blockHubStopButton_MoveHub.svg
new file mode 100644
index 00000000..5544d503
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubStopButton_MoveHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubStopButton_MoveHub_none.svg b/doc/main/blockimg/pybricks_blockHubStopButton_MoveHub_none.svg
new file mode 100644
index 00000000..3ff4d043
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubStopButton_MoveHub_none.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubStopButton_PrimeHub.svg b/doc/main/blockimg/pybricks_blockHubStopButton_PrimeHub.svg
new file mode 100644
index 00000000..26e29cd6
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubStopButton_PrimeHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubStopButton_PrimeHub_none.svg b/doc/main/blockimg/pybricks_blockHubStopButton_PrimeHub_none.svg
new file mode 100644
index 00000000..ef0dede1
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubStopButton_PrimeHub_none.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubStopButton_TechnicHub.svg b/doc/main/blockimg/pybricks_blockHubStopButton_TechnicHub.svg
new file mode 100644
index 00000000..905f88b0
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubStopButton_TechnicHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockHubStopButton_TechnicHub_none.svg b/doc/main/blockimg/pybricks_blockHubStopButton_TechnicHub_none.svg
new file mode 100644
index 00000000..02a06063
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockHubStopButton_TechnicHub_none.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockIfElse_if_else.svg b/doc/main/blockimg/pybricks_blockIfElse_if_else.svg
new file mode 100644
index 00000000..34be1a07
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockIfElse_if_else.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockIfElse_if_else_else.svg b/doc/main/blockimg/pybricks_blockIfElse_if_else_else.svg
new file mode 100644
index 00000000..61529731
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockIfElse_if_else_else.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockIfElse_if_only.svg b/doc/main/blockimg/pybricks_blockIfElse_if_only.svg
new file mode 100644
index 00000000..7450ae43
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockIfElse_if_only.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImportTaskCallStatement.svg b/doc/main/blockimg/pybricks_blockImportTaskCallStatement.svg
new file mode 100644
index 00000000..3b689161
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImportTaskCallStatement.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImportTaskCallValue.svg b/doc/main/blockimg/pybricks_blockImportTaskCallValue.svg
new file mode 100644
index 00000000..a4d10457
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImportTaskCallValue.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuAcceleration_EssentialHub.svg b/doc/main/blockimg/pybricks_blockImuAcceleration_EssentialHub.svg
new file mode 100644
index 00000000..d5819b21
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuAcceleration_EssentialHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuAcceleration_MoveHub.svg b/doc/main/blockimg/pybricks_blockImuAcceleration_MoveHub.svg
new file mode 100644
index 00000000..39d36b62
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuAcceleration_MoveHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuAcceleration_PrimeHub.svg b/doc/main/blockimg/pybricks_blockImuAcceleration_PrimeHub.svg
new file mode 100644
index 00000000..7657a650
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuAcceleration_PrimeHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuAcceleration_TechnicHub.svg b/doc/main/blockimg/pybricks_blockImuAcceleration_TechnicHub.svg
new file mode 100644
index 00000000..2585d116
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuAcceleration_TechnicHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuGetHeading_EssentialHub.svg b/doc/main/blockimg/pybricks_blockImuGetHeading_EssentialHub.svg
new file mode 100644
index 00000000..fb9dfdeb
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuGetHeading_EssentialHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuGetHeading_PrimeHub.svg b/doc/main/blockimg/pybricks_blockImuGetHeading_PrimeHub.svg
new file mode 100644
index 00000000..b16b7dcb
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuGetHeading_PrimeHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuGetHeading_TechnicHub.svg b/doc/main/blockimg/pybricks_blockImuGetHeading_TechnicHub.svg
new file mode 100644
index 00000000..a1988223
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuGetHeading_TechnicHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuResetHeading_EssentialHub.svg b/doc/main/blockimg/pybricks_blockImuResetHeading_EssentialHub.svg
new file mode 100644
index 00000000..442342bf
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuResetHeading_EssentialHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuResetHeading_PrimeHub.svg b/doc/main/blockimg/pybricks_blockImuResetHeading_PrimeHub.svg
new file mode 100644
index 00000000..45309d35
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuResetHeading_PrimeHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuResetHeading_TechnicHub.svg b/doc/main/blockimg/pybricks_blockImuResetHeading_TechnicHub.svg
new file mode 100644
index 00000000..ea450a7a
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuResetHeading_TechnicHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuRotation_EssentialHub_imu.angular_velocity.svg b/doc/main/blockimg/pybricks_blockImuRotation_EssentialHub_imu.angular_velocity.svg
new file mode 100644
index 00000000..c6c15131
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuRotation_EssentialHub_imu.angular_velocity.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuRotation_EssentialHub_imu.rotation.svg b/doc/main/blockimg/pybricks_blockImuRotation_EssentialHub_imu.rotation.svg
new file mode 100644
index 00000000..6d5d7971
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuRotation_EssentialHub_imu.rotation.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuRotation_PrimeHub_imu.angular_velocity.svg b/doc/main/blockimg/pybricks_blockImuRotation_PrimeHub_imu.angular_velocity.svg
new file mode 100644
index 00000000..a977a0c5
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuRotation_PrimeHub_imu.angular_velocity.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuRotation_PrimeHub_imu.rotation.svg b/doc/main/blockimg/pybricks_blockImuRotation_PrimeHub_imu.rotation.svg
new file mode 100644
index 00000000..a6b8eef4
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuRotation_PrimeHub_imu.rotation.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuRotation_TechnicHub_imu.angular_velocity.svg b/doc/main/blockimg/pybricks_blockImuRotation_TechnicHub_imu.angular_velocity.svg
new file mode 100644
index 00000000..2909494f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuRotation_TechnicHub_imu.angular_velocity.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuRotation_TechnicHub_imu.rotation.svg b/doc/main/blockimg/pybricks_blockImuRotation_TechnicHub_imu.rotation.svg
new file mode 100644
index 00000000..50ed3a16
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuRotation_TechnicHub_imu.rotation.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockImuStatus_EssentialHub_ready.svg b/doc/main/blockimg/pybricks_blockImuStatus_EssentialHub_ready.svg
new file mode 100644
index 00000000..b669ba65
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuStatus_EssentialHub_ready.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockImuStatus_EssentialHub_stationary.svg b/doc/main/blockimg/pybricks_blockImuStatus_EssentialHub_stationary.svg
new file mode 100644
index 00000000..bab424c3
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuStatus_EssentialHub_stationary.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockImuStatus_InventorHub_ready.svg b/doc/main/blockimg/pybricks_blockImuStatus_InventorHub_ready.svg
new file mode 100644
index 00000000..794e2fec
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuStatus_InventorHub_ready.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockImuStatus_InventorHub_stationary.svg b/doc/main/blockimg/pybricks_blockImuStatus_InventorHub_stationary.svg
new file mode 100644
index 00000000..4c9967eb
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuStatus_InventorHub_stationary.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockImuStatus_PrimeHub_ready.svg b/doc/main/blockimg/pybricks_blockImuStatus_PrimeHub_ready.svg
new file mode 100644
index 00000000..43527c76
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuStatus_PrimeHub_ready.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockImuStatus_PrimeHub_stationary.svg b/doc/main/blockimg/pybricks_blockImuStatus_PrimeHub_stationary.svg
new file mode 100644
index 00000000..22be1110
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuStatus_PrimeHub_stationary.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockImuStatus_TechnicHub_ready.svg b/doc/main/blockimg/pybricks_blockImuStatus_TechnicHub_ready.svg
new file mode 100644
index 00000000..ce79638f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuStatus_TechnicHub_ready.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockImuStatus_TechnicHub_stationary.svg b/doc/main/blockimg/pybricks_blockImuStatus_TechnicHub_stationary.svg
new file mode 100644
index 00000000..58126034
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuStatus_TechnicHub_stationary.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockImuUp_EssentialHub.svg b/doc/main/blockimg/pybricks_blockImuUp_EssentialHub.svg
new file mode 100644
index 00000000..9a6ceabc
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuUp_EssentialHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockImuUp_InventorHub.svg b/doc/main/blockimg/pybricks_blockImuUp_InventorHub.svg
new file mode 100644
index 00000000..9e8b349e
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuUp_InventorHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockImuUp_MoveHub.svg b/doc/main/blockimg/pybricks_blockImuUp_MoveHub.svg
new file mode 100644
index 00000000..e4f51c48
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuUp_MoveHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockImuUp_PrimeHub.svg b/doc/main/blockimg/pybricks_blockImuUp_PrimeHub.svg
new file mode 100644
index 00000000..0b4a7dd4
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuUp_PrimeHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockImuUp_TechnicHub.svg b/doc/main/blockimg/pybricks_blockImuUp_TechnicHub.svg
new file mode 100644
index 00000000..aa57280f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockImuUp_TechnicHub.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockIsIn.svg b/doc/main/blockimg/pybricks_blockIsIn.svg
new file mode 100644
index 00000000..60cc1b58
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockIsIn.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockJoystickValue_dpad.svg b/doc/main/blockimg/pybricks_blockJoystickValue_dpad.svg
new file mode 100644
index 00000000..a8b26082
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockJoystickValue_dpad.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockJoystickValue_lj_x.svg b/doc/main/blockimg/pybricks_blockJoystickValue_lj_x.svg
new file mode 100644
index 00000000..15de884f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockJoystickValue_lj_x.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockJoystickValue_lj_y.svg b/doc/main/blockimg/pybricks_blockJoystickValue_lj_y.svg
new file mode 100644
index 00000000..3deae878
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockJoystickValue_lj_y.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockJoystickValue_lt.svg b/doc/main/blockimg/pybricks_blockJoystickValue_lt.svg
new file mode 100644
index 00000000..e3c1f9fe
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockJoystickValue_lt.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockJoystickValue_profile.svg b/doc/main/blockimg/pybricks_blockJoystickValue_profile.svg
new file mode 100644
index 00000000..efebf67c
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockJoystickValue_profile.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockJoystickValue_rj_x.svg b/doc/main/blockimg/pybricks_blockJoystickValue_rj_x.svg
new file mode 100644
index 00000000..5b9b3328
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockJoystickValue_rj_x.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockJoystickValue_rj_y.svg b/doc/main/blockimg/pybricks_blockJoystickValue_rj_y.svg
new file mode 100644
index 00000000..57617532
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockJoystickValue_rj_y.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockJoystickValue_rt.svg b/doc/main/blockimg/pybricks_blockJoystickValue_rt.svg
new file mode 100644
index 00000000..ccca7eb6
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockJoystickValue_rt.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockLightAmbient_ColorDistanceSensor.svg b/doc/main/blockimg/pybricks_blockLightAmbient_ColorDistanceSensor.svg
new file mode 100644
index 00000000..9a434652
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightAmbient_ColorDistanceSensor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightAmbient_ColorSensor.svg b/doc/main/blockimg/pybricks_blockLightAmbient_ColorSensor.svg
new file mode 100644
index 00000000..573d22b0
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightAmbient_ColorSensor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightMatrixDo_light_matrix_number.svg b/doc/main/blockimg/pybricks_blockLightMatrixDo_light_matrix_number.svg
new file mode 100644
index 00000000..7300702d
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightMatrixDo_light_matrix_number.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightMatrixDo_light_matrix_off.svg b/doc/main/blockimg/pybricks_blockLightMatrixDo_light_matrix_off.svg
new file mode 100644
index 00000000..3f3cd5a3
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightMatrixDo_light_matrix_off.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightMatrixDo_light_matrix_pixel.svg b/doc/main/blockimg/pybricks_blockLightMatrixDo_light_matrix_pixel.svg
new file mode 100644
index 00000000..ef4e569d
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightMatrixDo_light_matrix_pixel.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightMatrixDo_light_matrix_symbol.svg b/doc/main/blockimg/pybricks_blockLightMatrixDo_light_matrix_symbol.svg
new file mode 100644
index 00000000..b1f33140
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightMatrixDo_light_matrix_symbol.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_cityhub_off.svg b/doc/main/blockimg/pybricks_blockLightOnColor_cityhub_off.svg
new file mode 100644
index 00000000..14f0daa1
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_cityhub_off.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_cityhub_on.svg b/doc/main/blockimg/pybricks_blockLightOnColor_cityhub_on.svg
new file mode 100644
index 00000000..d2c04fb6
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_cityhub_on.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_colordistancesensor_off.svg b/doc/main/blockimg/pybricks_blockLightOnColor_colordistancesensor_off.svg
new file mode 100644
index 00000000..c6c309cc
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_colordistancesensor_off.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_colordistancesensor_on.svg b/doc/main/blockimg/pybricks_blockLightOnColor_colordistancesensor_on.svg
new file mode 100644
index 00000000..4a9ba0e8
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_colordistancesensor_on.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_colorlightmatrix_off.svg b/doc/main/blockimg/pybricks_blockLightOnColor_colorlightmatrix_off.svg
new file mode 100644
index 00000000..d4396b84
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_colorlightmatrix_off.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_colorlightmatrix_on.svg b/doc/main/blockimg/pybricks_blockLightOnColor_colorlightmatrix_on.svg
new file mode 100644
index 00000000..b86b77e0
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_colorlightmatrix_on.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_colorlightmatrix_on_list.svg b/doc/main/blockimg/pybricks_blockLightOnColor_colorlightmatrix_on_list.svg
new file mode 100644
index 00000000..9ce8787f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_colorlightmatrix_on_list.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_essentialhub_off.svg b/doc/main/blockimg/pybricks_blockLightOnColor_essentialhub_off.svg
new file mode 100644
index 00000000..d8547824
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_essentialhub_off.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_essentialhub_on.svg b/doc/main/blockimg/pybricks_blockLightOnColor_essentialhub_on.svg
new file mode 100644
index 00000000..b58a7206
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_essentialhub_on.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_movehub_off.svg b/doc/main/blockimg/pybricks_blockLightOnColor_movehub_off.svg
new file mode 100644
index 00000000..84b62727
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_movehub_off.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_movehub_on.svg b/doc/main/blockimg/pybricks_blockLightOnColor_movehub_on.svg
new file mode 100644
index 00000000..f54d8fb2
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_movehub_on.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_primehub_off.svg b/doc/main/blockimg/pybricks_blockLightOnColor_primehub_off.svg
new file mode 100644
index 00000000..d8874b2f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_primehub_off.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_primehub_on.svg b/doc/main/blockimg/pybricks_blockLightOnColor_primehub_on.svg
new file mode 100644
index 00000000..36ba9be4
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_primehub_on.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_remote_on.svg b/doc/main/blockimg/pybricks_blockLightOnColor_remote_on.svg
new file mode 100644
index 00000000..f4480757
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_remote_on.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_technichub_off.svg b/doc/main/blockimg/pybricks_blockLightOnColor_technichub_off.svg
new file mode 100644
index 00000000..60771231
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_technichub_off.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOnColor_technichub_on.svg b/doc/main/blockimg/pybricks_blockLightOnColor_technichub_on.svg
new file mode 100644
index 00000000..c797cb2f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOnColor_technichub_on.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOn_colorsensor_off.svg b/doc/main/blockimg/pybricks_blockLightOn_colorsensor_off.svg
new file mode 100644
index 00000000..fc3de1d9
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOn_colorsensor_off.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOn_colorsensor_on.svg b/doc/main/blockimg/pybricks_blockLightOn_colorsensor_on.svg
new file mode 100644
index 00000000..2ded1b5b
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOn_colorsensor_on.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOn_colorsensor_on_list.svg b/doc/main/blockimg/pybricks_blockLightOn_colorsensor_on_list.svg
new file mode 100644
index 00000000..b2eb99b6
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOn_colorsensor_on_list.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOn_light_off.svg b/doc/main/blockimg/pybricks_blockLightOn_light_off.svg
new file mode 100644
index 00000000..bbfa5968
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOn_light_off.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOn_light_on.svg b/doc/main/blockimg/pybricks_blockLightOn_light_on.svg
new file mode 100644
index 00000000..bb8f4491
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOn_light_on.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOn_ultrasonicsensor_off.svg b/doc/main/blockimg/pybricks_blockLightOn_ultrasonicsensor_off.svg
new file mode 100644
index 00000000..2120e77d
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOn_ultrasonicsensor_off.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOn_ultrasonicsensor_on.svg b/doc/main/blockimg/pybricks_blockLightOn_ultrasonicsensor_on.svg
new file mode 100644
index 00000000..0f52bd16
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOn_ultrasonicsensor_on.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightOn_ultrasonicsensor_on_list.svg b/doc/main/blockimg/pybricks_blockLightOn_ultrasonicsensor_on_list.svg
new file mode 100644
index 00000000..0d67258e
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightOn_ultrasonicsensor_on_list.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightReflection_ColorDistanceSensor.svg b/doc/main/blockimg/pybricks_blockLightReflection_ColorDistanceSensor.svg
new file mode 100644
index 00000000..c59c8cd7
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightReflection_ColorDistanceSensor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightReflection_ColorSensor.svg b/doc/main/blockimg/pybricks_blockLightReflection_ColorSensor.svg
new file mode 100644
index 00000000..23afad58
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightReflection_ColorSensor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLightReflection_InfraredSensor.svg b/doc/main/blockimg/pybricks_blockLightReflection_InfraredSensor.svg
new file mode 100644
index 00000000..00805101
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLightReflection_InfraredSensor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockListCreate_list_3.svg b/doc/main/blockimg/pybricks_blockListCreate_list_3.svg
new file mode 100644
index 00000000..7161e30c
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListCreate_list_3.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockListCreate_list_empty.svg b/doc/main/blockimg/pybricks_blockListCreate_list_empty.svg
new file mode 100644
index 00000000..e4f07a77
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListCreate_list_empty.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockListGet_list_get_first.svg b/doc/main/blockimg/pybricks_blockListGet_list_get_first.svg
new file mode 100644
index 00000000..e9642d7d
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListGet_list_get_first.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockListGet_list_get_index.svg b/doc/main/blockimg/pybricks_blockListGet_list_get_index.svg
new file mode 100644
index 00000000..7e268a8e
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListGet_list_get_index.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockListGet_list_get_last.svg b/doc/main/blockimg/pybricks_blockListGet_list_get_last.svg
new file mode 100644
index 00000000..9cf25957
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListGet_list_get_last.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockListGet_list_get_random.svg b/doc/main/blockimg/pybricks_blockListGet_list_get_random.svg
new file mode 100644
index 00000000..90ef7ca7
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListGet_list_get_random.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockListLength.svg b/doc/main/blockimg/pybricks_blockListLength.svg
new file mode 100644
index 00000000..45ed000a
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListLength.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockListSet_list_insert_first.svg b/doc/main/blockimg/pybricks_blockListSet_list_insert_first.svg
new file mode 100644
index 00000000..f4493a5f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListSet_list_insert_first.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockListSet_list_insert_index.svg b/doc/main/blockimg/pybricks_blockListSet_list_insert_index.svg
new file mode 100644
index 00000000..cd67b763
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListSet_list_insert_index.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockListSet_list_insert_last.svg b/doc/main/blockimg/pybricks_blockListSet_list_insert_last.svg
new file mode 100644
index 00000000..1213dcaf
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListSet_list_insert_last.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockListSet_list_remove_first.svg b/doc/main/blockimg/pybricks_blockListSet_list_remove_first.svg
new file mode 100644
index 00000000..e1412958
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListSet_list_remove_first.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockListSet_list_remove_index.svg b/doc/main/blockimg/pybricks_blockListSet_list_remove_index.svg
new file mode 100644
index 00000000..bad6d83b
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListSet_list_remove_index.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockListSet_list_remove_last.svg b/doc/main/blockimg/pybricks_blockListSet_list_remove_last.svg
new file mode 100644
index 00000000..697d0713
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListSet_list_remove_last.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockListSet_list_set_first.svg b/doc/main/blockimg/pybricks_blockListSet_list_set_first.svg
new file mode 100644
index 00000000..47a46724
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListSet_list_set_first.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockListSet_list_set_index.svg b/doc/main/blockimg/pybricks_blockListSet_list_set_index.svg
new file mode 100644
index 00000000..021529e1
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListSet_list_set_index.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockListSet_list_set_last.svg b/doc/main/blockimg/pybricks_blockListSet_list_set_last.svg
new file mode 100644
index 00000000..0f56c21e
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListSet_list_set_last.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockListUnpack.svg b/doc/main/blockimg/pybricks_blockListUnpack.svg
new file mode 100644
index 00000000..a326fc3b
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockListUnpack.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLogicCompareDouble.svg b/doc/main/blockimg/pybricks_blockLogicCompareDouble.svg
new file mode 100644
index 00000000..f897f0ac
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicCompareDouble.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLogicCompare_eq.svg b/doc/main/blockimg/pybricks_blockLogicCompare_eq.svg
new file mode 100644
index 00000000..dfa81b99
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicCompare_eq.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLogicCompare_gt.svg b/doc/main/blockimg/pybricks_blockLogicCompare_gt.svg
new file mode 100644
index 00000000..3cf0e9a6
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicCompare_gt.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLogicCompare_gte.svg b/doc/main/blockimg/pybricks_blockLogicCompare_gte.svg
new file mode 100644
index 00000000..0b220885
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicCompare_gte.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLogicCompare_lt.svg b/doc/main/blockimg/pybricks_blockLogicCompare_lt.svg
new file mode 100644
index 00000000..a3da597d
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicCompare_lt.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLogicCompare_lte.svg b/doc/main/blockimg/pybricks_blockLogicCompare_lte.svg
new file mode 100644
index 00000000..95d86b72
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicCompare_lte.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLogicCompare_neq.svg b/doc/main/blockimg/pybricks_blockLogicCompare_neq.svg
new file mode 100644
index 00000000..3d72a855
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicCompare_neq.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLogicIsNone_is_none.svg b/doc/main/blockimg/pybricks_blockLogicIsNone_is_none.svg
new file mode 100644
index 00000000..966bdec7
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicIsNone_is_none.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLogicIsNone_is_not_none.svg b/doc/main/blockimg/pybricks_blockLogicIsNone_is_not_none.svg
new file mode 100644
index 00000000..4011ff57
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicIsNone_is_not_none.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLogicIsNone_not.svg b/doc/main/blockimg/pybricks_blockLogicIsNone_not.svg
new file mode 100644
index 00000000..0a6cc019
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicIsNone_not.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLogicOperation_and.svg b/doc/main/blockimg/pybricks_blockLogicOperation_and.svg
new file mode 100644
index 00000000..29023f9b
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicOperation_and.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLogicOperation_or.svg b/doc/main/blockimg/pybricks_blockLogicOperation_or.svg
new file mode 100644
index 00000000..d186d5b2
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicOperation_or.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLogicTernary.svg b/doc/main/blockimg/pybricks_blockLogicTernary.svg
new file mode 100644
index 00000000..f6169b58
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicTernary.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLogicTernaryDouble.svg b/doc/main/blockimg/pybricks_blockLogicTernaryDouble.svg
new file mode 100644
index 00000000..8997100e
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicTernaryDouble.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockLogicTrueFalse_false.svg b/doc/main/blockimg/pybricks_blockLogicTrueFalse_false.svg
new file mode 100644
index 00000000..0f36fc84
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicTrueFalse_false.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockLogicTrueFalse_true.svg b/doc/main/blockimg/pybricks_blockLogicTrueFalse_true.svg
new file mode 100644
index 00000000..217090fa
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockLogicTrueFalse_true.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathArithmetic_add.svg b/doc/main/blockimg/pybricks_blockMathArithmetic_add.svg
new file mode 100644
index 00000000..3bf27758
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathArithmetic_add.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathArithmetic_divide.svg b/doc/main/blockimg/pybricks_blockMathArithmetic_divide.svg
new file mode 100644
index 00000000..b2273965
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathArithmetic_divide.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathArithmetic_minus.svg b/doc/main/blockimg/pybricks_blockMathArithmetic_minus.svg
new file mode 100644
index 00000000..fb7f3283
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathArithmetic_minus.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathArithmetic_multiply.svg b/doc/main/blockimg/pybricks_blockMathArithmetic_multiply.svg
new file mode 100644
index 00000000..85d89283
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathArithmetic_multiply.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathArithmetic_power.svg b/doc/main/blockimg/pybricks_blockMathArithmetic_power.svg
new file mode 100644
index 00000000..66c3ffd0
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathArithmetic_power.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathFormula.svg b/doc/main/blockimg/pybricks_blockMathFormula.svg
new file mode 100644
index 00000000..1ef95121
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathFormula.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_abs.svg b/doc/main/blockimg/pybricks_blockMathOp_abs.svg
new file mode 100644
index 00000000..62bb32e0
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_abs.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_acos.svg b/doc/main/blockimg/pybricks_blockMathOp_acos.svg
new file mode 100644
index 00000000..a05815af
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_acos.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_asin.svg b/doc/main/blockimg/pybricks_blockMathOp_asin.svg
new file mode 100644
index 00000000..28ab3096
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_asin.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_atan.svg b/doc/main/blockimg/pybricks_blockMathOp_atan.svg
new file mode 100644
index 00000000..8932de8c
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_atan.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_atan2.svg b/doc/main/blockimg/pybricks_blockMathOp_atan2.svg
new file mode 100644
index 00000000..98b79111
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_atan2.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_cos.svg b/doc/main/blockimg/pybricks_blockMathOp_cos.svg
new file mode 100644
index 00000000..a16dc6fa
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_cos.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_exp.svg b/doc/main/blockimg/pybricks_blockMathOp_exp.svg
new file mode 100644
index 00000000..85e4d2b1
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_exp.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_ln.svg b/doc/main/blockimg/pybricks_blockMathOp_ln.svg
new file mode 100644
index 00000000..c849b678
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_ln.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_max.svg b/doc/main/blockimg/pybricks_blockMathOp_max.svg
new file mode 100644
index 00000000..67dc57f6
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_max.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_min.svg b/doc/main/blockimg/pybricks_blockMathOp_min.svg
new file mode 100644
index 00000000..db085ce8
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_min.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_modulo.svg b/doc/main/blockimg/pybricks_blockMathOp_modulo.svg
new file mode 100644
index 00000000..e97e97bb
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_modulo.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_pow10.svg b/doc/main/blockimg/pybricks_blockMathOp_pow10.svg
new file mode 100644
index 00000000..020cbad8
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_pow10.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_root.svg b/doc/main/blockimg/pybricks_blockMathOp_root.svg
new file mode 100644
index 00000000..37c0916f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_root.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_round.svg b/doc/main/blockimg/pybricks_blockMathOp_round.svg
new file mode 100644
index 00000000..e5b49892
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_round.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_rounddown.svg b/doc/main/blockimg/pybricks_blockMathOp_rounddown.svg
new file mode 100644
index 00000000..2259f503
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_rounddown.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_roundup.svg b/doc/main/blockimg/pybricks_blockMathOp_roundup.svg
new file mode 100644
index 00000000..70a120f1
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_roundup.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_sin.svg b/doc/main/blockimg/pybricks_blockMathOp_sin.svg
new file mode 100644
index 00000000..9d3d9410
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_sin.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMathOp_tan.svg b/doc/main/blockimg/pybricks_blockMathOp_tan.svg
new file mode 100644
index 00000000..a507d6bb
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMathOp_tan.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorConfigure_motor_acceleration.svg b/doc/main/blockimg/pybricks_blockMotorConfigure_motor_acceleration.svg
new file mode 100644
index 00000000..40cd5f65
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorConfigure_motor_acceleration.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorConfigure_motor_max_speed.svg b/doc/main/blockimg/pybricks_blockMotorConfigure_motor_max_speed.svg
new file mode 100644
index 00000000..eeb379f9
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorConfigure_motor_max_speed.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorConfigure_motor_max_torque.svg b/doc/main/blockimg/pybricks_blockMotorConfigure_motor_max_torque.svg
new file mode 100644
index 00000000..b869bfb9
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorConfigure_motor_max_torque.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorConfigure_motor_max_voltage.svg b/doc/main/blockimg/pybricks_blockMotorConfigure_motor_max_voltage.svg
new file mode 100644
index 00000000..e2caffd5
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorConfigure_motor_max_voltage.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorConfigure_motor_target_tolerances.svg b/doc/main/blockimg/pybricks_blockMotorConfigure_motor_target_tolerances.svg
new file mode 100644
index 00000000..47f468db
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorConfigure_motor_target_tolerances.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorDuty_DCMotor.svg b/doc/main/blockimg/pybricks_blockMotorDuty_DCMotor.svg
new file mode 100644
index 00000000..f6cf6bbc
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorDuty_DCMotor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorDuty_Motor.svg b/doc/main/blockimg/pybricks_blockMotorDuty_Motor.svg
new file mode 100644
index 00000000..09e511d1
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorDuty_Motor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorDuty_PFMotor.svg b/doc/main/blockimg/pybricks_blockMotorDuty_PFMotor.svg
new file mode 100644
index 00000000..ba92e232
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorDuty_PFMotor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorMeasure_motor_angle.svg b/doc/main/blockimg/pybricks_blockMotorMeasure_motor_angle.svg
new file mode 100644
index 00000000..4cb684a5
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorMeasure_motor_angle.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorMeasure_motor_get_speed_average.svg b/doc/main/blockimg/pybricks_blockMotorMeasure_motor_get_speed_average.svg
new file mode 100644
index 00000000..22d2ded8
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorMeasure_motor_get_speed_average.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorMeasure_motor_load.svg b/doc/main/blockimg/pybricks_blockMotorMeasure_motor_load.svg
new file mode 100644
index 00000000..84ed5da3
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorMeasure_motor_load.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorMeasure_motor_speed.svg b/doc/main/blockimg/pybricks_blockMotorMeasure_motor_speed.svg
new file mode 100644
index 00000000..dd21ec1e
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorMeasure_motor_speed.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorMeasure_motor_stalled.svg b/doc/main/blockimg/pybricks_blockMotorMeasure_motor_stalled.svg
new file mode 100644
index 00000000..ba363a8f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorMeasure_motor_stalled.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorResetAngle.svg b/doc/main/blockimg/pybricks_blockMotorResetAngle.svg
new file mode 100644
index 00000000..660e3e55
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorResetAngle.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorRun_run.svg b/doc/main/blockimg/pybricks_blockMotorRun_run.svg
new file mode 100644
index 00000000..2193fe91
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorRun_run.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorRun_run_angle.svg b/doc/main/blockimg/pybricks_blockMotorRun_run_angle.svg
new file mode 100644
index 00000000..d9a0f5f8
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorRun_run_angle.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorRun_run_target.svg b/doc/main/blockimg/pybricks_blockMotorRun_run_target.svg
new file mode 100644
index 00000000..9d4bdc44
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorRun_run_target.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorRun_run_until_stalled.svg b/doc/main/blockimg/pybricks_blockMotorRun_run_until_stalled.svg
new file mode 100644
index 00000000..ebb25107
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorRun_run_until_stalled.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorStop_DCMotor_brake.svg b/doc/main/blockimg/pybricks_blockMotorStop_DCMotor_brake.svg
new file mode 100644
index 00000000..0d9ccc05
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorStop_DCMotor_brake.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorStop_DCMotor_coast.svg b/doc/main/blockimg/pybricks_blockMotorStop_DCMotor_coast.svg
new file mode 100644
index 00000000..0ebb377b
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorStop_DCMotor_coast.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorStop_Motor_brake.svg b/doc/main/blockimg/pybricks_blockMotorStop_Motor_brake.svg
new file mode 100644
index 00000000..cb8fdaa2
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorStop_Motor_brake.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorStop_Motor_coast.svg b/doc/main/blockimg/pybricks_blockMotorStop_Motor_coast.svg
new file mode 100644
index 00000000..d853fae4
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorStop_Motor_coast.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorStop_Motor_hold.svg b/doc/main/blockimg/pybricks_blockMotorStop_Motor_hold.svg
new file mode 100644
index 00000000..0168968c
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorStop_Motor_hold.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorStop_PFMotor_brake.svg b/doc/main/blockimg/pybricks_blockMotorStop_PFMotor_brake.svg
new file mode 100644
index 00000000..5c6d75d6
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorStop_PFMotor_brake.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorStop_PFMotor_coast.svg b/doc/main/blockimg/pybricks_blockMotorStop_PFMotor_coast.svg
new file mode 100644
index 00000000..79dda5ed
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorStop_PFMotor_coast.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMotorTrack.svg b/doc/main/blockimg/pybricks_blockMotorTrack.svg
new file mode 100644
index 00000000..48ee4be8
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMotorTrack.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockMultiTask.svg b/doc/main/blockimg/pybricks_blockMultiTask.svg
new file mode 100644
index 00000000..064cc374
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockMultiTask.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockPrint_print_basic.svg b/doc/main/blockimg/pybricks_blockPrint_print_basic.svg
new file mode 100644
index 00000000..620512b8
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockPrint_print_basic.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockPrint_print_multiple.svg b/doc/main/blockimg/pybricks_blockPrint_print_multiple.svg
new file mode 100644
index 00000000..80b2b788
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockPrint_print_multiple.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockProgramStop.svg b/doc/main/blockimg/pybricks_blockProgramStop.svg
new file mode 100644
index 00000000..4d180f20
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockProgramStop.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockRandInt.svg b/doc/main/blockimg/pybricks_blockRandInt.svg
new file mode 100644
index 00000000..be48019a
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockRandInt.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockReadInput_read_input_first_byte.svg b/doc/main/blockimg/pybricks_blockReadInput_read_input_first_byte.svg
new file mode 100644
index 00000000..0e7dfea3
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockReadInput_read_input_first_byte.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockReadInput_read_input_first_char.svg b/doc/main/blockimg/pybricks_blockReadInput_read_input_first_char.svg
new file mode 100644
index 00000000..1096f597
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockReadInput_read_input_first_char.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockReadInput_read_input_last_byte.svg b/doc/main/blockimg/pybricks_blockReadInput_read_input_last_byte.svg
new file mode 100644
index 00000000..bd0e8d77
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockReadInput_read_input_last_byte.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockReadInput_read_input_last_char.svg b/doc/main/blockimg/pybricks_blockReadInput_read_input_last_char.svg
new file mode 100644
index 00000000..7c978b52
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockReadInput_read_input_last_char.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_blockSpeakerBeep_PrimeHub.svg b/doc/main/blockimg/pybricks_blockSpeakerBeep_PrimeHub.svg
new file mode 100644
index 00000000..ac00122a
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockSpeakerBeep_PrimeHub.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockStopWatchDo_StopWatch_pause.svg b/doc/main/blockimg/pybricks_blockStopWatchDo_StopWatch_pause.svg
new file mode 100644
index 00000000..fce54116
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockStopWatchDo_StopWatch_pause.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockStopWatchDo_StopWatch_reset.svg b/doc/main/blockimg/pybricks_blockStopWatchDo_StopWatch_reset.svg
new file mode 100644
index 00000000..0ec2af71
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockStopWatchDo_StopWatch_reset.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockStopWatchDo_StopWatch_resume.svg b/doc/main/blockimg/pybricks_blockStopWatchDo_StopWatch_resume.svg
new file mode 100644
index 00000000..752357f7
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockStopWatchDo_StopWatch_resume.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockStopWatchTime.svg b/doc/main/blockimg/pybricks_blockStopWatchTime.svg
new file mode 100644
index 00000000..0bc2b886
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockStopWatchTime.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockTaskReturn.svg b/doc/main/blockimg/pybricks_blockTaskReturn.svg
new file mode 100644
index 00000000..7b253180
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockTaskReturn.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockTextLiteral.svg b/doc/main/blockimg/pybricks_blockTextLiteral.svg
new file mode 100644
index 00000000..57ed31f4
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockTextLiteral.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockTilt_EssentialHub_imu.tilt.pitch.svg b/doc/main/blockimg/pybricks_blockTilt_EssentialHub_imu.tilt.pitch.svg
new file mode 100644
index 00000000..bcf86dea
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockTilt_EssentialHub_imu.tilt.pitch.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockTilt_EssentialHub_imu.tilt.roll.svg b/doc/main/blockimg/pybricks_blockTilt_EssentialHub_imu.tilt.roll.svg
new file mode 100644
index 00000000..90972b5b
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockTilt_EssentialHub_imu.tilt.roll.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockTilt_MoveHub_imu.tilt.pitch.svg b/doc/main/blockimg/pybricks_blockTilt_MoveHub_imu.tilt.pitch.svg
new file mode 100644
index 00000000..4c916ff2
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockTilt_MoveHub_imu.tilt.pitch.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockTilt_MoveHub_imu.tilt.roll.svg b/doc/main/blockimg/pybricks_blockTilt_MoveHub_imu.tilt.roll.svg
new file mode 100644
index 00000000..196ea993
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockTilt_MoveHub_imu.tilt.roll.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockTilt_PrimeHub_imu.tilt.pitch.svg b/doc/main/blockimg/pybricks_blockTilt_PrimeHub_imu.tilt.pitch.svg
new file mode 100644
index 00000000..a42f9080
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockTilt_PrimeHub_imu.tilt.pitch.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockTilt_PrimeHub_imu.tilt.roll.svg b/doc/main/blockimg/pybricks_blockTilt_PrimeHub_imu.tilt.roll.svg
new file mode 100644
index 00000000..a78abdb5
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockTilt_PrimeHub_imu.tilt.roll.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockTilt_TechnicHub_imu.tilt.pitch.svg b/doc/main/blockimg/pybricks_blockTilt_TechnicHub_imu.tilt.pitch.svg
new file mode 100644
index 00000000..d112f9b5
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockTilt_TechnicHub_imu.tilt.pitch.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockTilt_TechnicHub_imu.tilt.roll.svg b/doc/main/blockimg/pybricks_blockTilt_TechnicHub_imu.tilt.roll.svg
new file mode 100644
index 00000000..f72baa1a
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockTilt_TechnicHub_imu.tilt.roll.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockTilt_TiltSensor_imu.tilt.pitch.svg b/doc/main/blockimg/pybricks_blockTilt_TiltSensor_imu.tilt.pitch.svg
new file mode 100644
index 00000000..c704bcb0
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockTilt_TiltSensor_imu.tilt.pitch.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockTilt_TiltSensor_imu.tilt.roll.svg b/doc/main/blockimg/pybricks_blockTilt_TiltSensor_imu.tilt.roll.svg
new file mode 100644
index 00000000..1f174f26
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockTilt_TiltSensor_imu.tilt.roll.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockVariableGetValue.svg b/doc/main/blockimg/pybricks_blockVariableGetValue.svg
new file mode 100644
index 00000000..eacd3ffd
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockVariableGetValue.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockVariableSetValue.svg b/doc/main/blockimg/pybricks_blockVariableSetValue.svg
new file mode 100644
index 00000000..37f204ef
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockVariableSetValue.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockVector.svg b/doc/main/blockimg/pybricks_blockVector.svg
new file mode 100644
index 00000000..adb5bd14
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockVector.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockWaitForever.svg b/doc/main/blockimg/pybricks_blockWaitForever.svg
new file mode 100644
index 00000000..ded7bf9c
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockWaitForever.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockWaitTime.svg b/doc/main/blockimg/pybricks_blockWaitTime.svg
new file mode 100644
index 00000000..9d95da33
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockWaitTime.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_blockWaitUntil.svg b/doc/main/blockimg/pybricks_blockWaitUntil.svg
new file mode 100644
index 00000000..92773397
--- /dev/null
+++ b/doc/main/blockimg/pybricks_blockWaitUntil.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_car.svg b/doc/main/blockimg/pybricks_variables_set_car.svg
new file mode 100644
index 00000000..dea02178
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_car.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_variables_set_city_hub_option0.svg b/doc/main/blockimg/pybricks_variables_set_city_hub_option0.svg
new file mode 100644
index 00000000..dc7483cf
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_city_hub_option0.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_city_hub_option3.svg b/doc/main/blockimg/pybricks_variables_set_city_hub_option3.svg
new file mode 100644
index 00000000..12cc11ff
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_city_hub_option3.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_color_distance_sensor_colordistancesensor_default.svg b/doc/main/blockimg/pybricks_variables_set_color_distance_sensor_colordistancesensor_default.svg
new file mode 100644
index 00000000..a5992511
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_color_distance_sensor_colordistancesensor_default.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_color_distance_sensor_colordistancesensor_detectable_colors.svg b/doc/main/blockimg/pybricks_variables_set_color_distance_sensor_colordistancesensor_detectable_colors.svg
new file mode 100644
index 00000000..b74278ca
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_color_distance_sensor_colordistancesensor_detectable_colors.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_color_light_matrix.svg b/doc/main/blockimg/pybricks_variables_set_color_light_matrix.svg
new file mode 100644
index 00000000..302e9ee4
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_color_light_matrix.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_color_sensor_colorsensor_default.svg b/doc/main/blockimg/pybricks_variables_set_color_sensor_colorsensor_default.svg
new file mode 100644
index 00000000..190266e9
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_color_sensor_colorsensor_default.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_color_sensor_colorsensor_detectable_colors.svg b/doc/main/blockimg/pybricks_variables_set_color_sensor_colorsensor_detectable_colors.svg
new file mode 100644
index 00000000..69ca91c2
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_color_sensor_colorsensor_detectable_colors.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_dc_motor.svg b/doc/main/blockimg/pybricks_variables_set_dc_motor.svg
new file mode 100644
index 00000000..1a789683
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_dc_motor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_drive_base.svg b/doc/main/blockimg/pybricks_variables_set_drive_base.svg
new file mode 100644
index 00000000..365109e4
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_drive_base.svg
@@ -0,0 +1,989 @@
+
+
\ No newline at end of file
diff --git a/doc/main/blockimg/pybricks_variables_set_essential_hub_option0.svg b/doc/main/blockimg/pybricks_variables_set_essential_hub_option0.svg
new file mode 100644
index 00000000..edad736a
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_essential_hub_option0.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_essential_hub_option4.svg b/doc/main/blockimg/pybricks_variables_set_essential_hub_option4.svg
new file mode 100644
index 00000000..62890c51
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_essential_hub_option4.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_force_sensor.svg b/doc/main/blockimg/pybricks_variables_set_force_sensor.svg
new file mode 100644
index 00000000..ec98239f
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_force_sensor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_infrared_sensor.svg b/doc/main/blockimg/pybricks_variables_set_infrared_sensor.svg
new file mode 100644
index 00000000..344f8787
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_infrared_sensor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_inventor_hub_option0.svg b/doc/main/blockimg/pybricks_variables_set_inventor_hub_option0.svg
new file mode 100644
index 00000000..3e9b5f9c
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_inventor_hub_option0.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_inventor_hub_option4.svg b/doc/main/blockimg/pybricks_variables_set_inventor_hub_option4.svg
new file mode 100644
index 00000000..15bea6ab
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_inventor_hub_option4.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_light.svg b/doc/main/blockimg/pybricks_variables_set_light.svg
new file mode 100644
index 00000000..0f6c6635
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_light.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_motor.svg b/doc/main/blockimg/pybricks_variables_set_motor.svg
new file mode 100644
index 00000000..1fa98f18
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_motor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_move_hub_option0.svg b/doc/main/blockimg/pybricks_variables_set_move_hub_option0.svg
new file mode 100644
index 00000000..e6ef2405
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_move_hub_option0.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_move_hub_option4.svg b/doc/main/blockimg/pybricks_variables_set_move_hub_option4.svg
new file mode 100644
index 00000000..62fd5098
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_move_hub_option4.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_pf_motor.svg b/doc/main/blockimg/pybricks_variables_set_pf_motor.svg
new file mode 100644
index 00000000..38a7e11a
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_pf_motor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_prime_hub_option0.svg b/doc/main/blockimg/pybricks_variables_set_prime_hub_option0.svg
new file mode 100644
index 00000000..d3c4eb19
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_prime_hub_option0.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_prime_hub_option4.svg b/doc/main/blockimg/pybricks_variables_set_prime_hub_option4.svg
new file mode 100644
index 00000000..35533391
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_prime_hub_option4.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_remote_connect_any.svg b/doc/main/blockimg/pybricks_variables_set_remote_connect_any.svg
new file mode 100644
index 00000000..5c699574
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_remote_connect_any.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_remote_connect_name.svg b/doc/main/blockimg/pybricks_variables_set_remote_connect_name.svg
new file mode 100644
index 00000000..95286cb7
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_remote_connect_name.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_remote_connect_rename.svg b/doc/main/blockimg/pybricks_variables_set_remote_connect_rename.svg
new file mode 100644
index 00000000..ba5470ac
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_remote_connect_rename.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_stopwatch.svg b/doc/main/blockimg/pybricks_variables_set_stopwatch.svg
new file mode 100644
index 00000000..12128928
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_stopwatch.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_technic_hub_option0.svg b/doc/main/blockimg/pybricks_variables_set_technic_hub_option0.svg
new file mode 100644
index 00000000..10223e81
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_technic_hub_option0.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_technic_hub_option4.svg b/doc/main/blockimg/pybricks_variables_set_technic_hub_option4.svg
new file mode 100644
index 00000000..271d551d
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_technic_hub_option4.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_tilt_sensor.svg b/doc/main/blockimg/pybricks_variables_set_tilt_sensor.svg
new file mode 100644
index 00000000..ed516ceb
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_tilt_sensor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_ultrasonic_sensor.svg b/doc/main/blockimg/pybricks_variables_set_ultrasonic_sensor.svg
new file mode 100644
index 00000000..566026fc
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_ultrasonic_sensor.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_set_xbox_controller.svg b/doc/main/blockimg/pybricks_variables_set_xbox_controller.svg
new file mode 100644
index 00000000..d605d262
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_set_xbox_controller.svg
@@ -0,0 +1,989 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_setup_any.svg b/doc/main/blockimg/pybricks_variables_setup_any.svg
new file mode 100644
index 00000000..0dba5975
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_setup_any.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_setup_function_basic.svg b/doc/main/blockimg/pybricks_variables_setup_function_basic.svg
new file mode 100644
index 00000000..b8c9a736
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_setup_function_basic.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_setup_function_with_args.svg b/doc/main/blockimg/pybricks_variables_setup_function_with_args.svg
new file mode 100644
index 00000000..7346fef6
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_setup_function_with_args.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blockimg/pybricks_variables_setup_imported_function.svg b/doc/main/blockimg/pybricks_variables_setup_imported_function.svg
new file mode 100644
index 00000000..33f0bceb
--- /dev/null
+++ b/doc/main/blockimg/pybricks_variables_setup_imported_function.svg
@@ -0,0 +1,975 @@
+
+
diff --git a/doc/main/blocks/index.rst b/doc/main/blocks/index.rst
new file mode 100644
index 00000000..53cd483f
--- /dev/null
+++ b/doc/main/blocks/index.rst
@@ -0,0 +1,148 @@
+.. pybricks-requirements::
+
+Other blocks
+=====================================================
+
+Most blocks correspond directly to one of the documented Python commands. This
+page lists the remaining blocks.
+
+This page will be expanded with more details in the next release.
+
+Math
+------------------------
+
+See also :mod:`umath` for other math operations.
+
+.. blockimg:: pybricks_blockMathFormula
+
+.. blockimg:: pybricks_blockMathOp_modulo
+
+.. blockimg:: pybricks_blockMathArithmetic_add
+
+.. blockimg:: pybricks_blockMathArithmetic_minus
+
+.. blockimg:: pybricks_blockMathArithmetic_multiply
+
+.. blockimg:: pybricks_blockMathArithmetic_divide
+
+.. blockimg:: pybricks_blockMathArithmetic_power
+
+Logic
+--------------------------
+
+.. blockimg:: pybricks_blockLogicCompareDouble
+
+.. blockimg:: pybricks_blockLogicCompare_eq
+
+.. blockimg:: pybricks_blockLogicCompare_gte
+
+.. blockimg:: pybricks_blockLogicCompare_gt
+
+.. blockimg:: pybricks_blockLogicCompare_lte
+
+.. blockimg:: pybricks_blockLogicCompare_lt
+
+.. blockimg:: pybricks_blockLogicCompare_neq
+
+.. blockimg:: pybricks_blockLogicIsNone_is_none
+
+.. blockimg:: pybricks_blockLogicIsNone_is_not_none
+
+.. blockimg:: pybricks_blockLogicIsNone_not
+
+.. blockimg:: pybricks_blockLogicOperation_and
+
+.. blockimg:: pybricks_blockLogicOperation_or
+
+.. blockimg:: pybricks_blockLogicTernary
+
+.. blockimg:: pybricks_blockLogicTernaryDouble
+
+.. blockimg:: pybricks_blockIsIn
+
+Flow
+--------------------------
+
+.. blockimg:: pybricks_blockFlowBreakContinue_break
+
+.. blockimg:: pybricks_blockFlowBreakContinue_continue
+
+.. blockimg:: pybricks_blockFlowForEach_loop_for
+
+.. blockimg:: pybricks_blockFlowForEach_loop_for_list
+
+.. blockimg:: pybricks_blockFlowForEach_loop_for_range
+
+.. blockimg:: pybricks_blockFlowRepeat
+
+.. blockimg:: pybricks_blockFlowWhile_until
+
+.. blockimg:: pybricks_blockFlowWhile_while
+
+
+.. blockimg:: pybricks_blockIfElse_if_else
+
+.. blockimg:: pybricks_blockIfElse_if_else_else
+
+.. blockimg:: pybricks_blockIfElse_if_only
+
+
+Device and system setup
+--------------------------
+
+.. blockimg:: pybricks_blockGlobalSetup
+
+Waiting
+------------------------
+
+.. blockimg:: pybricks_blockWaitTime
+
+.. blockimg:: pybricks_blockWaitUntil
+
+.. blockimg:: pybricks_blockWaitForever
+
+
+
+Variables
+--------------------------
+
+.. blockimg:: pybricks_variables_setup_any
+
+.. blockimg:: pybricks_blockVariableGetValue
+
+.. blockimg:: pybricks_blockVariableSetValue
+
+Multitasking
+--------------------------
+
+.. blockimg:: pybricks_blockGlobalStart
+
+.. blockimg:: pybricks_blockMultiTask
+
+Your own tasks
+--------------------------
+
+.. blockimg:: pybricks_variables_setup_function_basic
+
+.. blockimg:: pybricks_variables_setup_function_with_args
+
+.. blockimg:: pybricks_blockTaskReturn
+
+External tasks
+--------------------------
+
+.. blockimg:: pybricks_variables_setup_imported_function
+
+.. blockimg:: pybricks_blockImportTaskCallStatement
+
+.. blockimg:: pybricks_blockImportTaskCallValue
+
+Comments
+--------------------------
+
+.. blockimg:: pybricks_blockComment
+
+Stopping programs
+--------------------------
+
+.. blockimg:: pybricks_blockProgramStop
diff --git a/doc/main/conf.py b/doc/main/conf.py
index 212f11a6..f6d3b063 100644
--- a/doc/main/conf.py
+++ b/doc/main/conf.py
@@ -8,7 +8,7 @@
# General information about the project.
project = "pybricks"
-copyright = "2018-2021 The Pybricks Authors"
+copyright = "2018-2023 The Pybricks Authors"
author = ""
_TITLE = "Pybricks Modules and Examples"
@@ -29,12 +29,14 @@
# HACK: this allows Number type alias to be imported by Sphinx
os.environ["SPHINX_BUILD"] = "True"
-# Addtional configuration of the IDE docs
+html_css_files = ["css/blocks.css"]
+
+# Additional configuration of the IDE docs
if "ide" in tags.tags: # noqa F821
_DISCLAIMER = ""
html_show_copyright = False
html_show_sphinx = False
- html_css_files = ["css/ide.css"]
+ html_css_files.append("css/ide.css")
html_js_files = ["js/ide.js"]
imgmath_image_format = "svg"
@@ -45,9 +47,8 @@
exec(open(os.path.abspath("../common/conf.py")).read())
-# Addtional configuration of the IDE docs
+# Additional configuration of the IDE docs
if "ide" in tags.tags: # noqa F821
-
extensions.remove("sphinx.ext.mathjax") # noqa F821
extensions.append("sphinx.ext.imgmath") # noqa F821
html_theme_options["prev_next_buttons_location"] = None # noqa F821
diff --git a/doc/main/diagrams_source/xboxcontroller.png b/doc/main/diagrams_source/xboxcontroller.png
new file mode 100644
index 00000000..c114d75f
Binary files /dev/null and b/doc/main/diagrams_source/xboxcontroller.png differ
diff --git a/doc/main/hubs/cityhub.rst b/doc/main/hubs/cityhub.rst
index 1bc2b9de..401cff5d 100644
--- a/doc/main/hubs/cityhub.rst
+++ b/doc/main/hubs/cityhub.rst
@@ -2,32 +2,65 @@
City Hub
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
.. figure:: ../../main/cad/output/hub-city.png
:width: 30%
+.. blockimg:: pybricks_variables_set_city_hub_option0
+
+.. blockimg:: pybricks_variables_set_city_hub_option3
+ :stack:
+
.. autoclass:: pybricks.hubs.CityHub
:no-members:
.. rubric:: Using the hub status light
+ .. blockimg:: pybricks_blockLightOnColor_cityhub_on
+
.. automethod:: pybricks.hubs::CityHub.light.on
+ .. blockimg:: pybricks_blockLightOnColor_cityhub_off
+
.. automethod:: pybricks.hubs::CityHub.light.off
.. automethod:: pybricks.hubs::CityHub.light.blink
.. automethod:: pybricks.hubs::CityHub.light.animate
+ .. rubric:: Using connectionless Bluetooth messaging
+
+ .. blockimg:: pybricks_blockBleBroadcast_CityHub
+
+ .. automethod:: pybricks.hubs::CityHub.ble.broadcast
+
+ .. blockimg:: pybricks_blockBleObserve_CityHub
+
+ .. automethod:: pybricks.hubs::CityHub.ble.observe
+
+ .. automethod:: pybricks.hubs::CityHub.ble.signal_strength
+
+ .. automethod:: pybricks.hubs::CityHub.ble.version
+
.. rubric:: Using the battery
+ .. blockimg:: pybricks_blockBatteryMeasure_CityHub_battery.voltage
+
.. automethod:: pybricks.hubs::CityHub.battery.voltage
+ .. blockimg:: pybricks_blockBatteryMeasure_CityHub_battery.current
+
.. automethod:: pybricks.hubs::CityHub.battery.current
.. rubric:: Button and system control
- .. automethod:: pybricks.hubs::CityHub.button.pressed
+ .. blockimg:: pybricks_blockButtonIsPressed_CityHub
+
+ .. automethod:: pybricks.hubs::CityHub.buttons.pressed
+
+ .. blockimg:: pybricks_blockHubStopButton_CityHub
+
+ .. blockimg:: pybricks_blockHubStopButton_CityHub_none
+ :stack:
.. automethod:: pybricks.hubs::CityHub.system.set_stop_button
@@ -39,6 +72,8 @@ City Hub
when you update the Pybricks firmware or if you restore the original
firmware.
+ .. blockimg:: pybricks_blockHubShutdown_CityHub
+
.. automethod:: pybricks.hubs::CityHub.system.shutdown
.. automethod:: pybricks.hubs::CityHub.system.reset_reason
@@ -70,6 +105,23 @@ Creating light animations
.. literalinclude::
../../../examples/pup/hub_common/build/light_animate_cityhub.py
+
+Bluetooth examples
+------------------
+
+Broadcasting data to other hubs
+*******************************
+
+.. literalinclude::
+ ../../../examples/pup/hub_common/build/ble_broadcast_cityhub.py
+
+Observing data from other hubs
+******************************
+
+.. literalinclude::
+ ../../../examples/pup/hub_common/build/ble_observe_cityhub.py
+
+
Button and system examples
----------------------------------
diff --git a/doc/main/hubs/essentialhub.rst b/doc/main/hubs/essentialhub.rst
index a24ac1d0..b63516cc 100644
--- a/doc/main/hubs/essentialhub.rst
+++ b/doc/main/hubs/essentialhub.rst
@@ -6,13 +6,22 @@ Essential Hub
.. figure:: ../../main/cad/output/hub-essential.png
:width: 30%
+.. blockimg:: pybricks_variables_set_essential_hub_option0
+
+.. blockimg:: pybricks_variables_set_essential_hub_option4
+ :stack:
+
.. autoclass:: pybricks.hubs.EssentialHub
:no-members:
.. rubric:: Using the hub status light
+ .. blockimg:: pybricks_blockLightOnColor_essentialhub_on
+
.. automethod:: pybricks.hubs::EssentialHub.light.on
+ .. blockimg:: pybricks_blockLightOnColor_essentialhub_off
+
.. automethod:: pybricks.hubs::EssentialHub.light.off
.. automethod:: pybricks.hubs::EssentialHub.light.blink
@@ -21,36 +30,84 @@ Essential Hub
.. rubric:: Using the button
- .. automethod:: pybricks.hubs::EssentialHub.button.pressed
+ .. blockimg:: pybricks_blockButtonIsPressed_EssentialHub
+
+ .. automethod:: pybricks.hubs::EssentialHub.buttons.pressed
+
+ .. blockimg:: pybricks_blockHubStopButton_EssentialHub
+
+ .. blockimg:: pybricks_blockHubStopButton_EssentialHub_none
+ :stack:
+
+ .. automethod:: pybricks.hubs::EssentialHub.system.set_stop_button
.. rubric:: Using the IMU
+ .. blockimg:: pybricks_blockImuStatus_EssentialHub_ready
+
.. automethod:: pybricks.hubs::EssentialHub.imu.ready
+ .. blockimg:: pybricks_blockImuStatus_EssentialHub_stationary
+
.. automethod:: pybricks.hubs::EssentialHub.imu.stationary
+ .. blockimg:: pybricks_blockImuUp_EssentialHub
+
.. automethod:: pybricks.hubs::EssentialHub.imu.up
+ .. blockimg:: pybricks_blockTilt_EssentialHub_imu.tilt.pitch
+
+ .. blockimg:: pybricks_blockTilt_EssentialHub_imu.tilt.roll
+ :stack:
+
.. automethod:: pybricks.hubs::EssentialHub.imu.tilt
+ .. blockimg:: pybricks_blockImuAcceleration_EssentialHub
+
.. automethod:: pybricks.hubs::EssentialHub.imu.acceleration
+ .. blockimg:: pybricks_blockImuRotation_EssentialHub_imu.angular_velocity
+
.. automethod:: pybricks.hubs::EssentialHub.imu.angular_velocity
+ .. blockimg:: pybricks_blockImuGetHeading_EssentialHub
+
.. automethod:: pybricks.hubs::EssentialHub.imu.heading
+ .. blockimg:: pybricks_blockImuResetHeading_EssentialHub
+
.. automethod:: pybricks.hubs::EssentialHub.imu.reset_heading
+ .. blockimg:: pybricks_blockImuRotation_EssentialHub_imu.rotation
+
.. automethod:: pybricks.hubs::EssentialHub.imu.rotation
.. automethod:: pybricks.hubs::EssentialHub.imu.orientation
.. automethod:: pybricks.hubs::EssentialHub.imu.settings
+ .. rubric:: Using connectionless Bluetooth messaging
+
+ .. blockimg:: pybricks_blockBleBroadcast_EssentialHub
+
+ .. automethod:: pybricks.hubs::EssentialHub.ble.broadcast
+
+ .. blockimg:: pybricks_blockBleObserve_EssentialHub
+
+ .. automethod:: pybricks.hubs::EssentialHub.ble.observe
+
+ .. automethod:: pybricks.hubs::EssentialHub.ble.signal_strength
+
+ .. automethod:: pybricks.hubs::EssentialHub.ble.version
+
.. rubric:: Using the battery
+ .. blockimg:: pybricks_blockBatteryMeasure_EssentialHub_battery.voltage
+
.. automethod:: pybricks.hubs::EssentialHub.battery.voltage
+ .. blockimg:: pybricks_blockBatteryMeasure_EssentialHub_battery.current
+
.. automethod:: pybricks.hubs::EssentialHub.battery.current
.. rubric:: Getting the charger status
@@ -63,14 +120,14 @@ Essential Hub
.. rubric:: System control
- .. automethod:: pybricks.hubs::EssentialHub.system.set_stop_button
-
.. automethod:: pybricks.hubs::EssentialHub.system.name
.. automethod:: pybricks.hubs::EssentialHub.system.storage
You can store up to 512 bytes of data on this hub.
+ .. blockimg:: pybricks_blockHubShutdown_EssentialHub
+
.. automethod:: pybricks.hubs::EssentialHub.system.shutdown
.. automethod:: pybricks.hubs::EssentialHub.system.reset_reason
@@ -136,6 +193,23 @@ Reading acceleration and angular velocity on one axis
.. literalinclude::
../../../examples/pup/hub_common/build/imu_read_scalar_essentialhub.py
+
+Bluetooth examples
+------------------
+
+Broadcasting data to other hubs
+*******************************
+
+.. literalinclude::
+ ../../../examples/pup/hub_common/build/ble_broadcast_essentialhub.py
+
+Observing data from other hubs
+******************************
+
+.. literalinclude::
+ ../../../examples/pup/hub_common/build/ble_observe_essentialhub.py
+
+
System examples
----------------------------------
diff --git a/doc/main/hubs/movehub.rst b/doc/main/hubs/movehub.rst
index 2c14ad2c..90643d88 100644
--- a/doc/main/hubs/movehub.rst
+++ b/doc/main/hubs/movehub.rst
@@ -8,13 +8,22 @@ Move Hub
.. figure:: ../../main/diagrams/movehub.png
:width: 100%
+.. blockimg:: pybricks_variables_set_move_hub_option0
+
+.. blockimg:: pybricks_variables_set_move_hub_option4
+ :stack:
+
.. autoclass:: pybricks.hubs.MoveHub
:no-members:
.. rubric:: Using the hub status light
+ .. blockimg:: pybricks_blockLightOnColor_movehub_on
+
.. automethod:: pybricks.hubs::MoveHub.light.on
+ .. blockimg:: pybricks_blockLightOnColor_movehub_off
+
.. automethod:: pybricks.hubs::MoveHub.light.off
.. automethod:: pybricks.hubs::MoveHub.light.blink
@@ -23,23 +32,59 @@ Move Hub
.. rubric:: Using the IMU
+ .. blockimg:: pybricks_blockImuUp_MoveHub
+
.. automethod:: pybricks.hubs::MoveHub.imu.up
+ .. blockimg:: pybricks_blockTilt_MoveHub_imu.tilt.pitch
+
+ .. blockimg:: pybricks_blockTilt_MoveHub_imu.tilt.roll
+ :stack:
+
+ .. automethod:: pybricks.hubs::MoveHub.imu.tilt
+
+ .. blockimg:: pybricks_blockImuAcceleration_MoveHub
+
.. automethod:: pybricks.hubs::MoveHub.imu.acceleration
.. versionchanged:: 3.2
Changed acceleration units from m/s² to mm/s².
+ .. rubric:: Using connectionless Bluetooth messaging
+
+ .. blockimg:: pybricks_blockBleBroadcast_PrimeHub
+
+ .. automethod:: pybricks.hubs::PrimeHub.ble.broadcast
+
+ .. blockimg:: pybricks_blockBleObserve_PrimeHub
+
+ .. automethod:: pybricks.hubs::PrimeHub.ble.observe
+
+ .. automethod:: pybricks.hubs::MoveHub.ble.signal_strength
+
+ .. automethod:: pybricks.hubs::MoveHub.ble.version
+
.. rubric:: Using the battery
+ .. blockimg:: pybricks_blockBatteryMeasure_MoveHub_battery.voltage
+
.. automethod:: pybricks.hubs::MoveHub.battery.voltage
+ .. blockimg:: pybricks_blockBatteryMeasure_MoveHub_battery.current
+
.. automethod:: pybricks.hubs::MoveHub.battery.current
.. rubric:: Button and system control
- .. automethod:: pybricks.hubs::MoveHub.button.pressed
+ .. blockimg:: pybricks_blockButtonIsPressed_PrimeHub
+
+ .. automethod:: pybricks.hubs::MoveHub.buttons.pressed
+
+ .. blockimg:: pybricks_blockHubStopButton_MoveHub
+
+ .. blockimg:: pybricks_blockHubStopButton_MoveHub_none
+ :stack:
.. automethod:: pybricks.hubs::MoveHub.system.set_stop_button
@@ -51,6 +96,8 @@ Move Hub
when you update the Pybricks firmware or if you restore the original
firmware.
+ .. blockimg:: pybricks_blockHubShutdown_MoveHub
+
.. automethod:: pybricks.hubs::MoveHub.system.shutdown
.. automethod:: pybricks.hubs::MoveHub.system.reset_reason
@@ -85,6 +132,23 @@ Reading acceleration
.. literalinclude::
../../../examples/pup/hub_movehub/imu_read_acceleration.py
+
+Bluetooth examples
+------------------
+
+Broadcasting data to other hubs
+*******************************
+
+.. literalinclude::
+ ../../../examples/pup/hub_common/build/ble_broadcast_movehub.py
+
+Observing data from other hubs
+******************************
+
+.. literalinclude::
+ ../../../examples/pup/hub_common/build/ble_observe_movehub.py
+
+
Button and system examples
----------------------------------
diff --git a/doc/main/hubs/primehub.rst b/doc/main/hubs/primehub.rst
index 1390f9ac..89ff24f2 100644
--- a/doc/main/hubs/primehub.rst
+++ b/doc/main/hubs/primehub.rst
@@ -6,6 +6,11 @@ Prime Hub / Inventor Hub
.. figure:: ../../main/cad/output/hub-spike-inventor.png
:width: 80%
+.. blockimg:: pybricks_variables_set_inventor_hub_option0
+
+.. blockimg:: pybricks_variables_set_inventor_hub_option4
+ :stack:
+
.. class:: InventorHub
This class is the same as the ``PrimeHub`` class, shown below. Both classes
@@ -13,6 +18,11 @@ Prime Hub / Inventor Hub
These hubs are completely identical. They use the same Pybricks firmware.
+.. blockimg:: pybricks_variables_set_prime_hub_option0
+
+.. blockimg:: pybricks_variables_set_prime_hub_option4
+ :stack:
+
.. autoclass:: pybricks.hubs.PrimeHub
:no-members:
@@ -21,8 +31,12 @@ Prime Hub / Inventor Hub
.. figure:: ../../main/diagrams/primehub_light.png
:width: 22 em
+ .. blockimg:: pybricks_blockLightOnColor_primehub_on
+
.. automethod:: pybricks.hubs::PrimeHub.light.on
+ .. blockimg:: pybricks_blockLightOnColor_primehub_off
+
.. automethod:: pybricks.hubs::PrimeHub.light.off
.. automethod:: pybricks.hubs::PrimeHub.light.blink
@@ -36,16 +50,24 @@ Prime Hub / Inventor Hub
.. automethod:: pybricks.hubs::PrimeHub.display.orientation
+ .. blockimg:: pybricks_blockLightMatrixDo_light_matrix_off
+
.. automethod:: pybricks.hubs::PrimeHub.display.off
+ .. blockimg:: pybricks_blockLightMatrixDo_light_matrix_pixel
+
.. automethod:: pybricks.hubs::PrimeHub.display.pixel
.. automethod:: pybricks.hubs::PrimeHub.display.icon
.. automethod:: pybricks.hubs::PrimeHub.display.animate
+ .. blockimg:: pybricks_blockLightMatrixDo_light_matrix_number
+
.. automethod:: pybricks.hubs::PrimeHub.display.number
+ .. blockimg:: pybricks_blockLightMatrixDo_light_matrix_symbol
+
.. automethod:: pybricks.hubs::PrimeHub.display.char
.. automethod:: pybricks.hubs::PrimeHub.display.text
@@ -55,26 +77,56 @@ Prime Hub / Inventor Hub
.. figure:: ../../main/diagrams/primehub_buttons.png
:width: 22 em
+ .. blockimg:: pybricks_blockButtonIsPressed_PrimeHub
+
.. automethod:: pybricks.hubs::PrimeHub.buttons.pressed
+ .. blockimg:: pybricks_blockHubStopButton_PrimeHub
+
+ .. blockimg:: pybricks_blockHubStopButton_PrimeHub_none
+ :stack:
+
+ .. automethod:: pybricks.hubs::PrimeHub.system.set_stop_button
+
.. rubric:: Using the IMU
+ .. blockimg:: pybricks_blockImuStatus_PrimeHub_ready
+
.. automethod:: pybricks.hubs::PrimeHub.imu.ready
+ .. blockimg:: pybricks_blockImuStatus_PrimeHub_stationary
+
.. automethod:: pybricks.hubs::PrimeHub.imu.stationary
+ .. blockimg:: pybricks_blockImuUp_PrimeHub
+
.. automethod:: pybricks.hubs::PrimeHub.imu.up
+ .. blockimg:: pybricks_blockTilt_PrimeHub_imu.tilt.pitch
+
+ .. blockimg:: pybricks_blockTilt_PrimeHub_imu.tilt.roll
+ :stack:
+
.. automethod:: pybricks.hubs::PrimeHub.imu.tilt
+ .. blockimg:: pybricks_blockImuAcceleration_PrimeHub
+
.. automethod:: pybricks.hubs::PrimeHub.imu.acceleration
+ .. blockimg:: pybricks_blockImuRotation_PrimeHub_imu.angular_velocity
+
.. automethod:: pybricks.hubs::PrimeHub.imu.angular_velocity
+ .. blockimg:: pybricks_blockImuGetHeading_PrimeHub
+
.. automethod:: pybricks.hubs::PrimeHub.imu.heading
+ .. blockimg:: pybricks_blockImuResetHeading_PrimeHub
+
.. automethod:: pybricks.hubs::PrimeHub.imu.reset_heading
+ .. blockimg:: pybricks_blockImuRotation_PrimeHub_imu.rotation
+
.. automethod:: pybricks.hubs::PrimeHub.imu.rotation
.. automethod:: pybricks.hubs::PrimeHub.imu.orientation
@@ -89,10 +141,28 @@ Prime Hub / Inventor Hub
.. automethod:: pybricks.hubs::PrimeHub.speaker.play_notes
+ .. rubric:: Using connectionless Bluetooth messaging
+
+ .. blockimg:: pybricks_blockBleBroadcast_PrimeHub
+
+ .. automethod:: pybricks.hubs::PrimeHub.ble.broadcast
+
+ .. blockimg:: pybricks_blockBleObserve_PrimeHub
+
+ .. automethod:: pybricks.hubs::PrimeHub.ble.observe
+
+ .. automethod:: pybricks.hubs::PrimeHub.ble.signal_strength
+
+ .. automethod:: pybricks.hubs::PrimeHub.ble.version
+
.. rubric:: Using the battery
+ .. blockimg:: pybricks_blockBatteryMeasure_PrimeHub_battery.voltage
+
.. automethod:: pybricks.hubs::PrimeHub.battery.voltage
+ .. blockimg:: pybricks_blockBatteryMeasure_PrimeHub_battery.current
+
.. automethod:: pybricks.hubs::PrimeHub.battery.current
.. rubric:: Getting the charger status
@@ -105,14 +175,14 @@ Prime Hub / Inventor Hub
.. rubric:: System control
- .. automethod:: pybricks.hubs::PrimeHub.system.set_stop_button
-
.. automethod:: pybricks.hubs::PrimeHub.system.name
.. automethod:: pybricks.hubs::PrimeHub.system.storage
You can store up to 512 bytes of data on this hub.
+ .. blockimg:: pybricks_blockHubShutdown_PrimeHub
+
.. automethod:: pybricks.hubs::PrimeHub.system.shutdown
.. automethod:: pybricks.hubs::PrimeHub.system.reset_reason
@@ -247,6 +317,23 @@ Reading acceleration and angular velocity on one axis
.. literalinclude::
../../../examples/pup/hub_common/build/imu_read_scalar_primehub.py
+
+Bluetooth examples
+------------------
+
+Broadcasting data to other hubs
+*******************************
+
+.. literalinclude::
+ ../../../examples/pup/hub_common/build/ble_broadcast_primehub.py
+
+Observing data from other hubs
+******************************
+
+.. literalinclude::
+ ../../../examples/pup/hub_common/build/ble_observe_primehub.py
+
+
System examples
----------------------------------
diff --git a/doc/main/hubs/technichub.rst b/doc/main/hubs/technichub.rst
index ab6c115f..198f2bad 100644
--- a/doc/main/hubs/technichub.rst
+++ b/doc/main/hubs/technichub.rst
@@ -6,13 +6,22 @@ Technic Hub
.. figure:: ../../main/cad/output/hub-technic.png
:width: 40%
+.. blockimg:: pybricks_variables_set_technic_hub_option0
+
+.. blockimg:: pybricks_variables_set_technic_hub_option4
+ :stack:
+
.. autoclass:: pybricks.hubs.TechnicHub
:no-members:
.. rubric:: Using the hub status light
+ .. blockimg:: pybricks_blockLightOnColor_technichub_on
+
.. automethod:: pybricks.hubs::TechnicHub.light.on
+ .. blockimg:: pybricks_blockLightOnColor_technichub_off
+
.. automethod:: pybricks.hubs::TechnicHub.light.off
.. automethod:: pybricks.hubs::TechnicHub.light.blink
@@ -21,37 +30,83 @@ Technic Hub
.. rubric:: Using the IMU
+ .. blockimg:: pybricks_blockImuStatus_TechnicHub_ready
+
.. automethod:: pybricks.hubs::TechnicHub.imu.ready
+ .. blockimg:: pybricks_blockImuStatus_TechnicHub_stationary
+
.. automethod:: pybricks.hubs::TechnicHub.imu.stationary
+ .. blockimg:: pybricks_blockImuUp_TechnicHub
+
.. automethod:: pybricks.hubs::TechnicHub.imu.up
+ .. blockimg:: pybricks_blockTilt_TechnicHub_imu.tilt.pitch
+
+ .. blockimg:: pybricks_blockTilt_TechnicHub_imu.tilt.roll
+ :stack:
+
.. automethod:: pybricks.hubs::TechnicHub.imu.tilt
+ .. blockimg:: pybricks_blockImuAcceleration_TechnicHub
+
.. automethod:: pybricks.hubs::TechnicHub.imu.acceleration
+ .. blockimg:: pybricks_blockImuRotation_TechnicHub_imu.angular_velocity
+
.. automethod:: pybricks.hubs::TechnicHub.imu.angular_velocity
+ .. blockimg:: pybricks_blockImuGetHeading_TechnicHub
+
.. automethod:: pybricks.hubs::TechnicHub.imu.heading
+ .. blockimg:: pybricks_blockImuResetHeading_TechnicHub
+
.. automethod:: pybricks.hubs::TechnicHub.imu.reset_heading
+ .. blockimg:: pybricks_blockImuRotation_TechnicHub_imu.rotation
+
.. automethod:: pybricks.hubs::TechnicHub.imu.rotation
.. automethod:: pybricks.hubs::TechnicHub.imu.orientation
.. automethod:: pybricks.hubs::TechnicHub.imu.settings
+ .. rubric:: Using connectionless Bluetooth messaging
+
+ .. blockimg:: pybricks_blockBleBroadcast_TechnicHub
+
+ .. automethod:: pybricks.hubs::TechnicHub.ble.broadcast
+
+ .. blockimg:: pybricks_blockBleObserve_TechnicHub
+
+ .. automethod:: pybricks.hubs::TechnicHub.ble.observe
+
+ .. automethod:: pybricks.hubs::TechnicHub.ble.signal_strength
+
+ .. automethod:: pybricks.hubs::TechnicHub.ble.version
+
.. rubric:: Using the battery
+ .. blockimg:: pybricks_blockBatteryMeasure_TechnicHub_battery.voltage
+
.. automethod:: pybricks.hubs::TechnicHub.battery.voltage
+ .. blockimg:: pybricks_blockBatteryMeasure_TechnicHub_battery.current
+
.. automethod:: pybricks.hubs::TechnicHub.battery.current
.. rubric:: Button and system control
- .. automethod:: pybricks.hubs::TechnicHub.button.pressed
+ .. blockimg:: pybricks_blockButtonIsPressed_TechnicHub
+
+ .. automethod:: pybricks.hubs::TechnicHub.buttons.pressed
+
+ .. blockimg:: pybricks_blockHubStopButton_TechnicHub
+
+ .. blockimg:: pybricks_blockHubStopButton_TechnicHub_none
+ :stack:
.. automethod:: pybricks.hubs::TechnicHub.system.set_stop_button
@@ -63,6 +118,8 @@ Technic Hub
when you update the Pybricks firmware or if you restore the original
firmware.
+ .. blockimg:: pybricks_blockHubShutdown_TechnicHub
+
.. automethod:: pybricks.hubs::TechnicHub.system.shutdown
.. automethod:: pybricks.hubs::TechnicHub.system.reset_reason
@@ -128,6 +185,23 @@ Reading acceleration and angular velocity on one axis
.. literalinclude::
../../../examples/pup/hub_common/build/imu_read_scalar_technichub.py
+
+Bluetooth examples
+------------------
+
+Broadcasting data to other hubs
+*******************************
+
+.. literalinclude::
+ ../../../examples/pup/hub_common/build/ble_broadcast_technichub.py
+
+Observing data from other hubs
+******************************
+
+.. literalinclude::
+ ../../../examples/pup/hub_common/build/ble_observe_technichub.py
+
+
Button and system examples
----------------------------------
diff --git a/doc/main/index.rst b/doc/main/index.rst
index e594a38a..8dc3e5e7 100644
--- a/doc/main/index.rst
+++ b/doc/main/index.rst
@@ -62,6 +62,13 @@ above to reveal this menu.
robotics
signaltypes
+.. toctree::
+ :maxdepth: 1
+ :caption: Code with blocks
+ :hidden:
+
+ blocks/index
+
.. toctree::
:maxdepth: 1
:caption: MicroPython modules
diff --git a/doc/main/iodevices/index.rst b/doc/main/iodevices/index.rst
index 8ff07827..f40d4c64 100644
--- a/doc/main/iodevices/index.rst
+++ b/doc/main/iodevices/index.rst
@@ -11,6 +11,7 @@
pupdevice
lwp3device
+ xboxcontroller
This module has classes for generic and custom input/output devices.
@@ -25,3 +26,9 @@ This module has classes for generic and custom input/output devices.
.. figure:: ../../main/cad/output/hub-lwp3.png
:width: 80 %
:target: lwp3device.html
+
+.. pybricks-classlink:: XboxController
+
+.. figure:: ../../main/diagrams_source/xboxcontroller.png
+ :width: 40 %
+ :target: xboxcontroller.html
diff --git a/doc/main/iodevices/lwp3device.rst b/doc/main/iodevices/lwp3device.rst
index 10af18a3..3172c2f4 100644
--- a/doc/main/iodevices/lwp3device.rst
+++ b/doc/main/iodevices/lwp3device.rst
@@ -1,3 +1,5 @@
+.. pybricks-requirements:: pybricks-iodevices
+
LEGO Wireless Protocol v3 device
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/doc/main/iodevices/xboxcontroller.rst b/doc/main/iodevices/xboxcontroller.rst
new file mode 100644
index 00000000..f5522f3e
--- /dev/null
+++ b/doc/main/iodevices/xboxcontroller.rst
@@ -0,0 +1,124 @@
+.. pybricks-requirements:: xbox-controller
+
+Xbox Controller
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. figure:: ../../main/diagrams_source/xboxcontroller.png
+ :width: 60 %
+
+.. blockimg:: pybricks_variables_set_xbox_controller
+
+.. autoclass:: pybricks.iodevices.XboxController
+ :no-members:
+
+ .. blockimg:: pybricks_blockButtonIsPressed_XboxController
+
+ .. automethod:: pybricks.iodevices::XboxController.buttons.pressed
+
+ Buttons include:
+
+ * ``Button.A``, ``Button.B``, ``Button.X``, ``Button.Y``.
+ * ``Button.UP``, ``Button.DOWN``, ``Button.LEFT``, ``Button.RIGHT``
+ (direction pad). At most two of these can be pressed at the same time.
+ * ``Button.LB`` and ``Button.RB`` (bumpers).
+ * ``Button.LJ`` and ``Button.RJ`` (pressing the joysticks).
+ * ``Button.VIEW``, ``Button.MENU``, ``Button.GUIDE`` (the Xbox logo), and ``Button.UPLOAD``.
+ * ``Button.P1``, ``Button.P2``, ``Button.P3``, and ``Button.P4`` (Elite Series 2 only).
+ Pressing the paddles may also be detected as other button presses,
+ depending on the currently active profile.
+
+ .. blockimg:: pybricks_blockJoystickValue_lj_x
+
+ .. blockimg:: pybricks_blockJoystickValue_lj_y
+ :stack:
+
+ .. automethod:: pybricks.iodevices::XboxController.joystick_left
+
+ .. blockimg:: pybricks_blockJoystickValue_rj_x
+
+ .. blockimg:: pybricks_blockJoystickValue_rj_y
+ :stack:
+
+ .. automethod:: pybricks.iodevices::XboxController.joystick_right
+
+ .. blockimg:: pybricks_blockJoystickValue_lt
+
+ .. blockimg:: pybricks_blockJoystickValue_rt
+ :stack:
+
+ .. automethod:: pybricks.iodevices::XboxController.triggers
+
+ .. blockimg:: pybricks_blockJoystickValue_dpad
+
+ .. automethod:: pybricks.iodevices::XboxController.dpad
+
+ .. blockimg:: pybricks_blockJoystickValue_profile
+
+ .. automethod:: pybricks.iodevices::XboxController.profile
+
+ .. blockimg:: pybricks_blockGamepadRumble_default
+
+ .. blockimg:: pybricks_blockGamepadRumble_default_with_list
+ :stack:
+
+ .. blockimg:: pybricks_blockGamepadRumble_with_options
+ :stack:
+
+ .. automethod:: pybricks.iodevices::XboxController.rumble
+
+.. _xbox-controller-pairing:
+
+Xbox Controller Pairing Instructions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The first time you use a controller with a hub, you will need to pair
+them: Turn the controller on and then press and hold the pairing
+button on the back of the controller for a few seconds. When you release
+it, the Xbox button starts flashing more rapidly. Then start your program.
+
+When pairing and the connection is succesful, the Xbox button will stop
+flashing and stay on for as long as the program is running.
+
+Repeat Connections
+==================
+
+If you keep using the same controller with the same hub, you can simply
+turn the controller on the next time and the hub will connect to it
+automatically when your program with this class runs.
+
+The Xbox controller only accepts this simpler connection with the most
+recently connected device. So if you connect to your Xbox console again, or
+connect to another hub, you will need to pair them again as described
+above.
+
+Compatible Controllers
+============================
+
+All Xbox controllers released since 2016 are compatible. This includes the
+controller from the One S (``1708`` from 2016), the Elite Series 2 (``1797``
+from 2019), and the Series X/S (``1914`` from 2020), which is
+the latest model as of this writing.
+
+.. raw:: html
+
+
See also
+ this overview of model numbers including pictures of each controller.
+
+Updating the Xbox Controller
+============================
+
+If you frequently use the Xbox Controller with your console, your controller
+is probably already up to date. If you have not used it for a while or if you
+bought one recently, you may need to update it.
+
+To update the controller without a console, you can use the Xbox Accessories
+app on a Windows computer. You can download it from the Microsoft Store.
+Connect the controller via USB to the computer and follow the instructions in
+the app to click on "Update now".
+
+Technic Hub Limitations
+=======================
+
+Due to limitations of the Technic Hub, the hub will disconnect from the
+computer when searching for the Xbox controller. This means you will not be
+able to see output from the ``print`` command. Also, you'll have to connect to
+the computer again if you want to change your program.
diff --git a/doc/main/micropython/builtins.rst b/doc/main/micropython/builtins.rst
index 3ce655f4..61c9b4ba 100644
--- a/doc/main/micropython/builtins.rst
+++ b/doc/main/micropython/builtins.rst
@@ -13,6 +13,10 @@ Input and output
.. pybricks-requirements::
+.. blockimg:: pybricks_blockPrint_print_basic
+
+.. blockimg:: pybricks_blockPrint_print_multiple
+
.. autofunction:: ubuiltins.print
Basic types
@@ -20,6 +24,10 @@ Basic types
.. pybricks-requirements::
+.. blockimg:: pybricks_blockLogicTrueFalse_false
+
+.. blockimg:: pybricks_blockLogicTrueFalse_true
+
.. autoclass:: ubuiltins.bool
.. pybricks-requirements:: stm32-float
@@ -64,18 +72,74 @@ Sequences
.. pybricks-requirements::
+.. blockimg:: pybricks_blockListLength
+
.. autofunction:: ubuiltins.len
.. pybricks-requirements::
+.. blockimg:: pybricks_blockListCreate_list_empty
+ :stack:
+
+.. blockimg:: pybricks_blockListCreate_list_3
+ :stack:
+
+.. blockimg:: pybricks_blockListUnpack
+ :stack:
+
+.. blockimg:: pybricks_blockListGet_list_get_first
+ :stack:
+
+.. blockimg:: pybricks_blockListGet_list_get_index
+ :stack:
+
+.. blockimg:: pybricks_blockListGet_list_get_last
+ :stack:
+
+.. blockimg:: pybricks_blockListGet_list_get_random
+ :stack:
+
+.. blockimg:: pybricks_blockListSet_list_insert_first
+ :stack:
+
+.. blockimg:: pybricks_blockListSet_list_insert_index
+ :stack:
+
+.. blockimg:: pybricks_blockListSet_list_insert_last
+ :stack:
+
+.. blockimg:: pybricks_blockListSet_list_remove_first
+ :stack:
+
+.. blockimg:: pybricks_blockListSet_list_remove_index
+ :stack:
+
+.. blockimg:: pybricks_blockListSet_list_remove_last
+ :stack:
+
+.. blockimg:: pybricks_blockListSet_list_set_first
+ :stack:
+
+.. blockimg:: pybricks_blockListSet_list_set_index
+ :stack:
+
+.. blockimg:: pybricks_blockListSet_list_set_last
+ :stack:
+
.. autoclass:: ubuiltins.list
.. pybricks-requirements:: stm32-extra
+.. autoclass:: ubuiltins.set
+
+.. pybricks-requirements:: stm32-extra
+
.. autoclass:: ubuiltins.slice
.. pybricks-requirements::
+.. blockimg:: pybricks_blockTextLiteral
+
.. autoclass:: ubuiltins.str
.. pybricks-requirements::
@@ -161,6 +225,8 @@ See also :mod:`umath` for floating point math operations.
.. pybricks-requirements::
+.. blockimg:: pybricks_blockMathOp_abs
+
.. autofunction:: ubuiltins.abs
.. pybricks-requirements::
@@ -169,10 +235,14 @@ See also :mod:`umath` for floating point math operations.
.. pybricks-requirements::
+.. blockimg:: pybricks_blockMathOp_max
+
.. autofunction:: ubuiltins.max
.. pybricks-requirements::
+.. blockimg:: pybricks_blockMathOp_min
+
.. autofunction:: ubuiltins.min
.. pybricks-requirements::
@@ -181,6 +251,8 @@ See also :mod:`umath` for floating point math operations.
.. pybricks-requirements::
+.. blockimg:: pybricks_blockMathOp_round
+
.. autofunction:: ubuiltins.round
.. pybricks-requirements::
diff --git a/doc/main/micropython/umath.rst b/doc/main/micropython/umath.rst
index eed3c41e..bcee45b7 100644
--- a/doc/main/micropython/umath.rst
+++ b/doc/main/micropython/umath.rst
@@ -13,8 +13,12 @@ without importing anything.
Rounding and sign
-------------------------------------
+.. blockimg:: pybricks_blockMathOp_roundup
+
.. autofunction:: umath.ceil
+.. blockimg:: pybricks_blockMathOp_rounddown
+
.. autofunction:: umath.floor
.. autofunction:: umath.trunc
@@ -30,15 +34,25 @@ Powers and logarithms
.. autodata:: umath.e
+.. blockimg:: pybricks_blockMathOp_exp
+
.. autofunction:: umath.exp
+.. blockimg:: pybricks_blockMathArithmetic_power
+
+.. blockimg:: pybricks_blockMathOp_pow10
+
.. autofunction:: umath.pow
+.. blockimg:: pybricks_blockMathOp_ln
+
.. autofunction:: umath.log
+.. blockimg:: pybricks_blockMathOp_root
+
.. autofunction:: umath.sqrt
-Trigonomety
+Trigonometry
-------------------------------
.. autodata:: umath.pi
@@ -47,18 +61,32 @@ Trigonomety
.. autofunction:: umath.radians
+.. blockimg:: pybricks_blockMathOp_sin
+
.. autofunction:: umath.sin
+.. blockimg:: pybricks_blockMathOp_asin
+
.. autofunction:: umath.asin
+.. blockimg:: pybricks_blockMathOp_cos
+
.. autofunction:: umath.cos
+.. blockimg:: pybricks_blockMathOp_acos
+
.. autofunction:: umath.acos
+.. blockimg:: pybricks_blockMathOp_tan
+
.. autofunction:: umath.tan
+.. blockimg:: pybricks_blockMathOp_atan
+
.. autofunction:: umath.atan
+.. blockimg:: pybricks_blockMathOp_atan2
+
.. autofunction:: umath.atan2
Other math functions
diff --git a/doc/main/micropython/urandom.rst b/doc/main/micropython/urandom.rst
index b95c5a60..448959b2 100644
--- a/doc/main/micropython/urandom.rst
+++ b/doc/main/micropython/urandom.rst
@@ -8,6 +8,8 @@
.. rubric:: Basic random numbers
+ .. blockimg:: pybricks_blockRandInt
+
.. autofunction:: randint
.. autofunction:: random
diff --git a/doc/main/parameters/axis.rst b/doc/main/parameters/axis.rst
index 49b19ff7..42f1246b 100644
--- a/doc/main/parameters/axis.rst
+++ b/doc/main/parameters/axis.rst
@@ -5,3 +5,6 @@ Axis
.. autoclass:: pybricks.parameters.Axis
:no-members:
+
+On Move Hub, doing math with these vectors is not supported. The axes can still
+be used to set up the hub orientation.
diff --git a/doc/main/parameters/button.rst b/doc/main/parameters/button.rst
index 9e29d88c..e678f8b5 100644
--- a/doc/main/parameters/button.rst
+++ b/doc/main/parameters/button.rst
@@ -5,46 +5,108 @@ Button
.. class:: Button
- Buttons on a hub or remote.
-
- .. autoattribute:: pybricks.parameters.Button.LEFT_DOWN
- :annotation:
+ .. rubric:: Remote and hub buttons
.. autoattribute:: pybricks.parameters.Button.LEFT_MINUS
:annotation:
- .. autoattribute:: pybricks.parameters.Button.DOWN
- :annotation:
+ Powered Up Remote only.
- .. autoattribute:: pybricks.parameters.Button.RIGHT_DOWN
+ .. autoattribute:: pybricks.parameters.Button.LEFT_PLUS
:annotation:
+ Powered Up Remote only.
+
.. autoattribute:: pybricks.parameters.Button.RIGHT_MINUS
:annotation:
- .. autoattribute:: pybricks.parameters.Button.LEFT
+ Powered Up Remote only.
+
+ .. autoattribute:: pybricks.parameters.Button.RIGHT_PLUS
:annotation:
+ Powered Up Remote only.
+
.. autoattribute:: pybricks.parameters.Button.CENTER
:annotation:
+ Powered Up Remote (green button) or hub power button.
+
+ .. autoattribute:: pybricks.parameters.Button.LEFT
+ :annotation:
+
+ Powered Up Remote (left red button) and Prime/Inventor Hub (left button).
+
.. autoattribute:: pybricks.parameters.Button.RIGHT
:annotation:
- .. autoattribute:: pybricks.parameters.Button.LEFT_UP
+ Powered Up Remote (right red button) and Prime/Inventor Hub (right button).
+
+ .. autoattribute:: pybricks.parameters.Button.BLUETOOTH
:annotation:
- .. autoattribute:: pybricks.parameters.Button.LEFT_PLUS
+ Prime/Inventor Hub button with Bluetooth icon.
+
+ .. rubric:: Xbox controller buttons
+
+ .. autoattribute:: pybricks.parameters.Button.A
:annotation:
- .. autoattribute:: pybricks.parameters.Button.UP
+ .. autoattribute:: pybricks.parameters.Button.B
:annotation:
- .. autoattribute:: pybricks.parameters.Button.BEACON
+ .. autoattribute:: pybricks.parameters.Button.X
:annotation:
- .. autoattribute:: pybricks.parameters.Button.RIGHT_UP
+ .. autoattribute:: pybricks.parameters.Button.Y
:annotation:
- .. autoattribute:: pybricks.parameters.Button.RIGHT_PLUS
+ .. autoattribute:: pybricks.parameters.Button.LB
+ :annotation:
+
+ The left bumper.
+
+ .. autoattribute:: pybricks.parameters.Button.RB
+ :annotation:
+
+ The right bumper.
+
+ .. autoattribute:: pybricks.parameters.Button.LJ
+ :annotation:
+
+ Pressing the left joystick.
+
+ .. autoattribute:: pybricks.parameters.Button.RJ
+ :annotation:
+
+ Pressing the right joystick.
+
+ .. autoattribute:: pybricks.parameters.Button.GUIDE
+ :annotation:
+
+ The Xbox button in the center of the controller.
+
+ .. autoattribute:: pybricks.parameters.Button.MENU
+ :annotation:
+
+ .. autoattribute:: pybricks.parameters.Button.UPLOAD
+ :annotation:
+
+ Only available on newer Xbox controllers.
+
+ .. autoattribute:: pybricks.parameters.Button.VIEW
+ :annotation:
+
+ .. rubric:: Xbox Elite Series 2 controller paddles
+
+ .. autoattribute:: pybricks.parameters.Button.P1
+ :annotation:
+
+ .. autoattribute:: pybricks.parameters.Button.P2
+ :annotation:
+
+ .. autoattribute:: pybricks.parameters.Button.P3
+ :annotation:
+
+ .. autoattribute:: pybricks.parameters.Button.P4
:annotation:
diff --git a/doc/main/pupdevices/colordistancesensor.rst b/doc/main/pupdevices/colordistancesensor.rst
index f5c587fb..081dc80c 100644
--- a/doc/main/pupdevices/colordistancesensor.rst
+++ b/doc/main/pupdevices/colordistancesensor.rst
@@ -6,17 +6,31 @@ Color and Distance Sensor
.. figure:: ../../main/cad/output/pupdevice-colordistance.png
:width: 35 %
+.. blockimg:: pybricks_variables_set_color_distance_sensor_colordistancesensor_default
+
+.. blockimg:: pybricks_variables_set_color_distance_sensor_colordistancesensor_detectable_colors
+
.. autoclass:: pybricks.pupdevices.ColorDistanceSensor
:no-members:
+ .. blockimg:: pybricks_blockColor_ColorDistanceSensor_color
+
.. automethod:: pybricks.pupdevices.ColorDistanceSensor.color
+ .. blockimg:: pybricks_blockLightReflection_ColorDistanceSensor
+
.. automethod:: pybricks.pupdevices.ColorDistanceSensor.reflection
+ .. blockimg:: pybricks_blockLightAmbient_ColorDistanceSensor
+
.. automethod:: pybricks.pupdevices.ColorDistanceSensor.ambient
+ .. blockimg:: pybricks_blockDistance_ColorDistanceSensor
+
.. automethod:: pybricks.pupdevices.ColorDistanceSensor.distance
+ .. blockimg:: pybricks_blockColor_ColorDistanceSensor_hsv
+
.. automethod:: pybricks.pupdevices.ColorDistanceSensor.hsv
.. automethod:: pybricks.pupdevices.ColorDistanceSensor.detectable_colors
@@ -27,8 +41,12 @@ Color and Distance Sensor
it off. If you use the sensor to measure something afterwards, the light
automatically turns back on at the default color for that sensing method.
+ .. blockimg:: pybricks_blockLightOnColor_colordistancesensor_on
+
.. automethod:: pybricks.pupdevices::ColorDistanceSensor.light.on
+ .. blockimg:: pybricks_blockLightOnColor_colordistancesensor_off
+
.. automethod:: pybricks.pupdevices::ColorDistanceSensor.light.off
Examples
diff --git a/doc/main/pupdevices/colorlightmatrix.rst b/doc/main/pupdevices/colorlightmatrix.rst
index 25ef7246..4d629b7f 100644
--- a/doc/main/pupdevices/colorlightmatrix.rst
+++ b/doc/main/pupdevices/colorlightmatrix.rst
@@ -6,10 +6,17 @@ Color Light Matrix
.. figure:: ../../main/diagrams/sensor_colorlightmatrix.png
:width: 35 %
+.. blockimg:: pybricks_variables_set_color_light_matrix
+
.. autoclass:: pybricks.pupdevices.ColorLightMatrix
:no-members:
+ .. blockimg:: pybricks_blockLightOnColor_colorlightmatrix_on
+
+ .. blockimg:: pybricks_blockLightOnColor_colorlightmatrix_on_list
+
.. automethod:: pybricks.pupdevices.ColorLightMatrix.on
- .. automethod:: pybricks.pupdevices.ColorLightMatrix.off
+ .. blockimg:: pybricks_blockLightOnColor_colorlightmatrix_off
+ .. automethod:: pybricks.pupdevices.ColorLightMatrix.off
diff --git a/doc/main/pupdevices/colorsensor.rst b/doc/main/pupdevices/colorsensor.rst
index a897c795..7d390e0e 100644
--- a/doc/main/pupdevices/colorsensor.rst
+++ b/doc/main/pupdevices/colorsensor.rst
@@ -6,17 +6,29 @@ Color Sensor
.. figure:: ../../main/diagrams/sensor_color_lights.png
:width: 70 %
+.. blockimg:: pybricks_variables_set_color_sensor_colorsensor_default
+
+.. blockimg:: pybricks_variables_set_color_sensor_colorsensor_detectable_colors
+
.. autoclass:: pybricks.pupdevices.ColorSensor
:no-members:
+ .. blockimg:: pybricks_blockColor_ColorSensor_color
+
.. automethod:: pybricks.pupdevices.ColorSensor.color
+ .. blockimg:: pybricks_blockLightReflection_ColorSensor
+
.. automethod:: pybricks.pupdevices.ColorSensor.reflection
+ .. blockimg:: pybricks_blockLightAmbient_ColorSensor
+
.. automethod:: pybricks.pupdevices.ColorSensor.ambient
.. rubric:: Advanced color sensing
+ .. blockimg:: pybricks_blockColor_ColorSensor_hsv
+
.. automethod:: pybricks.pupdevices.ColorSensor.hsv
.. automethod:: pybricks.pupdevices.ColorSensor.detectable_colors
@@ -27,8 +39,15 @@ Color Sensor
light. If you use the sensor to measure something, the lights will
be turned on or off as needed for the measurement.
+ .. blockimg:: pybricks_blockLightOn_colorsensor_on
+
+ .. blockimg:: pybricks_blockLightOn_colorsensor_on_list
+ :stack:
+
.. automethod:: pybricks.pupdevices::ColorSensor.lights.on
+ .. blockimg:: pybricks_blockLightOn_colorsensor_off
+
.. automethod:: pybricks.pupdevices::ColorSensor.lights.off
diff --git a/doc/main/pupdevices/dcmotor.rst b/doc/main/pupdevices/dcmotor.rst
index d10b76e0..58f776de 100644
--- a/doc/main/pupdevices/dcmotor.rst
+++ b/doc/main/pupdevices/dcmotor.rst
@@ -13,15 +13,23 @@ Motors without rotation sensors
Powered Up motors without rotation sensors. The arrows indicate the default
positive direction.
+.. blockimg:: pybricks_variables_set_dc_motor
+
.. autoclass:: pybricks.pupdevices.DCMotor
:no-members:
+ .. blockimg:: pybricks_blockMotorDuty_DCMotor
+
.. automethod:: pybricks.pupdevices.DCMotor.dc
:noindex:
+ .. blockimg:: pybricks_blockMotorStop_DCMotor_coast
+
.. automethod:: pybricks.pupdevices.DCMotor.stop
:noindex:
+ .. blockimg:: pybricks_blockMotorStop_DCMotor_brake
+
.. automethod:: pybricks.pupdevices.DCMotor.brake
:noindex:
diff --git a/doc/main/pupdevices/forcesensor.rst b/doc/main/pupdevices/forcesensor.rst
index abab947a..eacf0e34 100644
--- a/doc/main/pupdevices/forcesensor.rst
+++ b/doc/main/pupdevices/forcesensor.rst
@@ -6,11 +6,17 @@ Force Sensor
.. figure:: ../../main/cad/output/pupdevice-force.png
:width: 35 %
+.. blockimg:: pybricks_variables_set_force_sensor
+
.. autoclass:: pybricks.pupdevices.ForceSensor
:no-members:
+ .. blockimg:: pybricks_blockForce_ForceSensor
+
.. automethod:: pybricks.pupdevices.ForceSensor.force
+ .. blockimg:: pybricks_blockDistance_ForceSensor
+
.. automethod:: pybricks.pupdevices.ForceSensor.distance
.. automethod:: pybricks.pupdevices.ForceSensor.pressed
diff --git a/doc/main/pupdevices/infraredsensor.rst b/doc/main/pupdevices/infraredsensor.rst
index b8986d9a..a3f1800a 100644
--- a/doc/main/pupdevices/infraredsensor.rst
+++ b/doc/main/pupdevices/infraredsensor.rst
@@ -6,11 +6,17 @@ Infrared Sensor
.. figure:: ../../main/cad/output/pupdevice-infrared.png
:width: 35 %
+.. blockimg:: pybricks_variables_set_infrared_sensor
+
.. autoclass:: pybricks.pupdevices.InfraredSensor
:no-members:
+ .. blockimg:: pybricks_blockDistance_InfraredSensor
+
.. automethod:: pybricks.pupdevices.InfraredSensor.distance
+ .. blockimg:: pybricks_blockLightReflection_InfraredSensor
+
.. automethod:: pybricks.pupdevices.InfraredSensor.reflection
.. automethod:: pybricks.pupdevices.InfraredSensor.count
diff --git a/doc/main/pupdevices/light.rst b/doc/main/pupdevices/light.rst
index 983a6271..6e569044 100644
--- a/doc/main/pupdevices/light.rst
+++ b/doc/main/pupdevices/light.rst
@@ -6,11 +6,17 @@ Light
.. figure:: ../../main/cad/output/pupdevice-light.png
:width: 35 %
+.. blockimg:: pybricks_variables_set_light
+
.. autoclass:: pybricks.pupdevices.Light
:no-members:
+ .. blockimg:: pybricks_blockLightOn_light_on
+
.. automethod:: pybricks.pupdevices.Light.on
+ .. blockimg:: pybricks_blockLightOn_light_off
+
.. automethod:: pybricks.pupdevices.Light.off
Examples
diff --git a/doc/main/pupdevices/motor.rst b/doc/main/pupdevices/motor.rst
index 89cbc706..ec8befd7 100644
--- a/doc/main/pupdevices/motor.rst
+++ b/doc/main/pupdevices/motor.rst
@@ -13,59 +13,103 @@ Motors with rotation sensors
positive direction. See the :mod:`hubs ` module for default
directions of built-in motors.
+.. blockimg:: pybricks_variables_set_motor
+
.. autoclass:: pybricks.pupdevices.Motor
:no-members:
.. rubric:: Measuring
+ .. blockimg:: pybricks_blockMotorMeasure_motor_angle
+
.. automethod:: pybricks.pupdevices.Motor.angle
+ .. blockimg:: pybricks_blockMotorResetAngle
+
.. automethod:: pybricks.pupdevices.Motor.reset_angle
+ .. blockimg:: pybricks_blockMotorMeasure_motor_speed
+
+ .. blockimg:: pybricks_blockMotorMeasure_motor_get_speed_average
+
.. automethod:: pybricks.pupdevices.Motor.speed
+ .. blockimg:: pybricks_blockMotorMeasure_motor_load
+
.. automethod:: pybricks.pupdevices.Motor.load
+ .. blockimg:: pybricks_blockMotorMeasure_motor_stalled
+
.. automethod:: pybricks.pupdevices.Motor.stalled
.. rubric:: Stopping
+ .. blockimg:: pybricks_blockMotorStop_Motor_coast
+
.. automethod:: pybricks.pupdevices.Motor.stop
+ .. blockimg:: pybricks_blockMotorStop_Motor_brake
+
.. automethod:: pybricks.pupdevices.Motor.brake
+ .. blockimg:: pybricks_blockMotorStop_Motor_hold
+
.. automethod:: pybricks.pupdevices.Motor.hold
.. rubric:: Running forever
+ .. blockimg:: pybricks_blockMotorRun_run
+
.. automethod:: pybricks.pupdevices.Motor.run
+ .. blockimg:: pybricks_blockMotorDuty_Motor
+
.. automethod:: pybricks.pupdevices.Motor.dc
.. rubric:: Running by a fixed amount
.. automethod:: pybricks.pupdevices.Motor.run_time
+ .. blockimg:: pybricks_blockMotorRun_run_angle
+
.. automethod:: pybricks.pupdevices.Motor.run_angle
+ .. blockimg:: pybricks_blockMotorRun_run_target
+
.. automethod:: pybricks.pupdevices.Motor.run_target
- .. automethod:: pybricks.pupdevices.Motor.track_target
+ .. blockimg:: pybricks_blockMotorRun_run_until_stalled
.. automethod:: pybricks.pupdevices.Motor.run_until_stalled
+ .. blockimg:: pybricks_blockMotorTrack
+
+ .. automethod:: pybricks.pupdevices.Motor.track_target
+
.. automethod:: pybricks.pupdevices.Motor.done
.. _settings:
.. rubric:: Motor settings
+ .. blockimg:: pybricks_blockMotorConfigure_motor_max_voltage
+
.. automethod:: pybricks.pupdevices.Motor.settings
+ .. automethod:: pybricks.pupdevices.Motor.close
+
.. rubric:: Control settings
.. pybricks-requirements:: pybricks-common-control
+ .. blockimg:: pybricks_blockMotorConfigure_motor_max_speed
+
+ .. blockimg:: pybricks_blockMotorConfigure_motor_acceleration
+ :stack:
+
+ .. blockimg:: pybricks_blockMotorConfigure_motor_max_torque
+ :stack:
+
.. automethod:: pybricks.pupdevices.Motor.control.limits
.. pybricks-requirements:: pybricks-common-control
@@ -74,6 +118,8 @@ Motors with rotation sensors
.. pybricks-requirements:: pybricks-common-control
+ .. blockimg:: pybricks_blockMotorConfigure_motor_target_tolerances
+
.. automethod:: pybricks.pupdevices.Motor.control.target_tolerances
.. pybricks-requirements:: pybricks-common-control
diff --git a/doc/main/pupdevices/pfmotor.rst b/doc/main/pupdevices/pfmotor.rst
index 24985f90..2e396026 100644
--- a/doc/main/pupdevices/pfmotor.rst
+++ b/doc/main/pupdevices/pfmotor.rst
@@ -18,16 +18,24 @@ and ambient conditions.
motor (right). Here, the receiver uses channel
1 with a motor on the red port.
+.. blockimg:: pybricks_variables_set_pf_motor
+
.. autoclass:: pybricks.pupdevices.PFMotor
:noindex:
:no-members:
+ .. blockimg:: pybricks_blockMotorDuty_PFMotor
+
.. automethod:: pybricks.pupdevices.PFMotor.dc
:noindex:
+ .. blockimg:: pybricks_blockMotorStop_PFMotor_coast
+
.. automethod:: pybricks.pupdevices.PFMotor.stop
:noindex:
+ .. blockimg:: pybricks_blockMotorStop_PFMotor_brake
+
.. automethod:: pybricks.pupdevices.PFMotor.brake
:noindex:
diff --git a/doc/main/pupdevices/remote.rst b/doc/main/pupdevices/remote.rst
index fae164d4..a8a6e03c 100644
--- a/doc/main/pupdevices/remote.rst
+++ b/doc/main/pupdevices/remote.rst
@@ -6,17 +6,30 @@ Remote Control
.. figure:: ../../main/cad/output/pupdevice-remote.png
:width: 60 %
+.. blockimg:: pybricks_variables_set_remote_connect_any
+
+.. blockimg:: pybricks_variables_set_remote_connect_name
+ :stack:
+
.. autoclass:: pybricks.pupdevices.Remote
:no-members:
.. automethod:: pybricks.pupdevices::Remote.name
+ .. blockimg:: pybricks_blockLightOnColor_remote_on
+
.. automethod:: pybricks.pupdevices::Remote.light.on
+ .. blockimg:: pybricks_blockLightOnColor_remote_on
+
.. automethod:: pybricks.pupdevices::Remote.light.off
+ .. blockimg:: pybricks_blockButtonIsPressed_Remote
+
.. automethod:: pybricks.pupdevices::Remote.buttons.pressed
+ .. automethod:: pybricks.pupdevices::Remote.disconnect
+
Examples
-------------------
@@ -63,11 +76,15 @@ Changing the name of the remote
You can change the Bluetooth name of the remote. The factory default name is
``Handset``.
+.. blockimg:: pybricks_variables_set_remote_connect_rename
+
.. literalinclude::
../../../examples/pup/remote/set_name.py
You can specify this name when connecting to the remote.
This lets you pick the right one if multiple remotes are nearby.
+.. blockimg:: pybricks_variables_set_remote_connect_name
+
.. literalinclude::
../../../examples/pup/remote/use_name.py
diff --git a/doc/main/pupdevices/tiltsensor.rst b/doc/main/pupdevices/tiltsensor.rst
index 6d363314..ce40c234 100644
--- a/doc/main/pupdevices/tiltsensor.rst
+++ b/doc/main/pupdevices/tiltsensor.rst
@@ -6,9 +6,16 @@ Tilt Sensor
.. figure:: ../../main/cad/output/pupdevice-tilt.png
:width: 35 %
+.. blockimg:: pybricks_variables_set_tilt_sensor
+
.. autoclass:: pybricks.pupdevices.TiltSensor
:no-members:
+ .. blockimg:: pybricks_blockTilt_TiltSensor_imu.tilt.pitch
+
+ .. blockimg:: pybricks_blockTilt_TiltSensor_imu.tilt.roll
+ :stack:
+
.. automethod:: tilt
Examples
diff --git a/doc/main/pupdevices/ultrasonicsensor.rst b/doc/main/pupdevices/ultrasonicsensor.rst
index 4898d0ad..c3e48f5d 100644
--- a/doc/main/pupdevices/ultrasonicsensor.rst
+++ b/doc/main/pupdevices/ultrasonicsensor.rst
@@ -6,9 +6,13 @@ Ultrasonic Sensor
.. figure:: ../../main/diagrams/sensor_ultrasonic_lights.png
:width: 80 %
+.. blockimg:: pybricks_variables_set_ultrasonic_sensor
+
.. autoclass:: pybricks.pupdevices.UltrasonicSensor
:no-members:
+ .. blockimg:: pybricks_blockDistance_UltrasonicSensor
+
.. automethod:: pybricks.pupdevices.UltrasonicSensor.distance
.. automethod:: pybricks.pupdevices.UltrasonicSensor.presence
@@ -18,8 +22,15 @@ Ultrasonic Sensor
This sensor has 4 built-in lights. You can adjust the brightness of each
light.
+ .. blockimg:: pybricks_blockLightOn_ultrasonicsensor_on
+
+ .. blockimg:: pybricks_blockLightOn_ultrasonicsensor_on_list
+ :stack:
+
.. automethod:: pybricks.pupdevices::UltrasonicSensor.lights.on
+ .. blockimg:: pybricks_blockLightOn_ultrasonicsensor_off
+
.. automethod:: pybricks.pupdevices::UltrasonicSensor.lights.off
Examples
diff --git a/doc/main/robotics.rst b/doc/main/robotics.rst
index 98c93aeb..739c9785 100644
--- a/doc/main/robotics.rst
+++ b/doc/main/robotics.rst
@@ -6,6 +6,8 @@
.. pybricks-requirements::
+.. blockimg:: pybricks_variables_set_drive_base
+
.. autoclass:: pybricks.robotics.DriveBase
:no-members:
@@ -17,12 +19,26 @@
This is measured using the internal rotation sensors. Because wheels may
slip while moving, the traveled distance and angle are only estimates.
+ .. blockimg:: pybricks_blockDriveBaseDrive_drivebase_drive_straight
+
.. automethod:: pybricks.robotics.DriveBase.straight
+ .. blockimg:: pybricks_blockDriveBaseDrive_drivebase_drive_turn
+
.. automethod:: pybricks.robotics.DriveBase.turn
+ .. blockimg:: pybricks_blockDriveBaseDrive_drivebase_drive_curve
+
.. automethod:: pybricks.robotics.DriveBase.curve
+ .. blockimg:: pybricks_blockDriveBaseConfigure_drivebase_straight_speed
+
+ .. blockimg:: pybricks_blockDriveBaseConfigure_drivebase_straight_acceleration
+
+ .. blockimg:: pybricks_blockDriveBaseConfigure_drivebase_turn_rate
+
+ .. blockimg:: pybricks_blockDriveBaseConfigure_drivebase_turn_acceleration
+
.. automethod:: pybricks.robotics.DriveBase.settings
.. automethod:: pybricks.robotics.DriveBase.done
@@ -35,22 +51,71 @@
using :meth:`.drive` again. For example, you can drive until a
sensor is triggered and then stop or turn around.
+ .. blockimg:: pybricks_blockDriveBaseDrive_drivebase_drive_forever
+
.. automethod:: pybricks.robotics.DriveBase.drive
+ .. blockimg:: pybricks_blockDriveBaseStop_coast
+
.. automethod:: pybricks.robotics.DriveBase.stop
+ .. blockimg:: pybricks_blockDriveBaseStop_brake
+
+ .. automethod:: pybricks.robotics.DriveBase.brake
+
+ .. blockimg:: pybricks_blockDriveBaseStop_hold
+
.. rubric:: Measuring
+ .. blockimg:: pybricks_blockDriveBaseMeasure_drivebase_get_distance
+
.. automethod:: pybricks.robotics.DriveBase.distance
+ .. blockimg:: pybricks_blockDriveBaseMeasure_drivebase_get_angle
+
.. automethod:: pybricks.robotics.DriveBase.angle
+ .. blockimg:: pybricks_blockDriveBaseMeasure_drivebase_get_speed
+
+ .. blockimg:: pybricks_blockDriveBaseMeasure_drivebase_get_turn_rate
+
.. automethod:: pybricks.robotics.DriveBase.state
.. automethod:: pybricks.robotics.DriveBase.reset
.. automethod:: pybricks.robotics.DriveBase.stalled
+ .. pybricks-requirements:: gyro
+
+ .. rubric:: Driving with the gyro
+
+ .. blockimg:: pybricks_blockDriveBaseUseGyro
+
+ .. automethod:: pybricks.robotics.DriveBase.use_gyro
+
+ If your hub is not mounted flat in your robot, make sure to specify
+ the ``top_side`` and ``front_side`` parameters when you initialize the
+ :class:`PrimeHub() `,
+ :class:`InventorHub() `,
+ :class:`EssentialHub() `, or
+ :class:`TechnicHub() `. This way your robot
+ knows which rotation to measure when turning.
+
+ The gyro in each hub is a bit different, which can cause it to be a few
+ degrees off for big turns, or many small turns in the same
+ direction. For example, you may need to use
+ :meth:`turn(357) ` or
+ :meth:`turn(362) `
+ on your robot to make a full turn.
+
+ By default, this class tries to maintain the robot's position after a move
+ completes. This means the wheels will spin if you pick the robot up, in an
+ effort to maintain its heading angle. To avoid this, you can choose
+ ``then=Stop.COAST`` in your last
+ :meth:`straight `,
+ :meth:`turn `, or
+ :meth:`curve ` command.
+
.. _measuring:
.. rubric:: Measuring and validating the robot dimensions
@@ -112,47 +177,49 @@
The :meth:`done` and :meth:`stalled` methods have been moved.
+.. pybricks-requirements::
-.. pybricks-requirements:: gyro
+.. blockimg:: pybricks_variables_set_car
-.. class:: GyroDriveBase
+.. versionadded:: 3.4
- This class works just like the :class:`DriveBase`, but it uses the hub's
- built-in gyroscope to drive straight and turn more accurately.
+.. autoclass:: pybricks.robotics.Car
+ :no-members:
- If your hub is not mounted flat in your robot, make sure to specify
- the ``top_side`` and ``front_side`` parameters when you initialize the
- :class:`PrimeHub() `,
- :class:`InventorHub() `,
- :class:`EssentialHub() `, or
- :class:`TechnicHub() `. This way your robot
- knows which rotation to measure when turning.
+ .. blockimg:: pybricks_blockCarSteer
- The gyro in each hub is a bit different, which can cause it to be a few
- degrees off for big turns, or many small turns in the same
- direction. For example, you may need to use
- :meth:`turn(357) ` or
- :meth:`turn(362) `
- on your robot to make a full turn.
+ .. automethod:: pybricks.robotics.Car.steer
- By default, this class tries to maintain the robot's position after a move
- completes. This means the wheels will spin if you pick the robot up, in an
- effort to maintain its heading angle. To avoid this, you can choose
- ``then=Stop.COAST`` in your last
- :meth:`straight `,
- :meth:`turn `, or
- :meth:`curve ` command.
+ .. blockimg:: pybricks_blockCarDrive_car_drive_at_power
+
+ .. automethod:: pybricks.robotics.Car.drive_power
+
+ .. blockimg:: pybricks_blockCarDrive_car_drive_at_speed
+
+ .. automethod:: pybricks.robotics.Car.drive_speed
Examples
-------------------
-Driving straight and turning in place
-**********************************************
+Driving straight and turning in place with a drive base
+********************************************************
-The following program shows the basics of driving and turning.
-
-To use the built-in gyro, just replace the two occurences of
-:class:`DriveBase` with :class:`GyroDriveBase`.
+This program shows the basics of driving and turning.
.. literalinclude::
../../examples/pup/robotics/drivebase_basics.py
+
+Remote controlling a car with front wheel steering
+**************************************************
+
+This program shows how you can drive a car with front wheel steering
+using the :class:`remote control `.
+
+In this program, the ports match those of the `LEGO Technic 42099 Off-Roader
+`_, but you can
+use any other car with front wheel steering. If your vehicle has only one
+drive motor, you can use a single motor instead of a tuple of the motors used
+below.
+
+.. literalinclude::
+ ../../examples/pup/robotics/car_remote.py
diff --git a/doc/main/signaltypes.rst b/doc/main/signaltypes.rst
index 675aeaef..91e174dd 100644
--- a/doc/main/signaltypes.rst
+++ b/doc/main/signaltypes.rst
@@ -248,7 +248,7 @@ For example, you can choose the frequency of a beep to change the pitch.
temperature: °C
---------------
-Temperature is measured in degrees Celcius (°C). To convert to degrees
+Temperature is measured in degrees Celsius (°C). To convert to degrees
Fahrenheit (°F) or Kelvin (K), you can use the following conversion formulas:
:math:`^{\circ}\kern1pt\!F =\kern1pt^{\circ}\kern1pt\!C \cdot \frac{9}{5} + 32`.
diff --git a/doc/main/tools/index.rst b/doc/main/tools/index.rst
index 7172d2d5..2316b682 100644
--- a/doc/main/tools/index.rst
+++ b/doc/main/tools/index.rst
@@ -9,19 +9,59 @@
Timing tools
---------------
+.. blockimg:: pybricks_blockWaitTime
+
.. autofunction:: wait
+.. blockimg:: pybricks_variables_set_stopwatch
+
.. autoclass:: pybricks.tools.StopWatch
:no-members:
+ .. blockimg:: pybricks_blockStopWatchTime
+
.. automethod:: pybricks.tools.StopWatch.time
+ .. blockimg:: pybricks_blockStopWatchDo_StopWatch_pause
+
.. automethod:: pybricks.tools.StopWatch.pause
+ .. blockimg:: pybricks_blockStopWatchDo_StopWatch_resume
+
.. automethod:: pybricks.tools.StopWatch.resume
+ .. blockimg:: pybricks_blockStopWatchDo_StopWatch_reset
+
.. automethod:: pybricks.tools.StopWatch.reset
+Input tools
+-----------
+
+.. blockimg:: pybricks_blockReadInput_read_input_first_byte
+
+.. blockimg:: pybricks_blockReadInput_read_input_first_char
+ :stack:
+
+.. blockimg:: pybricks_blockReadInput_read_input_last_byte
+ :stack:
+
+.. blockimg:: pybricks_blockReadInput_read_input_last_char
+ :stack:
+
+.. autofunction:: pybricks.tools.read_input_byte
+
+.. versionchanged:: 3.3
+
+ Added ``last`` and ``chr`` options.
+
+
+.. pybricks-requirements:: light-matrix
+
+.. autofunction:: pybricks.tools.hub_menu
+
+.. literalinclude::
+ ../../../examples/pup/tools/hub_menu.py
+
Linear algebra tools
--------------------
@@ -40,6 +80,42 @@ Linear algebra tools
.. pybricks-requirements:: stm32-float
+.. blockimg:: pybricks_blockVector
+
.. autofunction:: pybricks.tools.vector
.. autofunction:: pybricks.tools.cross
+
+Multitasking
+--------------------
+
+.. versionadded:: 3.3
+
+Pybricks supports cooperative multitasking using the ``async`` and ``await``
+keywords. This allows operations that normally take some time to complete to
+run in parallel with other operations.
+
+.. blockimg:: pybricks_blockMultiTask
+
+.. autofunction:: pybricks.tools.multitask
+
+.. autofunction:: pybricks.tools.run_task
+
+The following example shows how to use multitasking to make a robot drive
+forward, then turn and move a gripper at the same time, and then drive
+backward.
+
+.. literalinclude::
+ ../../../examples/pup/robotics/drivebase_async.py
+
+.. class:: coroutine
+
+.. class:: await
+
+Whenever you see a function or method prefixed by ``await``, this means that
+it supports multitasking. When running a coroutine with ``run_task``, all
+methods and functions prefixed by ``await`` will act as coroutines.
+
+If you don't use multitasking, you can ignore the ``await`` keyword and write
+programs as usual. Specifically, when ``run_task`` is not used, functions
+prefixed by ``await`` will act as normal functions.
diff --git a/examples/ev3/bluetooth_pc/pybricks/bluetooth.py b/examples/ev3/bluetooth_pc/pybricks/bluetooth.py
index 67b195de..61bfc9ff 100644
--- a/examples/ev3/bluetooth_pc/pybricks/bluetooth.py
+++ b/examples/ev3/bluetooth_pc/pybricks/bluetooth.py
@@ -71,6 +71,7 @@ class ThreadingRFCOMMServer(ThreadingMixIn, RFCOMMServer):
"""
Version of :class:`RFCOMMServer` that handles connections in a new thread.
"""
+
daemon_threads = True
@@ -103,4 +104,5 @@ class ThreadingRFCOMMClient(ThreadingMixIn, RFCOMMClient):
"""
Version of :class:`RFCOMMClient` that handles connections in a new thread.
"""
+
daemon_threads = True
diff --git a/examples/ev3/bluetooth_pc/pybricks/messaging.py b/examples/ev3/bluetooth_pc/pybricks/messaging.py
index 796ad652..34d384ba 100644
--- a/examples/ev3/bluetooth_pc/pybricks/messaging.py
+++ b/examples/ev3/bluetooth_pc/pybricks/messaging.py
@@ -261,7 +261,7 @@ def __init__(self):
EV3.
The remote EV3 can either be running MicroPython or the standard EV3
- firmare.
+ firmware.
"""
super().__init__()
super(ThreadingRFCOMMServer, self).__init__(
@@ -304,7 +304,7 @@ class BluetoothMailboxClient(MailboxHandlerMixIn):
remote EV3s.
The remote EV3s can either be running MicroPython or the standard EV3
- firmare.
+ firmware.
"""
def __enter__(self):
diff --git a/examples/ev3/ps4/main.py b/examples/ev3/ps4/main.py
index 009ff97a..578458d1 100644
--- a/examples/ev3/ps4/main.py
+++ b/examples/ev3/ps4/main.py
@@ -36,7 +36,7 @@ def scale(val, src, dst):
# Create a loop to react to events
-# This loop reacte to all main PS4 button and stick events. I have left out
+# This loop reacts to all main PS4 button and stick events. I have left out
# buttons like share and options, but can easily be added in by referring
# to the table at: https://github.com/codeadamca/python-connect-ps4
diff --git a/examples/pup/hub_common/ble_broadcast.py b/examples/pup/hub_common/ble_broadcast.py
new file mode 100644
index 00000000..7a9d5fb3
--- /dev/null
+++ b/examples/pup/hub_common/ble_broadcast.py
@@ -0,0 +1,25 @@
+# ThisHub = MoveHub CityHub TechnicHub PrimeHub EssentialHub
+from pybricks.hubs import ThisHub
+from pybricks.pupdevices import Motor
+from pybricks.parameters import Port
+from pybricks.tools import wait
+
+# Initialize the hub.
+hub = ThisHub(broadcast_channel=1)
+
+# Initialize the motors.
+left_motor = Motor(Port.A)
+right_motor = Motor(Port.B)
+
+while True:
+ # Read the motor angles to be sent to the other hub.
+ left_angle = left_motor.angle()
+ right_angle = right_motor.angle()
+
+ # Set the broadcast data and start broadcasting if not already doing so.
+ data = (left_angle, right_angle)
+ hub.ble.broadcast(data)
+
+ # Broadcasts are only sent every 100 milliseconds, so there is no reason
+ # to call the broadcast() method more often than that.
+ wait(100)
diff --git a/examples/pup/hub_common/ble_observe.py b/examples/pup/hub_common/ble_observe.py
new file mode 100644
index 00000000..87249a61
--- /dev/null
+++ b/examples/pup/hub_common/ble_observe.py
@@ -0,0 +1,38 @@
+# ThisHub = MoveHub CityHub TechnicHub PrimeHub EssentialHub
+from pybricks.hubs import ThisHub
+from pybricks.pupdevices import Motor
+from pybricks.parameters import Color, Port
+from pybricks.tools import wait
+
+# Initialize the hub.
+hub = ThisHub(observe_channels=[1])
+
+# Initialize the motors.
+left_motor = Motor(Port.A)
+right_motor = Motor(Port.B)
+
+while True:
+ # Receive broadcast from the other hub.
+
+ data = hub.ble.observe(1)
+
+ if data is None:
+ # No data has been received in the last 1 second.
+ hub.light.on(Color.RED)
+ else:
+ # Data was received and is less that one second old.
+ hub.light.on(Color.GREEN)
+
+ # *data* contains the same values in the same order
+ # that were passed to hub.ble.broadcast() on the
+ # other hub.
+ left_angle, right_angle = data
+
+ # Make the motors on this hub mirror the position of the
+ # motors on the other hub.
+ left_motor.track_target(left_angle)
+ right_motor.track_target(right_angle)
+
+ # Broadcasts are only sent every 100 milliseconds, so there is
+ # no reason to call the observe() method more often than that.
+ wait(100)
diff --git a/examples/pup/hub_common/button_single.py b/examples/pup/hub_common/button_single.py
index 24c40a25..5e75f970 100644
--- a/examples/pup/hub_common/button_single.py
+++ b/examples/pup/hub_common/button_single.py
@@ -14,7 +14,7 @@
while watch.time() < 5000:
# Set light to green if pressed, else red.
- if hub.button.pressed():
+ if hub.buttons.pressed():
hub.light.on(Color.GREEN)
else:
hub.light.on(Color.RED)
diff --git a/examples/pup/robotics/car_remote.py b/examples/pup/robotics/car_remote.py
new file mode 100644
index 00000000..9cb615ce
--- /dev/null
+++ b/examples/pup/robotics/car_remote.py
@@ -0,0 +1,40 @@
+from pybricks.parameters import Direction, Port, Button
+from pybricks.pupdevices import Motor, Remote
+from pybricks.robotics import Car
+from pybricks.tools import wait
+
+# Set up motors.
+front = Motor(Port.A, Direction.COUNTERCLOCKWISE)
+rear = Motor(Port.B, Direction.COUNTERCLOCKWISE)
+steer = Motor(Port.C, Direction.CLOCKWISE)
+
+# Connect to the remote.
+remote = Remote()
+
+# Set up the car.
+car = Car(steer, [front, rear])
+
+# The main program starts here.
+while True:
+ # Read remote state.
+ pressed = remote.buttons.pressed()
+
+ # Steer using the left pad. Steering is the percentage
+ # of the angle determined while initializing.
+ steering = 0
+ if Button.LEFT_PLUS in pressed:
+ steering += 100
+ elif Button.LEFT_MINUS in pressed:
+ steering -= 100
+ car.steer(steering)
+
+ # Drive using the right pad.
+ power = 0
+ if Button.RIGHT_PLUS in pressed:
+ power += 100
+ elif Button.RIGHT_MINUS in pressed:
+ power -= 100
+ car.drive_power(power)
+
+ # Wait briefly.
+ wait(10)
diff --git a/examples/pup/robotics/drivebase_async.py b/examples/pup/robotics/drivebase_async.py
new file mode 100644
index 00000000..cadd1da0
--- /dev/null
+++ b/examples/pup/robotics/drivebase_async.py
@@ -0,0 +1,27 @@
+from pybricks.pupdevices import Motor
+from pybricks.parameters import Direction, Port
+from pybricks.robotics import DriveBase
+from pybricks.tools import multitask, run_task
+
+# Set up all devices.
+left = Motor(Port.A, Direction.COUNTERCLOCKWISE)
+right = Motor(Port.B)
+gripper = Motor(Port.C)
+drive_base = DriveBase(left, right, 56, 114)
+
+
+# Move the gripper up and down.
+async def move_gripper():
+ await gripper.run_angle(500, -90)
+ await gripper.run_angle(500, 90)
+
+
+# Drive forward, turn move gripper at the same time, and drive backward.
+async def main():
+ await drive_base.straight(250)
+ await multitask(drive_base.turn(90), move_gripper())
+ await drive_base.straight(-250)
+
+
+# Runs the main program from start to finish.
+run_task(main())
diff --git a/examples/pup/robotics/drivebase_basics.py b/examples/pup/robotics/drivebase_basics.py
index 66e189fc..e391657c 100644
--- a/examples/pup/robotics/drivebase_basics.py
+++ b/examples/pup/robotics/drivebase_basics.py
@@ -11,6 +11,9 @@
# The distance between the two wheel-ground contact points is 112mm.
drive_base = DriveBase(left_motor, right_motor, wheel_diameter=56, axle_track=112)
+# Optionally, uncomment the line below to use the gyro for improved accuracy.
+# drive_base.use_gyro(True)
+
# Drive forward by 500mm (half a meter).
drive_base.straight(500)
diff --git a/examples/pup/tools/hub_menu.py b/examples/pup/tools/hub_menu.py
new file mode 100644
index 00000000..62a054af
--- /dev/null
+++ b/examples/pup/tools/hub_menu.py
@@ -0,0 +1,16 @@
+from pybricks.tools import hub_menu
+
+# This example assumes that you have three other programs in Pybricks Code,
+# called "fly_mission", "drive_mission", and "zigzag". This example creates a
+# menu that lets you pick which one to run.
+
+# Choose a letter.
+selected = hub_menu("F", "D", "Z")
+
+# Based on the selection, run a program.
+if selected == "F":
+ import fly_mission
+elif selected == "D":
+ import drive_mission
+elif selected == "Z":
+ import zigzag
diff --git a/jedi/CHANGELOG.md b/jedi/CHANGELOG.md
index 25902ac4..3aceb3be 100644
--- a/jedi/CHANGELOG.md
+++ b/jedi/CHANGELOG.md
@@ -4,6 +4,51 @@
## Unreleased
+## 1.16.0 - 2024-04-05
+
+### Changed
+- Updated `pybricks` package to v3.5.0b2.
+
+## 1.15.0 - 2024-03-21
+
+### Changed
+- Updated `pybricks` package to v3.5.0b1.
+
+## 1.14.0 - 2024-03-05
+
+### Changed
+- Updated `pybricks` package to v3.4.0b5.
+
+## 1.13.0 - 2024-01-30
+
+### Changed
+- Updated `pybricks` package to v3.4.0b3.
+
+## 1.12.0 - 2023-11-24
+
+### Changed
+- Updated `pybricks` package to v3.3.0.
+
+## 1.11.0 - 2023-11-20
+
+### Changed
+- Updated `pybricks` package to v3.3.0c1.
+
+## 1.10.0 - 2023-10-26
+
+### Changed
+- Updated `pybricks` package to v3.3.0b9.
+
+## 1.9.0 - 2023-05-16
+
+### Changed
+- Updated `pybricks` package to v3.3.0b5.
+
+## 1.8.0 - 2023-04-21
+
+### Changed
+- Updated `pybricks` package to v3.3.0b4.
+
## 1.7.0 - 2022-12-28
### Added
diff --git a/jedi/poetry.lock b/jedi/poetry.lock
index 3c676772..e95841f5 100644
--- a/jedi/poetry.lock
+++ b/jedi/poetry.lock
@@ -1,24 +1,26 @@
-[[package]]
-name = "attrs"
-version = "22.1.0"
-description = "Classes Without Boilerplate"
-category = "dev"
-optional = false
-python-versions = ">=3.5"
-
-[package.extras]
-dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"]
-docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
-tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"]
-tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
+# This file is automatically @generated by Poetry and should not be changed by hand.
[[package]]
name = "black"
-version = "22.10.0"
+version = "22.12.0"
description = "The uncompromising code formatter."
category = "dev"
optional = false
python-versions = ">=3.7"
+files = [
+ {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"},
+ {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"},
+ {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"},
+ {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"},
+ {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"},
+ {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"},
+ {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"},
+ {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"},
+ {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"},
+ {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"},
+ {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"},
+ {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"},
+]
[package.dependencies]
click = ">=8.0.0"
@@ -35,11 +37,15 @@ uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "click"
-version = "8.1.3"
+version = "8.1.7"
description = "Composable command line interface toolkit"
category = "dev"
optional = false
python-versions = ">=3.7"
+files = [
+ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
+ {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
+]
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
@@ -51,6 +57,10 @@ description = "Cross-platform colored terminal text."
category = "dev"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
[[package]]
name = "docstring-parser"
@@ -59,14 +69,22 @@ description = "Parse Python docstrings in reST, Google and Numpydoc format"
category = "main"
optional = false
python-versions = ">=3.6,<4.0"
+files = [
+ {file = "docstring_parser-0.14.1-py3-none-any.whl", hash = "sha256:14ac6ec1f1ba6905c4d8cb90fd0bc55394f5678183752c90e44812bf28d7a515"},
+ {file = "docstring_parser-0.14.1.tar.gz", hash = "sha256:2c77522e31b7c88b1ab457a1f3c9ae38947ad719732260ba77ee8a3deb58622a"},
+]
[[package]]
name = "exceptiongroup"
-version = "1.0.4"
+version = "1.2.0"
description = "Backport of PEP 654 (exception groups)"
category = "dev"
optional = false
python-versions = ">=3.7"
+files = [
+ {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"},
+ {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"},
+]
[package.extras]
test = ["pytest (>=6)"]
@@ -78,6 +96,10 @@ description = "the modular source code checker: pep8 pyflakes and co"
category = "dev"
optional = false
python-versions = ">=3.6"
+files = [
+ {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"},
+ {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"},
+]
[package.dependencies]
mccabe = ">=0.6.0,<0.7.0"
@@ -86,11 +108,15 @@ pyflakes = ">=2.4.0,<2.5.0"
[[package]]
name = "iniconfig"
-version = "1.1.1"
-description = "iniconfig: brain-dead simple config-ini parsing"
+version = "2.0.0"
+description = "brain-dead simple config-ini parsing"
category = "dev"
optional = false
-python-versions = "*"
+python-versions = ">=3.7"
+files = [
+ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
+ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
+]
[[package]]
name = "jedi"
@@ -99,6 +125,10 @@ description = "An autocompletion tool for Python that can be used for text edito
category = "main"
optional = false
python-versions = ">=3.6"
+files = [
+ {file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"},
+ {file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"},
+]
[package.dependencies]
parso = ">=0.8.0,<0.9.0"
@@ -114,65 +144,90 @@ description = "McCabe checker, plugin for flake8"
category = "dev"
optional = false
python-versions = "*"
+files = [
+ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
+ {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
+]
[[package]]
name = "mypy-extensions"
-version = "0.4.3"
-description = "Experimental type system extensions for programs checked with the mypy typechecker."
+version = "1.0.0"
+description = "Type system extensions for programs checked with the mypy type checker."
category = "dev"
optional = false
-python-versions = "*"
+python-versions = ">=3.5"
+files = [
+ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
+ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
+]
[[package]]
name = "packaging"
-version = "21.3"
+version = "24.0"
description = "Core utilities for Python packages"
category = "dev"
optional = false
-python-versions = ">=3.6"
-
-[package.dependencies]
-pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
+python-versions = ">=3.7"
+files = [
+ {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"},
+ {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"},
+]
[[package]]
name = "parso"
-version = "0.8.3"
+version = "0.8.4"
description = "A Python Parser"
category = "main"
optional = false
python-versions = ">=3.6"
+files = [
+ {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"},
+ {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"},
+]
[package.extras]
-qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
-testing = ["docopt", "pytest (<6.0.0)"]
+qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"]
+testing = ["docopt", "pytest"]
[[package]]
name = "pathspec"
-version = "0.10.2"
+version = "0.12.1"
description = "Utility library for gitignore style pattern matching of file paths."
category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
+files = [
+ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
+ {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
+]
[[package]]
name = "platformdirs"
-version = "2.5.4"
+version = "4.2.0"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
+files = [
+ {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"},
+ {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"},
+]
[package.extras]
-docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"]
-test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
+docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"]
[[package]]
name = "pluggy"
-version = "1.0.0"
+version = "1.4.0"
description = "plugin and hook calling mechanisms for python"
category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
+files = [
+ {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"},
+ {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"},
+]
[package.extras]
dev = ["pre-commit", "tox"]
@@ -180,11 +235,12 @@ testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "pybricks"
-version = "3.2.0c1"
+version = "3.5.0b2"
description = "Documentation and user-API stubs for Pybricks MicroPython"
category = "main"
optional = false
python-versions = "^3.8"
+files = []
develop = true
[package.source]
@@ -198,6 +254,10 @@ description = "Python style guide checker"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+ {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"},
+ {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"},
+]
[[package]]
name = "pyflakes"
@@ -206,28 +266,24 @@ description = "passive checker of Python programs"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-
-[[package]]
-name = "pyparsing"
-version = "3.0.9"
-description = "pyparsing module - Classes and methods to define and execute parsing grammars"
-category = "dev"
-optional = false
-python-versions = ">=3.6.8"
-
-[package.extras]
-diagrams = ["jinja2", "railroad-diagrams"]
+files = [
+ {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"},
+ {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"},
+]
[[package]]
name = "pytest"
-version = "7.2.0"
+version = "7.4.4"
description = "pytest: simple powerful testing with Python"
category = "dev"
optional = false
python-versions = ">=3.7"
+files = [
+ {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"},
+ {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"},
+]
[package.dependencies]
-attrs = ">=19.2.0"
colorama = {version = "*", markers = "sys_platform == \"win32\""}
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
iniconfig = "*"
@@ -236,7 +292,7 @@ pluggy = ">=0.12,<2.0"
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
[package.extras]
-testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
+testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
[[package]]
name = "tomli"
@@ -245,6 +301,10 @@ description = "A lil' TOML parser"
category = "dev"
optional = false
python-versions = ">=3.7"
+files = [
+ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
+ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
+]
[[package]]
name = "typing-extensions"
@@ -253,118 +313,12 @@ description = "Backported and Experimental Type Hints for Python 3.7+"
category = "main"
optional = false
python-versions = ">=3.7"
-
-[metadata]
-lock-version = "1.1"
-python-versions = ">= 3.10, < 3.11"
-content-hash = "971c6d0dddd9bb8e33a942e2360905a7d80a1a9d33015c0defc08345df5c1019"
-
-[metadata.files]
-attrs = [
- {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"},
- {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"},
-]
-black = [
- {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"},
- {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"},
- {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"},
- {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"},
- {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"},
- {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"},
- {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"},
- {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"},
- {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"},
- {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"},
- {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"},
- {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"},
- {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"},
- {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"},
- {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"},
- {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"},
- {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"},
- {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"},
- {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"},
- {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"},
- {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"},
-]
-click = [
- {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
- {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
-]
-colorama = [
- {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
- {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
-]
-docstring-parser = [
- {file = "docstring_parser-0.14.1-py3-none-any.whl", hash = "sha256:14ac6ec1f1ba6905c4d8cb90fd0bc55394f5678183752c90e44812bf28d7a515"},
- {file = "docstring_parser-0.14.1.tar.gz", hash = "sha256:2c77522e31b7c88b1ab457a1f3c9ae38947ad719732260ba77ee8a3deb58622a"},
-]
-exceptiongroup = [
- {file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"},
- {file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"},
-]
-flake8 = [
- {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"},
- {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"},
-]
-iniconfig = [
- {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
- {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
-]
-jedi = [
- {file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"},
- {file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"},
-]
-mccabe = [
- {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
- {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
-]
-mypy-extensions = [
- {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
- {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
-]
-packaging = [
- {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
- {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
-]
-parso = [
- {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"},
- {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"},
-]
-pathspec = [
- {file = "pathspec-0.10.2-py3-none-any.whl", hash = "sha256:88c2606f2c1e818b978540f73ecc908e13999c6c3a383daf3705652ae79807a5"},
- {file = "pathspec-0.10.2.tar.gz", hash = "sha256:8f6bf73e5758fd365ef5d58ce09ac7c27d2833a8d7da51712eac6e27e35141b0"},
-]
-platformdirs = [
- {file = "platformdirs-2.5.4-py3-none-any.whl", hash = "sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10"},
- {file = "platformdirs-2.5.4.tar.gz", hash = "sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7"},
-]
-pluggy = [
- {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
- {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
-]
-pybricks = []
-pycodestyle = [
- {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"},
- {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"},
-]
-pyflakes = [
- {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"},
- {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"},
-]
-pyparsing = [
- {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
- {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
-]
-pytest = [
- {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"},
- {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"},
-]
-tomli = [
- {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
- {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
-]
-typing-extensions = [
+files = [
{file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"},
{file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"},
]
+
+[metadata]
+lock-version = "2.0"
+python-versions = ">= 3.10, < 3.12"
+content-hash = "a634c0231937213565b3dff33539075fd544a4261bf8f84e99b294f34ec7edd4"
diff --git a/jedi/pyproject.toml b/jedi/pyproject.toml
index 16b911a3..f027f157 100644
--- a/jedi/pyproject.toml
+++ b/jedi/pyproject.toml
@@ -1,13 +1,13 @@
[tool.poetry]
name = "pybricks_jedi"
-version = "1.7.0"
+version = "1.16.0"
description = "Code completion for Pybricks."
authors = ["The Pybricks Authors "]
license = "MIT"
[tool.poetry.dependencies]
-python = ">= 3.10, < 3.11"
-pybricks = "3.2.0c1"
+python = ">= 3.10, < 3.12"
+pybricks = "3.5.0b2"
jedi = "0.18.1"
typing-extensions = "4.2.0"
docstring-parser = "0.14.1"
diff --git a/jedi/tests/test_complete_city_hub.py b/jedi/tests/test_complete_city_hub.py
index e9e09504..7f7f0d2a 100644
--- a/jedi/tests/test_complete_city_hub.py
+++ b/jedi/tests/test_complete_city_hub.py
@@ -33,7 +33,8 @@ def test_hub_dot():
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"battery",
- "button",
+ "ble",
+ "buttons",
"light",
"system",
]
@@ -50,7 +51,7 @@ def test_hub_dot_battery_dot():
def test_hub_dot_button_dot():
- line = "hub.button."
+ line = "hub.buttons."
code = _create_snippet(line)
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
diff --git a/jedi/tests/test_complete_essential_hub.py b/jedi/tests/test_complete_essential_hub.py
index 37d9d9dd..d66f9eed 100644
--- a/jedi/tests/test_complete_essential_hub.py
+++ b/jedi/tests/test_complete_essential_hub.py
@@ -33,7 +33,8 @@ def test_hub_dot():
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"battery",
- "button",
+ "ble",
+ "buttons",
"charger",
"imu",
"light",
@@ -52,7 +53,7 @@ def test_hub_dot_battery_dot():
def test_hub_dot_buttons_dot():
- line = "hub.button."
+ line = "hub.buttons."
code = _create_snippet(line)
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
diff --git a/jedi/tests/test_complete_import.py b/jedi/tests/test_complete_import.py
index d8eb85f9..96f889ef 100644
--- a/jedi/tests/test_complete_import.py
+++ b/jedi/tests/test_complete_import.py
@@ -108,6 +108,7 @@ def test_from_pybricks_iodevices_import():
"LWP3Device",
"PUPDevice",
"UARTDevice",
+ "XboxController",
]
@@ -148,7 +149,7 @@ def test_from_pybricks_pupdevices_import():
def test_from_pybricks_robotics_import():
code = "from pybricks.robotics import "
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
- assert [c["insertText"] for c in completions] == ["DriveBase", "GyroDriveBase"]
+ assert [c["insertText"] for c in completions] == ["Car", "DriveBase"]
def test_from_pybricks_tools_import():
@@ -157,7 +158,11 @@ def test_from_pybricks_tools_import():
assert [c["insertText"] for c in completions] == [
"cross",
"DataLog",
+ "hub_menu",
"Matrix",
+ "multitask",
+ "read_input_byte",
+ "run_task",
"StopWatch",
"vector",
"wait",
diff --git a/jedi/tests/test_complete_move_hub.py b/jedi/tests/test_complete_move_hub.py
index c370aa52..e295b584 100644
--- a/jedi/tests/test_complete_move_hub.py
+++ b/jedi/tests/test_complete_move_hub.py
@@ -33,7 +33,8 @@ def test_hub_dot():
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"battery",
- "button",
+ "ble",
+ "buttons",
"imu",
"light",
"system",
@@ -51,7 +52,7 @@ def test_hub_dot_battery_dot():
def test_hub_dot_button_dot():
- line = "hub.button."
+ line = "hub.buttons."
code = _create_snippet(line)
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
@@ -65,6 +66,7 @@ def test_hub_dot_imu_dot():
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"acceleration",
+ "tilt",
"up",
]
diff --git a/jedi/tests/test_complete_parameters.py b/jedi/tests/test_complete_parameters.py
index 36252a62..6076cbf2 100644
--- a/jedi/tests/test_complete_parameters.py
+++ b/jedi/tests/test_complete_parameters.py
@@ -20,26 +20,6 @@ def _create_snippet(class_name: str) -> str:
ENUMS = [
- pytest.param(
- "Button",
- [
- "BEACON",
- "BLUETOOTH",
- "CENTER",
- "DOWN",
- "LEFT",
- "LEFT_DOWN",
- "LEFT_MINUS",
- "LEFT_PLUS",
- "LEFT_UP",
- "RIGHT",
- "RIGHT_DOWN",
- "RIGHT_MINUS",
- "RIGHT_PLUS",
- "RIGHT_UP",
- "UP",
- ],
- ),
pytest.param(
"Color",
[
diff --git a/jedi/tests/test_complete_prime_hub.py b/jedi/tests/test_complete_prime_hub.py
index 7f760640..65080ad8 100644
--- a/jedi/tests/test_complete_prime_hub.py
+++ b/jedi/tests/test_complete_prime_hub.py
@@ -33,6 +33,7 @@ def test_hub_dot():
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"battery",
+ "ble",
"buttons",
"charger",
"display",
diff --git a/jedi/tests/test_complete_technic_hub.py b/jedi/tests/test_complete_technic_hub.py
index 2eb03ef9..0188853f 100644
--- a/jedi/tests/test_complete_technic_hub.py
+++ b/jedi/tests/test_complete_technic_hub.py
@@ -33,7 +33,8 @@ def test_hub_dot():
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
"battery",
- "button",
+ "ble",
+ "buttons",
"imu",
"light",
"system",
@@ -51,7 +52,7 @@ def test_hub_dot_battery_dot():
def test_hub_dot_button_dot():
- line = "hub.button."
+ line = "hub.buttons."
code = _create_snippet(line)
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
assert [c["insertText"] for c in completions] == [
diff --git a/jedi/tests/test_get_signature.py b/jedi/tests/test_get_signature.py
index b3dc7717..b64ce156 100644
--- a/jedi/tests/test_get_signature.py
+++ b/jedi/tests/test_get_signature.py
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: MIT
-# Copyright (c) 2022 The Pybricks Authors
+# Copyright (c) 2022-2023 The Pybricks Authors
"""
Tests for correct signatures of the pupdevices.Motor class.
@@ -29,7 +29,12 @@ def _get_function_signature(module: str, function: str) -> SignatureHelp:
FUNCTION_PARAMS = [
- pytest.param("pybricks.tools", "wait", [(["time: Number"], "None")]),
+ pytest.param(
+ "pybricks.tools",
+ "read_input_byte",
+ [(["last: bool=False", "chr: bool=False"], "Optional[int | str]")],
+ ),
+ pytest.param("pybricks.tools", "wait", [(["time: Number"], "MaybeAwaitable")]),
pytest.param(
"pybricks.tools",
"vector",
@@ -78,17 +83,51 @@ def _get_constructor_signature(module: str, type: str) -> SignatureHelp:
CONSTRUCTOR_PARAMS = [
- pytest.param("pybricks.hubs", "MoveHub", [[]]),
- pytest.param("pybricks.hubs", "CityHub", [[]]),
+ pytest.param(
+ "pybricks.hubs",
+ "MoveHub",
+ [["broadcast_channel: int=0", "observe_channels: Sequence[int]=[]"]],
+ ),
+ pytest.param(
+ "pybricks.hubs",
+ "CityHub",
+ [["broadcast_channel: int=0", "observe_channels: Sequence[int]=[]"]],
+ ),
pytest.param(
"pybricks.hubs",
"TechnicHub",
- [["top_side: Axis=Axis.Z", "front_side: Axis=Axis.X"]],
+ [
+ [
+ "top_side: Axis=Axis.Z",
+ "front_side: Axis=Axis.X",
+ "broadcast_channel: int=0",
+ "observe_channels: Sequence[int]=[]",
+ ]
+ ],
),
pytest.param(
"pybricks.hubs",
"PrimeHub",
- [["top_side: Axis=Axis.Z", "front_side: Axis=Axis.X"]],
+ [
+ [
+ "top_side: Axis=Axis.Z",
+ "front_side: Axis=Axis.X",
+ "broadcast_channel: int=0",
+ "observe_channels: Sequence[int]=[]",
+ ]
+ ],
+ ),
+ pytest.param(
+ "pybricks.hubs",
+ "EssentialHub",
+ [
+ [
+ "top_side: Axis=Axis.Z",
+ "front_side: Axis=Axis.X",
+ "broadcast_channel: int=0",
+ "observe_channels: Sequence[int]=[]",
+ ]
+ ],
),
pytest.param(
"pybricks.pupdevices",
@@ -218,9 +257,7 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
),
pytest.param("pybricks.hubs", "MoveHub", "battery.voltage", [([], "int")]),
pytest.param("pybricks.hubs", "MoveHub", "battery.current", [([], "int")]),
- pytest.param(
- "pybricks.hubs", "MoveHub", "button.pressed", [([], "Collection[Button]")]
- ),
+ pytest.param("pybricks.hubs", "MoveHub", "buttons.pressed", [([], "Set[Button]")]),
pytest.param(
"pybricks.hubs",
"MoveHub",
@@ -255,9 +292,7 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
),
pytest.param("pybricks.hubs", "CityHub", "battery.voltage", [([], "int")]),
pytest.param("pybricks.hubs", "CityHub", "battery.current", [([], "int")]),
- pytest.param(
- "pybricks.hubs", "CityHub", "button.pressed", [([], "Collection[Button]")]
- ),
+ pytest.param("pybricks.hubs", "CityHub", "buttons.pressed", [([], "Set[Button]")]),
pytest.param(
"pybricks.hubs",
"CityHub",
@@ -323,7 +358,7 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
pytest.param("pybricks.hubs", "TechnicHub", "battery.voltage", [([], "int")]),
pytest.param("pybricks.hubs", "TechnicHub", "battery.current", [([], "int")]),
pytest.param(
- "pybricks.hubs", "TechnicHub", "button.pressed", [([], "Collection[Button]")]
+ "pybricks.hubs", "TechnicHub", "buttons.pressed", [([], "Set[Button]")]
),
pytest.param(
"pybricks.hubs",
@@ -388,9 +423,7 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
"display.text",
[(["text: str", "on: Number=500", "off: Number=50"], "None")],
),
- pytest.param(
- "pybricks.hubs", "PrimeHub", "buttons.pressed", [([], "Collection[Button]")]
- ),
+ pytest.param("pybricks.hubs", "PrimeHub", "buttons.pressed", [([], "Set[Button]")]),
pytest.param("pybricks.hubs", "PrimeHub", "imu.up", [([], "Side")]),
pytest.param("pybricks.hubs", "PrimeHub", "imu.tilt", [([], "Tuple[int, int]")]),
pytest.param(
@@ -429,13 +462,13 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
"pybricks.hubs",
"PrimeHub",
"speaker.beep",
- [(["frequency: Number=500", "duration: Number=100"], "None")],
+ [(["frequency: Number=500", "duration: Number=100"], "MaybeAwaitable")],
),
pytest.param(
"pybricks.hubs",
"PrimeHub",
"speaker.play_notes",
- [(["notes: Iterable[str]", "tempo: Number=120"], "None")],
+ [(["notes: Iterable[str]", "tempo: Number=120"], "MaybeAwaitable")],
),
pytest.param("pybricks.hubs", "PrimeHub", "battery.voltage", [([], "int")]),
pytest.param("pybricks.hubs", "PrimeHub", "battery.current", [([], "int")]),
@@ -477,7 +510,7 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
[(["colors: Collection[Color]", "interval: Number"], "None")],
),
pytest.param(
- "pybricks.hubs", "EssentialHub", "button.pressed", [([], "Collection[Button]")]
+ "pybricks.hubs", "EssentialHub", "buttons.pressed", [([], "Set[Button]")]
),
pytest.param("pybricks.hubs", "EssentialHub", "imu.up", [([], "Side")]),
pytest.param(
@@ -571,7 +604,7 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
"then: Stop=Stop.HOLD",
"wait: bool=True",
],
- "None",
+ "MaybeAwaitable",
)
],
),
@@ -587,7 +620,7 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
"then: Stop=Stop.HOLD",
"wait: bool=True",
],
- "None",
+ "MaybeAwaitable",
)
],
),
@@ -603,7 +636,7 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
"then: Stop=Stop.HOLD",
"wait: bool=True",
],
- "None",
+ "MaybeAwaitable",
)
],
),
@@ -624,7 +657,7 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
"then: Stop=Stop.COAST",
"duty_limit: Optional[Number]=None",
],
- "int",
+ "MaybeAwaitableInt",
)
],
),
@@ -703,24 +736,53 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
],
),
pytest.param(
- "pybricks.pupdevices", "TiltSensor", "tilt", [([], "Tuple[int, int]")]
+ "pybricks.pupdevices",
+ "TiltSensor",
+ "tilt",
+ [([], "MaybeAwaitableTuple[int, int]")],
+ ),
+ pytest.param(
+ "pybricks.pupdevices", "InfraredSensor", "distance", [([], "MaybeAwaitableInt")]
+ ),
+ pytest.param(
+ "pybricks.pupdevices",
+ "InfraredSensor",
+ "reflection",
+ [([], "MaybeAwaitableInt")],
),
- pytest.param("pybricks.pupdevices", "InfraredSensor", "distance", [([], "int")]),
- pytest.param("pybricks.pupdevices", "InfraredSensor", "reflection", [([], "int")]),
- pytest.param("pybricks.pupdevices", "InfraredSensor", "count", [([], "int")]),
pytest.param(
- "pybricks.pupdevices", "ColorDistanceSensor", "color", [([], "Color")]
+ "pybricks.pupdevices", "InfraredSensor", "count", [([], "MaybeAwaitableInt")]
),
pytest.param(
- "pybricks.pupdevices", "ColorDistanceSensor", "reflection", [([], "int")]
+ "pybricks.pupdevices",
+ "ColorDistanceSensor",
+ "color",
+ [([], "MaybeAwaitableColor")],
),
pytest.param(
- "pybricks.pupdevices", "ColorDistanceSensor", "ambient", [([], "int")]
+ "pybricks.pupdevices",
+ "ColorDistanceSensor",
+ "reflection",
+ [([], "MaybeAwaitableInt")],
),
pytest.param(
- "pybricks.pupdevices", "ColorDistanceSensor", "distance", [([], "int")]
+ "pybricks.pupdevices",
+ "ColorDistanceSensor",
+ "ambient",
+ [([], "MaybeAwaitableInt")],
+ ),
+ pytest.param(
+ "pybricks.pupdevices",
+ "ColorDistanceSensor",
+ "distance",
+ [([], "MaybeAwaitableInt")],
+ ),
+ pytest.param(
+ "pybricks.pupdevices",
+ "ColorDistanceSensor",
+ "hsv",
+ [([], "MaybeAwaitableColor")],
),
- pytest.param("pybricks.pupdevices", "ColorDistanceSensor", "hsv", [([], "Color")]),
pytest.param(
"pybricks.pupdevices",
"ColorDistanceSensor",
@@ -731,27 +793,36 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
"pybricks.pupdevices",
"ColorDistanceSensor",
"light.on",
- [(["color: Color"], "None")],
+ [(["color: Color"], "MaybeAwaitable")],
),
pytest.param(
- "pybricks.pupdevices", "ColorDistanceSensor", "light.off", [([], "None")]
+ "pybricks.pupdevices",
+ "ColorDistanceSensor",
+ "light.off",
+ [([], "MaybeAwaitable")],
),
- pytest.param("pybricks.pupdevices", "PFMotor", "dc", [(["duty: Number"], "None")]),
- pytest.param("pybricks.pupdevices", "PFMotor", "stop", [([], "None")]),
- pytest.param("pybricks.pupdevices", "PFMotor", "brake", [([], "None")]),
+ pytest.param(
+ "pybricks.pupdevices", "PFMotor", "dc", [(["duty: Number"], "MaybeAwaitable")]
+ ),
+ pytest.param("pybricks.pupdevices", "PFMotor", "stop", [([], "MaybeAwaitable")]),
+ pytest.param("pybricks.pupdevices", "PFMotor", "brake", [([], "MaybeAwaitable")]),
pytest.param(
"pybricks.pupdevices",
"ColorSensor",
"color",
- [(["surface: bool=True"], "Optional[Color]")],
+ [(["surface: bool=True"], "MaybeAwaitableColor")],
+ ),
+ pytest.param(
+ "pybricks.pupdevices", "ColorSensor", "reflection", [([], "MaybeAwaitableInt")]
+ ),
+ pytest.param(
+ "pybricks.pupdevices", "ColorSensor", "ambient", [([], "MaybeAwaitableInt")]
),
- pytest.param("pybricks.pupdevices", "ColorSensor", "reflection", [([], "int")]),
- pytest.param("pybricks.pupdevices", "ColorSensor", "ambient", [([], "int")]),
pytest.param(
"pybricks.pupdevices",
"ColorSensor",
"hsv",
- [(["surface: bool=True"], "Color")],
+ [(["surface: bool=True"], "MaybeAwaitableColor")],
),
pytest.param(
"pybricks.pupdevices",
@@ -763,11 +834,28 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
"pybricks.pupdevices",
"ColorSensor",
"lights.on",
- [(["brightness: Union[Number, Tuple[Number, Number, Number]]"], "None")],
+ [
+ (
+ ["brightness: Union[Number, Tuple[Number, Number, Number]]"],
+ "MaybeAwaitable",
+ )
+ ],
+ ),
+ pytest.param(
+ "pybricks.pupdevices", "ColorSensor", "lights.off", [([], "MaybeAwaitable")]
+ ),
+ pytest.param(
+ "pybricks.pupdevices",
+ "UltrasonicSensor",
+ "distance",
+ [([], "MaybeAwaitableInt")],
+ ),
+ pytest.param(
+ "pybricks.pupdevices",
+ "UltrasonicSensor",
+ "presence",
+ [([], "MaybeAwaitableBool")],
),
- pytest.param("pybricks.pupdevices", "ColorSensor", "lights.off", [([], "None")]),
- pytest.param("pybricks.pupdevices", "UltrasonicSensor", "distance", [([], "int")]),
- pytest.param("pybricks.pupdevices", "UltrasonicSensor", "presence", [([], "bool")]),
pytest.param(
"pybricks.pupdevices",
"UltrasonicSensor",
@@ -775,29 +863,40 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
[
(
["brightness: Union[Number, Tuple[Number, Number, Number, Number]]"],
- "None",
+ "MaybeAwaitable",
)
],
),
pytest.param(
- "pybricks.pupdevices", "UltrasonicSensor", "lights.off", [([], "None")]
+ "pybricks.pupdevices",
+ "UltrasonicSensor",
+ "lights.off",
+ [([], "MaybeAwaitable")],
+ ),
+ pytest.param(
+ "pybricks.pupdevices", "ForceSensor", "force", [([], "MaybeAwaitableFloat")]
+ ),
+ pytest.param(
+ "pybricks.pupdevices", "ForceSensor", "distance", [([], "MaybeAwaitableFloat")]
),
- pytest.param("pybricks.pupdevices", "ForceSensor", "force", [([], "float")]),
- pytest.param("pybricks.pupdevices", "ForceSensor", "distance", [([], "float")]),
pytest.param(
"pybricks.pupdevices",
"ForceSensor",
"pressed",
- [(["force: Number=3"], "bool")],
+ [(["force: Number=3"], "MaybeAwaitableBool")],
+ ),
+ pytest.param(
+ "pybricks.pupdevices", "ForceSensor", "touched", [([], "MaybeAwaitableBool")]
),
- pytest.param("pybricks.pupdevices", "ForceSensor", "touched", [([], "bool")]),
pytest.param(
"pybricks.pupdevices",
"ColorLightMatrix",
"on",
- [(["color: Union[Color, Collection[Color]]"], "None")],
+ [(["color: Union[Color, Collection[Color]]"], "MaybeAwaitable")],
+ ),
+ pytest.param(
+ "pybricks.pupdevices", "ColorLightMatrix", "off", [([], "MaybeAwaitable")]
),
- pytest.param("pybricks.pupdevices", "ColorLightMatrix", "off", [([], "None")]),
pytest.param(
"pybricks.pupdevices", "Light", "on", [(["brightness: Number=100"], "None")]
),
@@ -809,14 +908,19 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
[(["name: str"], "None"), ([], "str")],
),
pytest.param(
- "pybricks.pupdevices", "Remote", "light.on", [(["color: Color"], "None")]
+ "pybricks.pupdevices",
+ "Remote",
+ "light.on",
+ [(["color: Color"], "MaybeAwaitable")],
+ ),
+ pytest.param(
+ "pybricks.pupdevices", "Remote", "light.off", [([], "MaybeAwaitable")]
),
- pytest.param("pybricks.pupdevices", "Remote", "light.off", [([], "None")]),
pytest.param(
"pybricks.pupdevices",
"Remote",
"buttons.pressed",
- [([], "Collection[Button]")],
+ [([], "Set[Button]")],
),
pytest.param("pybricks.tools", "StopWatch", "time", [([], "int")]),
pytest.param("pybricks.tools", "StopWatch", "pause", [([], "None")]),
@@ -826,13 +930,23 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
"pybricks.robotics",
"DriveBase",
"straight",
- [(["distance: Number", "then: Stop=Stop.HOLD", "wait: bool=True"], "None")],
+ [
+ (
+ ["distance: Number", "then: Stop=Stop.HOLD", "wait: bool=True"],
+ "MaybeAwaitable",
+ )
+ ],
),
pytest.param(
"pybricks.robotics",
"DriveBase",
"turn",
- [(["angle: Number", "then: Stop=Stop.HOLD", "wait: bool=True"], "None")],
+ [
+ (
+ ["angle: Number", "then: Stop=Stop.HOLD", "wait: bool=True"],
+ "MaybeAwaitable",
+ )
+ ],
),
pytest.param(
"pybricks.robotics",
@@ -846,7 +960,7 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
"then: Stop=Stop.HOLD",
"wait: bool=True",
],
- "None",
+ "MaybeAwaitable",
)
],
),
@@ -874,6 +988,7 @@ def _get_method_signature(module: str, type: str, method: str) -> SignatureHelp:
[(["speed: Number", "turn_rate: Number"], "None")],
),
pytest.param("pybricks.robotics", "DriveBase", "stop", [([], "None")]),
+ pytest.param("pybricks.robotics", "DriveBase", "brake", [([], "None")]),
pytest.param("pybricks.robotics", "DriveBase", "distance", [([], "int")]),
pytest.param("pybricks.robotics", "DriveBase", "angle", [([], "int")]),
pytest.param(
diff --git a/npm/ide-docs/CHANGELOG.md b/npm/ide-docs/CHANGELOG.md
index 376b90e8..d025391c 100644
--- a/npm/ide-docs/CHANGELOG.md
+++ b/npm/ide-docs/CHANGELOG.md
@@ -2,6 +2,66 @@
+## 2.19.0 - 2024-04-11
+
+### Changed
+- Updated docs to v3.5.0.
+
+## 2.18.0 - 2024-04-05
+
+### Changed
+- Updated docs to v3.5.0b2.
+
+## 2.17.0 - 2024-03-21
+
+### Changed
+- Updated docs to v3.5.0b1.
+
+## 2.16.0 - 2024-03-11
+
+### Changed
+- Updated docs to v3.4.0.
+
+## 2.15.0 - 2024-03-05
+
+### Changed
+- Updated docs to v3.4.0b5.
+
+## 2.14.0 - 2024-01-30
+
+### Changed
+- Updated docs to v3.4.0b3.
+
+## 2.13.0 - 2023-11-24
+
+### Changed
+- Updated docs to v3.4.0b1.
+
+## 2.12.0 - 2023-11-24
+
+### Changed
+- Updated docs to v3.3.0.
+
+## 2.11.0 - 2023-11-20
+
+### Changed
+- Updated docs to v3.3.0c1.
+
+## 2.10.0 - 2023-10-26
+
+### Changed
+- Updated docs to v3.3.0b9.
+
+## 2.9.0 - 2023-05-16
+
+### Changed
+- Updated docs to v3.3.0b5.
+
+## 2.8.0 - 2023-04-21
+
+### Changed
+- Updated docs to v3.3.0b4.
+
## 2.7.0 - 2022-12-20
### Changed
diff --git a/npm/ide-docs/LICENSE b/npm/ide-docs/LICENSE
index b4831908..508e3fdd 100644
--- a/npm/ide-docs/LICENSE
+++ b/npm/ide-docs/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2018-2021 The Pybricks Authors
+Copyright (c) 2018-2023 The Pybricks Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/npm/ide-docs/package.json b/npm/ide-docs/package.json
index eef2c89f..7c32c18e 100644
--- a/npm/ide-docs/package.json
+++ b/npm/ide-docs/package.json
@@ -1,6 +1,6 @@
{
"name": "@pybricks/ide-docs",
- "version": "2.7.0",
+ "version": "2.19.0",
"description": "Special build of Pybricks API docs for embedding in an IDE.",
"repository": {
"type": "git",
diff --git a/npm/jedi/CHANGELOG.md b/npm/jedi/CHANGELOG.md
index 27644cd1..fb8067ba 100644
--- a/npm/jedi/CHANGELOG.md
+++ b/npm/jedi/CHANGELOG.md
@@ -4,6 +4,54 @@
## Unreleased
+## 1.16.0 - 2024-04-05
+
+### Changed
+- Updated `pybricks_jedi` Python package to v1.16.0.
+
+## 1.15.0 - 2024-03-21
+
+### Changed
+- Updated `pybricks_jedi` Python package to v1.15.0.
+
+## 1.14.0 - 2024-03-05
+
+### Changed
+- Updated `pybricks_jedi` Python package to v1.14.0.
+
+## 1.13.0 - 2024-01-30
+
+### Changed
+- Updated `pybricks_jedi` Python package to v1.13.0.
+
+### Changed
+- Updated `pybricks_jedi` Python package to v1.12.0.
+
+## 1.12.0 - 2023-11-24
+
+### Changed
+- Updated `pybricks_jedi` Python package to v1.12.0.
+
+## 1.11.0 - 2023-11-20
+
+### Changed
+- Updated `pybricks_jedi` Python package to v1.11.0.
+
+## 1.10.0 - 2023-10-26
+
+### Changed
+- Updated `pybricks_jedi` Python package to v1.10.0.
+
+## 1.9.0 - 2023-05-16
+
+### Changed
+- Updated `pybricks_jedi` Python package to v1.9.0.
+
+## 1.8.0 - 2023-04-21
+
+### Changed
+- Updated `pybricks_jedi` Python package to v1.8.0.
+
## 1.7.0 - 2022-12-28
### Changed
diff --git a/npm/jedi/build.py b/npm/jedi/build.py
index 779b68af..20288e5b 100755
--- a/npm/jedi/build.py
+++ b/npm/jedi/build.py
@@ -12,7 +12,7 @@
package_json = {
"name": "@pybricks/jedi",
- "version": "1.7.0",
+ "version": "1.16.0",
"description": "Binary distribution of pybricks-jedi Python package and dependencies for use with Pyodide.",
"repository": {
"type": "git",
@@ -30,7 +30,7 @@
shutil.rmtree(BUILD_DIR, True)
BUILD_DIR.mkdir()
-# download package and depedencies (*.whl files)
+# download package and dependencies (*.whl files)
subprocess.check_call(
[
sys.executable,
@@ -38,7 +38,7 @@
"pip",
"download",
"--only-binary=any",
- "pybricks-jedi==1.7.0",
+ "pybricks-jedi==1.16.0",
],
cwd=BUILD_DIR,
)
diff --git a/poetry.lock b/poetry.lock
index 40d13b63..ba59682c 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,29 +1,56 @@
+# This file is automatically @generated by Poetry and should not be changed by hand.
+
[[package]]
name = "alabaster"
-version = "0.7.12"
+version = "0.7.13"
description = "A configurable sidebar-enabled Sphinx theme"
category = "dev"
optional = false
-python-versions = "*"
+python-versions = ">=3.6"
+files = [
+ {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"},
+ {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"},
+]
[[package]]
-name = "Babel"
-version = "2.11.0"
+name = "babel"
+version = "2.13.0"
description = "Internationalization utilities"
category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
+files = [
+ {file = "Babel-2.13.0-py3-none-any.whl", hash = "sha256:fbfcae1575ff78e26c7449136f1abbefc3c13ce542eeb13d43d50d8b047216ec"},
+ {file = "Babel-2.13.0.tar.gz", hash = "sha256:04c3e2d28d2b7681644508f836be388ae49e0cfe91465095340395b60d00f210"},
+]
[package.dependencies]
-pytz = ">=2015.7"
+pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""}
+
+[package.extras]
+dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
[[package]]
name = "black"
-version = "22.10.0"
+version = "22.12.0"
description = "The uncompromising code formatter."
category = "dev"
optional = false
python-versions = ">=3.7"
+files = [
+ {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"},
+ {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"},
+ {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"},
+ {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"},
+ {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"},
+ {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"},
+ {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"},
+ {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"},
+ {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"},
+ {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"},
+ {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"},
+ {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"},
+]
[package.dependencies]
click = ">=8.0.0"
@@ -41,38 +68,139 @@ uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "certifi"
-version = "2022.12.7"
+version = "2023.7.22"
description = "Python package for providing Mozilla's CA Bundle."
category = "dev"
optional = false
python-versions = ">=3.6"
+files = [
+ {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"},
+ {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"},
+]
[[package]]
name = "chardet"
-version = "5.1.0"
+version = "5.2.0"
description = "Universal encoding detector for Python 3"
category = "dev"
optional = false
python-versions = ">=3.7"
+files = [
+ {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"},
+ {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"},
+]
[[package]]
name = "charset-normalizer"
-version = "2.1.1"
+version = "3.3.1"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "dev"
optional = false
-python-versions = ">=3.6.0"
-
-[package.extras]
-unicode-backport = ["unicodedata2"]
+python-versions = ">=3.7.0"
+files = [
+ {file = "charset-normalizer-3.3.1.tar.gz", hash = "sha256:d9137a876020661972ca6eec0766d81aef8a5627df628b664b234b73396e727e"},
+ {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8aee051c89e13565c6bd366813c386939f8e928af93c29fda4af86d25b73d8f8"},
+ {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:352a88c3df0d1fa886562384b86f9a9e27563d4704ee0e9d56ec6fcd270ea690"},
+ {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:223b4d54561c01048f657fa6ce41461d5ad8ff128b9678cfe8b2ecd951e3f8a2"},
+ {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f861d94c2a450b974b86093c6c027888627b8082f1299dfd5a4bae8e2292821"},
+ {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1171ef1fc5ab4693c5d151ae0fdad7f7349920eabbaca6271f95969fa0756c2d"},
+ {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28f512b9a33235545fbbdac6a330a510b63be278a50071a336afc1b78781b147"},
+ {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0e842112fe3f1a4ffcf64b06dc4c61a88441c2f02f373367f7b4c1aa9be2ad5"},
+ {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f9bc2ce123637a60ebe819f9fccc614da1bcc05798bbbaf2dd4ec91f3e08846"},
+ {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f194cce575e59ffe442c10a360182a986535fd90b57f7debfaa5c845c409ecc3"},
+ {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9a74041ba0bfa9bc9b9bb2cd3238a6ab3b7618e759b41bd15b5f6ad958d17605"},
+ {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b578cbe580e3b41ad17b1c428f382c814b32a6ce90f2d8e39e2e635d49e498d1"},
+ {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6db3cfb9b4fcecb4390db154e75b49578c87a3b9979b40cdf90d7e4b945656e1"},
+ {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:debb633f3f7856f95ad957d9b9c781f8e2c6303ef21724ec94bea2ce2fcbd056"},
+ {file = "charset_normalizer-3.3.1-cp310-cp310-win32.whl", hash = "sha256:87071618d3d8ec8b186d53cb6e66955ef2a0e4fa63ccd3709c0c90ac5a43520f"},
+ {file = "charset_normalizer-3.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:e372d7dfd154009142631de2d316adad3cc1c36c32a38b16a4751ba78da2a397"},
+ {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae4070f741f8d809075ef697877fd350ecf0b7c5837ed68738607ee0a2c572cf"},
+ {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58e875eb7016fd014c0eea46c6fa92b87b62c0cb31b9feae25cbbe62c919f54d"},
+ {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dbd95e300367aa0827496fe75a1766d198d34385a58f97683fe6e07f89ca3e3c"},
+ {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de0b4caa1c8a21394e8ce971997614a17648f94e1cd0640fbd6b4d14cab13a72"},
+ {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:985c7965f62f6f32bf432e2681173db41336a9c2611693247069288bcb0c7f8b"},
+ {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a15c1fe6d26e83fd2e5972425a772cca158eae58b05d4a25a4e474c221053e2d"},
+ {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673"},
+ {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be4d9c2770044a59715eb57c1144dedea7c5d5ae80c68fb9959515037cde2008"},
+ {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:851cf693fb3aaef71031237cd68699dded198657ec1e76a76eb8be58c03a5d1f"},
+ {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:31bbaba7218904d2eabecf4feec0d07469284e952a27400f23b6628439439fa7"},
+ {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:871d045d6ccc181fd863a3cd66ee8e395523ebfbc57f85f91f035f50cee8e3d4"},
+ {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:501adc5eb6cd5f40a6f77fbd90e5ab915c8fd6e8c614af2db5561e16c600d6f3"},
+ {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f5fb672c396d826ca16a022ac04c9dce74e00a1c344f6ad1a0fdc1ba1f332213"},
+ {file = "charset_normalizer-3.3.1-cp311-cp311-win32.whl", hash = "sha256:bb06098d019766ca16fc915ecaa455c1f1cd594204e7f840cd6258237b5079a8"},
+ {file = "charset_normalizer-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:8af5a8917b8af42295e86b64903156b4f110a30dca5f3b5aedea123fbd638bff"},
+ {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7ae8e5142dcc7a49168f4055255dbcced01dc1714a90a21f87448dc8d90617d1"},
+ {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5b70bab78accbc672f50e878a5b73ca692f45f5b5e25c8066d748c09405e6a55"},
+ {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ceca5876032362ae73b83347be8b5dbd2d1faf3358deb38c9c88776779b2e2f"},
+ {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d95638ff3613849f473afc33f65c401a89f3b9528d0d213c7037c398a51296"},
+ {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9edbe6a5bf8b56a4a84533ba2b2f489d0046e755c29616ef8830f9e7d9cf5728"},
+ {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6a02a3c7950cafaadcd46a226ad9e12fc9744652cc69f9e5534f98b47f3bbcf"},
+ {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10b8dd31e10f32410751b3430996f9807fc4d1587ca69772e2aa940a82ab571a"},
+ {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edc0202099ea1d82844316604e17d2b175044f9bcb6b398aab781eba957224bd"},
+ {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b891a2f68e09c5ef989007fac11476ed33c5c9994449a4e2c3386529d703dc8b"},
+ {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:71ef3b9be10070360f289aea4838c784f8b851be3ba58cf796262b57775c2f14"},
+ {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:55602981b2dbf8184c098bc10287e8c245e351cd4fdcad050bd7199d5a8bf514"},
+ {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:46fb9970aa5eeca547d7aa0de5d4b124a288b42eaefac677bde805013c95725c"},
+ {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:520b7a142d2524f999447b3a0cf95115df81c4f33003c51a6ab637cbda9d0bf4"},
+ {file = "charset_normalizer-3.3.1-cp312-cp312-win32.whl", hash = "sha256:8ec8ef42c6cd5856a7613dcd1eaf21e5573b2185263d87d27c8edcae33b62a61"},
+ {file = "charset_normalizer-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:baec8148d6b8bd5cee1ae138ba658c71f5b03e0d69d5907703e3e1df96db5e41"},
+ {file = "charset_normalizer-3.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63a6f59e2d01310f754c270e4a257426fe5a591dc487f1983b3bbe793cf6bac6"},
+ {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d6bfc32a68bc0933819cfdfe45f9abc3cae3877e1d90aac7259d57e6e0f85b1"},
+ {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f3100d86dcd03c03f7e9c3fdb23d92e32abbca07e7c13ebd7ddfbcb06f5991f"},
+ {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39b70a6f88eebe239fa775190796d55a33cfb6d36b9ffdd37843f7c4c1b5dc67"},
+ {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e12f8ee80aa35e746230a2af83e81bd6b52daa92a8afaef4fea4a2ce9b9f4fa"},
+ {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b6cefa579e1237ce198619b76eaa148b71894fb0d6bcf9024460f9bf30fd228"},
+ {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:61f1e3fb621f5420523abb71f5771a204b33c21d31e7d9d86881b2cffe92c47c"},
+ {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f6e2a839f83a6a76854d12dbebde50e4b1afa63e27761549d006fa53e9aa80e"},
+ {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:1ec937546cad86d0dce5396748bf392bb7b62a9eeb8c66efac60e947697f0e58"},
+ {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:82ca51ff0fc5b641a2d4e1cc8c5ff108699b7a56d7f3ad6f6da9dbb6f0145b48"},
+ {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:633968254f8d421e70f91c6ebe71ed0ab140220469cf87a9857e21c16687c034"},
+ {file = "charset_normalizer-3.3.1-cp37-cp37m-win32.whl", hash = "sha256:c0c72d34e7de5604df0fde3644cc079feee5e55464967d10b24b1de268deceb9"},
+ {file = "charset_normalizer-3.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:63accd11149c0f9a99e3bc095bbdb5a464862d77a7e309ad5938fbc8721235ae"},
+ {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5a3580a4fdc4ac05f9e53c57f965e3594b2f99796231380adb2baaab96e22761"},
+ {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2465aa50c9299d615d757c1c888bc6fef384b7c4aec81c05a0172b4400f98557"},
+ {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb7cd68814308aade9d0c93c5bd2ade9f9441666f8ba5aa9c2d4b389cb5e2a45"},
+ {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e43805ccafa0a91831f9cd5443aa34528c0c3f2cc48c4cb3d9a7721053874b"},
+ {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:854cc74367180beb327ab9d00f964f6d91da06450b0855cbbb09187bcdb02de5"},
+ {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c15070ebf11b8b7fd1bfff7217e9324963c82dbdf6182ff7050519e350e7ad9f"},
+ {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c4c99f98fc3a1835af8179dcc9013f93594d0670e2fa80c83aa36346ee763d2"},
+ {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fb765362688821404ad6cf86772fc54993ec11577cd5a92ac44b4c2ba52155b"},
+ {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dced27917823df984fe0c80a5c4ad75cf58df0fbfae890bc08004cd3888922a2"},
+ {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a66bcdf19c1a523e41b8e9d53d0cedbfbac2e93c649a2e9502cb26c014d0980c"},
+ {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ecd26be9f112c4f96718290c10f4caea6cc798459a3a76636b817a0ed7874e42"},
+ {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f70fd716855cd3b855316b226a1ac8bdb3caf4f7ea96edcccc6f484217c9597"},
+ {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:17a866d61259c7de1bdadef418a37755050ddb4b922df8b356503234fff7932c"},
+ {file = "charset_normalizer-3.3.1-cp38-cp38-win32.whl", hash = "sha256:548eefad783ed787b38cb6f9a574bd8664468cc76d1538215d510a3cd41406cb"},
+ {file = "charset_normalizer-3.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:45f053a0ece92c734d874861ffe6e3cc92150e32136dd59ab1fb070575189c97"},
+ {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bc791ec3fd0c4309a753f95bb6c749ef0d8ea3aea91f07ee1cf06b7b02118f2f"},
+ {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8c61fb505c7dad1d251c284e712d4e0372cef3b067f7ddf82a7fa82e1e9a93"},
+ {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2c092be3885a1b7899cd85ce24acedc1034199d6fca1483fa2c3a35c86e43041"},
+ {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2000c54c395d9e5e44c99dc7c20a64dc371f777faf8bae4919ad3e99ce5253e"},
+ {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4cb50a0335382aac15c31b61d8531bc9bb657cfd848b1d7158009472189f3d62"},
+ {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c30187840d36d0ba2893bc3271a36a517a717f9fd383a98e2697ee890a37c273"},
+ {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe81b35c33772e56f4b6cf62cf4aedc1762ef7162a31e6ac7fe5e40d0149eb67"},
+ {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0bf89afcbcf4d1bb2652f6580e5e55a840fdf87384f6063c4a4f0c95e378656"},
+ {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:06cf46bdff72f58645434d467bf5228080801298fbba19fe268a01b4534467f5"},
+ {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3c66df3f41abee950d6638adc7eac4730a306b022570f71dd0bd6ba53503ab57"},
+ {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd805513198304026bd379d1d516afbf6c3c13f4382134a2c526b8b854da1c2e"},
+ {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:9505dc359edb6a330efcd2be825fdb73ee3e628d9010597aa1aee5aa63442e97"},
+ {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:31445f38053476a0c4e6d12b047b08ced81e2c7c712e5a1ad97bc913256f91b2"},
+ {file = "charset_normalizer-3.3.1-cp39-cp39-win32.whl", hash = "sha256:bd28b31730f0e982ace8663d108e01199098432a30a4c410d06fe08fdb9e93f4"},
+ {file = "charset_normalizer-3.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:555fe186da0068d3354cdf4bbcbc609b0ecae4d04c921cc13e209eece7720727"},
+ {file = "charset_normalizer-3.3.1-py3-none-any.whl", hash = "sha256:800561453acdecedaac137bf09cd719c7a440b6800ec182f077bb8e7025fb708"},
+]
[[package]]
name = "click"
-version = "8.1.3"
+version = "8.1.7"
description = "Composable command line interface toolkit"
category = "dev"
optional = false
python-versions = ">=3.7"
+files = [
+ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
+ {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
+]
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
@@ -84,6 +212,10 @@ description = "Cross-platform colored terminal text."
category = "dev"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
[[package]]
name = "doc8"
@@ -92,6 +224,10 @@ description = "Style checker for Sphinx (or other) RST documentation"
category = "dev"
optional = false
python-versions = "*"
+files = [
+ {file = "doc8-0.8.1-py2.py3-none-any.whl", hash = "sha256:4d58a5c8c56cedd2b2c9d6e3153be5d956cf72f6051128f0f2255c66227df721"},
+ {file = "doc8-0.8.1.tar.gz", hash = "sha256:4d1df12598807cf08ffa9a1d5ef42d229ee0de42519da01b768ff27211082c12"},
+]
[package.dependencies]
chardet = "*"
@@ -103,11 +239,15 @@ stevedore = "*"
[[package]]
name = "docutils"
-version = "0.17.1"
+version = "0.18.1"
description = "Docutils -- Python Documentation Utilities"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+ {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"},
+ {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"},
+]
[[package]]
name = "flake8"
@@ -116,6 +256,10 @@ description = "the modular source code checker: pep8 pyflakes and co"
category = "dev"
optional = false
python-versions = ">=3.6"
+files = [
+ {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"},
+ {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"},
+]
[package.dependencies]
mccabe = ">=0.6.0,<0.7.0"
@@ -129,6 +273,10 @@ description = "Internationalized Domain Names in Applications (IDNA)"
category = "dev"
optional = false
python-versions = ">=3.5"
+files = [
+ {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
+ {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
+]
[[package]]
name = "imagesize"
@@ -137,30 +285,42 @@ description = "Getting image size from png/jpeg/jpeg2000/gif file"
category = "dev"
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 = "5.1.0"
+version = "6.8.0"
description = "Read metadata from Python packages"
category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
+files = [
+ {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"},
+ {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"},
+]
[package.dependencies]
zipp = ">=0.5"
[package.extras]
-docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
perf = ["ipython"]
-testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
+testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"]
[[package]]
-name = "Jinja2"
+name = "jinja2"
version = "3.1.2"
description = "A very fast and expressive template engine."
category = "dev"
optional = false
python-versions = ">=3.7"
+files = [
+ {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
+ {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
+]
[package.dependencies]
MarkupSafe = ">=2.0"
@@ -169,12 +329,64 @@ MarkupSafe = ">=2.0"
i18n = ["Babel (>=2.7)"]
[[package]]
-name = "MarkupSafe"
-version = "2.1.1"
+name = "markupsafe"
+version = "2.1.3"
description = "Safely add untrusted strings to HTML/XML markup."
category = "dev"
optional = false
python-versions = ">=3.7"
+files = [
+ {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"},
+ {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"},
+]
[[package]]
name = "mccabe"
@@ -183,53 +395,74 @@ description = "McCabe checker, plugin for flake8"
category = "dev"
optional = false
python-versions = "*"
+files = [
+ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
+ {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
+]
[[package]]
name = "mypy-extensions"
-version = "0.4.3"
-description = "Experimental type system extensions for programs checked with the mypy typechecker."
+version = "1.0.0"
+description = "Type system extensions for programs checked with the mypy type checker."
category = "dev"
optional = false
-python-versions = "*"
+python-versions = ">=3.5"
+files = [
+ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
+ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
+]
[[package]]
name = "packaging"
-version = "21.3"
+version = "23.2"
description = "Core utilities for Python packages"
category = "dev"
optional = false
-python-versions = ">=3.6"
-
-[package.dependencies]
-pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
+python-versions = ">=3.7"
+files = [
+ {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
+ {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
+]
[[package]]
name = "pathspec"
-version = "0.10.2"
+version = "0.11.2"
description = "Utility library for gitignore style pattern matching of file paths."
category = "dev"
optional = false
python-versions = ">=3.7"
+files = [
+ {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"},
+ {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
+]
[[package]]
name = "pbr"
-version = "5.11.0"
+version = "5.11.1"
description = "Python Build Reasonableness"
category = "dev"
optional = false
python-versions = ">=2.6"
+files = [
+ {file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"},
+ {file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"},
+]
[[package]]
name = "platformdirs"
-version = "2.5.4"
+version = "3.11.0"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev"
optional = false
python-versions = ">=3.7"
+files = [
+ {file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"},
+ {file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"},
+]
[package.extras]
-docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"]
-test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
+docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
[[package]]
name = "pycodestyle"
@@ -238,6 +471,10 @@ description = "Python style guide checker"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+ {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"},
+ {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"},
+]
[[package]]
name = "pyflakes"
@@ -246,50 +483,55 @@ description = "passive checker of Python programs"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"},
+ {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"},
+]
[[package]]
-name = "Pygments"
-version = "2.13.0"
+name = "pygments"
+version = "2.16.1"
description = "Pygments is a syntax highlighting package written in Python."
category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
+files = [
+ {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"},
+ {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"},
+]
[package.extras]
plugins = ["importlib-metadata"]
-[[package]]
-name = "pyparsing"
-version = "3.0.9"
-description = "pyparsing module - Classes and methods to define and execute parsing grammars"
-category = "dev"
-optional = false
-python-versions = ">=3.6.8"
-
-[package.extras]
-diagrams = ["jinja2", "railroad-diagrams"]
-
[[package]]
name = "pytz"
-version = "2022.6"
+version = "2023.3.post1"
description = "World timezone definitions, modern and historical"
category = "dev"
optional = false
python-versions = "*"
+files = [
+ {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"},
+ {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"},
+]
[[package]]
name = "requests"
-version = "2.28.1"
+version = "2.31.0"
description = "Python HTTP for Humans."
category = "dev"
optional = false
-python-versions = ">=3.7, <4"
+python-versions = ">=3.7"
+files = [
+ {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
+ {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
+]
[package.dependencies]
certifi = ">=2017.4.17"
-charset-normalizer = ">=2,<3"
+charset-normalizer = ">=2,<4"
idna = ">=2.5,<4"
-urllib3 = ">=1.21.1,<1.27"
+urllib3 = ">=1.21.1,<3"
[package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
@@ -302,6 +544,9 @@ description = "reStructuredText linter"
category = "dev"
optional = false
python-versions = "*"
+files = [
+ {file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"},
+]
[package.dependencies]
docutils = ">=0.11,<1.0"
@@ -313,6 +558,10 @@ description = "Python 2 and 3 compatibility utilities"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
+ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
+]
[[package]]
name = "snowballstemmer"
@@ -321,14 +570,19 @@ description = "This package provides 29 stemmers for 28 languages generated from
category = "dev"
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 = "Sphinx"
-version = "5.1.0.dev20221209"
+version = "5.1.0.dev20231023"
description = "Python documentation generator"
category = "dev"
optional = false
python-versions = ">=3.6"
+files = []
develop = false
[package.dependencies]
@@ -353,36 +607,45 @@ sphinxcontrib-serializinghtml = ">=1.1.5"
[package.extras]
docs = ["sphinxcontrib-websupport"]
lint = ["docutils-stubs", "flake8 (>=3.5.0)", "isort", "mypy (>=0.950)", "types-requests", "types-typed-ast"]
-test = ["cython", "html5lib", "pytest (>=4.6)", "typed-ast"]
+test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"]
[package.source]
type = "git"
url = "https://github.com/pybricks/sphinx.git"
-reference = "b00124cb"
-resolved_reference = "b00124cb07318fd6875f6d53e0b26e50c7dde597"
+reference = "cd277d09"
+resolved_reference = "cd277d098ea2df9c79f0a4cbce28a426ec4120bc"
[[package]]
name = "sphinx-rtd-theme"
-version = "1.1.1"
+version = "1.3.0"
description = "Read the Docs theme for Sphinx"
category = "dev"
optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
+files = [
+ {file = "sphinx_rtd_theme-1.3.0-py2.py3-none-any.whl", hash = "sha256:46ddef89cc2416a81ecfbeaceab1881948c014b1b6e4450b815311a89fb977b0"},
+ {file = "sphinx_rtd_theme-1.3.0.tar.gz", hash = "sha256:590b030c7abb9cf038ec053b95e5380b5c70d61591eb0b552063fbe7c41f0931"},
+]
[package.dependencies]
-docutils = "<0.18"
-sphinx = ">=1.6,<6"
+docutils = "<0.19"
+sphinx = ">=1.6,<8"
+sphinxcontrib-jquery = ">=4,<5"
[package.extras]
dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"]
[[package]]
name = "sphinxcontrib-applehelp"
-version = "1.0.2"
-description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books"
+version = "1.0.4"
+description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books"
category = "dev"
optional = false
-python-versions = ">=3.5"
+python-versions = ">=3.8"
+files = [
+ {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"},
+ {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"},
+]
[package.extras]
lint = ["docutils-stubs", "flake8", "mypy"]
@@ -395,6 +658,10 @@ description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp
category = "dev"
optional = false
python-versions = ">=3.5"
+files = [
+ {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"},
+ {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"},
+]
[package.extras]
lint = ["docutils-stubs", "flake8", "mypy"]
@@ -402,16 +669,35 @@ test = ["pytest"]
[[package]]
name = "sphinxcontrib-htmlhelp"
-version = "2.0.0"
+version = "2.0.1"
description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
+files = [
+ {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"},
+ {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"},
+]
[package.extras]
lint = ["docutils-stubs", "flake8", "mypy"]
test = ["html5lib", "pytest"]
+[[package]]
+name = "sphinxcontrib-jquery"
+version = "4.1"
+description = "Extension to include jQuery on newer Sphinx releases"
+category = "dev"
+optional = false
+python-versions = ">=2.7"
+files = [
+ {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"},
+ {file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"},
+]
+
+[package.dependencies]
+Sphinx = ">=1.8"
+
[[package]]
name = "sphinxcontrib-jsmath"
version = "1.0.1"
@@ -419,6 +705,10 @@ description = "A sphinx extension which renders display math in HTML via JavaScr
category = "dev"
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"]
@@ -430,6 +720,10 @@ description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp d
category = "dev"
optional = false
python-versions = ">=3.5"
+files = [
+ {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"},
+ {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"},
+]
[package.extras]
lint = ["docutils-stubs", "flake8", "mypy"]
@@ -442,6 +736,10 @@ description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs
category = "dev"
optional = false
python-versions = ">=3.5"
+files = [
+ {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"},
+ {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"},
+]
[package.extras]
lint = ["docutils-stubs", "flake8", "mypy"]
@@ -449,11 +747,15 @@ test = ["pytest"]
[[package]]
name = "stevedore"
-version = "4.1.1"
+version = "5.1.0"
description = "Manage dynamic plugins for Python applications"
category = "dev"
optional = false
python-versions = ">=3.8"
+files = [
+ {file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"},
+ {file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"},
+]
[package.dependencies]
pbr = ">=2.0.0,<2.1.0 || >2.1.0"
@@ -465,6 +767,10 @@ description = "Python Library for Tom's Obvious, Minimal Language"
category = "dev"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
+ {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
+]
[[package]]
name = "tomli"
@@ -473,276 +779,58 @@ description = "A lil' TOML parser"
category = "dev"
optional = false
python-versions = ">=3.7"
+files = [
+ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
+ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
+]
[[package]]
name = "typing-extensions"
-version = "4.4.0"
-description = "Backported and Experimental Type Hints for Python 3.7+"
+version = "4.8.0"
+description = "Backported and Experimental Type Hints for Python 3.8+"
category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
+files = [
+ {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"},
+ {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"},
+]
[[package]]
name = "urllib3"
-version = "1.26.13"
+version = "2.0.7"
description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "dev"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
+python-versions = ">=3.7"
+files = [
+ {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"},
+ {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"},
+]
[package.extras]
-brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
-secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
-socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
+secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"]
+socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
+zstd = ["zstandard (>=0.18.0)"]
[[package]]
name = "zipp"
-version = "3.11.0"
+version = "3.17.0"
description = "Backport of pathlib-compatible object wrapper for zip files"
category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
+files = [
+ {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"},
+ {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"},
+]
[package.extras]
-docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"]
-testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
+docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"]
+testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"]
[metadata]
-lock-version = "1.1"
+lock-version = "2.0"
python-versions = "^3.8"
-content-hash = "35b6b0fa356034e7f45487c068c004da91e298009a637e024455e7e18bcc1396"
-
-[metadata.files]
-alabaster = [
- {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"},
- {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"},
-]
-Babel = [
- {file = "Babel-2.11.0-py3-none-any.whl", hash = "sha256:1ad3eca1c885218f6dce2ab67291178944f810a10a9b5f3cb8382a5a232b64fe"},
- {file = "Babel-2.11.0.tar.gz", hash = "sha256:5ef4b3226b0180dedded4229651c8b0e1a3a6a2837d45a073272f313e4cf97f6"},
-]
-black = [
- {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"},
- {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"},
- {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"},
- {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"},
- {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"},
- {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"},
- {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"},
- {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"},
- {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"},
- {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"},
- {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"},
- {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"},
- {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"},
- {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"},
- {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"},
- {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"},
- {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"},
- {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"},
- {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"},
- {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"},
- {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"},
-]
-certifi = [
- {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
- {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
-]
-chardet = [
- {file = "chardet-5.1.0-py3-none-any.whl", hash = "sha256:362777fb014af596ad31334fde1e8c327dfdb076e1960d1694662d46a6917ab9"},
- {file = "chardet-5.1.0.tar.gz", hash = "sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5"},
-]
-charset-normalizer = [
- {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"},
- {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"},
-]
-click = [
- {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
- {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
-]
-colorama = [
- {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
- {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
-]
-doc8 = [
- {file = "doc8-0.8.1-py2.py3-none-any.whl", hash = "sha256:4d58a5c8c56cedd2b2c9d6e3153be5d956cf72f6051128f0f2255c66227df721"},
- {file = "doc8-0.8.1.tar.gz", hash = "sha256:4d1df12598807cf08ffa9a1d5ef42d229ee0de42519da01b768ff27211082c12"},
-]
-docutils = [
- {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"},
- {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"},
-]
-flake8 = [
- {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"},
- {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"},
-]
-idna = [
- {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
- {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
-]
-imagesize = [
- {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"},
- {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"},
-]
-importlib-metadata = [
- {file = "importlib_metadata-5.1.0-py3-none-any.whl", hash = "sha256:d84d17e21670ec07990e1044a99efe8d615d860fd176fc29ef5c306068fda313"},
- {file = "importlib_metadata-5.1.0.tar.gz", hash = "sha256:d5059f9f1e8e41f80e9c56c2ee58811450c31984dfa625329ffd7c0dad88a73b"},
-]
-Jinja2 = [
- {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
- {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
-]
-MarkupSafe = [
- {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"},
- {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"},
- {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"},
- {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"},
- {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"},
- {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"},
-]
-mccabe = [
- {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
- {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
-]
-mypy-extensions = [
- {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
- {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
-]
-packaging = [
- {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
- {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
-]
-pathspec = [
- {file = "pathspec-0.10.2-py3-none-any.whl", hash = "sha256:88c2606f2c1e818b978540f73ecc908e13999c6c3a383daf3705652ae79807a5"},
- {file = "pathspec-0.10.2.tar.gz", hash = "sha256:8f6bf73e5758fd365ef5d58ce09ac7c27d2833a8d7da51712eac6e27e35141b0"},
-]
-pbr = [
- {file = "pbr-5.11.0-py2.py3-none-any.whl", hash = "sha256:db2317ff07c84c4c63648c9064a79fe9d9f5c7ce85a9099d4b6258b3db83225a"},
- {file = "pbr-5.11.0.tar.gz", hash = "sha256:b97bc6695b2aff02144133c2e7399d5885223d42b7912ffaec2ca3898e673bfe"},
-]
-platformdirs = [
- {file = "platformdirs-2.5.4-py3-none-any.whl", hash = "sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10"},
- {file = "platformdirs-2.5.4.tar.gz", hash = "sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7"},
-]
-pycodestyle = [
- {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"},
- {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"},
-]
-pyflakes = [
- {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"},
- {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"},
-]
-Pygments = [
- {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"},
- {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"},
-]
-pyparsing = [
- {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
- {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
-]
-pytz = [
- {file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"},
- {file = "pytz-2022.6.tar.gz", hash = "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2"},
-]
-requests = [
- {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"},
- {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"},
-]
-restructuredtext-lint = [
- {file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"},
-]
-six = [
- {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
- {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
-]
-snowballstemmer = [
- {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"},
- {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"},
-]
-Sphinx = []
-sphinx-rtd-theme = [
- {file = "sphinx_rtd_theme-1.1.1-py2.py3-none-any.whl", hash = "sha256:31faa07d3e97c8955637fc3f1423a5ab2c44b74b8cc558a51498c202ce5cbda7"},
- {file = "sphinx_rtd_theme-1.1.1.tar.gz", hash = "sha256:6146c845f1e1947b3c3dd4432c28998a1693ccc742b4f9ad7c63129f0757c103"},
-]
-sphinxcontrib-applehelp = [
- {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"},
- {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"},
-]
-sphinxcontrib-devhelp = [
- {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"},
- {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"},
-]
-sphinxcontrib-htmlhelp = [
- {file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"},
- {file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"},
-]
-sphinxcontrib-jsmath = [
- {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"},
-]
-sphinxcontrib-qthelp = [
- {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"},
- {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"},
-]
-sphinxcontrib-serializinghtml = [
- {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"},
- {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"},
-]
-stevedore = [
- {file = "stevedore-4.1.1-py3-none-any.whl", hash = "sha256:aa6436565c069b2946fe4ebff07f5041e0c8bf18c7376dd29edf80cf7d524e4e"},
- {file = "stevedore-4.1.1.tar.gz", hash = "sha256:7f8aeb6e3f90f96832c301bff21a7eb5eefbe894c88c506483d355565d88cc1a"},
-]
-toml = [
- {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
- {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
-]
-tomli = [
- {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
- {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
-]
-typing-extensions = [
- {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"},
- {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"},
-]
-urllib3 = [
- {file = "urllib3-1.26.13-py2.py3-none-any.whl", hash = "sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc"},
- {file = "urllib3-1.26.13.tar.gz", hash = "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8"},
-]
-zipp = [
- {file = "zipp-3.11.0-py3-none-any.whl", hash = "sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa"},
- {file = "zipp-3.11.0.tar.gz", hash = "sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766"},
-]
+content-hash = "c3ac22f3861c372d4572b51aa6263a693a8c42a7fa77ff5e735fea3be0e3f15b"
diff --git a/pyproject.toml b/pyproject.toml
index 78cc52d8..97efa139 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,8 +1,8 @@
[tool.poetry]
name = "pybricks"
-version = "3.3.0a4"
+version = "3.5.0"
description = "Documentation and user-API stubs for Pybricks MicroPython"
-authors = ["The Pybricks Authors "]
+authors = ["The Pybricks Authors "]
maintainers = ["Laurens Valk ", "David Lechner " ]
license = "MIT"
readme = "README.rst"
@@ -10,7 +10,6 @@ homepage = "https://pybricks.com"
repository = "https://github.com/pybricks/pybricks-api"
documentation = "https://docs.pybricks.com"
classifiers = [
- "Development Status :: 3 - Alpha",
"Programming Language :: Python :: Implementation :: MicroPython",
]
packages = [
@@ -29,11 +28,13 @@ packages = [
[tool.poetry.dependencies]
python = "^3.8"
-[tool.poetry.dev-dependencies]
+[tool.poetry.group.lint.dependencies]
black = "^22.3.0"
doc8 = "^0.8.1"
flake8 = "^4.0"
-Sphinx = { git = "https://github.com/pybricks/sphinx.git", rev = "b00124cb" }
+
+[tool.poetry.group.doc.dependencies]
+Sphinx = { git = "https://github.com/pybricks/sphinx.git", rev = "cd277d09" }
sphinx-rtd-theme = "^1.0.0"
toml = "^0.10.0"
diff --git a/rtd-requirements.txt b/rtd-requirements.txt
deleted file mode 100644
index 861a6528..00000000
--- a/rtd-requirements.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file is strictly for building docs on readthedocs.org
-# See pyproject.toml for local development
-git+https://github.com/pybricks/sphinx@b00124c#egg=Sphinx
-sphinx-rtd-theme==1.0.0
-toml
diff --git a/setup.cfg b/setup.cfg
index ce263880..ff996f0d 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,8 +1,8 @@
[flake8]
-exclude = .venv/,*.pyi,jedi/
+exclude = .venv/,*.pyi,jedi/,examples/pup/tools/hub_menu.py
max-line-length = 88
-ignore = E203,E501,W503
+ignore = E203,E501,W503,E701,E704
[doc8]
ignore-path = jedi/,.venv/,doc/main/build/,doc/api/build/,pybricks.egg-info/,npm/
diff --git a/src/pybricks/_common.py b/src/pybricks/_common.py
index 37a9acd3..c85109c7 100644
--- a/src/pybricks/_common.py
+++ b/src/pybricks/_common.py
@@ -1,19 +1,45 @@
# SPDX-License-Identifier: MIT
-# Copyright (c) 2018-2021 The Pybricks Authors
+# Copyright (c) 2018-2023 The Pybricks Authors
"""Generic cross-platform module for typical devices like lights, displays,
speakers, and batteries."""
from __future__ import annotations
-from typing import Union, Iterable, overload, Optional, Tuple, Collection, TYPE_CHECKING
+from typing import (
+ Union,
+ Iterable,
+ overload,
+ Optional,
+ Tuple,
+ Collection,
+ Set,
+ TYPE_CHECKING,
+)
from .tools import Matrix
from .parameters import Axis, Direction, Stop, Button, Port, Color, Side
if TYPE_CHECKING:
+ from typing import Any, Awaitable, TypeVar
+
from .parameters import Number
+ _T_co = TypeVar("_T_co", covariant=True)
+
+ class MaybeAwaitable(None, Awaitable[None]): ...
+
+ # HACK: Cannot subclass bool, so using Any instead.
+ class MaybeAwaitableBool(Any, Awaitable[bool]): ...
+
+ class MaybeAwaitableFloat(float, Awaitable[float]): ...
+
+ class MaybeAwaitableInt(int, Awaitable[int]): ...
+
+ class MaybeAwaitableTuple(Tuple[_T_co], Awaitable[Tuple[_T_co]]): ...
+
+ class MaybeAwaitableColor(Color, Awaitable[Color]): ...
+
class System:
"""System control actions for a hub."""
@@ -34,7 +60,8 @@ def set_stop_button(
button (Button): A button such
as :attr:`Button.CENTER `,
or a tuple of multiple buttons. Choose ``None`` to disable the
- stop button altogether.
+ stop button altogether. If you do, you can still turn the hub
+ off by holding the center button for three seconds.
"""
def shutdown(self) -> None:
@@ -69,17 +96,15 @@ def name(self) -> str:
"""
@overload
- def storage(self, offset: int, *, read: int) -> bytes:
- ...
+ def storage(self, offset: int, *, read: int) -> bytes: ...
@overload
- def storage(self, offset: int, *, write: bytes) -> None:
- ...
+ def storage(self, offset: int, *, write: bytes) -> None: ...
def storage(self, offset, read=None, write=None):
"""
- storage(self, offset, write=)
- storage(self, offset, read=) -> bytes
+ storage(offset, write=)
+ storage(offset, read=) -> bytes
Reads or writes binary data to persistent storage.
@@ -145,12 +170,10 @@ def brake(self) -> None:
is generated while the motor is still moving."""
@overload
- def settings(self, max_voltage: Number) -> None:
- ...
+ def settings(self, max_voltage: Number) -> None: ...
@overload
- def settings(self) -> Tuple[int]:
- ...
+ def settings(self) -> Tuple[int]: ...
def settings(self, *args):
"""
@@ -183,12 +206,10 @@ def limits(
speed: Optional[Number] = None,
acceleration: Optional[Number] = None,
torque: Optional[Number] = None,
- ) -> None:
- ...
+ ) -> None: ...
@overload
- def limits(self) -> Tuple[int, int, int]:
- ...
+ def limits(self) -> Tuple[int, int, int]: ...
def limits(self, *args):
"""
@@ -221,12 +242,10 @@ def pid(
kd: Optional[Number] = None,
integral_deadzone: Optional[Number] = None,
integral_rate: Optional[Number] = None,
- ) -> None:
- ...
+ ) -> None: ...
@overload
- def pid(self) -> Tuple[int, int, int, int, int]:
- ...
+ def pid(self) -> Tuple[int, int, int, int, int]: ...
def pid(self, *args):
"""pid(kp, ki, kd, integral_deadzone, integral_rate)
@@ -254,12 +273,10 @@ def pid(self, *args):
@overload
def target_tolerances(
self, speed: Optional[Number] = None, position: Optional[Number] = None
- ) -> None:
- ...
+ ) -> None: ...
@overload
- def target_tolerances(self) -> Tuple[int, int]:
- ...
+ def target_tolerances(self) -> Tuple[int, int]: ...
def target_tolerances(self, *args):
"""target_tolerances(speed, position)
@@ -280,12 +297,10 @@ def target_tolerances(self, *args):
@overload
def stall_tolerances(
self, speed: Optional[Number] = None, time: Optional[Number] = None
- ) -> None:
- ...
+ ) -> None: ...
@overload
- def stall_tolerances(self) -> Tuple[int, int]:
- ...
+ def stall_tolerances(self) -> Tuple[int, int]: ...
def stall_tolerances(self, speed, time):
"""stall_tolerances(speed, time)
@@ -327,12 +342,10 @@ def state(self) -> Tuple[float, float, float, bool]:
"""
@overload
- def settings(self, values: tuple) -> None:
- ...
+ def settings(self, values: tuple) -> None: ...
@overload
- def settings(self) -> tuple:
- ...
+ def settings(self) -> tuple: ...
def settings(self, speed, time):
"""settings(values)
@@ -378,25 +391,30 @@ def __init__(
turn when you give a positive speed value or
angle.
gears (list):
- List of gears linked to the motor.
+ List of gears linked to the motor. The gear connected
+ to the motor comes first and the gear connected to the output
+ comes last.
For example: ``[12, 36]`` represents a gear train with a
- 12-tooth and a 36-tooth gear. Use a list of lists for multiple
+ 12-tooth gear connected to the motor and a 36-tooth gear
+ connected to the output. Use a list of lists for multiple
gear trains, such as ``[[12, 36], [20, 16, 40]]``.
When you specify a gear train, all motor commands and settings
are automatically adjusted to account for the resulting gear
- ratio. The motor direction remains unchanged by this.
+ ratio. The motor direction remains unchanged by this.
reset_angle (bool):
Choose ``True`` to reset the rotation sensor value to the
absolute marker angle (between -180 and 179).
Choose ``False`` to keep the
current value, so your program knows where it left off last
time.
- profile (Number, deg): Precision profile. A lower value
- means more precise movement; a larger value means
- smoother movement. If no value is given, a suitable profile for
- this motor type will be selected automatically.
+ profile (Number, deg): Precision profile. This is the approximate
+ position tolerance in degrees that is acceptable in your
+ application. A lower value gives more precise but more erratic
+ movement; a higher value gives less precise but smoother
+ movement. If no value is given, a suitable profile for this
+ motor type will be selected automatically (about 11 degrees).
"""
def angle(self) -> int:
@@ -476,7 +494,7 @@ def run(self, speed: Number) -> None:
def run_time(
self, speed: Number, time: Number, then: Stop = Stop.HOLD, wait: bool = True
- ) -> None:
+ ) -> MaybeAwaitable:
"""run_time(speed, time, then=Stop.HOLD, wait=True)
Runs the motor at a constant speed for a given amount of time.
@@ -499,7 +517,7 @@ def run_angle(
rotation_angle: Number,
then: Stop = Stop.HOLD,
wait: bool = True,
- ) -> None:
+ ) -> MaybeAwaitable:
"""run_angle(speed, rotation_angle, then=Stop.HOLD, wait=True)
Runs the motor at a constant speed by a given angle.
@@ -519,7 +537,7 @@ def run_target(
target_angle: Number,
then: Stop = Stop.HOLD,
wait: bool = True,
- ) -> None:
+ ) -> MaybeAwaitable:
"""run_target(speed, target_angle, then=Stop.HOLD, wait=True)
Runs the motor at a constant speed towards a given target angle.
@@ -540,7 +558,7 @@ def run_until_stalled(
speed: Number,
then: Stop = Stop.COAST,
duty_limit: Optional[Number] = None,
- ) -> int:
+ ) -> MaybeAwaitableInt:
"""
run_until_stalled(speed, then=Stop.COAST, duty_limit=None) -> int: deg
@@ -580,17 +598,25 @@ def track_target(self, target_angle: Number) -> None:
rotate to.
"""
+ def close(self) -> None:
+ """close()
+
+ Closes the motor object so you can call ``Motor`` again to initialize
+ a new object.
+
+ This allows advanced users to change properties such as gearing in the
+ middle of the program, which can be useful for removeable attachments.
+ """
+
class Speaker:
"""Plays beeps and sounds using a speaker."""
@overload
- def volume(self, volume: Number) -> None:
- ...
+ def volume(self, volume: Number) -> None: ...
@overload
- def volume(self) -> int:
- ...
+ def volume(self) -> int: ...
def volume(self, *args):
"""volume(volume)
@@ -604,7 +630,7 @@ def volume(self, *args):
volume (Number, %): Volume of the speaker in the 0-100 range.
"""
- def beep(self, frequency: Number = 500, duration: Number = 100) -> None:
+ def beep(self, frequency: Number = 500, duration: Number = 100) -> MaybeAwaitable:
"""beep(frequency=500, duration=100)
Play a beep/tone.
@@ -618,7 +644,7 @@ def beep(self, frequency: Number = 500, duration: Number = 100) -> None:
play continues to play indefinitely.
"""
- def play_notes(self, notes: Iterable[str], tempo: Number = 120) -> None:
+ def play_notes(self, notes: Iterable[str], tempo: Number = 120) -> MaybeAwaitable:
"""play_notes(notes, tempo=120)
Plays a sequence of musical notes. For example:
@@ -705,10 +731,31 @@ def animate(self, colors: Collection[Color], interval: Number) -> None:
"""
+class ExternalColorLight:
+ """Control a multi-color light."""
+
+ def on(self, color: Color) -> MaybeAwaitable:
+ """on(color)
+
+ Turns on the light at the specified color.
+
+ Arguments:
+ color (Color): Color of the light.
+ """
+
+ def off(self) -> MaybeAwaitable:
+ """off()
+
+ Turns off the light.
+ """
+
+
class LightArray3:
"""Control an array of three single-color lights."""
- def on(self, brightness: Union[Number, Tuple[Number, Number, Number]]) -> None:
+ def on(
+ self, brightness: Union[Number, Tuple[Number, Number, Number]]
+ ) -> MaybeAwaitable:
"""on(brightness)
Turns on the lights at the specified brightness.
@@ -720,10 +767,11 @@ def on(self, brightness: Union[Number, Tuple[Number, Number, Number]]) -> None:
of each light individually.
"""
- def off(self) -> None:
+ def off(self) -> MaybeAwaitable:
"""off()
- Turns off all the lights."""
+ Turns off all the lights.
+ """
class LightArray4(LightArray3):
@@ -731,7 +779,7 @@ class LightArray4(LightArray3):
def on(
self, brightness: Union[Number, Tuple[Number, Number, Number, Number]]
- ) -> None:
+ ) -> MaybeAwaitable:
"""on(brightness)
Turns on the lights at the specified brightness.
@@ -856,11 +904,10 @@ def text(self, text: str, on: Number = 500, off: Number = 50) -> None:
class Keypad:
"""Get status of buttons on a keypad layout."""
- def __init__(self, active_buttons):
- ...
+ def __init__(self, active_buttons): ...
- def pressed(self) -> Collection[Button]:
- """pressed() -> Collection[Button]
+ def pressed(self) -> Set[Button]:
+ """pressed() -> Set[Button]
Checks which buttons are currently pressed.
@@ -951,17 +998,29 @@ def up(self) -> Side:
``Side.FRONT`` or ``Side.BACK``.
"""
+ def tilt(self) -> Tuple[int, int]:
+ """tilt() -> Tuple[int, int]
+
+ Gets the pitch and roll angles. This is relative to the
+ :ref:`user-specified neutral orientation `.
+
+ The order of rotation is pitch-then-roll. This is equivalent to a
+ positive rotation along the robot y-axis and then a positive rotation
+ along the x-axis.
+
+ Returns:
+ Tuple of pitch and roll angles in degrees.
+ """
+
class Accelerometer(SimpleAccelerometer):
"""Get measurements from an accelerometer."""
@overload
- def acceleration(self, axis: Axis) -> float:
- ...
+ def acceleration(self, axis: Axis) -> float: ...
@overload
- def acceleration(self) -> Matrix:
- ...
+ def acceleration(self) -> Matrix: ...
def acceleration(self, *args):
"""
@@ -980,20 +1039,6 @@ def acceleration(self, *args):
this returns a vector of accelerations along all axes.
"""
- def tilt(self) -> Tuple[int, int]:
- """tilt() -> Tuple[int, int]
-
- Gets the pitch and roll angles. This is relative to the
- :ref:`user-specified neutral orientation `.
-
- The order of rotation is pitch-then-roll. This is equivalent to a
- positive rotation along the robot y-axis and then a positive rotation
- along the x-axis.
-
- Returns:
- Tuple of pitch and roll angles in degrees.
- """
-
class IMU(Accelerometer):
def ready(self) -> bool:
@@ -1025,12 +1070,10 @@ def settings(
self,
angular_velocity_threshold: float = None,
acceleration_threshold: float = None,
- ) -> None:
- ...
+ ) -> None: ...
@overload
- def settings(self) -> Tuple[float, float]:
- ...
+ def settings(self) -> Tuple[float, float]: ...
def settings(self, *args):
"""
@@ -1095,12 +1138,10 @@ def reset_heading(self, angle: Number) -> None:
"""
@overload
- def angular_velocity(self, axis: Axis) -> float:
- ...
+ def angular_velocity(self, axis: Axis) -> float: ...
@overload
- def angular_velocity(self) -> Matrix:
- ...
+ def angular_velocity(self) -> Matrix: ...
def angular_velocity(self, *args):
"""
@@ -1164,7 +1205,7 @@ def __init__(self, port: Port):
port (Port): Port to which the sensor is connected.
"""
- def color(self) -> Color:
+ def color(self) -> MaybeAwaitableColor:
"""color() -> Color
Scans the color of a surface.
@@ -1178,7 +1219,7 @@ def color(self) -> Color:
Detected color.
"""
- def hsv(self) -> Color:
+ def hsv(self) -> MaybeAwaitableColor:
"""hsv() -> Color
Scans the color of a surface.
@@ -1192,7 +1233,7 @@ def hsv(self) -> Color:
saturation (0--100), and a brightness value (0--100).
"""
- def ambient(self) -> int:
+ def ambient(self) -> MaybeAwaitableInt:
"""ambient() -> int: %
Measures the ambient light intensity.
@@ -1202,7 +1243,7 @@ def ambient(self) -> int:
to 100% (bright).
"""
- def reflection(self) -> int:
+ def reflection(self) -> MaybeAwaitableInt:
"""reflection() -> int: %
Measures how much a surface reflects the light emitted by the
@@ -1214,12 +1255,10 @@ def reflection(self) -> int:
"""
@overload
- def detectable_colors(self, colors: Collection[Color]) -> None:
- ...
+ def detectable_colors(self, colors: Collection[Color]) -> None: ...
@overload
- def detectable_colors(self) -> Collection[Color]:
- ...
+ def detectable_colors(self) -> Collection[Color]: ...
def detectable_colors(self, *args):
"""
@@ -1234,6 +1273,8 @@ def detectable_colors(self, *args):
If you give no arguments, the currently chosen colors will be returned.
+ When coding with blocks, this is configured in the sensor setup block.
+
Arguments:
colors (list or tuple): List of :class:`Color <.parameters.Color>`
objects: the colors that you want to detect. You can pick
@@ -1248,7 +1289,7 @@ class AmbientColorSensor(CommonColorSensor):
"""Like CommonColorSensor, but also detects ambient colors when the sensor
light is turned off"""
- def color(self, surface: bool = True) -> Optional[Color]:
+ def color(self, surface: bool = True) -> MaybeAwaitableColor:
"""color(surface=True) -> Color
Scans the color of a surface or an external light source.
@@ -1267,7 +1308,7 @@ def color(self, surface: bool = True) -> Optional[Color]:
Detected color.`
"""
- def hsv(self, surface: bool = True) -> Color:
+ def hsv(self, surface: bool = True) -> MaybeAwaitableColor:
"""hsv(surface=True) -> Color
Scans the color of a surface or an external light source.
@@ -1285,3 +1326,86 @@ def hsv(self, surface: bool = True) -> Color:
Measured color. The color is described by a hue (0--359), a
saturation (0--100), and a brightness value (0--100).
"""
+
+
+class BLE:
+ """
+ Bluetooth Low Energy.
+
+ .. versionadded:: 3.3
+ """
+
+ def broadcast(self, data: Union[bool, int, float, str, bytes]) -> None:
+ """broadcast(data)
+
+ Starts broadcasting the given data on
+ the ``broadcast_channel`` you selected when initializing the hub.
+
+ Data may be of type ``int``, ``float``, ``str``, ``bytes``,
+ ``True``, or ``False``, or a list thereof.
+
+ Choose ``None`` to stop broadcasting. This helps improve performance
+ when you don't need the broadcast feature, especially when observing
+ at the same time.
+
+ The total data size is quite limited (26 bytes). ``True`` and
+ ``False`` take 1 byte each. ``float`` takes 5 bytes. ``int`` takes 2 to
+ 5 bytes depending on how big the number is. ``str`` and ``bytes`` take
+ the number of bytes in the object plus one extra byte.
+
+ When multitasking, only one task can broadcast at a time. To broadcast
+ information from multiple tasks (or block stacks), you could use a
+ dedicated separate task that broadcast new values when one or more
+ variables change.
+
+ Args:
+ data: The value or values to be broadcast.
+
+ .. versionadded:: 3.3
+ """
+
+ def observe(
+ self, channel: int
+ ) -> Optional[Tuple[Union[bool, int, float, str, bytes], ...]]:
+ """observe(channel) -> bool | int | float | str | bytes | tuple | None
+
+ Retrieves the last observed data for a given channel.
+
+ Receiving data is more reliable when the hub is not connected
+ to a computer or other devices at the same time.
+
+ Args:
+ channel (int): The channel to observe (0 to 255).
+
+ Returns:
+ The received data in the same format as it was sent, or ``None``
+ if no recent data is available.
+
+ .. versionadded:: 3.3
+ """
+
+ def signal_strength(self, channel: int) -> int:
+ """signal_strength(channel) -> int: dBm
+
+ Gets the average signal strength in dBm for the given channel.
+
+ This indicates how near the broadcasting device is. Nearby devices
+ may have a signal strength around -40 dBm, while far away devices
+ might have a signal strength around -70 dBm.
+
+ Args:
+ channel (int): The channel number (0 to 255).
+
+ Returns:
+ The signal strength or ``-128`` if there is no recent observed data.
+
+ .. versionadded:: 3.3
+ """
+
+ def version(self) -> str:
+ """version() -> str
+
+ Gets the firmware version from the Bluetooth chip.
+
+ .. versionadded:: 3.3
+ """
diff --git a/src/pybricks/hubs.py b/src/pybricks/hubs.py
index edd1bb0b..347ec04e 100644
--- a/src/pybricks/hubs.py
+++ b/src/pybricks/hubs.py
@@ -1,7 +1,10 @@
# SPDX-License-Identifier: MIT
-# Copyright (c) 2018-2022 The Pybricks Authors
+# Copyright (c) 2018-2023 The Pybricks Authors
"""LEGO® Programmable Hubs."""
+
+from typing import Sequence
+
from . import _common
from .ev3dev import _speaker
from .media.ev3dev import Image as _Image
@@ -37,7 +40,30 @@ class MoveHub:
light = _common.ColorLight()
imu = _common.SimpleAccelerometer()
system = _common.System()
- button = _common.Keypad([_Button.CENTER])
+ buttons = _common.Keypad([_Button.CENTER])
+ ble = _common.BLE()
+
+ def __init__(
+ self, broadcast_channel: int = 0, observe_channels: Sequence[int] = []
+ ):
+ """MoveHub(top_side=Axis.Z, front_side=Axis.X, broadcast_channel=0, observe_channels=[])
+
+ Arguments:
+ top_side (Axis): The axis that passes through the *top side* of
+ the hub.
+ front_side (Axis): The axis that passes through the *front side* of
+ the hub.
+ broadcast_channel:
+ A value from 0 to 255 indicating which channel ``hub.ble.broadcast()``
+ will use. Default is channel 0.
+ observe_channels:
+ A list of channels to listen to when ``hub.ble.observe()`` is
+ called. Listening to more channels requires more memory.
+ Default is an empty list (no channels).
+
+ .. versionchanged:: 3.3
+ Added *broadcast_channel* and *observe_channels* arguments.
+ """
class CityHub:
@@ -48,7 +74,26 @@ class CityHub:
battery = _common.Battery()
light = _common.ColorLight()
system = _common.System()
- button = _common.Keypad([_Button.CENTER])
+ buttons = _common.Keypad([_Button.CENTER])
+ ble = _common.BLE()
+
+ def __init__(
+ self, broadcast_channel: int = 0, observe_channels: Sequence[int] = []
+ ):
+ """CityHub(broadcast_channel=0, observe_channels=[])
+
+ Arguments:
+ broadcast_channel:
+ A value from 0 to 255 indicating which channel ``hub.ble.broadcast()``
+ will use. Default is channel 0.
+ observe_channels:
+ A list of channels to listen to when ``hub.ble.observe()`` is
+ called. Listening to more channels requires more memory.
+ Default is an empty list (no channels).
+
+ .. versionchanged:: 3.3
+ Added *broadcast_channel* and *observe_channels* arguments.
+ """
class TechnicHub:
@@ -60,10 +105,17 @@ class TechnicHub:
light = _common.ColorLight()
imu = _common.IMU()
system = _common.System()
- button = _common.Keypad([_Button.CENTER])
-
- def __init__(self, top_side: Axis = Axis.Z, front_side: Axis = Axis.X):
- """TechnicHub(top_side=Axis.Z, front_side=Axis.X)
+ buttons = _common.Keypad([_Button.CENTER])
+ ble = _common.BLE()
+
+ def __init__(
+ self,
+ top_side: Axis = Axis.Z,
+ front_side: Axis = Axis.X,
+ broadcast_channel: int = 0,
+ observe_channels: Sequence[int] = [],
+ ):
+ """TechnicHub(top_side=Axis.Z, front_side=Axis.X, broadcast_channel=0, observe_channels=[])
Initializes the hub. Optionally, specify how the hub is
:ref:`placed in your design ` by saying in which
@@ -75,6 +127,16 @@ def __init__(self, top_side: Axis = Axis.Z, front_side: Axis = Axis.X):
the hub.
front_side (Axis): The axis that passes through the *front side* of
the hub.
+ broadcast_channel:
+ A value from 0 to 255 indicating which channel ``hub.ble.broadcast()``
+ will use. Default is channel 0.
+ observe_channels:
+ A list of channels to listen to when ``hub.ble.observe()`` is
+ called. Listening to more channels requires more memory.
+ Default is an empty list (no channels).
+
+ .. versionchanged:: 3.3
+ Added *broadcast_channel* and *observe_channels* arguments.
"""
@@ -84,14 +146,21 @@ class EssentialHub:
# These class attributes are here for auto-documentation only.
# In reality, they are instance attributes created by __init__.
battery = _common.Battery()
- button = _common.Keypad([_Button.CENTER])
+ buttons = _common.Keypad([_Button.CENTER])
charger = _common.Charger()
light = _common.ColorLight()
imu = _common.IMU()
system = _common.System()
+ ble = _common.BLE()
- def __init__(self, top_side=Axis.Z, front_side=Axis.X):
- """__init__(top_side=Axis.Z, front_side=Axis.X)
+ def __init__(
+ self,
+ top_side: Axis = Axis.Z,
+ front_side: Axis = Axis.X,
+ broadcast_channel: int = 0,
+ observe_channels: Sequence[int] = [],
+ ):
+ """EssentialHub(top_side=Axis.Z, front_side=Axis.X, broadcast_channel=0, observe_channels=[])
Initializes the hub. Optionally, specify how the hub is
:ref:`placed in your design ` by saying in which
@@ -103,6 +172,16 @@ def __init__(self, top_side=Axis.Z, front_side=Axis.X):
the hub.
front_side (Axis): The axis that passes through the *front side* of
the hub.
+ broadcast_channel:
+ A value from 0 to 255 indicating which channel ``hub.ble.broadcast()``
+ will use. Default is channel 0.
+ observe_channels:
+ A list of channels to listen to when ``hub.ble.observe()`` is
+ called. Listening to more channels requires more memory.
+ Default is an empty list (no channels).
+
+ .. versionchanged:: 3.3
+ Added *broadcast_channel* and *observe_channels* arguments.
"""
pass
@@ -127,9 +206,16 @@ class PrimeHub:
speaker = _common.Speaker()
imu = _common.IMU()
system = _common.System()
+ ble = _common.BLE()
- def __init__(self, top_side: Axis = Axis.Z, front_side: Axis = Axis.X):
- """PrimeHub(top_side=Axis.Z, front_side=Axis.X)
+ def __init__(
+ self,
+ top_side: Axis = Axis.Z,
+ front_side: Axis = Axis.X,
+ broadcast_channel: int = 0,
+ observe_channels: Sequence[int] = [],
+ ):
+ """PrimeHub(top_side=Axis.Z, front_side=Axis.X, broadcast_channel=0, observe_channels=[])
Initializes the hub. Optionally, specify how the hub is
:ref:`placed in your design ` by saying in which
@@ -141,6 +227,16 @@ def __init__(self, top_side: Axis = Axis.Z, front_side: Axis = Axis.X):
the hub.
front_side (Axis): The axis that passes through the *front side* of
the hub.
+ broadcast_channel:
+ A value from 0 to 255 indicating which channel ``hub.ble.broadcast()``
+ will use. Default is channel 0.
+ observe_channels:
+ A list of channels to listen to when ``hub.ble.observe()`` is
+ called. Listening to more channels requires more memory.
+ Default is an empty list (no channels).
+
+ .. versionchanged:: 3.3
+ Added *broadcast_channel* and *observe_channels* arguments.
"""
diff --git a/src/pybricks/iodevices.py b/src/pybricks/iodevices.py
index 3d218398..2df478a2 100644
--- a/src/pybricks/iodevices.py
+++ b/src/pybricks/iodevices.py
@@ -1,13 +1,19 @@
# SPDX-License-Identifier: MIT
-# Copyright (c) 2018-2020 The Pybricks Authors
+# Copyright (c) 2018-2023 The Pybricks Authors
"""Generic input/output devices."""
-from typing import Dict, Tuple, Optional, overload
+from __future__ import annotations
+
+from typing import Dict, Tuple, Optional, overload, TYPE_CHECKING
from . import _common
from .parameters import Port as _Port
+if TYPE_CHECKING:
+ from ._common import MaybeAwaitable, MaybeAwaitableTuple
+ from .parameters import Number
+
class PUPDevice:
"""Powered Up motor or sensor."""
@@ -28,7 +34,7 @@ def info(self) -> Dict[str, str]:
Dictionary with information, such as the device ``id``.
"""
- def read(self, mode: int) -> Tuple:
+ def read(self, mode: int) -> MaybeAwaitableTuple:
"""read(mode) -> Tuple
Reads values from a given mode.
@@ -40,7 +46,7 @@ def read(self, mode: int) -> Tuple:
Values read from the sensor.
"""
- def write(self, mode: int, data: Tuple) -> None:
+ def write(self, mode: int, data: Tuple) -> MaybeAwaitable:
"""write(mode, data)
Writes values to the sensor. Only selected sensors and modes support
@@ -62,7 +68,7 @@ def __init__(self, port: _Port):
port (Port): Port to which the device is connected.
"""
- def read(self, mode: int) -> Tuple:
+ def read(self, mode: int) -> MaybeAwaitableTuple:
"""read(mode) -> Tuple
Reads values from a given mode.
@@ -95,7 +101,7 @@ def __init__(self, port: _Port):
port (Port): Port to which the device is connected.
"""
- def read(self, mode: str) -> Tuple:
+ def read(self, mode: str) -> MaybeAwaitableTuple:
"""read(mode) -> Tuple
Reads values at a given mode.
@@ -293,12 +299,10 @@ def __init__(self, hub_kind: int, name: str = None, timeout: int = 10000):
"""
@overload
- def name(self, name: str) -> None:
- ...
+ def name(self, name: str) -> MaybeAwaitable: ...
@overload
- def name(self) -> str:
- ...
+ def name(self) -> str: ...
def name(self, *args):
"""name(name)
@@ -311,7 +315,7 @@ def name(self, *args):
this method returns the current name.
"""
- def write(self, buf: bytes) -> None:
+ def write(self, buf: bytes) -> MaybeAwaitable:
"""write(buf)
Sends a message to the remote hub.
@@ -331,3 +335,118 @@ def read(self) -> bytes:
Returns:
The raw binary message.
"""
+
+ def disconnect(self) -> MaybeAwaitable:
+ """disconnect()
+
+ Disconnects the remote LWP3Device from the hub.
+ """
+
+
+class XboxController:
+ """Use the Microsoft® Xbox® controller as a sensor in your projects to
+ control them remotely.
+
+ The hub will scan for the controller and connect to it. It will disconnect
+ when the program ends.
+
+ For tips on connectivity and pairing, see :ref:`below `.
+ """
+
+ buttons = _common.Keypad([])
+
+ def __init__(self):
+ """"""
+
+ def joystick_left(self) -> Tuple[int, int]:
+ """joystick_left() -> Tuple
+
+ Gets the left joystick position as percentages between -100%
+ and 100%. The center position is (0, 0).
+
+ Returns:
+ Tuple of X (horizontal) and Y (vertical) position.
+ """
+
+ def joystick_right(self) -> Tuple[int, int]:
+ """joystick_right() -> Tuple
+
+ Gets the right joystick position as percentages between -100%
+ and 100%. The center position is (0, 0).
+
+ Returns:
+ Tuple of X (horizontal) and Y (vertical) position.
+ """
+
+ def triggers(self) -> Tuple[int, int]:
+ """triggers() -> Tuple
+
+ Gets the left and right trigger positions as percentages between 0%
+ and 100%.
+
+ Returns:
+ Tuple of left and right trigger positions.
+ """
+
+ def dpad(self) -> int:
+ """dpad() -> int
+
+ Gets the direction-pad value. ``1`` is up, ``2`` is up-right, ``3``
+ is right, ``4`` is down-right, ``5`` is down, ``6`` is down-left,
+ ``7`` is left, ``8`` is up-left, and ``0`` is not pressed.
+
+ This is essentially the same as reading the state of the
+ ``Button.UP``, ``Button.RIGHT``, ``Button.DOWN``, and ``Button.LEFT``
+ buttons, but this method conveniently returns a number that indicates
+ a direction.
+
+ Returns:
+ Direction-pad position, indicating a direction.
+ """
+
+ def profile(self) -> int:
+ """profile() -> int
+
+ Gets the current profile of the controller. Only available on the
+ Xbox Elite Controller Series 2.
+
+ Returns:
+ Profile number.
+ """
+
+ def rumble(
+ self,
+ power: Number | Tuple[Number, Number, Number, Number] = 100,
+ duration: int = 200,
+ count: int = 1,
+ delay: int = 100,
+ ) -> MaybeAwaitable:
+ """rumble(power=100, duration=200, count=1, delay=100)
+
+ Makes the builtin actuators rumble, creating force feedback.
+
+ If you give a single ``power`` value, the left and right main actuators
+ will both rumble with that power. For more fine-grained control, set
+ ``power`` as a tuple of four values, which control the left main
+ actuator, right main actuator, left trigger actuator, and the right
+ trigger actuator, respectively. For example, ``power=(0, 0, 100, 0)``
+ makes the left trigger rumble at full power.
+
+ The rumble runs in the background while your program continues. To
+ make your program wait, just pause the program for a matching duration.
+ For one rumble, this equals ``duration``. For multiple rumbles, this
+ equals ``count * (duration + delay)``.
+
+ Arguments:
+ power (Number, % or tuple): Rumble power.
+ duration (Number, ms): Rumble duration.
+ count (int): Rumble count.
+ delay (Number, ms): Delay before each rumble. Only if ``count > 1``.
+ """
+
+
+# hide from jedi
+if TYPE_CHECKING:
+ del MaybeAwaitable
+ del MaybeAwaitableTuple
+ del Number
diff --git a/src/pybricks/parameters.py b/src/pybricks/parameters.py
index 9ccd0fed..2b380815 100644
--- a/src/pybricks/parameters.py
+++ b/src/pybricks/parameters.py
@@ -115,8 +115,7 @@ def __init__(self, h: Number, s: Number = 100, v: Number = 100):
def __repr__(self):
return "Color(h={}, s={}, v={})".format(self.h, self.s, self.v)
- def __eq__(self, other: Color) -> bool:
- ...
+ def __eq__(self, other: Color) -> bool: ...
def __mul__(self, scale: float) -> Color:
v = max(0, min(self.v * scale, 100))
@@ -222,6 +221,22 @@ class Button(_PybricksEnum):
RIGHT_UP: Button = 9
RIGHT_PLUS: Button = 9
BLUETOOTH: Button = 9
+ A: Button = 0
+ B: Button = 0
+ X: Button = 0
+ Y: Button = 0
+ LB: Button = 0
+ RB: Button = 0
+ LJ: Button = 0
+ RJ: Button = 0
+ P1: Button = 0
+ P2: Button = 0
+ P3: Button = 0
+ P4: Button = 0
+ GUIDE: Button = 0
+ MENU: Button = 0
+ UPLOAD: Button = 0
+ VIEW: Button = 0
class Side(_PybricksEnum):
diff --git a/src/pybricks/pupdevices.py b/src/pybricks/pupdevices.py
index 0d431420..d9b3df43 100644
--- a/src/pybricks/pupdevices.py
+++ b/src/pybricks/pupdevices.py
@@ -1,16 +1,23 @@
# SPDX-License-Identifier: MIT
-# Copyright (c) 2018-2022 The Pybricks Authors
+# Copyright (c) 2018-2023 The Pybricks Authors
"""LEGO® Powered Up motor, sensors, and lights."""
from __future__ import annotations
-from typing import TYPE_CHECKING, Collection, Optional, Union, overload, Tuple
+from typing import TYPE_CHECKING, Collection, Optional, Union, overload
from . import _common
from .parameters import Button, Color, Direction
if TYPE_CHECKING:
+ from ._common import (
+ MaybeAwaitable,
+ MaybeAwaitableBool,
+ MaybeAwaitableFloat,
+ MaybeAwaitableInt,
+ MaybeAwaitableTuple,
+ )
from .parameters import Number, Port
@@ -48,25 +55,30 @@ def __init__(
turn when you give a positive speed value or
angle.
gears (list):
- List of gears linked to the motor.
+ List of gears linked to the motor. The gear connected
+ to the motor comes first and the gear connected to the output
+ comes last.
For example: ``[12, 36]`` represents a gear train with a
- 12-tooth and a 36-tooth gear. Use a list of lists for multiple
+ 12-tooth gear connected to the motor and a 36-tooth gear
+ connected to the output. Use a list of lists for multiple
gear trains, such as ``[[12, 36], [20, 16, 40]]``.
When you specify a gear train, all motor commands and settings
are automatically adjusted to account for the resulting gear
- ratio. The motor direction remains unchanged by this.
+ ratio. The motor direction remains unchanged by this.
reset_angle (bool):
Choose ``True`` to reset the rotation sensor value to the
absolute marker angle (between -180 and 179).
Choose ``False`` to keep the
current value, so your program knows where it left off last
time.
- profile (Number, deg): Precision profile. A lower value
- means more precise movement; a larger value means
- smoother movement. If no value is given, a suitable profile for
- this motor type will be selected automatically.
+ profile (Number, deg): Precision profile. This is the approximate
+ position tolerance in degrees that is acceptable in your
+ application. A lower value gives more precise but more erratic
+ movement; a higher value gives less precise but smoother
+ movement. If no value is given, a suitable profile for this
+ motor type will be selected automatically (about 11 degrees).
"""
def reset_angle(self, angle: Optional[Number] = None) -> None:
@@ -85,7 +97,7 @@ def reset_angle(self, angle: Optional[Number] = None) -> None:
class Remote:
"""LEGO® Powered Up Bluetooth Remote Control."""
- light = _common.ColorLight()
+ light = _common.ExternalColorLight()
buttons = _common.Keypad(
(
Button.LEFT_MINUS,
@@ -97,7 +109,7 @@ class Remote:
Button.RIGHT_PLUS,
)
)
- addresss: Union[str, None]
+ address: Union[str, None]
def __init__(self, name: Optional[str] = None, timeout: int = 10000):
"""Remote(name=None, timeout=10000)
@@ -115,12 +127,10 @@ def __init__(self, name: Optional[str] = None, timeout: int = 10000):
"""
@overload
- def name(self, name: str) -> None:
- ...
+ def name(self, name: str) -> None: ...
@overload
- def name(self) -> str:
- ...
+ def name(self) -> str: ...
def name(self, *args):
"""name(name)
@@ -133,6 +143,12 @@ def name(self, *args):
this method returns the current name.
"""
+ def disconnect(self) -> MaybeAwaitable:
+ """disconnect()
+
+ Disconnects the remote from the hub.
+ """
+
class TiltSensor:
"""LEGO® Powered Up Tilt Sensor."""
@@ -144,7 +160,7 @@ def __init__(self, port: Port):
port (Port): Port to which the sensor is connected.
"""
- def tilt(self) -> Tuple[int, int]:
+ def tilt(self) -> MaybeAwaitableTuple[int, int]:
"""tilt() -> Tuple[int, int]: deg
Measures the tilt relative to the horizontal plane.
@@ -157,7 +173,7 @@ def tilt(self) -> Tuple[int, int]:
class ColorDistanceSensor(_common.CommonColorSensor):
"""LEGO® Powered Up Color and Distance Sensor."""
- light = _common.ColorLight()
+ light = _common.ExternalColorLight()
# HACK: jedi can't find inherited __init__ so docs have to be duplicated
def __init__(self, port: Port):
@@ -167,7 +183,7 @@ def __init__(self, port: Port):
port (Port): Port to which the sensor is connected.
"""
- def distance(self) -> int:
+ def distance(self) -> MaybeAwaitableInt:
"""distance() -> int: %
Measures the relative distance between the sensor and an object
@@ -178,7 +194,7 @@ def distance(self) -> int:
"""
-class PFMotor(DCMotor):
+class PFMotor:
"""Control Power Functions motors with the infrared functionality of the
:class:`ColorDistanceSensor `."""
@@ -204,6 +220,32 @@ def __init__(
turn when you give a positive duty cycle value.
"""
+ def dc(self, duty: Number) -> MaybeAwaitable:
+ """dc(duty)
+
+ Rotates the motor at a given duty cycle (also known as "power").
+
+ Arguments:
+ duty (Number, %): The duty cycle (-100.0 to 100).
+ """
+
+ def stop(self) -> MaybeAwaitable:
+ """stop()
+
+ Stops the motor and lets it spin freely.
+
+ The motor gradually stops due to friction.
+ """
+
+ def brake(self) -> MaybeAwaitable:
+ """brake()
+
+ Passively brakes the motor.
+
+ The motor stops due to friction, plus the voltage that
+ is generated while the motor is still moving.
+ """
+
class ColorSensor(_common.AmbientColorSensor):
"""LEGO® SPIKE Color Sensor."""
@@ -232,7 +274,7 @@ def __init__(self, port: Port):
"""
- def distance(self) -> int:
+ def distance(self) -> MaybeAwaitableInt:
"""distance() -> int: mm
Measures the distance between the sensor and an object using
@@ -244,7 +286,7 @@ def distance(self) -> int:
"""
- def presence(self) -> bool:
+ def presence(self) -> MaybeAwaitableBool:
"""presence() -> bool
Checks for the presence of other ultrasonic sensors by detecting
@@ -265,7 +307,7 @@ def __init__(self, port: Port):
port (Port): Port to which the sensor is connected.
"""
- def force(self) -> float:
+ def force(self) -> MaybeAwaitableFloat:
"""force() -> float: N
Measures the force exerted on the sensor.
@@ -274,7 +316,7 @@ def force(self) -> float:
Measured force (up to approximately 10.00 N).
"""
- def distance(self) -> float:
+ def distance(self) -> MaybeAwaitableFloat:
"""distance() -> float: mm
Measures by how much the sensor button has moved.
@@ -283,7 +325,7 @@ def distance(self) -> float:
Movement up to approximately 8.00 mm.
"""
- def pressed(self, force: Number = 3) -> bool:
+ def pressed(self, force: Number = 3) -> MaybeAwaitableBool:
"""pressed(force=3) -> bool
Checks if the sensor button is pressed.
@@ -295,7 +337,7 @@ def pressed(self, force: Number = 3) -> bool:
``True`` if the sensor is pressed, ``False`` if it is not.
"""
- def touched(self) -> bool:
+ def touched(self) -> MaybeAwaitableBool:
"""touched() -> bool
Checks if the sensor is touched.
@@ -323,7 +365,7 @@ def __init__(self, port: Port):
"""
...
- def on(self, color: Union[Color, Collection[Color]]) -> None:
+ def on(self, color: Union[Color, Collection[Color]]) -> MaybeAwaitable:
"""on(colors)
Turns the lights on.
@@ -336,7 +378,7 @@ def on(self, color: Union[Color, Collection[Color]]) -> None:
"""
...
- def off(self) -> None:
+ def off(self) -> MaybeAwaitable:
"""off()
Turns all lights off.
@@ -354,7 +396,7 @@ def __init__(self, port: Port):
port (Port): Port to which the sensor is connected.
"""
- def reflection(self) -> int:
+ def reflection(self) -> MaybeAwaitableInt:
"""reflection() -> int: %
Measures the reflection of a surface using an infrared light.
@@ -364,7 +406,7 @@ def reflection(self) -> int:
100% (high reflection).
"""
- def distance(self) -> int:
+ def distance(self) -> MaybeAwaitableInt:
"""distance() -> int: %
Measures the relative distance between the sensor and an object
@@ -374,7 +416,7 @@ def distance(self) -> int:
Distance ranging from 0% (closest) to 100% (farthest).
"""
- def count(self) -> int:
+ def count(self) -> MaybeAwaitableInt:
"""count() -> int
Counts the number of objects that have passed by the sensor.
@@ -415,5 +457,10 @@ def off(self) -> None:
del Button
del Color
del Direction
+ del MaybeAwaitable
+ del MaybeAwaitableBool
+ del MaybeAwaitableFloat
+ del MaybeAwaitableInt
+ del MaybeAwaitableTuple
del Number
del Port
diff --git a/src/pybricks/robotics.py b/src/pybricks/robotics.py
index 65ef209a..776ade89 100644
--- a/src/pybricks/robotics.py
+++ b/src/pybricks/robotics.py
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: MIT
-# Copyright (c) 2018-2022 The Pybricks Authors
+# Copyright (c) 2018-2023 The Pybricks Authors
"""Robotics module for the Pybricks API."""
@@ -11,7 +11,7 @@
from .parameters import Stop
if TYPE_CHECKING:
- from ._common import Motor
+ from ._common import Motor, MaybeAwaitable
from .parameters import Number
@@ -86,6 +86,12 @@ def stop(self) -> None:
Stops the robot by letting the motors spin freely."""
+ def brake(self) -> None:
+ """brake()
+
+ Stops the robot by passively braking the motors.
+ """
+
def distance(self) -> int:
"""distance() -> int: mm
@@ -125,12 +131,10 @@ def settings(
straight_acceleration: Optional[Number] = None,
turn_rate: Optional[Number] = None,
turn_acceleration: Optional[Number] = None,
- ) -> None:
- ...
+ ) -> None: ...
@overload
- def settings(self) -> Tuple[int, int, int, int]:
- ...
+ def settings(self) -> Tuple[int, int, int, int]: ...
def settings(self, *args):
"""
@@ -161,7 +165,7 @@ def settings(self, *args):
def straight(
self, distance: Number, then: Stop = Stop.HOLD, wait: bool = True
- ) -> None:
+ ) -> MaybeAwaitable:
"""straight(distance, then=Stop.HOLD, wait=True)
Drives straight for a given distance and then stops.
@@ -173,7 +177,9 @@ def straight(
with the rest of the program.
"""
- def turn(self, angle: Number, then: Stop = Stop.HOLD, wait: bool = True) -> None:
+ def turn(
+ self, angle: Number, then: Stop = Stop.HOLD, wait: bool = True
+ ) -> MaybeAwaitable:
"""turn(angle, then=Stop.HOLD, wait=True)
Turns in place by a given angle and then stops.
@@ -187,7 +193,7 @@ def turn(self, angle: Number, then: Stop = Stop.HOLD, wait: bool = True) -> None
def curve(
self, radius: Number, angle: Number, then: Stop = Stop.HOLD, wait: bool = True
- ) -> None:
+ ) -> MaybeAwaitable:
"""curve(radius, angle, then=Stop.HOLD, wait=True)
Drives an arc along a circle of a given radius, by a given angle.
@@ -221,15 +227,90 @@ def stalled(self) -> bool:
``True`` if the drivebase is stalled, ``False`` if not.
"""
+ def use_gyro(self, use_gyro: bool) -> None:
+ """use_gyro(use_gyro)
-class GyroDriveBase(DriveBase):
- """A robotic vehicle with two powered wheels and an optional support
- wheel or caster. It measures the heading using the hub's built-in gyroscope,
- which can make turning and driving straight more accurate."""
+ Choose ``True`` to use the gyro sensor for turning and driving
+ straight. Choose ``False`` to rely only on the motor's built-in
+ rotation sensors.
+
+ Arguments:
+ use_gyro (bool): ``True`` to enable, ``False`` to disable.
+ """
+
+
+class Car:
+ """A vehicle with one steering motor, and one or more motors for driving.
+
+ When you use this class, the steering motor will automatically find the
+ center position. This also determines which angle corresponds to 100%
+ steering.
+ """
+
+ def __init__(
+ self,
+ steer_motor: Motor,
+ drive_motors: Motor | Tuple[Motor, ...],
+ torque_limit: Number = 100,
+ ):
+ """Car(steer_motor, drive_motors, torque_limit=100)
+
+ Arguments:
+ steer_motor (Motor):
+ The motor that steers the front wheels.
+ drive_motors (Motor): The motor that drives the wheels. Use a tuple
+ for multiple motors.
+ torque_limit (Number, %): The maximum torque limit used to find the
+ endpoints for the steering mechanism, as a percentage of the
+ maximum torque of the steering motor.
+ """
+
+ def steer(self, percentage: Number) -> None:
+ """steer(percentage)
+
+ Steers the front wheels by a given amount. For 100% steering, it
+ steers right by the angle that was determined on initialization.
+ For -100% steering, it steers left and 0% means straight.
+
+ Arguments:
+ steering (Number, %): Amount to steer the front wheels.
+ """
+
+ def drive_power(self, power: Number) -> None:
+ """drive_power(power)
+
+ Drives the car at a given power level. Positive values drive forward,
+ negative values drive backward.
+
+ The ``power`` value is used to set the motor voltage as a percentage of
+ the battery voltage. Below 10%, the car will coast the wheels in order
+ to roll out smoothly instead of braking abruptly.
+
+ This command is useful for remote control applications where you want
+ instant response to button presses or joystick movements.
+
+ Arguments:
+ speed (Number, %): Speed of the car.
+ """
+
+ def drive_speed(self, speed: Number) -> None:
+ """drive_speed(speed)
+
+ Drives the car at a given motor speed. Positive values drive forward,
+ negative values drive backward.
+
+ This command is useful for more precise driving with gentle
+ acceleration and deceleration. This automatically increases the power
+ to maintain speed as you drive across obstacles.
+
+ Arguments:
+ speed (Number, deg/s): Angular velocity of the drive motors.
+ """
# HACK: hide from jedi
if TYPE_CHECKING:
del Motor
del Number
+ del MaybeAwaitable
del Stop
diff --git a/src/pybricks/tools.py b/src/pybricks/tools.py
index 64f8bc7e..ff02af3e 100644
--- a/src/pybricks/tools.py
+++ b/src/pybricks/tools.py
@@ -5,13 +5,14 @@
from __future__ import annotations
-from typing import TYPE_CHECKING, Any, Sequence, Tuple, overload
+from typing import TYPE_CHECKING, Any, Optional, Sequence, Tuple, overload, Coroutine
if TYPE_CHECKING:
+ from ._common import MaybeAwaitable, MaybeAwaitableTuple
from .parameters import Number
-def wait(time: Number) -> None:
+def wait(time: Number) -> MaybeAwaitable:
"""wait(time)
Pauses the user program for a specified amount of time.
@@ -25,8 +26,7 @@ class StopWatch:
"""A stopwatch to measure time intervals. Similar to the stopwatch
feature on your phone."""
- def __init__(self):
- ...
+ def __init__(self): ...
def time(self) -> int:
"""time() -> int: ms
@@ -107,38 +107,27 @@ class Matrix:
A :class:`.Matrix` object is immutable."""
- def __add__(self, other) -> Matrix:
- ...
+ def __add__(self, other) -> Matrix: ...
- def __iadd__(self, other) -> Matrix:
- ...
+ def __iadd__(self, other) -> Matrix: ...
- def __sub__(self, other) -> Matrix:
- ...
+ def __sub__(self, other) -> Matrix: ...
- def __isub__(self, other) -> Matrix:
- ...
+ def __isub__(self, other) -> Matrix: ...
- def __mul__(self, other) -> Matrix:
- ...
+ def __mul__(self, other) -> Matrix: ...
- def __rmul__(self, other) -> Matrix:
- ...
+ def __rmul__(self, other) -> Matrix: ...
- def __imul__(self, other) -> Matrix:
- ...
+ def __imul__(self, other) -> Matrix: ...
- def __truediv__(self, other) -> Matrix:
- ...
+ def __truediv__(self, other) -> Matrix: ...
- def __itruediv__(self, other) -> Matrix:
- ...
+ def __itruediv__(self, other) -> Matrix: ...
- def __floordiv__(self, other) -> Matrix:
- ...
+ def __floordiv__(self, other) -> Matrix: ...
- def __ifloordiv__(self, other) -> Matrix:
- ...
+ def __ifloordiv__(self, other) -> Matrix: ...
def __init__(self, rows: Sequence[Sequence[float]]):
"""Matrix(rows)
@@ -222,6 +211,87 @@ def cross(a: Matrix, b: Matrix) -> Matrix:
"""
+def read_input_byte(last: bool = False, chr: bool = False) -> Optional[int | str]:
+ """
+ read_input_byte() -> int | str | None
+
+ Reads one byte from standard input without blocking and removes it from the
+ input buffer.
+
+ Arguments:
+ last (bool): Choose ``True`` to read the last (most recent) byte in the buffer and discard the rest.
+ Choose ``False`` to read only the first (oldest) byte.
+ chr (bool): Choose ``True`` to convert the result to a one-character string.
+
+ Returns:
+ The byte that was read, as a numeric value (``0`` to ``255``) or
+ string (e.g. ``"B"``). Returns ``None`` if no data is available. If
+ ``chr=True``, it also return ``None`` if the byte that was read is not
+ printable as a character.
+ """
+
+
+def hub_menu(*symbols: int | str) -> int | str:
+ """
+ hub_menu(symbol1, symbol2, ...) -> int | str
+
+ Shows a menu on the hub display and waits for the user to select an item
+ using the buttons. Can be used in your own menu-program that lets you
+ choose which of your other programs to run.
+
+ Note that this is just a convenience function that combines the display,
+ buttons, and waits to make a simple menu. This means that it can be used
+ anywhere in a program, not just at the start.
+
+ Arguments:
+ symbol1 (int or str): The first symbol to show in the menu.
+ symbol2 (int or str): The second symbol, and so on...
+
+ Returns:
+ The selected symbol.
+ """
+
+
+def multitask(*coroutines: Coroutine, race=False) -> MaybeAwaitableTuple:
+ """
+ multitask(coroutine1, coroutine2, ...) -> Tuple
+
+ Runs multiple coroutines concurrently. This creates a new coroutine that
+ can be used like any other, including in another ``multitask`` statement.
+
+ Arguments:
+ coroutines (coroutine, coroutine, ...): One or more coroutines to run
+ in parallel.
+ race (bool): Choose ``False`` to wait for all coroutines to finish.
+ Choose ``True`` to wait for one coroutine to finish and then
+ cancel the others, as if it's a "race".
+
+ Returns:
+ Tuple of the return values of each coroutine. Unfinished coroutines
+ will have ``None`` as their return value.
+ """
+
+
+def run_task(coroutine: Coroutine) -> Optional[bool]:
+ """
+ run_task(coroutine) -> bool | None
+
+ Runs a coroutine from start to finish while blocking the rest of the
+ program. This is used primarily to run the main coroutine of a program.
+
+ Calls to this function are not allowed to be nested.
+
+ Arguments:
+ coroutine (coroutine): The main coroutine to run.
+
+ Returns:
+ If no ``coroutine`` is given, this function returns whether the
+ run loop is currently active (``True``) or not (``False``).
+ """
+
+
# HACK: hide from jedi
if TYPE_CHECKING:
del Number
+ del MaybeAwaitable
+ del MaybeAwaitableTuple
diff --git a/src/ubuiltins/__init__.py b/src/ubuiltins/__init__.py
index 050c8fc5..d2cd104d 100644
--- a/src/ubuiltins/__init__.py
+++ b/src/ubuiltins/__init__.py
@@ -23,6 +23,7 @@
Any,
Callable,
Dict,
+ Hashable,
Iterable,
Iterator,
List,
@@ -33,6 +34,7 @@
SupportsFloat,
SupportsInt,
Tuple,
+ TypeVar,
Union,
overload,
)
@@ -55,6 +57,8 @@
_str = str
_type = type
+_Self = TypeVar("_Self")
+
# Functions and types
@@ -1084,6 +1088,207 @@ def round(*args):
"""
+class set:
+ @overload
+ def __init__(self) -> None:
+ ...
+
+ @overload
+ def __init__(self, iterable: Iterable[Hashable]) -> None:
+ ...
+
+ def __init__(self, *args) -> None:
+ """
+ set()
+ set(iterable)
+
+ Creates a new set.
+
+ With no arguments, creates a new empty set, otherwise creates a set
+ containing unique items of *iterable*.
+
+ Sets can also be created using a set literal::
+
+ my_set = {1, 2, 3}
+
+ Elements of a set must be hashable. There are only a few types, like
+ :class:`list` that aren't hashable.
+
+ Args:
+ iterable: An iterable of hashable objects.
+ """
+
+ def copy(self: _Self) -> _Self:
+ """
+ copy() -> set
+
+ Returns a shallow copy of the set.
+
+ Returns:
+ A new set.
+ """
+
+ def difference(self: _Self, *others: set) -> _Self:
+ """
+ difference(other1, other2, ...) -> set
+
+ Returns a new set with elements that are not in any of the other sets.
+
+ The difference can also be computed using the ``-`` operator::
+
+ diff = s - other
+
+ Args:
+ others: 1 or more other sets.
+
+ Returns:
+ A new set.
+ """
+
+ def intersection(self: _Self, *others: set) -> _Self:
+ """
+ intersection(other1, other2, ...) -> set
+
+ Returns a new set with elements that are common between this set and
+ all other sets.
+
+ The intersection can also be computed using the ``&`` operator::
+
+ intersect = s & other
+
+ Args:
+ others: 1 or more other sets.
+
+ Returns:
+ A new set.
+ """
+
+ def isdisjoint(self, other: set) -> bool:
+ """
+ isdisjoint(other) -> bool
+
+ Tests if a set and *other* have no elements in common.
+
+ Args:
+ other: Another set.
+
+ Returns:
+ ``True`` if this set has no elements in common with *other*,
+ otherwise ``False``.
+ """
+
+ def issubset(self, other: set) -> bool:
+ """
+ issubset(other) -> bool
+
+ Tests if a set is a subset of *other*.
+
+ The test can also be performed using using the ``<=`` operator::
+
+ if s <= other:
+ # s is subset of other
+ ...
+
+ Args:
+ other: Another set.
+
+ Returns:
+ ``True`` if this set is a subset of *other*, otherwise ``False``.
+ """
+
+ def issuperset(self, other: set) -> bool:
+ """
+ issuperset(other) -> bool
+
+ Tests if a set is a superset of *other*.
+
+ The test can also be performed using using the ``>=`` operator::
+
+ if s >= other:
+ # s is superset of other
+ ...
+
+ Args:
+ other: Another set.
+
+ Returns:
+ ``True`` if this set is a superset of *other*, otherwise ``False``.
+ """
+
+ def symmetric_difference(self: _Self, other: set) -> _Self:
+ """
+ symmetric_difference(other) -> bool
+
+ Returns a new set with elements in one set or the other but not in both.
+
+ The symmetric difference can also be computed using the ``^`` operator::
+
+ diff = s ^ other
+
+ Args:
+ other: Another set.
+
+ Returns:
+ A new set.
+ """
+
+ def union(self: _Self, *others: set) -> _Self:
+ """
+ union(other1, other2, ...) -> set
+
+ Returns a new set with elements from this set and all other sets.
+
+ The union can also be computed using the ``|`` operator::
+
+ u = s | other
+
+ Args:
+ others: 1 or more other sets.
+
+ Returns:
+ A new set.
+ """
+
+ def __contains__(self, item: Hashable) -> bool:
+ ...
+
+ def __len__(self) -> int:
+ ...
+
+ def __bool__(self) -> bool:
+ ...
+
+ def __gt__(self, other: set) -> bool:
+ ...
+
+ def __lt__(self, other: set) -> bool:
+ ...
+
+ def __ge__(self, other: set) -> bool:
+ ...
+
+ def __le__(self, other: set) -> bool:
+ ...
+
+ def __eq__(self, other: set) -> bool:
+ ...
+
+ def __ne__(self, other: set) -> bool:
+ ...
+
+ def __sub__(self: _Self, other: set) -> _Self:
+ ...
+
+ def __and__(self: _Self, other: set) -> _Self:
+ ...
+
+ def __or__(self: _Self, other: set) -> _Self:
+ ...
+
+ def __xor__(self: _Self, other: set) -> _Self:
+ ...
+
+
def setattr(object: Any, name: _str, value: Any) -> None:
"""
setattr(object, name, value)
@@ -1170,7 +1375,7 @@ def __init__(self) -> None:
If no argument is given, this creates an empty ``str`` object.
Arguments:
- object: If only this argument is given, this returns the stirng
+ object: If only this argument is given, this returns the string
representation of the object.
encoding (str): If the first argument is a ``bytearray`` or ``bytes``
object and the encoding argument is ``"utf-8"``, this will decode