Compare commits

...
Author SHA1 Message Date
Laurens Valk 7de33c0ce5 v3.2.0b1 2022-06-02 17:10:46 +02:00
Laurens Valk dbc5d327e3 doc/common/conf: Display s^2 units correctly.
Now that we no longer use these in hyperlinks, we can use the right
unicode to display this unit correctly.
2022-05-30 17:29:30 +02:00
Laurens Valk 2e39740e4b pybricks.nxtdevices: Add typing. 2022-05-30 17:19:38 +02:00
Laurens Valk 45e0744b3f pybricks.ev3devices: Add typing. 2022-05-30 15:34:07 +02:00
Laurens Valk aab6c0d3e0 pybricks.media.ev3dev: Repair build.
Upon temporarily including these to update typing for pybricks.ev3devices, a lot of build errors were encountered.

Even though we won't be re-including these pages any time soon, we'll want to occasionally make sure that they still build with more recent versions of Sphinx.
2022-05-30 14:29:14 +02:00
Laurens Valk 8a4c4a5400 CONTRIBUTING: Add basic docstring guidelines.
Fixes https://github.com/pybricks/pybricks-api/issues/99
2022-05-30 10:57:31 +02:00
Laurens Valk ecfbc6ca75 CONTRIBUTING: Fix formatting and link to setup.
We don't have a wiki.
2022-05-30 10:21:34 +02:00
Laurens Valk c3b6d44c59 pybricks.geometry: Add typing. 2022-05-30 10:17:47 +02:00
Laurens Valk db71a80f36 pybricks.common.IMU: Add typing. 2022-05-30 10:03:44 +02:00
Laurens Valk a80d5cf91e pybricks.common.Accelerometer: Add typing.
Also remove tapped and shaken, which are not implemented.
2022-05-30 09:46:00 +02:00
Laurens Valk 515d261bad pybricks.common.Charger: Add typing. 2022-05-30 09:29:14 +02:00
Laurens Valk dd54d67720 pybricks.common: Use Number as input type where allowed. 2022-05-28 11:33:08 +02:00
Laurens Valk 453332201e pybricks.common.Battery: Add typing. 2022-05-28 11:23:21 +02:00
Laurens Valk 3548ff47ce pybricks.common.Keypad: Add typing. 2022-05-28 11:20:07 +02:00
Laurens Valk a02b283f3f pybricks.common.LightMatrix: Add typing. 2022-05-28 11:15:17 +02:00
Laurens Valk f197531979 pybricks.common.LightArray: Add typing.
Remove blink and animate, which aren't implemented. These weren't displayed in the docs, so this is not a real change; it just makes typing more correct.
2022-05-28 10:55:40 +02:00
Laurens Valk 2167b9d52d pybricks.common.ColorLight: Add typing.
Also remove pybricks.common.Light which isn't used anywhere.

pupdevices.Light is a standalone light that does not support animations or blinks, so don't inherit from this nonexistent class.

Also remove the ColorLight.reset() method which was never implemented.
2022-05-27 20:00:28 +02:00
Laurens Valk 2be15fdf4d pybricks.common.Speaker: Add typing. 2022-05-27 19:14:22 +02:00
Laurens Valk aaf3ad1b9c pybricks.common.Control: Add typing. 2022-05-27 17:15:24 +02:00
Laurens Valk bd7806d2d4 all: Format with black.
Also activate auto formatting. Bump flake8 and mark black
disagreements in setup.cfg.
2022-05-27 16:22:05 +02:00
Laurens Valk 24f7d7c288 pybricks.common.Motor: Add typing. 2022-05-27 16:01:18 +02:00
Laurens Valk 5e0ba1de07 doc/common/conf: Format units in return type.
This formats return types so they don't look like tuples:

int: deg

If we can figure out how these nodes work, we can create proper links
and maybe use italics for the units or a slightly different font color.
2022-05-27 14:59:32 +02:00
Laurens Valk 2f8ba40034 poetry: Patch Sphinx to use docstring signatures when given.
This is the intended behavior everywhere, but it wasn't working for overloaded functions and methods.

See https://github.com/pybricks/sphinx/commit/f57417c042cbf4a72448518b7599517495cc6fde
2022-05-27 12:21:45 +02:00
Laurens Valk c4a09ab62a pybricks.common.DCMotor: Add typing. 2022-05-09 15:05:09 +02:00
Laurens Valk c0c53db5ee pybricks.common.System: Add typing. 2022-05-09 10:41:39 +02:00
Laurens Valk 5e09a6f1bd .vscode/settings: Add rewrap setting.
Now we can press Alt+Q to hard (re)wrap comments and docstrings.
2022-05-09 10:28:39 +02:00
Laurens Valk 5e9a8c5737 doc/main/signaltypes: Change how units are documented.
Previously, arguments had "types" like ":ref:`speed`", which would be rendered by Sphinx as a hyperlink and displayed as "rotational speed: deg/s".

This worked well enough but it had a few shortcomings:
- It looks bad on autocomplete, which doesn't know how to render RST with cross references.
- No real type information: int, float, ... ?
- Some units are very long, making the docs less concise.
- The unified approach doesn't always work. Some method arguments can be either deg/s or mm/s, depending on the application. This gets even lengthier.
- It's hard to maintain if you don't know what to link to.

In the new approach, the unit is just added to the type as plain text. Instead of giving the physical signal name, we give the real data type, which is more standard. The physical signal name is usually apparent from the docstring anyway, and can be inferred from the unit as well. This also solves all of the above problems.

Since most Pybricks methods allow both int and float for numeric inputs, we document these as a Number type, which is the union of int and float. Since the type is no longer directly tied to the type, we can still document the return type correctly, since this is never a union.

Instead of having complicated hacks in Sphinx to make this work (I have tried many), it turns out we can conveniently suppress broken references and still display the units. The only downside is that units will no longer have hyperlinks to the signal pages, at least for the moment. We should be able to make on_missing_reference a bit smarter to format the units as we see fit if needed.

The approach here is exemplified in the Motor.run_until_stalled method. Subsequent commits will apply it everywhere. Also clarify the behavior for duty_limit=None while we are updating this code anyway.
2022-05-09 10:28:31 +02:00
Laurens Valk f934fdd9bd pybricks.common.IMU: Change example to print G force.
Since we changed the acceleration units to mm/s/s, the output values are
fairly large.

The Matrix repr function prints values up to 999, so this avoids
truncating the output.

It is also a good demo of scalar division for a Matrix / Vector.
2022-04-01 16:32:39 +02:00
Laurens Valk 556728937f pybricks.common.Accelerometer: Use mm/s/s units.
Fixes https://github.com/pybricks/pybricks-api/issues/94

For Move Hub, this is a breaking change since Move Hub IMU support
was already released. For the other hubs, the IMU API has not been
released yet, so we can do this silently.
2022-04-01 15:41:15 +02:00
Laurens Valk 813ea61308 doc/main/conf.py: Show beta features on RTD/latest. 2022-04-01 14:51:38 +02:00
Laurens Valk 2e8e43bcdf rtd-requirements: Upgrade to Sphinx 4.4.0. 2022-04-01 14:31:35 +02:00
Laurens Valk e4ddd1ffce pybricks.geometry.Axis: Drop ANY.
This was previously dropped in a2583944d9
but it was added in again in c666009511.

Since this module was never included in a release (it was hidden),
it is OK to do this.
2022-04-01 14:28:38 +02:00
Laurens Valk 243f2948ef pybricks.hubs.primehub: Show in beta version.
Make it show up in the beta build and hide it in the release build.
2022-04-01 14:28:31 +02:00
Laurens Valk 81a1379781 doc/Makefile: Allow BETA=1 to include beta features.
Prior to every previous release, we we had to delete certain
features that did not make it into the release. This lets us
do that with a tag instead. This way we can keep a clean git
history that is easier to follow.
2022-04-01 13:39:04 +02:00
Laurens Valk 93a9370790 doc/common/extensions: Hide version directives in IDE build.
Version tags can be useful to keep track of new or updated features.

This lets us hide such details in the documentation that ships with the IDE to keep it concise.
2022-04-01 09:38:41 +02:00
Laurens Valk 1989561c90 .github/workflows: Fix typo in build name. 2022-03-22 15:49:23 +01:00
Laurens Valk 4101f9be79 poetry: Update Sphinx and RTD-theme.
We were not using a proper release for sphinx-rtd-theme
in order to work around some bugs. Meanwhile, a proper
release has come out, so let's upgrade to 1.0.0.

Also bump Sphinx to 4.4.

Also update and fix workarounds for cross references.
Fixes https://github.com/pybricks/pybricks-api/issues/98.
2022-03-22 15:38:04 +01:00
Laurens Valk 0a31bc711f pybricks.common.Control: Add deceleration setter.
Fixes https://github.com/pybricks/pybricks-api/issues/97
2022-03-21 11:17:34 +01:00
Pavel Lobodinský d8bd890101 pybricks.common: Charger, IMU and System auto-completion 2022-03-02 10:31:53 -06:00
David Lechner 2ba7edab0c pybricks.ev3/pupdevices: fix Motor code completion
The Microsoft Python extension for VS code doesn't include imports in
type hints, so the Motor type wasn't working properly. We can fix this
by wrapping the import type in a new, empty class definition.

The DCMotor class was also missing from ev3devices and the typing for
the overloaded reset_angle method in pupdevices was missing. These are
fixed as well.
2022-02-21 10:59:00 -06:00
Pavel Lobodinský 616051149b pybricks.common.Speaker: Add volume setter. 2022-01-20 08:56:29 +01:00
Laurens Valk e69c422f83 pybricks.common.Motor: Add absolute value example.
Fixes https://github.com/pybricks/support/issues/611
2022-01-20 08:39:43 +01:00
Laurens Valk 0ceabe8497 pybricks.common.Charger: Document it. 2022-01-14 15:14:28 +01:00
Laurens Valk d3ae4ec9ee pybricks.pupdevices.ColorSensor: Move cleanup example.
The color sensor light is much brighter, so having an example
to turn it off is a bit more useful.

Fixes https://github.com/pybricks/pybricks-api/pull/90
2022-01-07 14:11:03 +01:00
Laurens Valk ffb2f8aa96 pybricks.pupdevices.UltrasonicSensor: Move cleanup example.
Also generalize the example so that it can be used on all hubs.
2022-01-07 13:38:07 +01:00
Pavel Lobodinský 65c81834c9 pybricks.hubs.PrimeHub: Added a cleanup example. 2022-01-07 13:38:07 +01:00
Pavel Lobodinský 97002948d1 pybricks.common: Refactored Speaker API to be hub specific.
The Prime/Inventor Hub Speaker allows only a subset of EV3 Speaker API. Hence, splitting the API up.
2022-01-05 12:10:11 -06:00
Pavel Lobodinský 70aa5ee0e2 pybricks._common: Renamed incorrect argument name, fixed tuple type. 2022-01-03 11:01:33 +01:00
Pavel Lobodinský efc1650e7f pybricks.parameters: Added Icon class, added missing methods and attributes.
Added missing Icon class present in the firmware
2022-01-03 11:01:33 +01:00
Pavel Lobodinský fe60636072 pybricks.geometry: Fixed Matrix incorrect rows type, added missing methods. 2022-01-03 11:01:33 +01:00
Pavel Lobodinský a1342f77c9 pybricks.hubs: Default values for the PrimeHub. 2022-01-03 11:01:33 +01:00
Laurens Valk d806fe9fbe pybricks.common.Control: Fix docstring and type hints for limits().
Fixes https://github.com/pybricks/support/issues/565
2021-12-30 09:12:27 +01:00
David Lechner 1259d5d33a bump version for development 2021-12-16 15:36:52 -06:00
David Lechner 098b8eb9cb v3.1.0 2021-12-16 15:36:14 -06:00
David Lechner c666009511 pybricks.geometry: add Axis.ANY
This exists in the firmware but was missing here.
2021-12-16 15:08:50 -06:00
David Lechner 7f4234fc1e pybricks._common: remove type hint for integral_range()
This was removed in e061617.

Also fix import of Axis while we are touching this file.
2021-12-16 15:07:33 -06:00
David Lechner 482289c384 pybricks.robotics: add type hint for curve()
This method was added in 30803fc.
2021-12-16 15:06:00 -06:00
86 changed files with 2366 additions and 1846 deletions
+1 -1
View File
@@ -35,7 +35,7 @@ jobs:
run: poetry run doc8
- name: Build html docs for Read the Docs
run: poetry run make -C doc html
- name: Instal IDE docs dependencies
- name: Install IDE docs dependencies
run: |
sudo apt-get update
sudo apt-get install dvisvgm preview-latex-style texlive texlive-fonts-extra texlive-latex-extra
+8 -2
View File
@@ -1,9 +1,14 @@
{
"python.pythonPath": "${workspaceFolder}/.venv",
"python.formatting.provider": "black",
"python.linting.pycodestyleEnabled": false,
"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"
},
"python.languageServer": "Pylance",
"files.associations": {"*.inc": "restructuredtext"},
"restructuredtext.confPath": "${workspaceFolder}/doc/main",
@@ -34,5 +39,6 @@
"plaintext",
"python",
"restructuredtext",
]
],
"rewrap.wrappingColumn": 78,
}
+1
View File
@@ -78,3 +78,4 @@ thermistor
toctree
TODO
UART
utf-8
+16 -1
View File
@@ -2,7 +2,22 @@
<!-- refer to https://keepachangelog.com/en/1.0.0/ for guidance -->
## Unreleased
## 3.2.0b1 - 2022-06-02
### Added
- Code auto-completion for `hub.charger`, `hub.imu` and `hub.system`.
- Moved typing from several `.pyi` files to the actual python modules.
### Fixed
- Fixed code completion for `DCMotor` and `Motor` classes in MS Python VS Code extension.
- Fixed missing `DCMotor` type in `ev3devices`.
- Fixed type hint for `Motor.reset_angle()` in `pupdevices`.
### Changed
- Setter for acceleration can now also be used to set acceleration and
deceleration to different values, using a two-valued tuple.
## 3.1.0 - 2021-12-16
### Added
- Added maximum voltage setter for `DCMotor` and `Motor`.
+82 -5
View File
@@ -32,14 +32,91 @@ will actually be implemented.
- pybricks.tools.wait: Add example of waiting.
- pybricks.pupdevices: Fix all sensor class ports.
- umath.sin: Fix spelling of Hypotenuse.
- If an import path makes no sense, just use the file path without extensions:
- If an import path makes no sense, just use the file path without
extensions:
- .vscode/settings: Fix file associations.
- The subject briefly describes _what_ was changed. Use a short full sentence as in the examples above.
- The subject briefly describes _what_ was changed. Use a short full sentence
as in the examples above.
- The body describes _why_ the change was made, e.g. `The word "sensor" was
spelled incorrectly`.
[commits]: https://github.com/pybricks/pybricks-api/commits/master
**General docstring principles:**
The stubs libraries in this repository have two different purposes:
1. Auto-generating documentation with Sphinx. For this purpose, the
documentation should be concise and clear.
2. Provide autocomplete and intellisense in code editors. For this purpose,
the code needs to be 100% correct. This way, computers can parse your code
correctly and tell you when something is wrong.
Since these objectives don't always align, we address these separately in the
stubs library:
1. The first line(s) of the docstring contain the function or method signature
as it should be displayed in the human-readable documentation.
2. The real function signature can be as complex as it needs to be to make it
correct for intellisense. Overloads can be uses if needed.
In the rare case where the docstring signature is the same as the typed
version, we'll still include it for consistency.
**Docstring details:**
Make sure to look at existing function signatures and docstrings for
inspiration when documenting new functionality. As an example, consider:
```python
def run_until_stalled(
self,
speed: Number,
then: Stop = Stop.COAST,
duty_limit: Optional[Number] = None,
) -> int:
"""
run_until_stalled(speed, then=Stop.COAST, duty_limit=None) -> int: deg
Runs the motor at a constant speed until it stalls.
Arguments:
speed (Number, deg/s): Speed of the motor.
then (Stop): What to do after coming to a standstill.
duty_limit (Number, %): Duty cycle limit during this
command. This is useful to avoid applying the full motor
torque to a geared or lever mechanism. If it is ``None``, the
duty limit won't be changed during this command.
Returns:
Angle at which the motor becomes stalled.
"""
```
The real method signature at the top contains the full detail, including the
type of each argument and return value.
The docstring starts with the signature. Use more than one signature if needed
to represent overloaded methods. The signatures are written in the way they
should be displayed in the docs:
- Argument types are omitted because they are also shown with the argument
description below.
- Default values should be given (``then=Stop.COAST``).
- The return type should be given (``-> int``). When applicable, include
the unit of the return value, so it becomes ``-> int: deg``
Then follows a concise description of what this method, function, or class
does.
Then follows a list of arguments:
- For each argument, include the expected type and unit if applicable, e.g.
``(int)`` or ``(Number, deg/s)``.
- Use ``Number`` when ``int`` and ``float`` are both allowed.
- If the description is long, use the indentation shown above.
- Make it readable. Instead
of ``Union[float, SupportsFloat, complex, SupportsComplex]``,
just say _float or complex_.
Then follows a description of the return value. The type is omitted here since
it is already include in the docstring signature.
**Development environment:**
@@ -49,8 +126,8 @@ Prerequisites:
- [Python 3][python]
- [Poetry][poetry]
Information on installing prerequisites can be found on the [pybricks-micropython
wiki][wiki].
Information on installing prerequisites can be found on the
[pybricks-micropython contributor's guide][contributing].
Initial setup:
@@ -90,4 +167,4 @@ Linting:
[git]: https://git-scm.com/
[python]: https://www.python.org/
[poetry]: https://python-poetry.org/
[wiki]: https://github.com/pybricks-micropython/wiki
[contributing]: https://github.com/pybricks/pybricks-micropython/blob/master/CONTRIBUTING.md
+5 -2
View File
@@ -8,10 +8,13 @@ SPHINXPROJ = Pybricks
SOURCEDIR = main
BUILDDIR = "$(SOURCEDIR)"/build
TAG = main
ifeq ($(BETA),1)
BETATAG = "-tbeta"
endif
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) -t $(TAG) $(O)
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(TAG) $(BETATAG) $(O)
.PHONY: help Makefile
@@ -22,4 +25,4 @@ diagrams:
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) -t $(TAG) $(O)
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) -t $(TAG) $(BETATAG) $(O)
+138 -107
View File
@@ -29,19 +29,15 @@ from docutils.parsers.rst import Directive
from sphinx.application import Sphinx
import toml
TOP_DIR = os.path.abspath(os.path.join('..', '..'))
sys.path.insert(0, os.path.join(TOP_DIR, 'src'))
sys.path.append(os.path.abspath('../common/extensions'))
from pybricks.hubs import EV3Brick # noqa E402
from pybricks.media.ev3dev import Image # noqa E402
from pybricks._common import Speaker # noqa E402
TOP_DIR = os.path.abspath(os.path.join("..", ".."))
sys.path.insert(0, os.path.join(TOP_DIR, "src"))
sys.path.append(os.path.abspath("../common/extensions"))
# ON_RTD is whether we are on readthedocs.org
# this line of code grabbed from docs.readthedocs.org
ON_RTD = os.environ.get('READTHEDOCS', None) == 'True'
ON_RTD = os.environ.get("READTHEDOCS", None) == "True"
_pyproject = toml.load(os.path.join(TOP_DIR, 'pyproject.toml'))
_pyproject = toml.load(os.path.join(TOP_DIR, "pyproject.toml"))
# -- General configuration ------------------------------------------------
@@ -53,27 +49,29 @@ _pyproject = toml.load(os.path.join(TOP_DIR, 'pyproject.toml'))
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.napoleon',
'sphinx.ext.todo',
'sphinx.ext.mathjax',
'color',
'classlink',
'requirements',
'requirements-static',
"sphinx.ext.autodoc",
"sphinx.ext.napoleon",
"sphinx.ext.todo",
"sphinx.ext.mathjax",
# Custom Pybricks extensions
"color",
"classlink",
"requirements",
"requirements-static",
"versionchanged",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['../common/_templates']
templates_path = ["../common/_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
source_suffix = ".rst"
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -82,17 +80,17 @@ master_doc = 'index'
# The full version, including alpha/beta/rc tags.
release = "v" + _pyproject["tool"]["poetry"]["version"]
# The short X.Y version.
version = re.match(r'(v\d+\.\d+)', release)[0]
version = re.match(r"(v\d+\.\d+)", release)[0]
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
language = "en"
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'xcode'
pygments_style = "xcode"
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True
@@ -100,10 +98,10 @@ todo_include_todos = True
# Figure numbering
numfig = True
numfig_format = {
'figure': 'Figure %s',
'table': 'Table %s',
'code-block': 'Listing %s',
'section': 'Section %s'
"figure": "Figure %s",
"table": "Table %s",
"code-block": "Listing %s",
"section": "Section %s",
}
# Find cross-reference errors
@@ -111,59 +109,49 @@ nitpicky = True
# https://stackoverflow.com/a/30624034/1976323
nitpick_ignore = [
('py:class', 'bool'),
('py:class', 'bytearray'),
('py:class', 'bytes'),
('py:class', 'callable'),
('py:class', 'dict'),
('py:class', 'float'),
('py:class', 'int'),
('py:class', 'iter'),
('py:class', 'list'),
('py:class', 'object'),
('py:class', 'str'),
('py:class', 'tuple'),
('py:exc', 'OSError'),
('py:exc', 'RuntimeError'),
('py:exc', 'TypeError'),
('py:exc', 'ValueError'),
("py:class", "bool"),
("py:class", "bytearray"),
("py:class", "bytes"),
("py:class", "callable"),
("py:class", "dict"),
("py:class", "float"),
("py:class", "int"),
("py:class", "iter"),
("py:class", "list"),
("py:class", "object"),
("py:class", "str"),
("py:class", "tuple"),
("py:exc", "OSError"),
("py:exc", "RuntimeError"),
("py:exc", "TypeError"),
("py:exc", "ValueError"),
]
# not sure why, but this is needed for typing.IO in uselect
nitpick_ignore.append(('py:class', 'IO'))
# Workaround until change below is released.
# https://github.com/sphinx-doc/sphinx/commit/86091934db5ec593b4b0c982b7f08f3231ef995b
nitpick_ignore.extend([
('py:class', '0'),
('py:class', '1'),
('py:class', '2'),
('py:class', '3'),
('py:class', 'big'),
('py:class', 'little'),
])
nitpick_ignore.append(("py:obj", "typing.IO"))
# -- Autodoc options ------------------------------------------------------
autodoc_member_order = 'bysource'
autodoc_member_order = "bysource"
autodoc_default_options = {
'members': True,
'undoc-members': True,
"members": True,
"undoc-members": True,
}
autoclass_content = 'both' # This ensures init arguments are not ignored
autoclass_content = "both" # This ensures init arguments are not ignored
add_module_names = False # Hide module name
# -- Options for HTML output ----------------------------------------------
if ON_RTD:
html_theme = 'default'
html_theme = "default"
else:
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
html_context = {
'disclaimer': _DISCLAIMER,
"disclaimer": _DISCLAIMER,
}
# The theme to use for HTML and HTML Help pages. See the documentation for
@@ -176,14 +164,14 @@ html_context = {
# documentation.
#
html_theme_options = {
'style_external_links': True,
'logo_only': True,
"style_external_links": True,
"logo_only": True,
}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['../common/_static']
html_static_path = ["../common/_static"]
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
@@ -191,9 +179,9 @@ html_static_path = ['../common/_static']
# This is required for the alabaster theme
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
html_sidebars = {
'**': [
'relations.html', # needs 'show_related': True theme option to display
'searchbox.html',
"**": [
"relations.html", # needs 'show_related': True theme option to display
"searchbox.html",
]
}
@@ -203,7 +191,7 @@ html_scaled_image_link = False
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'Pybricksdoc'
htmlhelp_basename = "Pybricksdoc"
# -- Options for LaTeX output ---------------------------------------------
@@ -212,14 +200,12 @@ latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
'preamble': r'''
"preamble": r"""
\usepackage{CJKutf8}
\makeatletter
\fancypagestyle{normal}{
@@ -239,51 +225,46 @@ latex_elements = {
\renewcommand{\footrulewidth}{0.4pt}
}
\makeatother
''' % {
'disclaimer': ' '.join((_DISCLAIMER, '©', copyright)),
"""
% {
"disclaimer": " ".join((_DISCLAIMER, "©", copyright)),
},
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
'extraclassoptions': 'openany,oneside',
'releasename': 'Version',
"extraclassoptions": "openany,oneside",
"releasename": "Version",
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, ''.join([project, '-v', version, '.tex']), _TITLE,
author, 'manual'),
(master_doc, "".join([project, "-v", version, ".tex"]), _TITLE, author, "manual"),
]
# -- Content control -----------------------------------------------------
exclude_patterns = [
'ev3devices.rst',
'hubs/ev3brick.rst',
'iodevices/analogsensor.rst',
'iodevices/dcmotor.rst',
'iodevices/ev3devsensor.rst',
'iodevices/i2cdevice.rst',
'iodevices/lumpdevice.rst',
'iodevices/uartdevice.rst',
'media.rst',
'messaging.rst',
'nxtdevices.rst',
'tools/datalog.rst'
"ev3devices.rst",
"hubs/ev3brick.rst",
"iodevices/analogsensor.rst",
"iodevices/dcmotor.rst",
"iodevices/ev3devsensor.rst",
"iodevices/i2cdevice.rst",
"iodevices/lumpdevice.rst",
"iodevices/uartdevice.rst",
"media.rst",
"messaging.rst",
"nxtdevices.rst",
"tools/datalog.rst",
]
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'pybricks', 'Pybricks Documentation',
[author], 1)
]
man_pages = [(master_doc, "pybricks", "Pybricks Documentation", [author], 1)]
# -- Options for Texinfo output -------------------------------------------
@@ -292,33 +273,83 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'Pybricks', 'Pybricks Documentation',
author, 'Pybricks', 'One line description of project.',
'Miscellaneous'),
(
master_doc,
"Pybricks",
"Pybricks Documentation",
author,
"Pybricks",
"One line description of project.",
"Miscellaneous",
),
]
# -- .. availability:: directive
class AvailabilityDirective(Directive):
has_content = True
option_spec = {
'movehub': flag,
'cityhub': flag,
'technichub': flag,
'ev3dev-stretch': flag,
"movehub": flag,
"cityhub": flag,
"technichub": flag,
"ev3dev-stretch": flag,
}
def run(self):
if not self.options:
raise self.error('Must specify at least one platform.')
raise self.error("Must specify at least one platform.")
# TODO: make links to platform pages
return [nodes.emphasis(text='Availability: '),
nodes.Text(', '.join(self.options))]
return [
nodes.emphasis(text="Availability: "),
nodes.Text(", ".join(self.options)),
]
def on_missing_reference(app, env, node, contnode):
# References with special characters can't exist, so we have to supress
# 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 [
"deg",
"deg/s",
"deg/s²",
"mm",
"mm/s",
"mm/s²",
"%",
"mV",
"mA",
"ms",
"mNm",
"Hz",
]:
# 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
# Return types are denoted as "int: deg"
try:
# Try to unpack the node.
ret_type, ret_unit = str(contnode).split(": ")
except ValueError:
# Not a valid format, so skip.
continue
# If it's a match, we could format the node so it looks a bit nicer.
# For now just keep the colon notation as is.
if unit == ret_unit:
return nodes.Text(f"{ret_type}: {ret_unit}")
def setup(app: Sphinx):
app.add_directive('availability', AvailabilityDirective)
app.add_directive("availability", AvailabilityDirective)
app.connect("missing-reference", on_missing_reference)
# -- Python domain hacks ---------------------------------------------------
+13 -11
View File
@@ -13,21 +13,23 @@ class PybricksClasslinkDirective(Directive):
link = name if len(self.arguments) == 1 else self.arguments[1]
html = (
'<a href="{0}.html">'.format(link.lower()) +
'<dl class="py class">' +
'<dt>' +
'<em class="property">class </em>' +
'<code class="sig-name descname">' + name + '</code>' +
'</dt>' +
'<dd></dd>' +
'</dl>' +
'</a>'
'<a href="{0}.html">'.format(link.lower())
+ '<dl class="py class">'
+ "<dt>"
+ '<em class="property">class </em>'
+ '<code class="sig-name descname">'
+ name
+ "</code>"
+ "</dt>"
+ "<dd></dd>"
+ "</dl>"
+ "</a>"
)
# Return the node
node = nodes.raw('', html, format="html")
node = nodes.raw("", html, format="html")
return [node]
def setup(app):
app.add_directive_to_domain('py', 'pybricks-classlink', PybricksClasslinkDirective)
app.add_directive_to_domain("py", "pybricks-classlink", PybricksClasslinkDirective)
+8 -9
View File
@@ -16,28 +16,27 @@ class PybricksColorDirective(Directive):
color = getattr(Color, name)
# Convert HSV to RGB
r, g, b = hsv_to_rgb(color.h/360, color.s/100, color.v/100)
r, g, b = hsv_to_rgb(color.h / 360, color.s / 100, color.v / 100)
# Convert RGB to HEX
rgbhex = '#{0:02x}{1:02x}{2:02x}'.format(
round(r*255),
round(g*255),
round(b*255)
rgbhex = "#{0:02x}{1:02x}{2:02x}".format(
round(r * 255), round(g * 255), round(b * 255)
)
# Render a small block of the given color
css = "background-color: {0}; color: {0}; width: 50px;".format(rgbhex)
if name == "WHITE":
css += "border-style: solid; border-width: 0.5px;" + \
"border-color: #666666;"
css += (
"border-style: solid; border-width: 0.5px;" + "border-color: #666666;"
)
html = '<div id="test" style="{0}">_</div>'.format(css)
# Return the node
node = nodes.raw('', html, format="html")
node = nodes.raw("", html, format="html")
return [node]
def setup(app):
app.add_directive_to_domain('py', 'pybricks-color', PybricksColorDirective)
app.add_directive_to_domain("py", "pybricks-color", PybricksColorDirective)
+26 -25
View File
@@ -10,10 +10,10 @@ FEATURES_SMALL = set()
# Medium feature set.
FEATURES_MEDIUM = FEATURES_SMALL | {
'pybricks-geometry',
'pybricks-iodevices',
'stm32-extra',
'stm32-float',
"pybricks-geometry",
"pybricks-iodevices",
"stm32-extra",
"stm32-float",
}
# Large feature set.
@@ -21,11 +21,11 @@ FEATURES_LARGE = FEATURES_MEDIUM | set()
# Features per hub.
HUB_FEATURES = {
'movehub': {'movehub'} | FEATURES_SMALL,
'cityhub': {'cityhub'} | FEATURES_MEDIUM,
'technichub': {'technichub'} | FEATURES_MEDIUM,
'primehub': {'primehub', 'inventorhub'} | FEATURES_LARGE,
'inventorhub': {'primehub', 'inventorhub'} | FEATURES_LARGE,
"movehub": {"movehub"} | FEATURES_SMALL,
"cityhub": {"cityhub"} | FEATURES_MEDIUM,
"technichub": {"technichub"} | FEATURES_MEDIUM,
"primehub": {"primehub", "inventorhub"} | FEATURES_LARGE,
"inventorhub": {"primehub", "inventorhub"} | FEATURES_LARGE,
}
@@ -40,15 +40,15 @@ class PybricksRequirementsStaticDirective(Directive):
# CC BY-SA 4.0 via https://stackoverflow.com/a/63728208
env = self.state.document.settings.env
destdir = path.join(env.app.builder.outdir, '_images')
destdir = path.join(env.app.builder.outdir, "_images")
if not path.exists(destdir):
makedirs(destdir)
for hub in HUB_FEATURES:
for compat in ("true", "false"):
uri = 'compat_{0}_{1}_label.png'.format(hub, compat)
src_uri = path.join(env.app.builder.srcdir, 'images', uri)
build_uri = path.join(env.app.builder.outdir, '_images', uri)
uri = "compat_{0}_{1}_label.png".format(hub, compat)
src_uri = path.join(env.app.builder.srcdir, "images", uri)
build_uri = path.join(env.app.builder.outdir, "_images", uri)
copyfile(src_uri, build_uri)
# Get requirements from sphinx-directive.
@@ -67,13 +67,14 @@ class PybricksRequirementsStaticDirective(Directive):
depth_path = "../" * depth
# Table row with hub images.
compat_row = "".join([
hub_cell.format(
depth_path,
hub,
"true" if requirements <= features else "false")
for hub, features in HUB_FEATURES.items()
])
compat_row = "".join(
[
hub_cell.format(
depth_path, hub, "true" if requirements <= features else "false"
)
for hub, features in HUB_FEATURES.items()
]
)
# Generate full table.
html = """
@@ -86,16 +87,16 @@ class PybricksRequirementsStaticDirective(Directive):
</tbody>
</table>
</div>
""".format(compat_row)
""".format(
compat_row
)
# Return the node.
node = nodes.raw('', html, format="html")
node = nodes.raw("", html, format="html")
return [node]
def setup(app):
app.add_directive_to_domain(
'py',
'pybricks-requirements-static',
PybricksRequirementsStaticDirective
"py", "pybricks-requirements-static", PybricksRequirementsStaticDirective
)
+14 -14
View File
@@ -29,25 +29,25 @@ from sphinx.util.osutil import copyfile
from sphinx.util import logging
CSS_FILE = 'requirements.css'
JS_FILE = 'requirements.js'
CSS_FILE = "requirements.css"
JS_FILE = "requirements.js"
class PybricksRequirementsDirective(Directive):
has_content = True
option_spec = {'header': directives.unchanged}
option_spec = {"header": directives.unchanged}
required_arguments = 0
optional_arguments = 10
def run(self):
node = nodes.container()
node['classes'].append('toggle-content')
node["classes"].append("toggle-content")
par = nodes.container()
par['classes'].append('toggle-header')
par["classes"].append("toggle-header")
content = '.. pybricks-requirements-static:: ' + " ".join(self.arguments)
content = ".. pybricks-requirements-static:: " + " ".join(self.arguments)
self.state.nested_parse(StringList([content]), self.content_offset, node)
@@ -60,20 +60,20 @@ def add_assets(app):
def copy_assets(app, exception):
if app.builder.name not in ['html', 'readthedocs'] or exception:
if app.builder.name not in ["html", "readthedocs"] or exception:
return
logger = logging.getLogger(__name__)
logger.info('Copying requirements stylesheet/javascript... ', nonl=True)
dest = os.path.join(app.builder.outdir, '_static', CSS_FILE)
logger.info("Copying requirements stylesheet/javascript... ", nonl=True)
dest = os.path.join(app.builder.outdir, "_static", CSS_FILE)
source = os.path.join(os.path.abspath(os.path.dirname(__file__)), CSS_FILE)
copyfile(source, dest)
dest = os.path.join(app.builder.outdir, '_static', JS_FILE)
dest = os.path.join(app.builder.outdir, "_static", JS_FILE)
source = os.path.join(os.path.abspath(os.path.dirname(__file__)), JS_FILE)
copyfile(source, dest)
logger.info('done')
logger.info("done")
def setup(app):
app.add_directive('pybricks-requirements', PybricksRequirementsDirective)
app.connect('builder-inited', add_assets)
app.connect('build-finished', copy_assets)
app.add_directive("pybricks-requirements", PybricksRequirementsDirective)
app.connect("builder-inited", add_assets)
app.connect("build-finished", copy_assets)
+31
View File
@@ -0,0 +1,31 @@
"""This directive hides the builtin directives
* versionchanged
* versionadded
* deprecated
when building documentation with the 'ide' tag.
"""
from docutils import nodes
from docutils.parsers.rst import Directive
class PybricksVersionDirective(Directive):
has_content = True
def run(self):
html = ""
node = nodes.raw("", html, format="html")
return [node]
def setup(app):
if "ide" in app.tags.tags:
app.add_directive_to_domain(
"py", "deprecated", PybricksVersionDirective, override=True
)
app.add_directive_to_domain(
"py", "versionadded", PybricksVersionDirective, override=True
)
app.add_directive_to_domain(
"py", "versionchanged", PybricksVersionDirective, override=True
)
+25 -22
View File
@@ -6,45 +6,48 @@
import os
# General information about the project.
project = 'pybricks'
copyright = '2018-2021 The Pybricks Authors'
author = ''
project = "pybricks"
copyright = "2018-2021 The Pybricks Authors"
author = ""
_TITLE = 'Pybricks Modules and Examples'
_DISCLAIMER = 'LEGO, the LEGO logo, MINDSTORMS and the MINDSTORMS EV3 logo are\
_TITLE = "Pybricks Modules and Examples"
_DISCLAIMER = "LEGO, the LEGO logo, MINDSTORMS and the MINDSTORMS EV3 logo are\
trademarks and/or copyrights of the LEGO Group of companies \
which does not sponsor, authorize or endorse this site.'
which does not sponsor, authorize or endorse this site."
html_favicon = '../common/images/favicon.ico'
html_logo = '../common/images/pybricks-logo-rtd.png'
latex_logo = '../common/images/pybricks-logo-large.png'
html_favicon = "../common/images/favicon.ico"
html_logo = "../common/images/pybricks-logo-rtd.png"
latex_logo = "../common/images/pybricks-logo-large.png"
# Build main docs for RTD by default.
# Since tags cannot be passed via the TAG make variable on read the docs,
# add it manually.
if os.environ.get('READTHEDOCS', None) == 'True':
tags.add('main') # noqa F821
if os.environ.get("READTHEDOCS", None) == "True":
tags.add("main") # noqa F821
# On https://docs.pybricks.com/en/latest/, show features tagged as beta.
if os.environ.get("READTHEDOCS_VERSION_NAME", None) == "latest":
tags.add("beta") # noqa F821
# Addtional configuration of the IDE docs
if 'ide' in tags.tags: # noqa F821
_DISCLAIMER = ''
if "ide" in tags.tags: # noqa F821
_DISCLAIMER = ""
html_show_copyright = False
html_show_sphinx = False
html_css_files = ['css/ide.css']
html_js_files = ['js/ide.js']
html_css_files = ["css/ide.css"]
html_js_files = ["js/ide.js"]
imgmath_image_format = 'svg'
imgmath_image_format = "svg"
imgmath_use_preview = True # requires Sphinx v3
imgmath_latex_preamble = r'''
imgmath_latex_preamble = r"""
\usepackage{newtxsf}
'''
"""
exec(open(os.path.abspath("../common/conf.py")).read())
# Addtional configuration of the IDE docs
if 'ide' in tags.tags: # noqa F821
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
extensions.remove("sphinx.ext.mathjax") # noqa F821
extensions.append("sphinx.ext.imgmath") # noqa F821
html_theme_options["prev_next_buttons_location"] = None # noqa F821
+29 -4
View File
@@ -44,17 +44,42 @@ Motors
.. automethod:: pybricks.ev3devices.Motor.run_target
.. automethod:: pybricks.ev3devices.Motor.track_target
.. automethod:: pybricks.ev3devices.Motor.run_until_stalled
.. automethod:: pybricks.ev3devices.Motor.dc
.. rubric:: Advanced motion control
.. rubric:: Motor status
.. automethod:: pybricks.ev3devices.Motor.track_target
.. attribute:: control.scale
.. autoattribute:: pybricks.ev3devices.Motor.control
:annotation:
Number of degrees that the motor turns to complete one degree at the
output of the gear train. This is the gear ratio determined from the
``gears`` argument when initializing the motor.
.. automethod:: pybricks.ev3devices.Motor.control.done
.. automethod:: pybricks.ev3devices.Motor.control.stalled
.. automethod:: pybricks.ev3devices.Motor.control.load
.. rubric:: Motor settings
You can only change these settings while the controller is stopped. For
example, you can change them at the start of your program. Alternatively,
first call :meth:`stop() <pybricks.ev3devices.Motor.stop>`, and then change
the settings.
.. automethod:: pybricks.ev3devices.Motor.settings
.. automethod:: pybricks.ev3devices.Motor.control.limits
.. automethod:: pybricks.ev3devices.Motor.control.pid
.. automethod:: pybricks.ev3devices.Motor.control.target_tolerances
.. automethod:: pybricks.ev3devices.Motor.control.stall_tolerances
Touch Sensor
^^^^^^^^^^^^
+4
View File
@@ -38,14 +38,18 @@ MINDSTORMS EV3 Brick
.. automethod:: pybricks.hubs::EV3Brick.screen.clear
.. automethod:: pybricks.hubs::EV3Brick.screen.draw_text
:noindex:
.. automethod:: pybricks.hubs::EV3Brick.screen.print
:noindex:
.. automethod:: pybricks.hubs::EV3Brick.screen.set_font
:noindex:
.. automethod:: pybricks.hubs::EV3Brick.screen.load_image
.. automethod:: pybricks.hubs::EV3Brick.screen.draw_image
:noindex:
.. automethod:: pybricks.hubs::EV3Brick.screen.draw_pixel
+4
View File
@@ -27,6 +27,10 @@ Move Hub
.. automethod:: pybricks.hubs::MoveHub.imu.acceleration
.. versionchanged:: 3.2
Changed acceleration units from m/s² to mm/s².
.. rubric:: Using the battery
.. automethod:: pybricks.hubs::MoveHub.battery.voltage
+165 -141
View File
@@ -6,232 +6,256 @@ Prime Hub / Inventor Hub
.. figure:: ../../main/images/primeinventorhub.png
:height: 15 em
.. class:: InventorHub
.. only:: not beta
This class is the same as the ``PrimeHub`` class, shown below. Both classes
work on both hubs.
.. note:: Pybricks support for these hubs is currently in development.
Please check back later!
These hubs are completely identical. They use the same Pybricks firmware.
.. only:: beta
.. autoclass:: pybricks.hubs.PrimeHub
:no-members:
.. note:: Pybricks support for these hubs is in beta.
Check the `installation instructions`_ to try it out.
The following functions may change before the final release.
.. rubric:: Using the hub status light
.. class:: InventorHub
.. figure:: ../../main/images/primehub_light_label.png
:width: 22 em
This class is the same as the ``PrimeHub`` class, shown below. Both classes
work on both hubs.
.. automethod:: pybricks.hubs::PrimeHub.light.on
These hubs are completely identical. They use the same Pybricks firmware.
.. automethod:: pybricks.hubs::PrimeHub.light.off
.. autoclass:: pybricks.hubs.PrimeHub
:no-members:
.. automethod:: pybricks.hubs::PrimeHub.light.blink
.. rubric:: Using the hub status light
.. automethod:: pybricks.hubs::PrimeHub.light.animate
.. figure:: ../../main/images/primehub_light_label.png
:width: 22 em
.. rubric:: Using the light matrix display
.. automethod:: pybricks.hubs::PrimeHub.light.on
.. figure:: ../../main/images/primehub_display_label.png
:width: 22 em
.. automethod:: pybricks.hubs::PrimeHub.light.off
.. automethod:: pybricks.hubs::PrimeHub.display.orientation
.. automethod:: pybricks.hubs::PrimeHub.light.blink
.. automethod:: pybricks.hubs::PrimeHub.display.off
.. automethod:: pybricks.hubs::PrimeHub.light.animate
.. automethod:: pybricks.hubs::PrimeHub.display.pixel
.. rubric:: Using the light matrix display
.. automethod:: pybricks.hubs::PrimeHub.display.image
.. figure:: ../../main/images/primehub_display_label.png
:width: 22 em
.. automethod:: pybricks.hubs::PrimeHub.display.animate
.. automethod:: pybricks.hubs::PrimeHub.display.orientation
.. automethod:: pybricks.hubs::PrimeHub.display.number
.. automethod:: pybricks.hubs::PrimeHub.display.off
.. automethod:: pybricks.hubs::PrimeHub.display.char
.. automethod:: pybricks.hubs::PrimeHub.display.pixel
.. automethod:: pybricks.hubs::PrimeHub.display.text
.. automethod:: pybricks.hubs::PrimeHub.display.image
.. rubric:: Using the buttons
.. automethod:: pybricks.hubs::PrimeHub.display.animate
.. figure:: ../../main/images/primehub_buttons_label.png
:width: 22 em
.. automethod:: pybricks.hubs::PrimeHub.display.number
.. automethod:: pybricks.hubs::PrimeHub.buttons.pressed
.. automethod:: pybricks.hubs::PrimeHub.display.char
.. rubric:: Using the IMU
.. automethod:: pybricks.hubs::PrimeHub.display.text
.. automethod:: pybricks.hubs::PrimeHub.imu.up
.. rubric:: Using the buttons
.. automethod:: pybricks.hubs::PrimeHub.imu.tilt
.. figure:: ../../main/images/primehub_buttons_label.png
:width: 22 em
.. automethod:: pybricks.hubs::PrimeHub.imu.acceleration
.. automethod:: pybricks.hubs::PrimeHub.buttons.pressed
.. automethod:: pybricks.hubs::PrimeHub.imu.angular_velocity
.. rubric:: Using the IMU
.. automethod:: pybricks.hubs::PrimeHub.imu.heading
.. automethod:: pybricks.hubs::PrimeHub.imu.up
.. automethod:: pybricks.hubs::PrimeHub.imu.reset_heading
.. automethod:: pybricks.hubs::PrimeHub.imu.tilt
.. rubric:: Using the speaker
.. automethod:: pybricks.hubs::PrimeHub.imu.acceleration
.. automethod:: pybricks.hubs::PrimeHub.speaker.beep
.. automethod:: pybricks.hubs::PrimeHub.imu.angular_velocity
.. automethod:: pybricks.hubs::PrimeHub.speaker.play_notes
.. automethod:: pybricks.hubs::PrimeHub.imu.heading
.. rubric:: Using the battery
.. automethod:: pybricks.hubs::PrimeHub.imu.reset_heading
.. automethod:: pybricks.hubs::PrimeHub.battery.voltage
.. rubric:: Using the speaker
.. automethod:: pybricks.hubs::PrimeHub.battery.current
.. automethod:: pybricks.hubs::PrimeHub.speaker.volume
.. rubric:: System control
.. automethod:: pybricks.hubs::PrimeHub.speaker.beep
.. automethod:: pybricks.hubs::PrimeHub.system.set_stop_button
.. automethod:: pybricks.hubs::PrimeHub.speaker.play_notes
.. automethod:: pybricks.hubs::PrimeHub.system.name
.. rubric:: Using the battery
.. automethod:: pybricks.hubs::PrimeHub.system.shutdown
.. automethod:: pybricks.hubs::PrimeHub.battery.voltage
.. automethod:: pybricks.hubs::PrimeHub.system.reset_reason
.. automethod:: pybricks.hubs::PrimeHub.battery.current
.. note:: The examples below use the ``PrimeHub`` class. The examples work fine
on both hubs because they are the identical. If you prefer, you can
change this to ``InventorHub``.
.. rubric:: Getting the charger status
Status light examples
---------------------
.. automethod:: pybricks.hubs::PrimeHub.charger.connected
Turning the light on and off
****************************
.. automethod:: pybricks.hubs::PrimeHub.charger.current
.. literalinclude::
../../../examples/pup/hub_primehub/light_off.py
.. automethod:: pybricks.hubs::PrimeHub.charger.status
Changing brightness and using custom colors
*******************************************
.. rubric:: System control
.. literalinclude::
../../../examples/pup/hub_primehub/light_hsv.py
.. automethod:: pybricks.hubs::PrimeHub.system.set_stop_button
Making the light blink
**********************
.. automethod:: pybricks.hubs::PrimeHub.system.name
.. literalinclude::
../../../examples/pup/hub_primehub/light_blink.py
.. automethod:: pybricks.hubs::PrimeHub.system.shutdown
Creating light animations
*************************
.. automethod:: pybricks.hubs::PrimeHub.system.reset_reason
.. literalinclude::
../../../examples/pup/hub_primehub/light_animate.py
.. note:: The examples below use the ``PrimeHub`` class. The examples work fine
on both hubs because they are the identical. If you prefer, you can
change this to ``InventorHub``.
Matrix display examples
-----------------------
Status light examples
---------------------
Displaying images
*****************
Turning the light on and off
****************************
.. literalinclude::
../../../examples/pup/hub_primehub/display_image.py
.. literalinclude::
../../../examples/pup/hub_primehub/light_off.py
Displaying numbers
******************
Changing brightness and using custom colors
*******************************************
.. literalinclude::
../../../examples/pup/hub_primehub/display_number.py
.. literalinclude::
../../../examples/pup/hub_primehub/light_hsv.py
Displaying text
***************
Making the light blink
**********************
.. literalinclude::
../../../examples/pup/hub_primehub/display_text.py
.. literalinclude::
../../../examples/pup/hub_primehub/light_blink.py
Displaying individual pixels
****************************
Creating light animations
*************************
.. literalinclude::
../../../examples/pup/hub_primehub/display_pixel.py
.. literalinclude::
../../../examples/pup/hub_primehub/light_animate.py
Changing the display orientation
********************************
Matrix display examples
-----------------------
.. literalinclude::
../../../examples/pup/hub_primehub/display_orientation.py
Displaying images
*****************
.. literalinclude::
../../../examples/pup/hub_primehub/display_orientation_imu.py
.. literalinclude::
../../../examples/pup/hub_primehub/display_image.py
Making your own images
**********************
Displaying numbers
******************
.. literalinclude::
../../../examples/pup/hub_primehub/display_matrix.py
.. literalinclude::
../../../examples/pup/hub_primehub/display_number.py
Combining images to make expressions
************************************
Displaying text
***************
.. literalinclude::
../../../examples/pup/hub_primehub/display_expression.py
.. literalinclude::
../../../examples/pup/hub_primehub/display_text.py
Displaying animations
*********************
Displaying individual pixels
****************************
.. literalinclude::
../../../examples/pup/hub_primehub/display_animate.py
.. literalinclude::
../../../examples/pup/hub_primehub/display_pixel.py
Button examples
---------------
Changing the display orientation
********************************
Detecting button presses
************************
.. literalinclude::
../../../examples/pup/hub_primehub/display_orientation.py
.. literalinclude::
../../../examples/pup/hub_primehub/button_main.py
.. literalinclude::
../../../examples/pup/hub_primehub/display_orientation_imu.py
IMU examples
---------------
Making your own images
**********************
Testing which way is up
********************************
.. literalinclude::
../../../examples/pup/hub_primehub/display_matrix.py
.. literalinclude::
../../../examples/pup/hub_primehub/imu_up.py
Combining images to make expressions
************************************
.. literalinclude::
../../../examples/pup/hub_primehub/display_expression.py
Reading the tilt value
********************************
Displaying animations
*********************
.. literalinclude::
../../../examples/pup/hub_primehub/imu_tilt.py
.. literalinclude::
../../../examples/pup/hub_primehub/display_animate.py
Using a custom hub orientation
**************************************************
Button examples
---------------
.. literalinclude::
../../../examples/pup/hub_primehub/imu_tilt_blast.py
Detecting button presses
************************
Reading acceleration and angular velocity vectors
**************************************************
.. literalinclude::
../../../examples/pup/hub_primehub/button_main.py
.. literalinclude::
../../../examples/pup/hub_primehub/imu_read_vector.py
IMU examples
---------------
Reading acceleration and angular velocity on one axis
*****************************************************
Testing which way is up
********************************
.. literalinclude::
../../../examples/pup/hub_primehub/imu_read_scalar.py
.. literalinclude::
../../../examples/pup/hub_primehub/imu_up.py
System examples
----------------------------------
Changing the stop button combination
*****************************************
Reading the tilt value
********************************
.. literalinclude::
../../../examples/pup/hub_primehub/button_stop.py
.. literalinclude::
../../../examples/pup/hub_primehub/imu_tilt.py
Turning the hub off
*****************************************
Using a custom hub orientation
**************************************************
.. literalinclude::
../../../examples/pup/hub_primehub/imu_tilt_blast.py
Reading acceleration and angular velocity vectors
**************************************************
.. literalinclude::
../../../examples/pup/hub_primehub/imu_read_vector.py
Reading acceleration and angular velocity on one axis
*****************************************************
.. literalinclude::
../../../examples/pup/hub_primehub/imu_read_scalar.py
System examples
----------------------------------
Changing the stop button combination
*****************************************
.. literalinclude::
../../../examples/pup/hub_primehub/button_stop.py
Turning the hub off
*****************************************
.. literalinclude::
../../../examples/pup/hub_primehub/system_shutdown.py
.. _installation instructions: https://pybricks.com/install/
.. literalinclude::
../../../examples/pup/hub_primehub/system_shutdown.py
+6
View File
@@ -82,3 +82,9 @@ Blinking the built-in lights
.. literalinclude::
../../../examples/pup/sensor_color/lights_blink.py
Turning off the lights when the program ends
**********************************************
.. literalinclude::
../../../examples/pup/sensor_color/cleanup.py
+6
View File
@@ -122,6 +122,12 @@ Resetting the measured angle
.. literalinclude::
../../../examples/pup/motor/motor_reset_angle.py
Getting the absolute angle
*******************************************************
.. literalinclude::
../../../examples/pup/motor/motor_absolute.py
Movement examples
-----------------------
+24 -13
View File
@@ -4,6 +4,26 @@ Signals and Units
Many commands allow you to specify arguments in terms of well-known physical
quantities. This page gives an overview of each quantity and its unit.
Numbers
~~~~~~~
.. class:: Number
Numbers can be represented as integers or floating point values:
* Integers (:class:`int <ubuiltins.int>`) are whole numbers
like ``15`` or ``-123``.
* Floating point values (:class:`float <ubuiltins.float>`) are decimal
numbers like ``3.14`` or ``-123.45``.
If you see :class:`Number <Number>` as the argument type, both
:class:`int <ubuiltins.int>` and :class:`float <ubuiltins.float>` may be used.
For example, :func:`wait(15) <pybricks.tools.wait>` and
:func:`wait(15.75) <pybricks.tools.wait>` are both allowed. In most functions,
however, your input value will be truncated to a whole number anyway. In this
example, either command makes the program pause for just 15 milliseconds.
Time
~~~~~~
@@ -56,12 +76,12 @@ use the following table to convert between commonly used units.
.. _acceleration:
rotational acceleration: deg/s/s
rotational acceleration: deg/s²
--------------------------------
Rotational acceleration, or *angular acceleration* describes how fast the
rotational speed changes. This is expressed as the change of the number of
degrees per second, during one second (deg/s/s). This is also commonly written
degrees per second, during one second (deg/s²). This is also commonly written
as :math:`deg/s^2`.
For example, you can adjust the rotational acceleration setting of a ``Motor``
@@ -114,26 +134,17 @@ For example, the speed of a robotic vehicle is expressed in mm/s.
.. _linacceleration:
linear acceleration: mm/s/s
linear acceleration: mm/s²
--------------------------------
Linear acceleration describes how fast the speed changes. This is expressed as
the change of the millimeters per second, during one second (deg/s/s).
the change of the millimeters per second, during one second (mm/s²).
This is also commonly written as :math:`mm/s^2`.
For example, you can adjust the acceleration setting of a
:class:`DriveBase <.robotics.DriveBase>` to change how
smoothly or how quickly it reaches the constant speed set point.
.. _linacceleration_m:
linear acceleration: m/s/s
--------------------------------
As above, but expressed in meters per second squared: :math:`m/s^2`.
This is a more practical unit for large values such as those given by an
accelerometer.
Approximate and relative units
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+6 -2
View File
@@ -15,6 +15,10 @@ if "%TAG%" == "" (
set TAG=main
)
if "%BETA%" == "1" (
set BETATAG=-tbeta
)
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
@@ -30,11 +34,11 @@ if errorlevel 9009 (
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% -t %TAG%
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% -t %TAG% %BETATAG%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% -t %TAG%
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% -t %TAG% %BETATAG%
:end
popd
+5 -5
View File
@@ -9,17 +9,17 @@
from pybricks.messaging import BluetoothMailboxClient, TextMailbox
# This is the name of the remote EV3 or PC we are connecting to.
SERVER = 'ev3dev'
SERVER = "ev3dev"
client = BluetoothMailboxClient()
mbox = TextMailbox('greeting', client)
mbox = TextMailbox("greeting", client)
print('establishing connection...')
print("establishing connection...")
client.connect(SERVER)
print('connected!')
print("connected!")
# In this program, the client sends the first message and then waits for the
# server to reply.
mbox.send('hello!')
mbox.send("hello!")
mbox.wait()
print(mbox.read())
+5 -5
View File
@@ -17,17 +17,17 @@ from pybricks.messaging import BluetoothMailboxClient, TextMailbox
# visible on the EV3. You can skip pairing if you already know the EV3 address.
# This is the address of the server EV3 we are connecting to.
SERVER = 'CC:78:AB:D8:4E:F6'
SERVER = "CC:78:AB:D8:4E:F6"
client = BluetoothMailboxClient()
mbox = TextMailbox('greeting', client)
mbox = TextMailbox("greeting", client)
print('establishing connection...')
print("establishing connection...")
client.connect(SERVER)
print('connected!')
print("connected!")
# In this program, the client sends the first message and then waits for the
# server to reply.
mbox.send('hello!')
mbox.send("hello!")
mbox.wait()
print(mbox.read())
@@ -18,17 +18,17 @@ BDADDR_ANY = ""
def str2ba(string, ba):
"""Convert string to Bluetooth address"""
for i, v in enumerate(string.split(':')):
ba.b[5-i] = int(v, 16)
for i, v in enumerate(string.split(":")):
ba.b[5 - i] = int(v, 16)
def ba2str(ba):
"""Convert Bluetooth address to string"""
string = []
for b in ba.b:
string.append('{:02X}'.format(b))
string.append("{:02X}".format(b))
string.reverse()
return ':'.join(string).upper()
return ":".join(string).upper()
class RFCOMMServer:
@@ -37,6 +37,7 @@ class RFCOMMServer:
This is based on the ``socketserver.SocketServer`` class in the Python
standard library.
"""
request_queue_size = 1
def __init__(self, server_address, RequestHandlerClass):
@@ -88,6 +89,7 @@ class StreamRequestHandler:
This is based on ``socketserver.StreamRequestHandler`` from the Python
standard library.
"""
def __init__(self, request, client_address, server):
self.request = request
self.client_address = client_address
@@ -113,6 +115,7 @@ class ThreadingRFCOMMServer(ThreadingMixIn, RFCOMMServer):
"""Version of :class:`RFCOMMServer` that handles connections in a new
thread.
"""
pass
+33 -19
View File
@@ -5,8 +5,12 @@ from _thread import allocate_lock
from errno import ECONNRESET
from struct import pack, unpack
from .bluetooth import (BDADDR_ANY, ThreadingRFCOMMServer,
ThreadingRFCOMMClient, StreamRequestHandler)
from .bluetooth import (
BDADDR_ANY,
ThreadingRFCOMMServer,
ThreadingRFCOMMClient,
StreamRequestHandler,
)
def resolve(brick):
@@ -99,7 +103,7 @@ class LogicMailbox(Mailbox):
"""
def encode(self, value):
return b'\x01' if value else b'\x00'
return b"\x01" if value else b"\x00"
def decode(self, payload):
return bool(payload[0])
@@ -113,10 +117,10 @@ class NumericMailbox(Mailbox):
"""
def encode(self, value):
return pack('<f', value)
return pack("<f", value)
def decode(self, payload):
return unpack('<f', payload)[0]
return unpack("<f", payload)[0]
class TextMailbox(Mailbox):
@@ -127,10 +131,10 @@ class TextMailbox(Mailbox):
"""
def encode(self, value):
return ('{}\0'.format(value)).encode('utf-8')
return ("{}\0".format(value)).encode("utf-8")
def decode(self, payload):
return payload.decode().strip('\0')
return payload.decode().strip("\0")
# EV3 standard firmware is hard-coded to use channel 1
@@ -155,16 +159,16 @@ class MailboxHandler(StreamRequestHandler):
if ex.args[0] == ECONNRESET:
break
raise
size, = unpack('<H', buf)
(size,) = unpack("<H", buf)
buf = self.rfile.recv(size)
msg_count, cmd_type, cmd, name_size = unpack('<HBBB', buf[0:5])
msg_count, cmd_type, cmd, name_size = unpack("<HBBB", buf[0:5])
if cmd_type != SYSTEM_COMMAND_NO_REPLY:
raise ValueError('Bad message type')
raise ValueError("Bad message type")
if cmd != WRITEMAILBOX:
raise ValueError('Bad command')
mbox = buf[5:5+name_size].decode().strip('\0')
data_size, = unpack('<H', buf[5+name_size:7+name_size])
data = buf[7+name_size:7+name_size+data_size]
raise ValueError("Bad command")
mbox = buf[5 : 5 + name_size].decode().strip("\0")
(data_size,) = unpack("<H", buf[5 + name_size : 7 + name_size])
data = buf[7 + name_size : 7 + name_size + data_size]
with self.server._lock:
self.server._mailboxes[mbox] = data
@@ -216,9 +220,18 @@ class MailboxHandlerMixIn:
mbox_len = len(mbox) + 1
payload_len = len(payload)
send_len = 7 + mbox_len + payload_len
fmt = '<HHBBB{}sH{}s'.format(mbox_len, payload_len)
data = pack(fmt, send_len, 1, SYSTEM_COMMAND_NO_REPLY, WRITEMAILBOX,
mbox_len, mbox.encode('utf-8'), payload_len, payload)
fmt = "<HHBBB{}sH{}s".format(mbox_len, payload_len)
data = pack(
fmt,
send_len,
1,
SYSTEM_COMMAND_NO_REPLY,
WRITEMAILBOX,
mbox_len,
mbox.encode("utf-8"),
payload_len,
payload,
)
with self._lock:
if brick is None:
for client in self._clients.values():
@@ -255,7 +268,8 @@ class BluetoothMailboxServer(MailboxHandlerMixIn, ThreadingRFCOMMServer):
"""
super().__init__()
super(ThreadingRFCOMMServer, self).__init__(
(BDADDR_ANY, EV3_RFCOMM_CHANNEL), MailboxHandler)
(BDADDR_ANY, EV3_RFCOMM_CHANNEL), MailboxHandler
)
def wait_for_connection(self, count=1):
"""Waits for a :class:`BluetoothMailboxClient` on a remote device to
@@ -326,7 +340,7 @@ class BluetoothMailboxClient(MailboxHandlerMixIn):
raise ValueError('no paired devices matching "{}"'.format(brick))
client = MailboxRFCOMMClient(self, addr)
if self._clients.setdefault(addr, client) is not client:
raise ValueError('connection with this address already exists')
raise ValueError("connection with this address already exists")
try:
client.handle_request()
except Exception:
@@ -1,15 +1,9 @@
from uctypes import addressof, sizeof, struct
from usocket import socket, SOCK_STREAM
from _thread import start_new_thread
from pybricks.bluetooth import (
str2ba,
sockaddr_rc,
AF_BLUETOOTH,
BTPROTO_RFCOMM
)
from pybricks.bluetooth import str2ba, sockaddr_rc, AF_BLUETOOTH, BTPROTO_RFCOMM
from pybricks.tools import wait, StopWatch
@@ -25,7 +19,7 @@ def get_bluetooth_rfcomm_socket(address, channel):
return sock
class SpikePrimeStreamReader():
class SpikePrimeStreamReader:
def __init__(self, address):
try:
@@ -56,8 +50,8 @@ class SpikePrimeStreamReader():
break
try:
data = eval(raw)
if data['m'] == 0:
self._values = data['p']
if data["m"] == 0:
self._values = data["p"]
except (SyntaxError, KeyError):
pass
@@ -65,8 +59,8 @@ class SpikePrimeStreamReader():
return self._values
def device(self, port):
if 'A' <= port <= 'F':
return self.values()[ord(port)-ord('A')][1]
if "A" <= port <= "F":
return self.values()[ord(port) - ord("A")][1]
else:
raise ValueError
+1 -1
View File
@@ -9,7 +9,7 @@ ev3 = EV3Brick()
ev3.speaker.beep()
# Create the connection. See README.md to find the address for your SPIKE hub.
spike = SpikePrimeStreamReader('F4:84:4C:AA:C8:A4')
spike = SpikePrimeStreamReader("F4:84:4C:AA:C8:A4")
# Now you can simply read values!
for i in range(100):
+2 -2
View File
@@ -12,7 +12,7 @@ ev3 = EV3Brick()
ev3.speaker.beep()
# Create the connection. See README.md to find the address for your SPIKE hub.
spike = SpikePrimeStreamReader('F4:84:4C:AA:C8:A4')
spike = SpikePrimeStreamReader("F4:84:4C:AA:C8:A4")
# Initialize the motors and drive base
left_motor = Motor(Port.B)
@@ -24,5 +24,5 @@ while True:
yaw, pitch, roll = spike.orientation()
# Set speed and turn rate based on orientation
robot.drive(-pitch*6, roll*2)
robot.drive(-pitch * 6, roll * 2)
wait(20)
+4 -4
View File
@@ -9,15 +9,15 @@
from pybricks.messaging import BluetoothMailboxServer, TextMailbox
server = BluetoothMailboxServer()
mbox = TextMailbox('greeting', server)
mbox = TextMailbox("greeting", server)
# The server must be started before the client!
print('waiting for connection...')
print("waiting for connection...")
server.wait_for_connection()
print('connected!')
print("connected!")
# In this program, the server waits for the client to send the first message
# and then sends a reply.
mbox.wait()
print(mbox.read())
mbox.send('hello to you!')
mbox.send("hello to you!")
+1 -1
View File
@@ -8,7 +8,7 @@ def wait_for_button(ev3):
"""
# Show a picture of the buttons on the screen.
ev3.screen.load_image('buttons.png')
ev3.screen.load_image("buttons.png")
# Tip: add text or icons to the image to help you
# remember what each button will do in your program.
+1 -1
View File
@@ -8,7 +8,7 @@ from pybricks.tools import DataLog, StopWatch, wait
# log_2020_02_13_10_07_44_431260.csv
# * You can optionally specify the titles of your data columns. For example,
# if you want to record the motor angles at a given time, you could do:
data = DataLog('time', 'angle')
data = DataLog("time", "angle")
# Initialize a motor and make it move
wheel = Motor(Port.B)
+4 -4
View File
@@ -3,13 +3,13 @@ from pybricks.parameters import Color
from pybricks.tools import DataLog
# Create a data log file called my_file.txt
data = DataLog('time', 'angle', name='my_file', timestamp=False, extension='txt')
data = DataLog("time", "angle", name="my_file", timestamp=False, extension="txt")
# The log method uses the print() method to add a line of text.
# So, you can do much more than saving numbers. For example:
data.log('Temperature', 25)
data.log('Sunday', 'Monday', 'Tuesday')
data.log({'Kiwi': Color.GREEN}, {'Banana': Color.YELLOW})
data.log("Temperature", 25)
data.log("Sunday", "Monday", "Tuesday")
data.log({"Kiwi": Color.GREEN}, {"Banana": Color.YELLOW})
# You can upload the file to your computer, but you can also print the data:
print(data)
+4 -4
View File
@@ -13,22 +13,22 @@ class MySensor(Ev3devSensor):
super().__init__(port)
# Get the sysfs path.
self.path = '/sys/class/lego-sensor/sensor' + str(self.sensor_index)
self.path = "/sys/class/lego-sensor/sensor" + str(self.sensor_index)
def get_modes(self):
"""Get a list of mode strings so we don't have to look them up."""
# The path of the modes file.
modes_path = self.path + '/modes'
modes_path = self.path + "/modes"
# Open the modes file.
with open(modes_path, 'r') as m:
with open(modes_path, "r") as m:
# Read the contents.
contents = m.read()
# Strip the newline symbol, and split at every space symbol.
return contents.strip().split(' ')
return contents.strip().split(" ")
# Initialize the sensor
+2 -2
View File
@@ -10,10 +10,10 @@ sensor = Ev3devSensor(Port.S3)
while True:
# Read the raw RGB values
r, g, b = sensor.read('RGB-RAW')
r, g, b = sensor.read("RGB-RAW")
# Print results
print('R: {0}\t G: {1}\t B: {2}'.format(r, g, b))
print("R: {0}\t G: {1}\t B: {2}".format(r, g, b))
# Wait
wait(200)
+3 -3
View File
@@ -10,7 +10,7 @@ ev3 = EV3Brick()
device = I2CDevice(Port.S2, 0xD2 >> 1)
# Recommended for reading
result, = device.read(reg=0x0F, length=1)
(result,) = device.read(reg=0x0F, length=1)
# Read 1 byte from no particular register:
device.read(reg=None, length=1)
@@ -23,10 +23,10 @@ device.read(reg=None, length=0)
# can choose to skip the register or data as follows:
# Recommended for writing:
device.write(reg=0x22, data=b'\x08')
device.write(reg=0x22, data=b"\x08")
# Write 1 byte to no particular register:
device.write(reg=None, data=b'\x08')
device.write(reg=None, data=b"\x08")
# Write 0 bytes to a particular register:
device.write(reg=0x08, data=None)
+3 -2
View File
@@ -21,7 +21,7 @@ in_file = open(infile_path, "rb")
# Define the format the event data will be read.
# https://docs.python.org/3/library/struct.html#format-characters
FORMAT = 'llHHi'
FORMAT = "llHHi"
EVENT_SIZE = struct.calcsize(FORMAT)
event = in_file.read(EVENT_SIZE)
@@ -30,10 +30,11 @@ event = in_file.read(EVENT_SIZE)
# numbers (-100 to 100)
def scale(val, src, dst):
result = (float(val - src[0]) / (src[1] - src[0]))
result = float(val - src[0]) / (src[1] - src[0])
result = result * (dst[1] - dst[0]) + dst[0]
return result
# Create a loop to react to events
# This loop reacte 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
+1 -1
View File
@@ -7,7 +7,7 @@ from pybricks.tools import wait
class RCXTouchSensor(AnalogSensor):
def pressed(self):
return self.resistance() < 50*1000
return self.resistance() < 50 * 1000
ev3 = EV3Brick()
+41 -13
View File
@@ -15,12 +15,24 @@ ev3 = EV3Brick()
# SPLIT SCREEN ################################################################
# Make a sub-image for the left half of the screen
left = Image(ev3.screen, sub=True, x1=0, y1=0,
x2=ev3.screen.width // 2 - 1, y2=ev3.screen.height - 1)
left = Image(
ev3.screen,
sub=True,
x1=0,
y1=0,
x2=ev3.screen.width // 2 - 1,
y2=ev3.screen.height - 1,
)
# Make a sub-image for the right half of the screen
right = Image(ev3.screen, sub=True, x1=ev3.screen.width // 2, y1=0,
x2=ev3.screen.width - 1, y2=ev3.screen.height - 1)
right = Image(
ev3.screen,
sub=True,
x1=ev3.screen.width // 2,
y1=0,
x2=ev3.screen.width - 1,
y2=ev3.screen.height - 1,
)
# Use a monospaced font so that text is vertically aligned when we print
right.set_font(Font(size=8, monospace=True))
@@ -53,7 +65,7 @@ for t in range(200):
# Print every 10th value on right side
if t % 10 == 0:
right.print('{:10.2f}{:10.2f}'.format(x1, y1))
right.print("{:10.2f}{:10.2f}".format(x1, y1))
wait(100)
@@ -64,8 +76,8 @@ for t in range(200):
buf = Image(ev3.screen)
# Load images from file
bg = Image('background.png')
sprite = Image('sprite.png')
bg = Image("background.png")
sprite = Image("sprite.png")
# Number of cells in each sprite animation
NUM_CELLS = 8
@@ -75,12 +87,28 @@ CELL_WIDTH, CELL_HEIGHT = 75, 100
# Get sub-images for each individual cell
# This is more efficient that loading individual images
walk_right = [Image(sprite, sub=True, x1=x * CELL_WIDTH, y1=0,
x2=(x + 1) * CELL_WIDTH - 1, y2=CELL_HEIGHT - 1)
for x in range(NUM_CELLS)]
walk_left = [Image(sprite, sub=True, x1=x * CELL_WIDTH, y1=CELL_HEIGHT,
x2=(x + 1) * CELL_WIDTH - 1, y2=2 * CELL_HEIGHT - 1)
for x in range(NUM_CELLS)]
walk_right = [
Image(
sprite,
sub=True,
x1=x * CELL_WIDTH,
y1=0,
x2=(x + 1) * CELL_WIDTH - 1,
y2=CELL_HEIGHT - 1,
)
for x in range(NUM_CELLS)
]
walk_left = [
Image(
sprite,
sub=True,
x1=x * CELL_WIDTH,
y1=CELL_HEIGHT,
x2=(x + 1) * CELL_WIDTH - 1,
y2=2 * CELL_HEIGHT - 1,
)
for x in range(NUM_CELLS)
]
# Walk from left to right
+5 -5
View File
@@ -8,7 +8,7 @@ from pybricks.media.ev3dev import Font
# load them once at the beginning of the program like this:
tiny_font = Font(size=6)
big_font = Font(size=24, bold=True)
chinese_font = Font(size=24, lang='zh-cn')
chinese_font = Font(size=24, lang="zh-cn")
# Initialize the EV3
@@ -16,19 +16,19 @@ ev3 = EV3Brick()
# Say hello
ev3.screen.print('Hello!')
ev3.screen.print("Hello!")
# Say tiny hello
ev3.screen.set_font(tiny_font)
ev3.screen.print('hello')
ev3.screen.print("hello")
# Say big hello
ev3.screen.set_font(big_font)
ev3.screen.print('HELLO')
ev3.screen.print("HELLO")
# Say Chinese hello
ev3.screen.set_font(chinese_font)
ev3.screen.print('你好')
ev3.screen.print("你好")
# Wait some time to look at the screen
wait(5000)
+20 -6
View File
@@ -26,9 +26,23 @@ wait(1000)
# PLAY NOTES ##################################################################
# Twinkle, Twinkle Little Star
A = ['C4/4', 'C4/4', 'G4/4', 'G4/4', 'A4/4', 'A4/4', 'G4/2',
'F4/4', 'F4/4', 'E4/4', 'E4/4', 'D4/4', 'D4/4', 'C4/2']
B = ['G4/4', 'G4/4', 'F4/4', 'F4/4', 'E4/4', 'E4/4', 'D4/2'] * 2
A = [
"C4/4",
"C4/4",
"G4/4",
"G4/4",
"A4/4",
"A4/4",
"G4/2",
"F4/4",
"F4/4",
"E4/4",
"E4/4",
"D4/4",
"D4/4",
"C4/2",
]
B = ["G4/4", "G4/4", "F4/4", "F4/4", "E4/4", "E4/4", "D4/2"] * 2
TWINKLE = A + B + A
ev3.speaker.play_notes(TWINKLE)
@@ -46,10 +60,10 @@ wait(1000)
# TEXT TO SPEECH ##############################################################
# Say something in English
ev3.speaker.say('I am am E V 3. Pleased to meet you.')
ev3.speaker.say("I am am E V 3. Pleased to meet you.")
# Say something in Danish + female
ev3.speaker.set_speech_options(voice='da+f5')
ev3.speaker.say('Leg godt!')
ev3.speaker.set_speech_options(voice="da+f5")
ev3.speaker.say("Leg godt!")
wait(1000)
+1 -1
View File
@@ -11,7 +11,7 @@ ev3 = EV3Brick()
ser = UARTDevice(Port.S2, baudrate=115200)
# Write some data
ser.write(b'\r\nHello, world!\r\n')
ser.write(b"\r\nHello, world!\r\n")
# Play a sound while we wait for some data
for i in range(3):
@@ -10,8 +10,8 @@ def convert_raw_to_temperature(voltage):
# Convert the raw voltage to the NTC resistance
# according to the Vernier Adapter EV3 block.
counts = voltage/5000*4096
ntc = 15000*(counts)/(4130-counts)
counts = voltage / 5000 * 4096
ntc = 15000 * (counts) / (4130 - counts)
# Handle log(0) safely: make sure that ntc value is positive.
if ntc <= 0:
@@ -21,7 +21,7 @@ def convert_raw_to_temperature(voltage):
K0 = 1.02119e-3
K1 = 2.22468e-4
K2 = 1.33342e-7
return 1/(K0 + K1*log(ntc) + K2*log(ntc)**3)
return 1 / (K0 + K1 * log(ntc) + K2 * log(ntc) ** 3)
# Initialize the adapter on port 1
+2 -3
View File
@@ -12,12 +12,11 @@ hub.light.animate([Color.RED, Color.GREEN, Color.NONE], interval=500)
wait(10000)
# Make the color RED grow faint and bright using a sine pattern.
hub.light.animate(
[Color.RED * (0.5 * sin(i / 15 * pi) + 0.5) for i in range(30)], 40)
hub.light.animate([Color.RED * (0.5 * sin(i / 15 * pi) + 0.5) for i in range(30)], 40)
wait(10000)
# Cycle through a rainbow of colors.
hub.light.animate([Color(h=i*8) for i in range(45)], interval=40)
hub.light.animate([Color(h=i * 8) for i in range(45)], interval=40)
wait(10000)
+1 -1
View File
@@ -12,7 +12,7 @@ hub.light.off()
brightness = list(range(0, 100, 4)) + list(range(100, 0, -4))
# Create an animation of the heart icon with changing brightness.
hub.display.animate([Icon.HEART * i/100 for i in brightness], 30)
hub.display.animate([Icon.HEART * i / 100 for i in brightness], 30)
# The animation repeats in the background. Here we just wait.
while True:
@@ -12,15 +12,15 @@ while True:
# Start with random left brow: up or down.
if randint(0, 100) < 70:
brows = Icon.EYE_LEFT_BROW*0.5
brows = Icon.EYE_LEFT_BROW * 0.5
else:
brows = Icon.EYE_LEFT_BROW_UP*0.5
brows = Icon.EYE_LEFT_BROW_UP * 0.5
# Add random right brow: up or down.
if randint(0, 100) < 70:
brows += Icon.EYE_RIGHT_BROW*0.5
brows += Icon.EYE_RIGHT_BROW * 0.5
else:
brows += Icon.EYE_RIGHT_BROW_UP*0.5
brows += Icon.EYE_RIGHT_BROW_UP * 0.5
for i in range(3):
# Display eyes open plus the random brows.
@@ -28,5 +28,7 @@ while True:
wait(2000)
# Display eyes blinked plus the random brows.
hub.display.image(Icon.EYE_LEFT_BLINK*0.7 + Icon.EYE_RIGHT_BLINK*0.7 + brows)
hub.display.image(
Icon.EYE_LEFT_BLINK * 0.7 + Icon.EYE_RIGHT_BLINK * 0.7 + brows
)
wait(200)
+9 -7
View File
@@ -6,13 +6,15 @@ from pybricks.geometry import Matrix
hub = PrimeHub()
# Make a square that is bright on the outside and faint in the middle.
SQUARE = Matrix([
[100, 100, 100, 100, 100],
[100, 50, 50, 50, 100],
[100, 50, 0, 50, 100],
[100, 50, 50, 50, 100],
[100, 100, 100, 100, 100],
])
SQUARE = Matrix(
[
[100, 100, 100, 100, 100],
[100, 50, 50, 50, 100],
[100, 50, 0, 50, 100],
[100, 50, 50, 50, 100],
[100, 100, 100, 100, 100],
]
)
# Display the square.
hub.display.image(SQUARE)
+2 -2
View File
@@ -5,8 +5,8 @@ from pybricks.tools import wait
hub = PrimeHub()
# Display the letter A for two seconds.
hub.display.char('A')
hub.display.char("A")
wait(2000)
# Display text, one letter at a time.
hub.display.text('Hello, world!')
hub.display.text("Hello, world!")
+2 -2
View File
@@ -4,8 +4,8 @@ from pybricks.tools import wait
# Initialize the hub.
hub = PrimeHub()
# Get the acceleration vector.
print(hub.imu.acceleration())
# Get the acceleration vector in g's.
print(hub.imu.acceleration() / 9810)
# Get the angular velocity vector.
print(hub.imu.angular_velocity())
+2 -3
View File
@@ -12,12 +12,11 @@ hub.light.animate([Color.RED, Color.GREEN, Color.NONE], interval=500)
wait(10000)
# Make the color RED grow faint and bright using a sine pattern.
hub.light.animate(
[Color.RED * (0.5 * sin(i / 15 * pi) + 0.5) for i in range(30)], 40)
hub.light.animate([Color.RED * (0.5 * sin(i / 15 * pi) + 0.5) for i in range(30)], 40)
wait(10000)
# Cycle through a rainbow of colors.
hub.light.animate([Color(h=i*8) for i in range(45)], interval=40)
hub.light.animate([Color(h=i * 8) for i in range(45)], interval=40)
wait(10000)
+2 -2
View File
@@ -5,8 +5,8 @@ from pybricks.tools import wait
# Initialize the hub.
hub = ExampleHub()
# Get the acceleration vector.
print(hub.imu.acceleration())
# Get the acceleration vector in g's.
print(hub.imu.acceleration() / 9810)
# Get the angular velocity vector.
print(hub.imu.angular_velocity())
+2 -3
View File
@@ -13,12 +13,11 @@ hub.light.animate([Color.RED, Color.GREEN, Color.NONE], interval=500)
wait(10000)
# Make the color RED grow faint and bright using a sine pattern.
hub.light.animate(
[Color.RED * (0.5 * sin(i / 15 * pi) + 0.5) for i in range(30)], 40)
hub.light.animate([Color.RED * (0.5 * sin(i / 15 * pi) + 0.5) for i in range(30)], 40)
wait(10000)
# Cycle through a rainbow of colors.
hub.light.animate([Color(h=i*8) for i in range(45)], interval=40)
hub.light.animate([Color(h=i * 8) for i in range(45)], interval=40)
wait(10000)
@@ -3,10 +3,10 @@
import os
# Get list of scripts to be parsed
script_names = [f for f in os.listdir('.') if f != 'make_shared_examples.py']
script_names = [f for f in os.listdir(".") if f != "make_shared_examples.py"]
# Go through all template scripts
for script in (open(f, 'r') for f in script_names):
for script in (open(f, "r") for f in script_names):
# First line contains hub info
hubs = script.readline().strip().split()[3:]
@@ -15,17 +15,17 @@ for script in (open(f, 'r') for f in script_names):
for hub in hubs:
# Determine path to the hub
hub_path = os.path.join('..', 'hub_' + hub.lower())
hub_path = os.path.join("..", "hub_" + hub.lower())
# Reset source script
script.seek(0)
script.readline()
# Open destination script:
with open(os.path.join(hub_path, script.name), 'w') as dest_file:
with open(os.path.join(hub_path, script.name), "w") as dest_file:
# Read script line by line
for line in script.readlines():
# Replace hub name if present
dest_file.writelines(line.replace('ExampleHub', hub))
dest_file.writelines(line.replace("ExampleHub", hub))
@@ -4,8 +4,8 @@ from pybricks.tools import wait
# Initialize the hub.
hub = TechnicHub()
# Get the acceleration vector.
print(hub.imu.acceleration())
# Get the acceleration vector in g's.
print(hub.imu.acceleration() / 9810)
# Get the angular velocity vector.
print(hub.imu.angular_velocity())
+2 -3
View File
@@ -12,12 +12,11 @@ hub.light.animate([Color.RED, Color.GREEN, Color.NONE], interval=500)
wait(10000)
# Make the color RED grow faint and bright using a sine pattern.
hub.light.animate(
[Color.RED * (0.5 * sin(i / 15 * pi) + 0.5) for i in range(30)], 40)
hub.light.animate([Color.RED * (0.5 * sin(i / 15 * pi) + 0.5) for i in range(30)], 40)
wait(10000)
# Cycle through a rainbow of colors.
hub.light.animate([Color(h=i*8) for i in range(45)], interval=40)
hub.light.animate([Color(h=i * 8) for i in range(45)], interval=40)
wait(10000)
@@ -51,7 +51,7 @@ for port in ports:
raise
# Get the device id
id = device.info()['id']
id = device.info()["id"]
# Look up the name.
try:
+2 -2
View File
@@ -15,10 +15,10 @@ MAX = 100
# Make the brightness fade in and out.
while True:
# Get phase of the cosine.
phase = watch.time()/PERIOD*2*pi
phase = watch.time() / PERIOD * 2 * pi
# Evaluate the brightness.
brightness = (0.5 - 0.5*cos(phase))*MAX
brightness = (0.5 - 0.5 * cos(phase)) * MAX
# Set light brightness and wait a bit.
light.on(brightness)
+21
View File
@@ -0,0 +1,21 @@
from pybricks.pupdevices import Motor
from pybricks.parameters import Port
from pybricks.tools import wait
# Initialize a motor on port A.
example_motor = Motor(Port.A)
while True:
# Get the default angle value.
angle = example_motor.angle()
# Get the angle between 0 and 360.
absolute_angle = example_motor.angle() % 360
# Get the angle between -180 and 179.
wrapped_angle = (example_motor.angle() + 180) % 360 - 180
# Print the results.
print(angle, absolute_angle, wrapped_angle)
wait(100)
+1 -1
View File
@@ -7,6 +7,6 @@ my_remote = Remote()
print(my_remote.name())
# Choose a new name.
my_remote.name('truck2')
my_remote.name("truck2")
print("Done!")
+1 -1
View File
@@ -2,7 +2,7 @@ from pybricks.pupdevices import Remote
from pybricks.tools import wait
# Connect to a remote called truck2.
truck_remote = Remote('truck2', timeout=None)
truck_remote = Remote("truck2", timeout=None)
print("Connected!")
+23
View File
@@ -0,0 +1,23 @@
from pybricks.parameters import Port
from pybricks.pupdevices import ColorSensor
from pybricks.tools import wait
# Initialize the sensor.
sensor = ColorSensor(Port.A)
def main():
# Run the main code.
while True:
print(sensor.color())
wait(500)
# Wrap the main code in try/finally so that the cleanup code always runs
# when the program ends, even if an exception was raised.
try:
main()
finally:
# The cleanup code goes here.
print("Cleaning up.")
sensor.lights.off()
+2 -2
View File
@@ -15,12 +15,12 @@ PERIOD = 3000
while True:
# The phase is where we are in the unit circle now.
phase = watch.time()/PERIOD*2*pi
phase = watch.time() / PERIOD * 2 * pi
# Each light follows a sine wave with a mean of 50, with an amplitude of 50.
# We offset this sine wave by 90 degrees for each light, so that all the
# lights do something different.
brightness = [sin(phase + offset*pi/2) * 50 + 50 for offset in range(4)]
brightness = [sin(phase + offset * pi / 2) * 50 + 50 for offset in range(4)]
# Set the brightness values for all lights.
eyes.lights.on(brightness)
Generated
+238 -238
View File
@@ -6,54 +6,46 @@ category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "appdirs"
version = "1.4.4"
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "babel"
version = "2.9.1"
version = "2.10.1"
description = "Internationalization utilities"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
python-versions = ">=3.6"
[package.dependencies]
pytz = ">=2015.7"
[[package]]
name = "black"
version = "20.8b1"
version = "22.3.0"
description = "The uncompromising code formatter."
category = "dev"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.6.2"
[package.dependencies]
appdirs = "*"
click = ">=7.1.2"
click = ">=8.0.0"
mypy-extensions = ">=0.4.3"
pathspec = ">=0.6,<1"
regex = ">=2020.1.8"
toml = ">=0.10.1"
typed-ast = ">=1.4.0"
typing-extensions = ">=3.7.4"
pathspec = ">=0.9.0"
platformdirs = ">=2"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
[package.extras]
colorama = ["colorama (>=0.4.3)"]
d = ["aiohttp (>=3.3.2)", "aiohttp-cors"]
d = ["aiohttp (>=3.7.4)"]
jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "certifi"
version = "2021.5.30"
version = "2022.5.18.1"
description = "Python package for providing Mozilla's CA Bundle."
category = "dev"
optional = false
python-versions = "*"
python-versions = ">=3.6"
[[package]]
name = "chardet"
@@ -65,7 +57,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "charset-normalizer"
version = "2.0.4"
version = "2.0.12"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "dev"
optional = false
@@ -76,11 +68,11 @@ unicode_backport = ["unicodedata2"]
[[package]]
name = "click"
version = "8.0.1"
version = "8.1.3"
description = "Composable command line interface toolkit"
category = "dev"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.7"
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
@@ -111,7 +103,7 @@ stevedore = "*"
[[package]]
name = "docutils"
version = "0.16"
version = "0.17.1"
description = "Docutils -- Python Documentation Utilities"
category = "dev"
optional = false
@@ -119,20 +111,20 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "flake8"
version = "3.9.2"
version = "4.0.1"
description = "the modular source code checker: pep8 pyflakes and co"
category = "dev"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
python-versions = ">=3.6"
[package.dependencies]
mccabe = ">=0.6.0,<0.7.0"
pycodestyle = ">=2.7.0,<2.8.0"
pyflakes = ">=2.3.0,<2.4.0"
pycodestyle = ">=2.8.0,<2.9.0"
pyflakes = ">=2.4.0,<2.5.0"
[[package]]
name = "idna"
version = "3.2"
version = "3.3"
description = "Internationalized Domain Names in Applications (IDNA)"
category = "dev"
optional = false
@@ -140,19 +132,35 @@ python-versions = ">=3.5"
[[package]]
name = "imagesize"
version = "1.2.0"
version = "1.3.0"
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.*"
[[package]]
name = "importlib-metadata"
version = "4.11.4"
description = "Read metadata from Python packages"
category = "dev"
optional = false
python-versions = ">=3.7"
[package.dependencies]
zipp = ">=0.5"
[package.extras]
docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
perf = ["ipython"]
testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"]
[[package]]
name = "jinja2"
version = "3.0.1"
version = "3.1.2"
description = "A very fast and expressive template engine."
category = "dev"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.7"
[package.dependencies]
MarkupSafe = ">=2.0"
@@ -162,11 +170,11 @@ i18n = ["Babel (>=2.7)"]
[[package]]
name = "markupsafe"
version = "2.0.1"
version = "2.1.1"
description = "Safely add untrusted strings to HTML/XML markup."
category = "dev"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.7"
[[package]]
name = "mccabe"
@@ -186,14 +194,14 @@ python-versions = "*"
[[package]]
name = "packaging"
version = "21.0"
version = "21.3"
description = "Core utilities for Python packages"
category = "dev"
optional = false
python-versions = ">=3.6"
[package.dependencies]
pyparsing = ">=2.0.2"
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
[[package]]
name = "pathspec"
@@ -205,23 +213,35 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
[[package]]
name = "pbr"
version = "5.6.0"
version = "5.9.0"
description = "Python Build Reasonableness"
category = "dev"
optional = false
python-versions = ">=2.6"
[[package]]
name = "platformdirs"
version = "2.5.2"
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev"
optional = false
python-versions = ">=3.7"
[package.extras]
docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"]
test = ["appdirs (1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"]
[[package]]
name = "pycodestyle"
version = "2.7.0"
version = "2.8.0"
description = "Python style guide checker"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "pyflakes"
version = "2.3.1"
version = "2.4.0"
description = "passive checker of Python programs"
category = "dev"
optional = false
@@ -229,39 +249,34 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "pygments"
version = "2.9.0"
version = "2.12.0"
description = "Pygments is a syntax highlighting package written in Python."
category = "dev"
optional = false
python-versions = ">=3.5"
python-versions = ">=3.6"
[[package]]
name = "pyparsing"
version = "2.4.7"
description = "Python parsing module"
version = "3.0.9"
description = "pyparsing module - Classes and methods to define and execute parsing grammars"
category = "dev"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
python-versions = ">=3.6.8"
[package.extras]
diagrams = ["railroad-diagrams", "jinja2"]
[[package]]
name = "pytz"
version = "2021.1"
version = "2022.1"
description = "World timezone definitions, modern and historical"
category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "regex"
version = "2021.8.3"
description = "Alternative regular expression module, to replace re."
category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "requests"
version = "2.26.0"
version = "2.27.1"
description = "Python HTTP for Humans."
category = "dev"
optional = false
@@ -279,7 +294,7 @@ use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"]
[[package]]
name = "restructuredtext-lint"
version = "1.3.2"
version = "1.4.0"
description = "reStructuredText linter"
category = "dev"
optional = false
@@ -298,15 +313,15 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
[[package]]
name = "snowballstemmer"
version = "2.1.0"
version = "2.2.0"
description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "sphinx"
version = "4.1.2"
name = "Sphinx"
version = "5.1.0.dev20220527.dev-20220527"
description = "Python documentation generator"
category = "dev"
optional = false
@@ -316,8 +331,9 @@ python-versions = ">=3.6"
alabaster = ">=0.7,<0.8"
babel = ">=1.3"
colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""}
docutils = ">=0.14,<0.18"
docutils = ">=0.14,<0.19"
imagesize = "*"
importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""}
Jinja2 = ">=2.3"
packaging = "*"
Pygments = ">=2.0"
@@ -332,30 +348,30 @@ sphinxcontrib-serializinghtml = ">=1.1.5"
[package.extras]
docs = ["sphinxcontrib-websupport"]
lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.900)", "docutils-stubs", "types-typed-ast", "types-pkg-resources", "types-requests"]
test = ["pytest", "pytest-cov", "html5lib", "cython", "typed-ast"]
lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.950)", "docutils-stubs", "types-typed-ast", "types-requests"]
test = ["pytest (>=4.6)", "html5lib", "cython", "typed-ast"]
[package.source]
type = "git"
url = "https://github.com/pybricks/sphinx.git"
reference = "b00124cb"
resolved_reference = "b00124cb07318fd6875f6d53e0b26e50c7dde597"
[[package]]
name = "sphinx_rtd_theme"
version = "0.5.2"
description = ""
name = "sphinx-rtd-theme"
version = "1.0.0"
description = "Read the Docs theme for Sphinx"
category = "dev"
optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
[package.dependencies]
docutils = "<0.17"
docutils = "<0.18"
sphinx = ">=1.6"
[package.extras]
dev = ["transifex-client", "sphinxcontrib-httpdomain", "bump2version"]
[package.source]
type = "git"
url = "https://github.com/readthedocs/sphinx_rtd_theme.git"
reference = "f5b02911ae074c09e690d2ad87ef95c0b2ee678c"
resolved_reference = "f5b02911ae074c09e690d2ad87ef95c0b2ee678c"
[[package]]
name = "sphinxcontrib-applehelp"
version = "1.0.2"
@@ -429,7 +445,7 @@ test = ["pytest"]
[[package]]
name = "stevedore"
version = "3.3.0"
version = "3.5.0"
description = "Manage dynamic plugins for Python applications"
category = "dev"
optional = false
@@ -447,70 +463,100 @@ optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
[[package]]
name = "typed-ast"
version = "1.4.3"
description = "a fork of Python 2 and 3 ast modules with type comment support"
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
category = "dev"
optional = false
python-versions = "*"
python-versions = ">=3.7"
[[package]]
name = "typing-extensions"
version = "3.10.0.0"
description = "Backported and Experimental Type Hints for Python 3.5+"
version = "4.2.0"
description = "Backported and Experimental Type Hints for Python 3.7+"
category = "dev"
optional = false
python-versions = "*"
python-versions = ">=3.7"
[[package]]
name = "urllib3"
version = "1.26.6"
version = "1.26.9"
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.*, <4"
[package.extras]
brotli = ["brotlipy (>=0.6.0)"]
brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"]
secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"]
[[package]]
name = "zipp"
version = "3.8.0"
description = "Backport of pathlib-compatible object wrapper for zip files"
category = "dev"
optional = false
python-versions = ">=3.7"
[package.extras]
docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"]
[metadata]
lock-version = "1.1"
python-versions = "^3.8"
content-hash = "a30654ac4b71b01879e5875d1e1022ae9010643223c2a016c7293ff60f1dc655"
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"},
]
appdirs = [
{file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
{file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
]
babel = [
{file = "Babel-2.9.1-py2.py3-none-any.whl", hash = "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9"},
{file = "Babel-2.9.1.tar.gz", hash = "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0"},
{file = "Babel-2.10.1-py3-none-any.whl", hash = "sha256:3f349e85ad3154559ac4930c3918247d319f21910d5ce4b25d439ed8693b98d2"},
{file = "Babel-2.10.1.tar.gz", hash = "sha256:98aeaca086133efb3e1e2aad0396987490c8425929ddbcfe0550184fdc54cd13"},
]
black = [
{file = "black-20.8b1.tar.gz", hash = "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"},
{file = "black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09"},
{file = "black-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb"},
{file = "black-22.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a"},
{file = "black-22.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968"},
{file = "black-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d"},
{file = "black-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce"},
{file = "black-22.3.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82"},
{file = "black-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b"},
{file = "black-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015"},
{file = "black-22.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b"},
{file = "black-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a"},
{file = "black-22.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163"},
{file = "black-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464"},
{file = "black-22.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0"},
{file = "black-22.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176"},
{file = "black-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0"},
{file = "black-22.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20"},
{file = "black-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a"},
{file = "black-22.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad"},
{file = "black-22.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21"},
{file = "black-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265"},
{file = "black-22.3.0-py3-none-any.whl", hash = "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72"},
{file = "black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79"},
]
certifi = [
{file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"},
{file = "certifi-2021.5.30.tar.gz", hash = "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee"},
{file = "certifi-2022.5.18.1-py3-none-any.whl", hash = "sha256:f1d53542ee8cbedbe2118b5686372fb33c297fcd6379b050cca0ef13a597382a"},
{file = "certifi-2022.5.18.1.tar.gz", hash = "sha256:9c5705e395cd70084351dd8ad5c41e65655e08ce46f2ec9cf6c2c08390f71eb7"},
]
chardet = [
{file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"},
{file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"},
]
charset-normalizer = [
{file = "charset-normalizer-2.0.4.tar.gz", hash = "sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"},
{file = "charset_normalizer-2.0.4-py3-none-any.whl", hash = "sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b"},
{file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"},
{file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"},
]
click = [
{file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"},
{file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"},
{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.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
@@ -521,60 +567,70 @@ doc8 = [
{file = "doc8-0.8.1.tar.gz", hash = "sha256:4d1df12598807cf08ffa9a1d5ef42d229ee0de42519da01b768ff27211082c12"},
]
docutils = [
{file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"},
{file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"},
{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-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"},
{file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"},
{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.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"},
{file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"},
{file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
{file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
]
imagesize = [
{file = "imagesize-1.2.0-py2.py3-none-any.whl", hash = "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1"},
{file = "imagesize-1.2.0.tar.gz", hash = "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1"},
{file = "imagesize-1.3.0-py2.py3-none-any.whl", hash = "sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c"},
{file = "imagesize-1.3.0.tar.gz", hash = "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d"},
]
importlib-metadata = [
{file = "importlib_metadata-4.11.4-py3-none-any.whl", hash = "sha256:c58c8eb8a762858f49e18436ff552e83914778e50e9d2f1660535ffb364552ec"},
{file = "importlib_metadata-4.11.4.tar.gz", hash = "sha256:5d26852efe48c0a32b0509ffbc583fda1a2266545a78d104a6f4aff3db17d700"},
]
jinja2 = [
{file = "Jinja2-3.0.1-py3-none-any.whl", hash = "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4"},
{file = "Jinja2-3.0.1.tar.gz", hash = "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"},
{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.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"},
{file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"},
{file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"},
{file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"},
{file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"},
{file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"},
{file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"},
{file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
{file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
{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"},
@@ -585,92 +641,61 @@ mypy-extensions = [
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
]
packaging = [
{file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"},
{file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"},
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
]
pathspec = [
{file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
{file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
]
pbr = [
{file = "pbr-5.6.0-py2.py3-none-any.whl", hash = "sha256:c68c661ac5cc81058ac94247278eeda6d2e6aecb3e227b0387c30d277e7ef8d4"},
{file = "pbr-5.6.0.tar.gz", hash = "sha256:42df03e7797b796625b1029c0400279c7c34fd7df24a7d7818a1abb5b38710dd"},
{file = "pbr-5.9.0-py2.py3-none-any.whl", hash = "sha256:e547125940bcc052856ded43be8e101f63828c2d94239ffbe2b327ba3d5ccf0a"},
{file = "pbr-5.9.0.tar.gz", hash = "sha256:e8dca2f4b43560edef58813969f52a56cef023146cbb8931626db80e6c1c4308"},
]
platformdirs = [
{file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"},
{file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"},
]
pycodestyle = [
{file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
{file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
{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.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
{file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
{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.9.0-py3-none-any.whl", hash = "sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e"},
{file = "Pygments-2.9.0.tar.gz", hash = "sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f"},
{file = "Pygments-2.12.0-py3-none-any.whl", hash = "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519"},
{file = "Pygments-2.12.0.tar.gz", hash = "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb"},
]
pyparsing = [
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
{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-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"},
{file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"},
]
regex = [
{file = "regex-2021.8.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8764a78c5464ac6bde91a8c87dd718c27c1cabb7ed2b4beaf36d3e8e390567f9"},
{file = "regex-2021.8.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4551728b767f35f86b8e5ec19a363df87450c7376d7419c3cac5b9ceb4bce576"},
{file = "regex-2021.8.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:577737ec3d4c195c4aef01b757905779a9e9aee608fa1cf0aec16b5576c893d3"},
{file = "regex-2021.8.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c856ec9b42e5af4fe2d8e75970fcc3a2c15925cbcc6e7a9bcb44583b10b95e80"},
{file = "regex-2021.8.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3835de96524a7b6869a6c710b26c90e94558c31006e96ca3cf6af6751b27dca1"},
{file = "regex-2021.8.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cea56288eeda8b7511d507bbe7790d89ae7049daa5f51ae31a35ae3c05408531"},
{file = "regex-2021.8.3-cp36-cp36m-win32.whl", hash = "sha256:a4eddbe2a715b2dd3849afbdeacf1cc283160b24e09baf64fa5675f51940419d"},
{file = "regex-2021.8.3-cp36-cp36m-win_amd64.whl", hash = "sha256:57fece29f7cc55d882fe282d9de52f2f522bb85290555b49394102f3621751ee"},
{file = "regex-2021.8.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a5c6dbe09aff091adfa8c7cfc1a0e83fdb8021ddb2c183512775a14f1435fe16"},
{file = "regex-2021.8.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff4a8ad9638b7ca52313d8732f37ecd5fd3c8e3aff10a8ccb93176fd5b3812f6"},
{file = "regex-2021.8.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b63e3571b24a7959017573b6455e05b675050bbbea69408f35f3cb984ec54363"},
{file = "regex-2021.8.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fbc20975eee093efa2071de80df7f972b7b35e560b213aafabcec7c0bd00bd8c"},
{file = "regex-2021.8.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14caacd1853e40103f59571f169704367e79fb78fac3d6d09ac84d9197cadd16"},
{file = "regex-2021.8.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bb350eb1060591d8e89d6bac4713d41006cd4d479f5e11db334a48ff8999512f"},
{file = "regex-2021.8.3-cp37-cp37m-win32.whl", hash = "sha256:18fdc51458abc0a974822333bd3a932d4e06ba2a3243e9a1da305668bd62ec6d"},
{file = "regex-2021.8.3-cp37-cp37m-win_amd64.whl", hash = "sha256:026beb631097a4a3def7299aa5825e05e057de3c6d72b139c37813bfa351274b"},
{file = "regex-2021.8.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:16d9eaa8c7e91537516c20da37db975f09ac2e7772a0694b245076c6d68f85da"},
{file = "regex-2021.8.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3905c86cc4ab6d71635d6419a6f8d972cab7c634539bba6053c47354fd04452c"},
{file = "regex-2021.8.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:937b20955806381e08e54bd9d71f83276d1f883264808521b70b33d98e4dec5d"},
{file = "regex-2021.8.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:28e8af338240b6f39713a34e337c3813047896ace09d51593d6907c66c0708ba"},
{file = "regex-2021.8.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c09d88a07483231119f5017904db8f60ad67906efac3f1baa31b9b7f7cca281"},
{file = "regex-2021.8.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:85f568892422a0e96235eb8ea6c5a41c8ccbf55576a2260c0160800dbd7c4f20"},
{file = "regex-2021.8.3-cp38-cp38-win32.whl", hash = "sha256:bf6d987edd4a44dd2fa2723fca2790f9442ae4de2c8438e53fcb1befdf5d823a"},
{file = "regex-2021.8.3-cp38-cp38-win_amd64.whl", hash = "sha256:8fe58d9f6e3d1abf690174fd75800fda9bdc23d2a287e77758dc0e8567e38ce6"},
{file = "regex-2021.8.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7976d410e42be9ae7458c1816a416218364e06e162b82e42f7060737e711d9ce"},
{file = "regex-2021.8.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9569da9e78f0947b249370cb8fadf1015a193c359e7e442ac9ecc585d937f08d"},
{file = "regex-2021.8.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:459bbe342c5b2dec5c5223e7c363f291558bc27982ef39ffd6569e8c082bdc83"},
{file = "regex-2021.8.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4f421e3cdd3a273bace013751c345f4ebeef08f05e8c10757533ada360b51a39"},
{file = "regex-2021.8.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea212df6e5d3f60341aef46401d32fcfded85593af1d82b8b4a7a68cd67fdd6b"},
{file = "regex-2021.8.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a3b73390511edd2db2d34ff09aa0b2c08be974c71b4c0505b4a048d5dc128c2b"},
{file = "regex-2021.8.3-cp39-cp39-win32.whl", hash = "sha256:f35567470ee6dbfb946f069ed5f5615b40edcbb5f1e6e1d3d2b114468d505fc6"},
{file = "regex-2021.8.3-cp39-cp39-win_amd64.whl", hash = "sha256:bfa6a679410b394600eafd16336b2ce8de43e9b13f7fb9247d84ef5ad2b45e91"},
{file = "regex-2021.8.3.tar.gz", hash = "sha256:8935937dad2c9b369c3d932b0edbc52a62647c2afb2fafc0c280f14a8bf56a6a"},
{file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"},
{file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"},
]
requests = [
{file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"},
{file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"},
{file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"},
{file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"},
]
restructuredtext-lint = [
{file = "restructuredtext_lint-1.3.2.tar.gz", hash = "sha256:d3b10a1fe2ecac537e51ae6d151b223b78de9fafdd50e5eb6b08c243df173c80"},
{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.1.0-py2.py3-none-any.whl", hash = "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2"},
{file = "snowballstemmer-2.1.0.tar.gz", hash = "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914"},
{file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"},
{file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"},
]
sphinx = [
{file = "Sphinx-4.1.2-py3-none-any.whl", hash = "sha256:46d52c6cee13fec44744b8c01ed692c18a640f6910a725cbb938bc36e8d64544"},
{file = "Sphinx-4.1.2.tar.gz", hash = "sha256:3092d929cd807926d846018f2ace47ba2f3b671b309c7a89cd3306e80c826b13"},
Sphinx = []
sphinx-rtd-theme = [
{file = "sphinx_rtd_theme-1.0.0-py2.py3-none-any.whl", hash = "sha256:4d35a56f4508cfee4c4fb604373ede6feae2a306731d533f409ef5c3496fdbd8"},
{file = "sphinx_rtd_theme-1.0.0.tar.gz", hash = "sha256:eec6d497e4c2195fa0e8b2016b337532b8a699a68bcb22a512870e16925c6a5c"},
]
sphinx_rtd_theme = []
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"},
@@ -696,51 +721,26 @@ sphinxcontrib-serializinghtml = [
{file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"},
]
stevedore = [
{file = "stevedore-3.3.0-py3-none-any.whl", hash = "sha256:50d7b78fbaf0d04cd62411188fa7eedcb03eb7f4c4b37005615ceebe582aa82a"},
{file = "stevedore-3.3.0.tar.gz", hash = "sha256:3a5bbd0652bf552748871eaa73a4a8dc2899786bc497a2aa1fcb4dcdb0debeee"},
{file = "stevedore-3.5.0-py3-none-any.whl", hash = "sha256:a547de73308fd7e90075bb4d301405bebf705292fa90a90fc3bcf9133f58616c"},
{file = "stevedore-3.5.0.tar.gz", hash = "sha256:f40253887d8712eaa2bb0ea3830374416736dc8ec0e22f5a65092c1174c44335"},
]
toml = [
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
]
typed-ast = [
{file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"},
{file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"},
{file = "typed_ast-1.4.3-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528"},
{file = "typed_ast-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428"},
{file = "typed_ast-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3"},
{file = "typed_ast-1.4.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f"},
{file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341"},
{file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace"},
{file = "typed_ast-1.4.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f"},
{file = "typed_ast-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363"},
{file = "typed_ast-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7"},
{file = "typed_ast-1.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266"},
{file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e"},
{file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04"},
{file = "typed_ast-1.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899"},
{file = "typed_ast-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c"},
{file = "typed_ast-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805"},
{file = "typed_ast-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a"},
{file = "typed_ast-1.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff"},
{file = "typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41"},
{file = "typed_ast-1.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39"},
{file = "typed_ast-1.4.3-cp38-cp38-win32.whl", hash = "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927"},
{file = "typed_ast-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40"},
{file = "typed_ast-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3"},
{file = "typed_ast-1.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4"},
{file = "typed_ast-1.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0"},
{file = "typed_ast-1.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3"},
{file = "typed_ast-1.4.3-cp39-cp39-win32.whl", hash = "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808"},
{file = "typed_ast-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c"},
{file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"},
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-3.10.0.0-py2-none-any.whl", hash = "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497"},
{file = "typing_extensions-3.10.0.0-py3-none-any.whl", hash = "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"},
{file = "typing_extensions-3.10.0.0.tar.gz", hash = "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342"},
{file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"},
{file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"},
]
urllib3 = [
{file = "urllib3-1.26.6-py2.py3-none-any.whl", hash = "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4"},
{file = "urllib3-1.26.6.tar.gz", hash = "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"},
{file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"},
{file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"},
]
zipp = [
{file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"},
{file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"},
]
+5 -5
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pybricks"
version = "3.1.0rc1"
version = "3.2.0b1"
description = "Documentation and user-API stubs for Pybricks MicroPython"
authors = ["The Pybricks Authors <dev@pybricks.com>"]
maintainers = ["Laurens Valk <laurens@pybricks.com>", "David Lechner <david@pybricks.com>" ]
@@ -28,11 +28,11 @@ packages = [
python = "^3.8"
[tool.poetry.dev-dependencies]
black = {version = "^20.8b1", allow-prereleases = true}
black = "^22.3.0"
doc8 = "^0.8.1"
flake8 = "^3.8.4"
Sphinx = "^4.1.0"
sphinx-rtd-theme = { git = "https://github.com/readthedocs/sphinx_rtd_theme.git", rev = "f5b02911ae074c09e690d2ad87ef95c0b2ee678c" }
flake8 = "^4.0"
Sphinx = { git = "https://github.com/pybricks/sphinx.git", rev = "b00124cb" }
sphinx-rtd-theme = "^1.0.0"
toml = "^0.10.0"
[build-system]
+2 -2
View File
@@ -1,5 +1,5 @@
# This file is strictly for building docs on readthedocs.org
# See pyproject.toml for local development
Sphinx==4.1.2
git+git://github.com/readthedocs/sphinx_rtd_theme@f5b0291#egg=sphinx-rtd-theme
git+https://github.com/pybricks/sphinx@b00124c#egg=Sphinx
sphinx-rtd-theme==1.0.0
toml
+1
View File
@@ -2,6 +2,7 @@
[flake8]
exclude = .venv/,*.pyi
max-line-length = 88
ignore = E203,W503
[doc8]
ignore-path = .venv/,doc/main/build/,doc/api/build/,pybricks.egg-info/,npm/
+473 -387
View File
File diff suppressed because it is too large Load Diff
-154
View File
@@ -1,154 +0,0 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2020 The Pybricks Authors
from pybricks.geometry import Matrix, vector
from typing import Collection, Iterable, List, Optional, Tuple, Union, overload
from .parameters import Button, Color, Direction, Side, Stop, Port, Axis
from .media.ev3dev import SoundFile
class DCMotor:
def __init__(
self, port: Port, positive_direction: Direction = Direction.CLOCKWISE
): ...
def dc(self, duty: int) -> None: ...
def stop(self) -> None: ...
def brake(self) -> None: ...
class Control:
@overload
def limits(self) -> Tuple[int, int, int]: ...
@overload
def limits(
self,
speed: Optional[int] = None,
acceleration: Optional[int] = None,
actuation: Optional[int] = None,
) -> None: ...
def pid(self) -> Tuple[int, int, int, int, int, int]: ...
@overload
def pid(
self,
kp: Optional[int] = None,
ki: Optional[int] = None,
kd: Optional[int] = None,
integral_range: Optional[int] = None,
integral_rate: Optional[int] = None,
) -> None: ...
@overload
def target_tolerances(self) -> Tuple[int, int]: ...
@overload
def target_tolerances(
self, speed: Optional[int] = None, position: Optional[int] = None
) -> None: ...
@overload
def stall_tolerances(self) -> Tuple[int, int]: ...
@overload
def stall_tolerances(
self, speed: Optional[int] = None, time: Optional[int] = None
) -> None: ...
def trajectory(
self,
) -> Tuple[int, int, int, int, int, int, int, int, int, int, int, int]: ...
def stalled(self) -> bool: ...
def done(self) -> bool: ...
class Motor(DCMotor):
control: Control
def __init__(
self,
port: Port,
positive_direction: Direction = Direction.CLOCKWISE,
gears: Optional[Union[Collection[int], Collection[Collection[int]]]] = None,
): ...
def angle(self) -> int: ...
def speed(self) -> int: ...
def reset_angle(self, angle: int) -> None: ...
def hold(self) -> None: ...
def run(self, speed: int) -> None: ...
def run_time(
self, speed: int, time: int, then: Stop = Stop.HOLD, wait: bool = True
) -> None: ...
def run_angle(
self, speed: int, rotation_angle: int, then: Stop = Stop.HOLD, wait: bool = True
) -> None: ...
def run_target(
self, speed: int, target_angle: int, then: Stop = Stop.HOLD, wait: bool = True
) -> None: ...
def run_until_stalled(
self, speed: int, then: Stop = Stop.COAST, duty_limit: Optional[int] = None
) -> int: ...
def track_target(self, target_angle: int) -> None: ...
class Speaker:
def beep(self, frequency: int = 500, duration: int = 100) -> None: ...
def play_notes(self, notes: Iterable[str], tempo: int = 120) -> None: ...
def play_file(self, file_name: Union[SoundFile, str]) -> None: ...
def say(self, text: str) -> None: ...
def set_speech_options(
self,
language: Optional[str] = None,
voice: Optional[str] = None,
speed: Optional[int] = None,
pitch: Optional[int] = None,
): ...
def set_volume(self, volume: int, which: str = "_all_") -> None: ...
class Light:
def on(self, brightness: int = 100) -> None: ...
def off(self) -> None: ...
def blink(self, durations: Collection[int]) -> None: ...
def animate(self, brightness_values: Collection[int], interval: int) -> None: ...
def reset(self) -> None: ...
class ColorLight:
def on(self, color: Optional[Color]) -> None: ...
def off(self) -> None: ...
def blink(self, color: Color, durations: Collection[int]) -> None: ...
def animate(self, colors: Collection[Color], interval: int) -> None: ...
def reset(self) -> None: ...
class LightArray:
def __init__(self, n: int): ...
def on(self, brightness: int) -> None: ...
def off(self) -> None: ...
def blink(self, durations: Collection[int]) -> None: ...
def animate(self, brightness_values: Collection[int], interval: int) -> None: ...
class LightMatrix:
def __init__(self, rows: int, columns: int): ...
def orientation(self, up: Side) -> None: ...
def image(self, matrix: Matrix) -> None: ...
def animate(self, matrices: Collection[Matrix], interval, int) -> None: ...
def pixel(self, row: int, column: int, brightness: int = 100) -> None: ...
def off(self) -> None: ...
def number(self, number: int) -> None: ...
def char(self, char: str) -> None: ...
def text(self, text: str, on: int = 500, off: int = 50) -> None: ...
def reset(self) -> None: ...
class Keypad:
def pressed(self) -> Tuple[Button]: ...
class Battery:
def voltage(self) -> int: ...
def current(self) -> int: ...
class Accelerometer:
def neutral(self, top: Axis, front: Axis) -> None: ...
@overload
def acceleration(self) -> vector[float, float, float]: ...
@overload
def acceleration(self, axis: Axis) -> int: ...
def tilt(self) -> Tuple[int, int]: ...
def tapped(self) -> bool: ...
def shaken(self) -> bool: ...
def up(self) -> Side: ...
class IMU(Accelerometer):
def heading(self) -> int: ...
def reset_heading(self, angle): ...
@overload
def gyro(self) -> vector[float, float, float]: ...
@overload
def gyro(self, axis: Axis) -> int: ...
+112
View File
@@ -0,0 +1,112 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2018-2021 The Pybricks Authors
class Speaker:
"""Plays beeps and sounds using a speaker."""
def beep(self, frequency=500, duration=100):
"""Play a beep/tone.
Arguments:
frequency (:ref:`frequency`):
Frequency of the beep. Frequencies below 100
are treated as 100.
duration (:ref:`time`):
Duration of the beep. If the duration is less
than 0, then the method returns immediately and the frequency
play continues to play indefinitely.
"""
pass
def play_notes(self, notes, tempo=120):
"""Plays a sequence of musical notes. For example:
``['C4/4', 'C4/4', 'G4/4', 'G4/4']``.
Each note is a string with the following format:
- The first character is the name of the note, ``A`` to ``G``
or ``R`` for a rest.
- Note names can also include an accidental ``#`` (sharp) or
``b`` (flat). ``B#``/``Cb`` and ``E#``/``Fb`` are not
allowed.
- The note name is followed by the octave number ``2``
to ``8``. For example ``C4`` is middle C. The octave changes
to the next number at the note C, for example, ``B3`` is the
note below middle C (``C4``).
- The octave is followed by ``/`` and a number that indicates
the size of the note. For example ``/4`` is a quarter note,
``/8`` is an eighth note and so on.
- This can optionally followed by a ``.`` to make a dotted
note. Dotted notes are 1-1/2 times as long as notes without a
dot.
- The note can optionally end with a ``_`` which is a tie or a
slur. This causes there to be no pause between this note and
the next note.
Arguments:
notes (iter):
A sequence of notes to be played.
tempo (int):
Beats per minute. A quarter note is one beat.
"""
pass
def play_file(self, file):
"""Plays a sound file.
Arguments:
file (str):
Path to the sound file, including the file extension.
"""
pass
def say(self, text):
"""Says a given text string.
You can configure the language and voice of the text using
:meth:`.set_speech_options`.
Arguments:
text (str): What to say.
"""
pass
def set_speech_options(self, language=None, voice=None, speed=None, pitch=None):
"""Configures speech settings used by the :meth:`.say` method.
Any option that is set to ``None`` will not be changed. If an option
is set to an invalid value :meth:`.say` will use the default value
instead.
Arguments:
language (str):
Language of the text. For example, you can choose ``'en'``
(English) or ``'de'`` (German). [#espeak_lang]_
voice (str):
The voice to use. For example, you can choose ``'f1'`` (female
voice variant 1) or ``'m3'`` (male voice variant 3).
[#espeak_lang]_
speed (int):
Number of words per minute.
pitch (int):
Pitch (0 to 99). Higher numbers make the voice higher pitched
and lower numbers make the voice lower pitched.
"""
pass
def set_volume(self, volume, which="_all_"):
"""Sets the speaker volume.
Arguments:
volume (:ref:`percentage`):
Volume of the speaker.
which (str):
Which volume to set. ``'Beep'`` sets the volume for
`beep` and `play_notes`. ``'PCM'`` sets the
volume for :meth:`.play_file` and :meth:`.say`. ``'_all_'``
sets both at the same time.
"""
pass
+20
View File
@@ -0,0 +1,20 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2020-2021 The Pybricks Authors
from typing import Iterable, Optional, Union
from pybricks.media.ev3dev import SoundFile
class Speaker:
def beep(self, frequency: int = 500, duration: int = 100) -> None: ...
def play_notes(self, notes: Iterable[str], tempo: int = 120) -> None: ...
def play_file(self, file_name: Union[SoundFile, str]) -> None: ...
def say(self, text: str) -> None: ...
def set_speech_options(
self,
language: Optional[str] = None,
voice: Optional[str] = None,
speed: Optional[int] = None,
pitch: Optional[int] = None,
): ...
def set_volume(self, volume: int, which: str = "_all_") -> None: ...
+105 -85
View File
@@ -1,16 +1,22 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2018-2020 The Pybricks Authors
# Copyright (c) 2018-2022 The Pybricks Authors
"""LEGO® MINDSTORMS® EV3 motors and sensors."""
from .parameters import Direction as _Direction
from ._common import Motor # noqa E402
from .parameters import Direction, Port, Color, Button
from ._common import Motor as _Motor
from typing import Optional, Tuple, List
class Motor(_Motor):
pass
class TouchSensor:
"""LEGO® MINDSTORMS® EV3 Touch Sensor."""
def __init__(self, port):
def __init__(self, port: Port):
"""TouchSensor(port)
Arguments:
@@ -18,13 +24,14 @@ class TouchSensor:
"""
pass
def pressed(self):
"""Checks if the sensor is pressed.
def pressed(self) -> bool:
"""pressed() -> bool
Checks if the sensor is pressed.
Returns:
bool: ``True`` if the sensor is pressed, ``False`` if it is
``True`` if the sensor is pressed, ``False`` if it is
not pressed.
"""
pass
@@ -32,53 +39,59 @@ class TouchSensor:
class ColorSensor:
"""LEGO® MINDSTORMS® EV3 Color Sensor."""
def __init__(self, port):
def __init__(self, port: Port):
"""ColorSensor(port)
Arguments:
port (Port): Port to which the sensor is connected.
"""
pass
def color(self):
"""Measures the color of a surface.
def color(self) -> Optional[Color]:
"""color() -> Color
:returns:
``Color.BLACK``, ``Color.BLUE``, ``Color.GREEN``, ``Color.YELLOW``,
``Color.RED``, ``Color.WHITE``, ``Color.BROWN`` or ``None``.
:rtype: :class:`Color <.parameters.Color>`, or ``None`` if no color is
detected.
"""
pass
def ambient(self):
"""Measures the ambient light intensity.
Measures the color of a surface.
Returns:
:ref:`percentage`: Ambient light intensity, ranging from 0 (dark)
to 100 (bright).
``Color.BLACK``, ``Color.BLUE``, ``Color.GREEN``,
``Color.YELLOW``, ``Color.RED``, ``Color.WHITE``, ``Color.BROWN``,
or ``None`` if no color is detected.
"""
pass
def reflection(self):
"""Measures the reflection of a surface using a red light.
def ambient(self) -> int:
"""ambient() -> int: %
Measures the ambient light intensity.
Returns:
:ref:`percentage`: Reflection, ranging from 0 (no reflection) to
100 (high reflection).
Ambient light intensity, ranging from 0% (dark)
to 100% (bright).
"""
pass
def reflection(self) -> int:
"""reflection() -> int: %
Measures the reflection of a surface using a red light.
Returns:
Reflection, ranging from 0% (no reflection) to
100% (high reflection).
"""
pass
def rgb(self):
"""Measures the reflection of a surface using a red, green, and then a
def rgb(self) -> Tuple[int, int, int]:
"""rgb() -> Tuple[int, int, int]
Measures the reflection of a surface using a red, green, and then a
blue light.
:returns: Tuple of reflections for red, green, and blue light, each
ranging from 0.0 (no reflection) to 100.0 (high reflection).
:rtype: (:ref:`percentage`, :ref:`percentage`, :ref:`percentage`)
Returns:
Tuple of reflections for red, green, and blue light, each
ranging from 0.0% (no reflection) to 100.0% (high reflection).
"""
pass
@@ -86,7 +99,7 @@ class ColorSensor:
class InfraredSensor:
"""LEGO® MINDSTORMS® EV3 Infrared Sensor and Beacon."""
def __init__(self, port):
def __init__(self, port: Port):
"""InfraredSensor(port)
Arguments:
@@ -95,57 +108,66 @@ class InfraredSensor:
"""
pass
def distance(self):
"""Measures the relative distance between the sensor and an object using
def distance(self) -> int:
"""distance() -> int: %
Measures the relative distance between the sensor and an object using
infrared light.
Returns:
:ref:`relativedistance`: Relative distance ranging from 0 (closest)
to 100 (farthest).
Relative distance ranging from 0% (closest)
to 100% (farthest).
"""
pass
def beacon(self, channel):
"""Measures the relative distance and angle between the remote and the
def beacon(self, channel: int) -> Tuple[Optional[int], Optional[int]]:
"""
beacon(channel) -> Tuple[int, int]
beacon(channel) -> Tuple[None, None]
Measures the relative distance and angle between the remote and the
infrared sensor.
Arguments:
channel (int): Channel number of the remote.
:returns: Tuple of relative distance (0 to 100) and approximate angle
(-75 to 75 degrees) between remote and infrared sensor.
:rtype: (:ref:`relativedistance`, :ref:`angle`) or
(``None``, ``None``) if no remote is detected.
Returns:
Tuple of relative distance (0% to 100%) and approximate angle
(-75 to 75 degrees) between remote and infrared sensor or
a tuple of (``None``, ``None``) if no remote is detected.
"""
pass
def buttons(self, channel):
"""Checks which buttons on the infrared remote are pressed.
def buttons(self, channel: int) -> List[Button]:
"""buttons(channel) -> List[Button]
Checks which buttons on the infrared remote are pressed.
This method can detect up to two buttons at once. If you press
more buttons, you may not get useful data.
more buttons, you'll still get just two buttons.
Arguments:
channel (int): Channel number of the remote.
:returns: List of pressed buttons on the remote on selected channel.
:rtype: List of :class:`Button <Button>`
Returns:
List of pressed buttons on the remote on the selected channel.
"""
pass
def keypad(self):
"""Checks which buttons on the infrared remote are pressed.
def keypad(self) -> List[Button]:
"""keypad() -> List[Button]
Checks which buttons on the infrared remote are pressed.
This method can independently detect all 4 up/down buttons, but
it cannot detect the beacon button.
This method only works with the remote in channel 1.
:returns: List of pressed buttons on the remote on selected channel.
:rtype: List of :class:`Button <Button>`
Returns:
List of pressed buttons.
"""
pass
@@ -153,8 +175,8 @@ class InfraredSensor:
class GyroSensor:
"""LEGO® MINDSTORMS® EV3 Gyro Sensor."""
def __init__(self, port, positive_direction=_Direction.CLOCKWISE):
"""
def __init__(self, port: Port, positive_direction: Direction = Direction.CLOCKWISE):
"""GyroSensor(port)
Arguments:
port (Port): Port to which the sensor is connected.
@@ -165,41 +187,35 @@ class GyroSensor:
"""
pass
def speed(self):
"""Gets the speed (angular velocity) of the sensor.
def speed(self) -> int:
"""speed() -> int: deg/s
Gets the speed (angular velocity) of the sensor.
Returns:
:ref:`speed`: Sensor angular velocity.
Angular velocity.
"""
pass
def angle(self):
"""Gets the accumulated angle of the sensor.
def angle(self) -> int:
"""angle() -> int: deg
Gets the accumulated angle of the sensor.
Returns:
:ref:`angle`: Rotation angle.
Rotation angle.
"""
pass
def reset_angle(self, angle):
"""Sets the rotation angle of the sensor to a desired value.
def reset_angle(self, angle: int) -> None:
"""reset_angle(angle)
Sets the rotation angle of the sensor to a desired value.
Arguments:
angle (:ref:`angle`): Value to which the angle should be reset.
"""
pass
def _calibrate(self):
"""Calibrates the sensor.
This process sets the speed and angle to zero and ensures that the
angle value does not drift.
Make sure that the sensor does not move while calibrating.
This process can take up to 15 seconds.
angle (Number, deg): Value to which the angle should be reset.
"""
pass
@@ -207,7 +223,7 @@ class GyroSensor:
class UltrasonicSensor:
"""LEGO® MINDSTORMS® EV3 Ultrasonic Sensor."""
def __init__(self, port):
def __init__(self, port: Port):
"""UltrasonicSensor(port)
Arguments:
@@ -216,8 +232,10 @@ class UltrasonicSensor:
"""
pass
def distance(self, silent=False):
"""Measures the distance between the sensor and an object using
def distance(self, silent: bool = False) -> int:
"""distance(silent=False) -> int: mm
Measures the distance between the sensor and an object using
ultrasonic sound waves.
Arguments:
@@ -228,13 +246,15 @@ class UltrasonicSensor:
If this happens, unplug it and plug it back in.
Returns:
:ref:`distance`: Distance.
Measured distance.
"""
pass
def presence(self):
"""Checks for the presence of other ultrasonic sensors by detecting
def presence(self) -> bool:
"""presence() -> bool
Checks for the presence of other ultrasonic sensors by detecting
ultrasonic sounds.
If the other ultrasonic sensor is operating in silent mode, you can
@@ -242,7 +262,7 @@ class UltrasonicSensor:
measurement.
Returns:
bool: ``True`` if ultrasonic sounds are detected,
``True`` if ultrasonic sounds are detected,
``False`` if not.
"""
pass
-38
View File
@@ -1,38 +0,0 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2020 The Pybricks Authors
from typing import List, Optional, Tuple
from .parameters import Color, Direction, Port, Button
from ._common import Motor # noqa E402
class TouchSensor:
def __init__(self, port: Port): ...
def pressed(self) -> bool: ...
class ColorSensor:
def __init__(self, port: Port): ...
def color(self) -> Optional[Color]: ...
def ambient(self) -> int: ...
def reflection(self) -> int: ...
def rgb(self) -> Tuple[int, int, int]: ...
class InfraredSensor:
def __init__(self, port: Port): ...
def distance(self) -> int: ...
def beacon(self, channel: int) -> Tuple[Optional[int], Optional[int]]: ...
def buttons(self, channel: int) -> List[Button]: ...
def keypad(self) -> List[Button]: ...
class GyroSensor:
def __init__(
self, port: Port, positive_direction: Direction = Direction.CLOCKWISE
): ...
def speed(self) -> int: ...
def angle(self) -> int: ...
def reset_angle(self, angle: int) -> None: ...
class UltrasonicSensor:
def __init__(self, port: Port): ...
def distance(self, silent: bool = False) -> int: ...
def presence(self) -> bool: ...
+73 -17
View File
@@ -1,16 +1,58 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2018-2020 The Pybricks Authors
# Copyright (c) 2018-2022 The Pybricks Authors
"""Core linear algebra functionality for orientation sensors and robotics."""
from __future__ import annotations
from typing import Tuple, Collection, overload
class Matrix:
"""Mathematical representation of a matrix. It supports common operations
such as matrix addition (``+``), subtraction (``-``),
and multiplication (``*``). A :class:`.Matrix` object is immutable."""
"""Mathematical representation of a matrix. It supports
addition (``A + B``), subtraction (``A - B``),
and matrix multiplication (``A * B``) for matrices of compatible size.
def __init__(self, rows):
"""
It also supports scalar multiplication (``c * A`` or ``A * c``)
and scalar division (``A / c``).
A :class:`.Matrix` object is immutable."""
def __add__(self, other) -> Matrix:
...
def __iadd__(self, other) -> Matrix:
...
def __sub__(self, other) -> Matrix:
...
def __isub__(self, other) -> Matrix:
...
def __mul__(self, other) -> Matrix:
...
def __rmul__(self, other) -> Matrix:
...
def __imul__(self, other) -> Matrix:
...
def __truediv__(self, other) -> Matrix:
...
def __itruediv__(self, other) -> Matrix:
...
def __floordiv__(self, other) -> Matrix:
...
def __ifloordiv__(self, other) -> Matrix:
...
def __init__(self, rows: Collection[Collection[int]]):
"""Matrix(rows)
Arguments:
rows (list): List of rows. Each row is itself a list of numbers.
@@ -18,36 +60,49 @@ class Matrix:
"""
@property
def T(self):
def T(self) -> Matrix:
"""Returns a new :class:`.Matrix` that is the transpose of the
original."""
pass
@property
def shape(self):
def shape(self) -> Tuple[int, int]:
"""Returns a tuple (``m``, ``n``),
where ``m`` is the number of rows and ``n`` is the number of columns.
"""
pass
def vector(x, y, z=None):
"""Convenience function to create a :class:`.Matrix` with the
shape (``3``, ``1``) or (``2``, ``1``).
@overload
def vector(x: float, y: float) -> Matrix:
...
@overload
def vector(x: float, y: float, z: float) -> Matrix:
...
def vector(*args):
"""
vector(x, y) -> Matrix
vector(x, y, z) -> Matrix
Convenience function to create a :class:`.Matrix` with the
shape (``2``, ``1``) or (``3``, ``1``).
Arguments:
x (float): x-coordinate of the vector.
y (float): y-coordinate of the vector.
z (float): z-coordinate of the vector (optional).
Returns:
Matrix: A matrix with the shape of a column vector.
A matrix with the shape of a column vector.
"""
pass
class Axis():
class Axis:
"""Unit axes of a coordinate system.
.. data:: X = vector(1, 0, 0)
@@ -55,6 +110,7 @@ class Axis():
.. data:: Z = vector(0, 0, 1)
"""
X = vector(1, 0, 0)
Y = vector(0, 1, 0)
Z = vector(0, 0, 1)
X: Matrix = vector(1, 0, 0)
Y: Matrix = vector(0, 1, 0)
Z: Matrix = vector(0, 0, 1)
-18
View File
@@ -1,18 +0,0 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2020 The Pybricks Authors
from typing import Collection, Optional, Tuple
class Matrix:
def __init__(self, rows: Collection[int]): ...
@property
def T(self) -> Matrix: ...
@property
def shape(self) -> Tuple[int, int]: ...
def vector(x: float, y: float, z: Optional[float] = None) -> Matrix: ...
class Axis:
X: Matrix
Y: Matrix
Z: Matrix
+34 -21
View File
@@ -2,14 +2,21 @@
# Copyright (c) 2018-2020 The Pybricks Authors
"""LEGO® Programmable Hubs."""
from ._common import (Speaker as _Speaker, Battery as _Battery,
ColorLight as _ColorLight, Keypad as _Keypad,
LightMatrix as _LightMatrix, IMU as _IMU,
System as _System,
SimpleAccelerometer as _SimpleAccelerometer)
from ._common import (
Speaker as _Speaker,
Battery as _Battery,
ColorLight as _ColorLight,
Keypad as _Keypad,
LightMatrix as _LightMatrix,
IMU as _IMU,
Charger as _Charger,
System as _System,
SimpleAccelerometer as _SimpleAccelerometer,
)
from .ev3dev._speaker import Speaker as _EV3Speaker
from .geometry import Axis as _Axis
from .media.ev3dev import Image as _Image
from .parameters import Button as _Button
from .geometry import Axis as _Axis
class EV3Brick:
@@ -17,15 +24,17 @@ class EV3Brick:
# These class attributes are here for auto-documentation only.
# In reality, they are instance attributes created by __init__.
buttons = _Keypad((
_Button.LEFT,
_Button.RIGHT,
_Button.CENTER,
_Button.UP,
_Button.DOWN,
))
screen = _Image('_screen_')
speaker = _Speaker()
buttons = _Keypad(
(
_Button.LEFT,
_Button.RIGHT,
_Button.CENTER,
_Button.UP,
_Button.DOWN,
)
)
screen = _Image("_screen_")
speaker = _EV3Speaker()
battery = _Battery()
light = _ColorLight()
@@ -87,12 +96,15 @@ class PrimeHub:
# These class attributes are here for auto-documentation only.
# In reality, they are instance attributes created by __init__.
battery = _Battery()
buttons = _Keypad((
_Button.LEFT,
_Button.RIGHT,
_Button.CENTER,
_Button.BLUETOOTH,
))
buttons = _Keypad(
(
_Button.LEFT,
_Button.RIGHT,
_Button.CENTER,
_Button.BLUETOOTH,
)
)
charger = _Charger()
light = _ColorLight()
display = _LightMatrix(5, 5)
speaker = _Speaker()
@@ -118,4 +130,5 @@ class PrimeHub:
class InventorHub(PrimeHub):
"""LEGO® MINDSTORMS Inventor Hub."""
pass
+23 -9
View File
@@ -1,13 +1,24 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2020 The Pybricks Authors
from ._common import Speaker, Battery, ColorLight, LightMatrix, Keypad
from .media.ev3dev import Image
from ._common import (
Battery,
ColorLight,
Charger,
IMU,
Keypad,
LightMatrix,
SimpleAccelerometer,
Speaker,
System,
)
from .ev3dev._speaker import Speaker as EV3Speaker
from .geometry import Axis
from .media.ev3dev import Image
class EV3Brick:
screen: Image
speaker: Speaker
speaker: EV3Speaker
battery: Battery
light: ColorLight
buttons = Keypad
@@ -15,27 +26,30 @@ class EV3Brick:
class MoveHub:
battery: Battery
light: ColorLight
system: System
imu: SimpleAccelerometer
class CityHub:
battery: Battery
light: ColorLight
system: System
class TechnicHub:
def __init__(self, top_size: Axis, front_side: Axis): ...
battery: Battery
light: ColorLight
system: System
imu: IMU
class PrimeHub:
def __init__(self, top_size: Axis, front_side: Axis): ...
def __init__(self, top_side: Axis = Axis.Z, front_side: Axis = Axis.X): ...
battery: Battery
light: ColorLight
display: LightMatrix
buttons: Keypad
speaker: Speaker
system: System
imu: IMU
charger: Charger
class InventorHub(PrimeHub): ...
+173 -167
View File
@@ -117,8 +117,9 @@ class Image:
y (int):
The y-axis value where the top of the image will start.
source (Image or str):
The source :class:`Image`. If the argument is a string, then
the ``source`` image is loaded from file.
The source :class:`Image <pybricks.media.ev3dev.Image>`. If
the argument is a string, then the ``source`` image is loaded
from file.
transparent (Color):
The color of ``image`` to treat as transparent or ``None`` for
no transparency.
@@ -130,15 +131,17 @@ class Image:
Arguments:
source (Image or str):
The source :class:`Image`. If the argument is a string, then
the ``source`` image is loaded from file.
The source :class:`Image <pybricks.media.ev3dev.Image>`. If
the argument is a string, then the ``source`` image is loaded
from file.
"""
def draw_text(self, x, y, text, text_color=_Color.BLACK, background_color=None):
"""Draws text on |this image|.
The most recent font set using :meth:`set_font` will be used or
:data:`Font.DEFAULT` if no font has been set yet.
The most recent font set using :meth:`.set_font` will be used or
:data:`Font.DEFAULT <pybricks.media.ev3dev.Font.DEFAULT>` if no font
has been set yet.
Arguments:
x (int):
@@ -150,25 +153,27 @@ class Image:
text_color (Color):
The color used for drawing the text.
background_color (Color):
The color used to fill the rectangle behind the text or ``None``
for transparent background.
The color used to fill the rectangle behind the text or
``None`` for transparent background.
"""
pass
def print(self, *args, sep=' ', end='\n'):
def print(self, *args, sep=" ", end="\n"):
"""Prints a line of text on |this image|.
This method works like the builtin ``print()`` function, but it writes
on |this image| instead.
You can set the font using :meth:`set_font`. If no font has been set,
:data:`Font.DEFAULT` will be used. The text is always printed used
black text with a white background.
You can set the font using :meth:`.set_font`. If no font has been set,
:data:`Font.DEFAULT <pybricks.media.ev3dev.Font.DEFAULT>` will be
used. The text is always printed used black text with a white
background.
Unlike the builtin ``print()``, the text does not wrap if it is too
wide to fit on |this image|. It just gets cut off. But if the text would
go off of the bottom of |this image|, the entire image is scrolled up and
the text is printed in the new blank area at the bottom of |this image|.
wide to fit on |this image|. It just gets cut off. But if the text
would go off of the bottom of |this image|, the entire image is
scrolled up and the text is printed in the new blank area at the
bottom of |this image|.
Arguments:
* (object):
@@ -184,10 +189,10 @@ class Image:
def set_font(self, font):
"""Sets the font used for writing on |this image|.
The font is used for both :meth:`draw_text` and :meth:`print`.
The font is used for both :meth:`.draw_text` and :meth:`.print`.
Arguments:
font (:class:`Font`):
font (Font):
The font to use.
"""
pass
@@ -239,8 +244,9 @@ class Font:
DEFAULT = None # assigned later since we can't use Font() here
"""The default font."""
def __init__(self, family=None, size=12, bold=False, monospace=False,
lang=None, script=None):
def __init__(
self, family=None, size=12, bold=False, monospace=False, lang=None, script=None
):
"""The font object will be a font that is the "best" match based on the
parameters given and available fonts installed.
@@ -265,7 +271,7 @@ class Font:
@property
def family(self):
"""Gets the family name of the font."""
return 'Lucida'
return "Lucida"
@property
def style(self):
@@ -273,7 +279,7 @@ class Font:
Can be "Regular" or "Bold".
"""
return 'Regular'
return "Regular"
@property
def width(self):
@@ -312,159 +318,159 @@ class Font:
return 0
Font.DEFAULT = Font('Lucida', 12)
Font.DEFAULT = Font("Lucida", 12)
class SoundFile:
"""Paths to standard EV3 sounds."""
_BASE_PATH = '/usr/share/sounds/ev3dev/'
SHOUTING = _BASE_PATH + 'expressions/shouting.wav'
CHEERING = _BASE_PATH + 'expressions/cheering.wav'
CRYING = _BASE_PATH + 'expressions/crying.wav'
OUCH = _BASE_PATH + 'expressions/ouch.wav'
LAUGHING_2 = _BASE_PATH + 'expressions/laughing_2.wav'
SNEEZING = _BASE_PATH + 'expressions/sneezing.wav'
SMACK = _BASE_PATH + 'expressions/smack.wav'
BOING = _BASE_PATH + 'expressions/boing.wav'
BOO = _BASE_PATH + 'expressions/boo.wav'
UH_OH = _BASE_PATH + 'expressions/uh-oh.wav'
SNORING = _BASE_PATH + 'expressions/snoring.wav'
KUNG_FU = _BASE_PATH + 'expressions/kung_fu.wav'
FANFARE = _BASE_PATH + 'expressions/fanfare.wav'
CRUNCHING = _BASE_PATH + 'expressions/crunching.wav'
MAGIC_WAND = _BASE_PATH + 'expressions/magic_wand.wav'
LAUGHING_1 = _BASE_PATH + 'expressions/laughing_1.wav'
LEFT = _BASE_PATH + 'information/left.wav'
BACKWARDS = _BASE_PATH + 'information/backwards.wav'
RIGHT = _BASE_PATH + 'information/right.wav'
OBJECT = _BASE_PATH + 'information/object.wav'
COLOR = _BASE_PATH + 'information/color.wav'
FLASHING = _BASE_PATH + 'information/flashing.wav'
ERROR = _BASE_PATH + 'information/error.wav'
ERROR_ALARM = _BASE_PATH + 'information/error_alarm.wav'
DOWN = _BASE_PATH + 'information/down.wav'
FORWARD = _BASE_PATH + 'information/forward.wav'
ACTIVATE = _BASE_PATH + 'information/activate.wav'
SEARCHING = _BASE_PATH + 'information/searching.wav'
TOUCH = _BASE_PATH + 'information/touch.wav'
UP = _BASE_PATH + 'information/up.wav'
ANALYZE = _BASE_PATH + 'information/analyze.wav'
STOP = _BASE_PATH + 'information/stop.wav'
DETECTED = _BASE_PATH + 'information/detected.wav'
TURN = _BASE_PATH + 'information/turn.wav'
START = _BASE_PATH + 'information/start.wav'
MORNING = _BASE_PATH + 'communication/morning.wav'
EV3 = _BASE_PATH + 'communication/ev3.wav'
GO = _BASE_PATH + 'communication/go.wav'
GOOD_JOB = _BASE_PATH + 'communication/good_job.wav'
OKEY_DOKEY = _BASE_PATH + 'communication/okey-dokey.wav'
GOOD = _BASE_PATH + 'communication/good.wav'
NO = _BASE_PATH + 'communication/no.wav'
THANK_YOU = _BASE_PATH + 'communication/thank_you.wav'
YES = _BASE_PATH + 'communication/yes.wav'
GAME_OVER = _BASE_PATH + 'communication/game_over.wav'
OKAY = _BASE_PATH + 'communication/okay.wav'
SORRY = _BASE_PATH + 'communication/sorry.wav'
BRAVO = _BASE_PATH + 'communication/bravo.wav'
GOODBYE = _BASE_PATH + 'communication/goodbye.wav'
HI = _BASE_PATH + 'communication/hi.wav'
HELLO = _BASE_PATH + 'communication/hello.wav'
MINDSTORMS = _BASE_PATH + 'communication/mindstorms.wav'
LEGO = _BASE_PATH + 'communication/lego.wav'
FANTASTIC = _BASE_PATH + 'communication/fantastic.wav'
SPEED_IDLE = _BASE_PATH + 'movements/speed_idle.wav'
SPEED_DOWN = _BASE_PATH + 'movements/speed_down.wav'
SPEED_UP = _BASE_PATH + 'movements/speed_up.wav'
BROWN = _BASE_PATH + 'colors/brown.wav'
GREEN = _BASE_PATH + 'colors/green.wav'
BLACK = _BASE_PATH + 'colors/black.wav'
WHITE = _BASE_PATH + 'colors/white.wav'
RED = _BASE_PATH + 'colors/red.wav'
BLUE = _BASE_PATH + 'colors/blue.wav'
YELLOW = _BASE_PATH + 'colors/yellow.wav'
TICK_TACK = _BASE_PATH + 'mechanical/tick_tack.wav'
HORN_1 = _BASE_PATH + 'mechanical/horn_1.wav'
BACKING_ALERT = _BASE_PATH + 'mechanical/backing_alert.wav'
MOTOR_IDLE = _BASE_PATH + 'mechanical/motor_idle.wav'
AIR_RELEASE = _BASE_PATH + 'mechanical/air_release.wav'
AIRBRAKE = _BASE_PATH + 'mechanical/airbrake.wav'
RATCHET = _BASE_PATH + 'mechanical/ratchet.wav'
MOTOR_STOP = _BASE_PATH + 'mechanical/motor_stop.wav'
HORN_2 = _BASE_PATH + 'mechanical/horn_2.wav'
LASER = _BASE_PATH + 'mechanical/laser.wav'
SONAR = _BASE_PATH + 'mechanical/sonar.wav'
MOTOR_START = _BASE_PATH + 'mechanical/motor_start.wav'
INSECT_BUZZ_2 = _BASE_PATH + 'animals/insect_buzz_2.wav'
ELEPHANT_CALL = _BASE_PATH + 'animals/elephant_call.wav'
SNAKE_HISS = _BASE_PATH + 'animals/snake_hiss.wav'
DOG_BARK_2 = _BASE_PATH + 'animals/dog_bark_2.wav'
DOG_WHINE = _BASE_PATH + 'animals/dog_whine.wav'
INSECT_BUZZ_1 = _BASE_PATH + 'animals/insect_buzz_1.wav'
DOG_SNIFF = _BASE_PATH + 'animals/dog_sniff.wav'
T_REX_ROAR = _BASE_PATH + 'animals/t-rex_roar.wav'
INSECT_CHIRP = _BASE_PATH + 'animals/insect_chirp.wav'
DOG_GROWL = _BASE_PATH + 'animals/dog_growl.wav'
SNAKE_RATTLE = _BASE_PATH + 'animals/snake_rattle.wav'
DOG_BARK_1 = _BASE_PATH + 'animals/dog_bark_1.wav'
CAT_PURR = _BASE_PATH + 'animals/cat_purr.wav'
EIGHT = _BASE_PATH + 'numbers/eight.wav'
SEVEN = _BASE_PATH + 'numbers/seven.wav'
SIX = _BASE_PATH + 'numbers/six.wav'
FOUR = _BASE_PATH + 'numbers/four.wav'
TEN = _BASE_PATH + 'numbers/ten.wav'
ONE = _BASE_PATH + 'numbers/one.wav'
TWO = _BASE_PATH + 'numbers/two.wav'
THREE = _BASE_PATH + 'numbers/three.wav'
ZERO = _BASE_PATH + 'numbers/zero.wav'
FIVE = _BASE_PATH + 'numbers/five.wav'
NINE = _BASE_PATH + 'numbers/nine.wav'
READY = _BASE_PATH + 'system/ready.wav'
CONFIRM = _BASE_PATH + 'system/confirm.wav'
GENERAL_ALERT = _BASE_PATH + 'system/general_alert.wav'
CLICK = _BASE_PATH + 'system/click.wav'
OVERPOWER = _BASE_PATH + 'system/overpower.wav'
_BASE_PATH = "/usr/share/sounds/ev3dev/"
SHOUTING = _BASE_PATH + "expressions/shouting.wav"
CHEERING = _BASE_PATH + "expressions/cheering.wav"
CRYING = _BASE_PATH + "expressions/crying.wav"
OUCH = _BASE_PATH + "expressions/ouch.wav"
LAUGHING_2 = _BASE_PATH + "expressions/laughing_2.wav"
SNEEZING = _BASE_PATH + "expressions/sneezing.wav"
SMACK = _BASE_PATH + "expressions/smack.wav"
BOING = _BASE_PATH + "expressions/boing.wav"
BOO = _BASE_PATH + "expressions/boo.wav"
UH_OH = _BASE_PATH + "expressions/uh-oh.wav"
SNORING = _BASE_PATH + "expressions/snoring.wav"
KUNG_FU = _BASE_PATH + "expressions/kung_fu.wav"
FANFARE = _BASE_PATH + "expressions/fanfare.wav"
CRUNCHING = _BASE_PATH + "expressions/crunching.wav"
MAGIC_WAND = _BASE_PATH + "expressions/magic_wand.wav"
LAUGHING_1 = _BASE_PATH + "expressions/laughing_1.wav"
LEFT = _BASE_PATH + "information/left.wav"
BACKWARDS = _BASE_PATH + "information/backwards.wav"
RIGHT = _BASE_PATH + "information/right.wav"
OBJECT = _BASE_PATH + "information/object.wav"
COLOR = _BASE_PATH + "information/color.wav"
FLASHING = _BASE_PATH + "information/flashing.wav"
ERROR = _BASE_PATH + "information/error.wav"
ERROR_ALARM = _BASE_PATH + "information/error_alarm.wav"
DOWN = _BASE_PATH + "information/down.wav"
FORWARD = _BASE_PATH + "information/forward.wav"
ACTIVATE = _BASE_PATH + "information/activate.wav"
SEARCHING = _BASE_PATH + "information/searching.wav"
TOUCH = _BASE_PATH + "information/touch.wav"
UP = _BASE_PATH + "information/up.wav"
ANALYZE = _BASE_PATH + "information/analyze.wav"
STOP = _BASE_PATH + "information/stop.wav"
DETECTED = _BASE_PATH + "information/detected.wav"
TURN = _BASE_PATH + "information/turn.wav"
START = _BASE_PATH + "information/start.wav"
MORNING = _BASE_PATH + "communication/morning.wav"
EV3 = _BASE_PATH + "communication/ev3.wav"
GO = _BASE_PATH + "communication/go.wav"
GOOD_JOB = _BASE_PATH + "communication/good_job.wav"
OKEY_DOKEY = _BASE_PATH + "communication/okey-dokey.wav"
GOOD = _BASE_PATH + "communication/good.wav"
NO = _BASE_PATH + "communication/no.wav"
THANK_YOU = _BASE_PATH + "communication/thank_you.wav"
YES = _BASE_PATH + "communication/yes.wav"
GAME_OVER = _BASE_PATH + "communication/game_over.wav"
OKAY = _BASE_PATH + "communication/okay.wav"
SORRY = _BASE_PATH + "communication/sorry.wav"
BRAVO = _BASE_PATH + "communication/bravo.wav"
GOODBYE = _BASE_PATH + "communication/goodbye.wav"
HI = _BASE_PATH + "communication/hi.wav"
HELLO = _BASE_PATH + "communication/hello.wav"
MINDSTORMS = _BASE_PATH + "communication/mindstorms.wav"
LEGO = _BASE_PATH + "communication/lego.wav"
FANTASTIC = _BASE_PATH + "communication/fantastic.wav"
SPEED_IDLE = _BASE_PATH + "movements/speed_idle.wav"
SPEED_DOWN = _BASE_PATH + "movements/speed_down.wav"
SPEED_UP = _BASE_PATH + "movements/speed_up.wav"
BROWN = _BASE_PATH + "colors/brown.wav"
GREEN = _BASE_PATH + "colors/green.wav"
BLACK = _BASE_PATH + "colors/black.wav"
WHITE = _BASE_PATH + "colors/white.wav"
RED = _BASE_PATH + "colors/red.wav"
BLUE = _BASE_PATH + "colors/blue.wav"
YELLOW = _BASE_PATH + "colors/yellow.wav"
TICK_TACK = _BASE_PATH + "mechanical/tick_tack.wav"
HORN_1 = _BASE_PATH + "mechanical/horn_1.wav"
BACKING_ALERT = _BASE_PATH + "mechanical/backing_alert.wav"
MOTOR_IDLE = _BASE_PATH + "mechanical/motor_idle.wav"
AIR_RELEASE = _BASE_PATH + "mechanical/air_release.wav"
AIRBRAKE = _BASE_PATH + "mechanical/airbrake.wav"
RATCHET = _BASE_PATH + "mechanical/ratchet.wav"
MOTOR_STOP = _BASE_PATH + "mechanical/motor_stop.wav"
HORN_2 = _BASE_PATH + "mechanical/horn_2.wav"
LASER = _BASE_PATH + "mechanical/laser.wav"
SONAR = _BASE_PATH + "mechanical/sonar.wav"
MOTOR_START = _BASE_PATH + "mechanical/motor_start.wav"
INSECT_BUZZ_2 = _BASE_PATH + "animals/insect_buzz_2.wav"
ELEPHANT_CALL = _BASE_PATH + "animals/elephant_call.wav"
SNAKE_HISS = _BASE_PATH + "animals/snake_hiss.wav"
DOG_BARK_2 = _BASE_PATH + "animals/dog_bark_2.wav"
DOG_WHINE = _BASE_PATH + "animals/dog_whine.wav"
INSECT_BUZZ_1 = _BASE_PATH + "animals/insect_buzz_1.wav"
DOG_SNIFF = _BASE_PATH + "animals/dog_sniff.wav"
T_REX_ROAR = _BASE_PATH + "animals/t-rex_roar.wav"
INSECT_CHIRP = _BASE_PATH + "animals/insect_chirp.wav"
DOG_GROWL = _BASE_PATH + "animals/dog_growl.wav"
SNAKE_RATTLE = _BASE_PATH + "animals/snake_rattle.wav"
DOG_BARK_1 = _BASE_PATH + "animals/dog_bark_1.wav"
CAT_PURR = _BASE_PATH + "animals/cat_purr.wav"
EIGHT = _BASE_PATH + "numbers/eight.wav"
SEVEN = _BASE_PATH + "numbers/seven.wav"
SIX = _BASE_PATH + "numbers/six.wav"
FOUR = _BASE_PATH + "numbers/four.wav"
TEN = _BASE_PATH + "numbers/ten.wav"
ONE = _BASE_PATH + "numbers/one.wav"
TWO = _BASE_PATH + "numbers/two.wav"
THREE = _BASE_PATH + "numbers/three.wav"
ZERO = _BASE_PATH + "numbers/zero.wav"
FIVE = _BASE_PATH + "numbers/five.wav"
NINE = _BASE_PATH + "numbers/nine.wav"
READY = _BASE_PATH + "system/ready.wav"
CONFIRM = _BASE_PATH + "system/confirm.wav"
GENERAL_ALERT = _BASE_PATH + "system/general_alert.wav"
CLICK = _BASE_PATH + "system/click.wav"
OVERPOWER = _BASE_PATH + "system/overpower.wav"
class ImageFile:
"""Paths to standard EV3 images."""
_BASE_PATH = '/usr/share/images/ev3dev/mono/'
RIGHT = _BASE_PATH + 'information/right.png'
FORWARD = _BASE_PATH + 'information/forward.png'
ACCEPT = _BASE_PATH + 'information/accept.png'
QUESTION_MARK = _BASE_PATH + 'information/question_mark.png'
STOP_1 = _BASE_PATH + 'information/stop_1.png'
LEFT = _BASE_PATH + 'information/left.png'
DECLINE = _BASE_PATH + 'information/decline.png'
THUMBS_DOWN = _BASE_PATH + 'information/thumbs_down.png'
BACKWARD = _BASE_PATH + 'information/backward.png'
NO_GO = _BASE_PATH + 'information/no_go.png'
WARNING = _BASE_PATH + 'information/warning.png'
STOP_2 = _BASE_PATH + 'information/stop_2.png'
THUMBS_UP = _BASE_PATH + 'information/thumbs_up.png'
EV3 = _BASE_PATH + 'lego/ev3.png'
EV3_ICON = _BASE_PATH + 'lego/ev3_icon.png'
TARGET = _BASE_PATH + 'objects/target.png'
BOTTOM_RIGHT = _BASE_PATH + 'eyes/bottom_right.png'
BOTTOM_LEFT = _BASE_PATH + 'eyes/bottom_left.png'
EVIL = _BASE_PATH + 'eyes/evil.png'
CRAZY_2 = _BASE_PATH + 'eyes/crazy_2.png'
KNOCKED_OUT = _BASE_PATH + 'eyes/knocked_out.png'
PINCHED_RIGHT = _BASE_PATH + 'eyes/pinched_right.png'
WINKING = _BASE_PATH + 'eyes/winking.png'
DIZZY = _BASE_PATH + 'eyes/dizzy.png'
DOWN = _BASE_PATH + 'eyes/down.png'
TIRED_MIDDLE = _BASE_PATH + 'eyes/tired_middle.png'
MIDDLE_RIGHT = _BASE_PATH + 'eyes/middle_right.png'
SLEEPING = _BASE_PATH + 'eyes/sleeping.png'
MIDDLE_LEFT = _BASE_PATH + 'eyes/middle_left.png'
TIRED_RIGHT = _BASE_PATH + 'eyes/tired_right.png'
PINCHED_LEFT = _BASE_PATH + 'eyes/pinched_left.png'
PINCHED_MIDDLE = _BASE_PATH + 'eyes/pinched_middle.png'
CRAZY_1 = _BASE_PATH + 'eyes/crazy_1.png'
NEUTRAL = _BASE_PATH + 'eyes/neutral.png'
AWAKE = _BASE_PATH + 'eyes/awake.png'
UP = _BASE_PATH + 'eyes/up.png'
TIRED_LEFT = _BASE_PATH + 'eyes/tired_left.png'
ANGRY = _BASE_PATH + 'eyes/angry.png'
_BASE_PATH = "/usr/share/images/ev3dev/mono/"
RIGHT = _BASE_PATH + "information/right.png"
FORWARD = _BASE_PATH + "information/forward.png"
ACCEPT = _BASE_PATH + "information/accept.png"
QUESTION_MARK = _BASE_PATH + "information/question_mark.png"
STOP_1 = _BASE_PATH + "information/stop_1.png"
LEFT = _BASE_PATH + "information/left.png"
DECLINE = _BASE_PATH + "information/decline.png"
THUMBS_DOWN = _BASE_PATH + "information/thumbs_down.png"
BACKWARD = _BASE_PATH + "information/backward.png"
NO_GO = _BASE_PATH + "information/no_go.png"
WARNING = _BASE_PATH + "information/warning.png"
STOP_2 = _BASE_PATH + "information/stop_2.png"
THUMBS_UP = _BASE_PATH + "information/thumbs_up.png"
EV3 = _BASE_PATH + "lego/ev3.png"
EV3_ICON = _BASE_PATH + "lego/ev3_icon.png"
TARGET = _BASE_PATH + "objects/target.png"
BOTTOM_RIGHT = _BASE_PATH + "eyes/bottom_right.png"
BOTTOM_LEFT = _BASE_PATH + "eyes/bottom_left.png"
EVIL = _BASE_PATH + "eyes/evil.png"
CRAZY_2 = _BASE_PATH + "eyes/crazy_2.png"
KNOCKED_OUT = _BASE_PATH + "eyes/knocked_out.png"
PINCHED_RIGHT = _BASE_PATH + "eyes/pinched_right.png"
WINKING = _BASE_PATH + "eyes/winking.png"
DIZZY = _BASE_PATH + "eyes/dizzy.png"
DOWN = _BASE_PATH + "eyes/down.png"
TIRED_MIDDLE = _BASE_PATH + "eyes/tired_middle.png"
MIDDLE_RIGHT = _BASE_PATH + "eyes/middle_right.png"
SLEEPING = _BASE_PATH + "eyes/sleeping.png"
MIDDLE_LEFT = _BASE_PATH + "eyes/middle_left.png"
TIRED_RIGHT = _BASE_PATH + "eyes/tired_right.png"
PINCHED_LEFT = _BASE_PATH + "eyes/pinched_left.png"
PINCHED_MIDDLE = _BASE_PATH + "eyes/pinched_middle.png"
CRAZY_1 = _BASE_PATH + "eyes/crazy_1.png"
NEUTRAL = _BASE_PATH + "eyes/neutral.png"
AWAKE = _BASE_PATH + "eyes/awake.png"
UP = _BASE_PATH + "eyes/up.png"
TIRED_LEFT = _BASE_PATH + "eyes/tired_left.png"
ANGRY = _BASE_PATH + "eyes/angry.png"
+1 -1
View File
@@ -35,7 +35,7 @@ class Mailbox:
Returns:
The current value or ``None`` if the mailbox is empty.
"""
return ''
return ""
def send(self, value, brick=None):
"""Sends a value to this mailbox on connected devices.
+116 -100
View File
@@ -1,31 +1,37 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2018-2020 The Pybricks Authors
# Copyright (c) 2018-2022 The Pybricks Authors
"""Use LEGO® MINDSTORMS® NXT motors and sensors with the EV3 brick."""
from .iodevices import AnalogSensor as _AnalogSensor
from ._common import ColorLight as _ColorLight
from .parameters import Port, Color
from .iodevices import AnalogSensor
from ._common import ColorLight
from typing import Callable, Optional, Tuple
class TouchSensor:
"""LEGO® MINDSTORMS® NXT Touch Sensor."""
def __init__(self, port):
"""
def __init__(self, port: Port):
"""TouchSensor(port)
Arguments:
port (Port): Port to which the sensor is connected.
"""
pass
def pressed(self):
"""Checks if the sensor is pressed.
def pressed(self) -> bool:
"""pressed() -> bool
Checks if the sensor is pressed.
Returns:
bool: ``True`` if the sensor is pressed, ``False`` if it is
``True`` if the sensor is pressed, ``False`` if it is
not pressed.
"""
pass
@@ -33,86 +39,88 @@ class TouchSensor:
class LightSensor:
"""LEGO® MINDSTORMS® NXT Color Sensor."""
def __init__(self, port):
"""
def __init__(self, port: Port):
"""LightSensor(port)
Arguments:
port (Port): Port to which the sensor is connected.
"""
pass
def ambient(self):
"""Measures the ambient light intensity.
def ambient(self) -> int:
"""ambient() -> int: %
Measures the ambient light intensity.
Returns:
:ref:`percentage`: Ambient light intensity, ranging from 0 (dark)
to 100 (bright).
Ambient light intensity, ranging from 0% (dark) to 100% (bright).
"""
pass
def reflection(self):
"""Measures the reflection of a surface using a red light.
def reflection(self) -> int:
"""reflection() -> int: %
Measures the reflection of a surface using a red light.
Returns:
:ref:`percentage`: Reflection, ranging from 0 (no reflection) to
100 (high reflection).
Reflection, ranging from 0% (no reflection) to 100% (high
reflection).
"""
pass
class ColorSensor:
class ColorSensor(LightSensor):
"""LEGO® MINDSTORMS® NXT Color Sensor."""
light = _ColorLight()
light = ColorLight()
def __init__(self, port):
"""
def __init__(self, port: Port):
"""ColorSensor(port)
Arguments:
port (Port): Port to which the sensor is connected.
"""
pass
def color(self):
"""Measures the color of a surface.
def color(self) -> Color:
"""color() -> Color
:returns:
Measures the color of a surface.
Returns:
``Color.BLACK``, ``Color.BLUE``, ``Color.GREEN``, ``Color.YELLOW``,
``Color.RED``, ``Color.WHITE`` or ``Color.NONE``.
:rtype: :class:`Color <.parameters.Color>`
"""
pass
def ambient(self):
"""Measures the ambient light intensity.
def ambient(self) -> int:
"""ambient() -> int: %
Measures the ambient light intensity.
Returns:
:ref:`percentage`: Ambient light intensity, ranging from 0 (dark)
to 100 (bright).
Ambient light intensity, ranging from 0% (dark) to 100% (bright).
"""
pass
def reflection(self):
"""Measures the reflection of a surface.
def reflection(self) -> int:
"""reflection() -> int: %
Measures the reflection of a surface using a red light.
Returns:
:ref:`percentage`: Reflection, ranging from 0 (no reflection) to
100 (high reflection).
Reflection, ranging from 0% (no reflection) to 100% (high
reflection).
"""
pass
def rgb(self):
def rgb(self) -> Tuple[int, int, int]:
"""Measures the reflection of a surface using a red, green, and then a
blue light.
:returns: Tuple of reflections for red, green, and blue light, each
ranging from 0.0 (no reflection) to 100.0 (high reflection).
:rtype: (:ref:`percentage`, :ref:`percentage`, :ref:`percentage`)
Returns:
Tuple of reflections for red, green, and blue light, each
ranging from 0.0% (no reflection) to 100.0% (high reflection).
"""
pass
@@ -120,22 +128,22 @@ class ColorSensor:
class UltrasonicSensor:
"""LEGO® MINDSTORMS® NXT Ultrasonic Sensor."""
def __init__(self, port):
"""
def __init__(self, port: Port):
"""UltrasonicSensor(port)
Arguments:
port (Port): Port to which the sensor is connected.
"""
pass
def distance(self):
"""Measures the distance between the sensor and an object using
def distance(self) -> int:
"""distance() -> int: mm
Measures the distance between the sensor and an object using
ultrasonic sound waves.
Returns:
:ref:`distance`: Distance.
Measured distance.
"""
pass
@@ -143,17 +151,18 @@ class UltrasonicSensor:
class SoundSensor:
"""LEGO® MINDSTORMS® NXT Sound Sensor."""
def __init__(self, port):
"""
def __init__(self, port: Port):
"""SoundSensor(port)
Arguments:
port (Port): Port to which the sensor is connected.
"""
pass
def intensity(self, audible_only=True):
"""Measures the ambient sound intensity (loudness).
def intensity(self, audible_only: bool = True) -> int:
"""intensity(audible_only=True) -> int: %
Measures the ambient sound intensity (loudness).
Arguments:
audible_only (bool): Detect only audible sounds. This tries to
@@ -161,8 +170,7 @@ class SoundSensor:
human ear.
Returns:
:ref:`percentage`: Sound intensity.
Sound intensity.
"""
pass
@@ -170,21 +178,21 @@ class SoundSensor:
class TemperatureSensor:
"""LEGO® MINDSTORMS® NXT Temperature Sensor."""
def __init__(self, port):
"""
def __init__(self, port: Port):
"""TemperatureSensor(port)
Arguments:
port (Port): Port to which the sensor is connected.
"""
pass
def temperature(self):
"""Measures the temperature.
def temperature(self) -> int:
"""temperature() -> float: °C
Measures the temperature.
Returns:
:ref:`temperature`: Measured temperature.
Measured temperature.
"""
pass
@@ -192,26 +200,28 @@ class TemperatureSensor:
class EnergyMeter:
"""LEGO® MINDSTORMS® Education NXT Energy Meter."""
def __init__(self, port):
"""
def __init__(self, port: Port):
"""EnergyMeter(port)
Arguments:
port (Port): Port to which the sensor is connected.
"""
pass
def storage(self):
"""Gets the total available energy stored in the battery.
def storage(self) -> int:
"""storage() -> int: J
Gets the total available energy stored in the battery.
Returns:
:ref:`energy`: Remaining stored energy.
Remaining stored energy.
"""
pass
def input(self):
"""Measures the electrical signals at the input (bottom) side
def input(self) -> Tuple[int, int, int]:
"""input() -> Tuple[int, int, int]
Measures the electrical signals at the input (bottom) side
of the energy meter. It measures the voltage applied to it and the
current passing through it. The product of these two values is power.
This power value is the rate at which the stored energy increases. This
@@ -219,14 +229,15 @@ class EnergyMeter:
or an externally driven motor.
Returns:
(:ref:`voltage`, :ref:`current`, :ref:`power`): Voltage, current,
and power measured at the input port.
Voltage (mV), current (mA), and power (mW) measured at the input
port.
"""
pass
def output(self):
"""Measures the electrical signals at the output (top) side
def output(self) -> Tuple[int, int, int]:
"""output() -> Tuple[int, int, int]
Measures the electrical signals at the output (top) side
of the energy meter. It measures the voltage applied to the external
load and the current passing to it. The product of these two values
is power. This power value is the rate at which the stored energy
@@ -234,22 +245,21 @@ class EnergyMeter:
motor.
Returns:
(:ref:`voltage`, :ref:`current`, :ref:`power`): Voltage, current,
and power measured at the output port.
Voltage (mV), current (mA), and power (mW) measured at the output
port.
"""
pass
class VernierAdapter(_AnalogSensor):
class VernierAdapter(AnalogSensor):
"""LEGO® MINDSTORMS® Education NXT/EV3 Adapter for Vernier Sensors."""
def __init__(self, port, conversion=None):
"""
def __init__(self, port: Port, conversion: Optional[Callable[[int], float]] = None):
"""VernierAdapter(port, conversion=None)
Arguments:
port (Port): Port to which the sensor is connected.
conversion (callable): Function of the format ``conversion``.
conversion (callable): Function of the format :meth:`.conversion`.
This function is used to convert the raw analog voltage to the
sensor-specific output value. Each Vernier Sensor has its
own conversion function. The example given below demonstrates
@@ -257,33 +267,39 @@ class VernierAdapter(_AnalogSensor):
"""
pass
def voltage(self):
"""Measures the raw analog sensor voltage.
def voltage(self) -> int:
"""voltage() -> int: mV
Measures the raw analog sensor voltage.
Returns:
:ref:`voltage`: Analog voltage.
Analog voltage.
"""
pass
def conversion(self, voltage):
"""Converts the raw voltage (mV) to a sensor value.
def conversion(self, voltage: int) -> float:
"""conversion(voltage) -> float
If you did not provide a ``conversion`` function earlier, no conversion
will be applied.
Converts the raw voltage (mV) to a sensor value.
If you did not provide a :meth:`.conversion` function earlier, no
conversion will be applied.
Arguments:
voltage (:ref:`voltage`): Analog sensor voltage
voltage (Number, mV): Analog sensor voltage
:returns: Converted sensor value.
:rtype: float
Returns:
Converted sensor value.
"""
pass
def value(self):
"""Measures the sensor :meth:`.voltage` and then
def value(self) -> float:
"""value() -> float
Measures the sensor :meth:`.voltage` and then
applies your :meth:`.conversion` to give you the sensor value.
:returns: Converted sensor value.
:rtype: float
Returns:
Converted sensor value.
"""
pass
-51
View File
@@ -1,51 +0,0 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2020 The Pybricks Authors
from typing import Callable, Optional, Tuple
from ._common import ColorLight
from .iodevices import AnalogSensor
from .parameters import Color, Port
class TouchSensor:
def __init__(self, port: Port): ...
def pressed(self) -> bool: ...
class LightSensor:
def __init__(self, port: Port): ...
def ambient(self) -> int: ...
def reflection(self) -> int: ...
class ColorSensor:
light: ColorLight
def __init__(self, port: Port): ...
def color(self) -> Optional[Color]: ...
def ambient(self) -> int: ...
def reflection(self) -> int: ...
def rgb(self) -> Tuple[int, int, int]: ...
class UltrasonicSensor:
def __init__(self, port: Port): ...
def distance(self) -> int: ...
class SoundSensor:
def __init__(self, port: Port): ...
def intensity(self, audible_only: bool = True) -> int: ...
class TemperatureSensor:
def __init__(self, port: Port): ...
def temperature(self) -> int: ...
class EnergyMeter:
def __init__(self, port: Port): ...
def storage(self) -> int: ...
def input(self) -> Tuple[int, int, int]: ...
def output(self) -> Tuple[int, int, int]: ...
class VernierAdapter(AnalogSensor):
def __init__(
self, port: Port, conversion: Optional[Callable[[int], float]] = None
): ...
def voltage(self) -> int: ...
def conversion(self, voltage: int) -> float: ...
def value(self) -> float: ...
+22 -18
View File
@@ -8,20 +8,20 @@ from enum import Enum as _Enum
class _PybricksEnumMeta(type(_Enum)):
def __dir__(cls):
yield '__class__'
yield '__name__'
yield "__class__"
yield "__name__"
for member in cls:
yield member.name
class _PybricksEnum(_Enum, metaclass=_PybricksEnumMeta):
def __dir__(self):
yield '__class__'
yield "__class__"
for member in type(self):
yield member.name
def __str__(self):
return '{}.{}'.format(type(self).__name__, self.name)
return "{}.{}".format(type(self).__name__, self.name)
def __repr__(self):
return str(self)
@@ -39,8 +39,12 @@ class Color:
return "Color(h={}, s={}, v={})".format(self.h, self.s, self.v)
def __eq__(self, other):
return (isinstance(other, Color) and
self.h == other.h and self.s == other.s and self.v == other.v)
return (
isinstance(other, Color)
and self.h == other.h
and self.s == other.s
and self.v == other.v
)
def __mul__(self, scale):
v = max(0, min(self.v * scale, 100))
@@ -50,10 +54,10 @@ class Color:
return self.__mul__(scale)
def __truediv__(self, scale):
return self.__mul__(1/scale)
return self.__mul__(1 / scale)
def __floordiv__(self, scale):
return self.__mul__(1/scale)
return self.__mul__(1 / scale)
Color.NONE = Color(0, 0, 0)
@@ -75,18 +79,18 @@ class Port(_PybricksEnum):
"""Port on the programmable brick or hub."""
# Generic motor/sensor ports
A = ord('A')
B = ord('B')
C = ord('C')
D = ord('D')
E = ord('E')
F = ord('F')
A = ord("A")
B = ord("B")
C = ord("C")
D = ord("D")
E = ord("E")
F = ord("F")
# NXT/EV3 sensor ports
S1 = ord('1')
S2 = ord('2')
S3 = ord('3')
S4 = ord('4')
S1 = ord("1")
S2 = ord("2")
S3 = ord("3")
S4 = ord("4")
class Stop(_PybricksEnum):
+44
View File
@@ -1,6 +1,8 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2020 The Pybricks Authors
from geometry import Matrix
class Color:
BLACK: Color
BLUE: Color
@@ -15,6 +17,8 @@ class Color:
VIOLET: Color
WHITE: Color
YELLOW: Color
def __init__(self, h: int, s: int = 100, v: int = 100): ...
def __eq__(self, other: "Color") -> bool: ...
def __mul__(self, scale: float) -> Color: ...
def __rmul__(self, scale: float) -> Color: ...
def __truediv__(self, scale: float) -> Color: ...
@@ -25,6 +29,8 @@ class Port:
B: Port
C: Port
D: Port
E: Port
F: Port
S1: Port
S2: Port
S3: Port
@@ -63,3 +69,41 @@ class Side:
LEFT: Side
BACK: Side
BOTTOM: Side
class Icon:
UP: Matrix
DOWN: Matrix
LEFT: Matrix
RIGHT: Matrix
ARROW_RIGHT_UP: Matrix
ARROW_RIGHT_DOWN: Matrix
ARROW_LEFT_UP: Matrix
ARROW_LEFT_DOWN: Matrix
ARROW_UP: Matrix
ARROW_DOWN: Matrix
ARROW_LEFT: Matrix
ARROW_RIGHT: Matrix
HAPPY: Matrix
SAD: Matrix
EYE_LEFT: Matrix
EYE_RIGHT: Matrix
EYE_LEFT_BLINK: Matrix
EYE_RIGHT_BLINK: Matrix
EYE_RIGHT_BROW: Matrix
EYE_LEFT_BROW: Matrix
EYE_LEFT_BROW_UP: Matrix
EYE_RIGHT_BROW_UP: Matrix
HEART: Matrix
PAUSE: Matrix
EMPTY: Matrix
FULL: Matrix
SQUARE: Matrix
TRIANGLE_RIGHT: Matrix
TRIANGLE_LEFT: Matrix
TRIANGLE_UP: Matrix
TRIANGLE_DOWN: Matrix
CIRCLE: Matrix
CLOCKWISE: Matrix
COUNTERCLOCKWISE: Matrix
TRUE: Matrix
FALSE: Matrix
+48 -22
View File
@@ -1,26 +1,38 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2018-2020 The Pybricks Authors
# Copyright (c) 2018-2022 The Pybricks Authors
"""LEGO® Powered Up motor, sensors, and lights."""
from ._common import (Keypad as _Keypad, DCMotor,
ColorLight as _ColorLight, Motor as _Motor,
LightArray as _LightArray, Light as _Light)
from typing import Optional
from ._common import (
Keypad as _Keypad,
DCMotor as _DCMotor,
ColorLight as _ColorLight,
Motor as _Motor,
LightArray as _LightArray,
)
from .parameters import Direction as _Direction, Button as _Button
class DCMotor(_DCMotor):
pass
class Motor(_Motor):
"""Generic class to control motors with built-in rotation sensors."""
def reset_angle(self, angle=None):
"""Sets the accumulated rotation angle of the motor to a desired value.
def reset_angle(self, angle: Optional[int]) -> None:
"""reset_angle(angle=None)
Sets the accumulated rotation angle of the motor to a desired value.
If you don't specify an angle, the absolute angle
will be used if your motor supports it.
Arguments:
angle (:ref:`angle`): Value to which the angle should be reset.
angle (Number, deg): Value to which the angle should be reset.
"""
pass
@@ -29,15 +41,17 @@ class Remote:
"""LEGO® Powered Up Bluetooth Remote Control."""
light = _ColorLight()
buttons = _Keypad((
_Button.LEFT_MINUS,
_Button.RIGHT_MINUS,
_Button.LEFT,
_Button.CENTER,
_Button.RIGHT,
_Button.LEFT_PLUS,
_Button.RIGHT_PLUS
))
buttons = _Keypad(
(
_Button.LEFT_MINUS,
_Button.RIGHT_MINUS,
_Button.LEFT,
_Button.CENTER,
_Button.RIGHT,
_Button.LEFT_PLUS,
_Button.RIGHT_PLUS,
)
)
def __init__(self, name=None, timeout=10000):
"""When you instantiate this class, the hub will search for a remote
@@ -178,11 +192,7 @@ class PFMotor(DCMotor):
"""Control Power Functions motors with the infrared functionality of the
:class:`ColorDistanceSensor <pybricks.pupdevices.ColorDistanceSensor>`."""
def __init__(self,
sensor,
channel,
color,
positive_direction=_Direction.CLOCKWISE):
def __init__(self, sensor, channel, color, positive_direction=_Direction.CLOCKWISE):
"""
Arguments:
@@ -449,7 +459,7 @@ class InfraredSensor:
pass
class Light(_Light):
class Light:
"""LEGO® Powered Up Light."""
def __init__(self, port):
@@ -460,3 +470,19 @@ class Light(_Light):
"""
pass
def on(self, brightness: int = 100) -> None:
"""on(brightness=100)
Turns on the light at the specified brightness.
Arguments:
brightness (Number, %):
Brightness of the light.
"""
def off(self) -> None:
"""off()
Turns off the light."""
pass
+10 -5
View File
@@ -1,14 +1,19 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2020 The Pybricks Authors
# Copyright (c) 2020-2022 The Pybricks Authors
from typing import Collection, List, Optional, Tuple, Union
from ._common import Keypad, DCMotor, ColorLight, LightArray, Motor as BaseMotor, Light as BaseLight
from ._common import (
Keypad,
DCMotor as _DCMotor,
ColorLight,
LightArray,
Motor as _Motor,
Light as BaseLight,
)
from .parameters import Color, Direction, Port
class Motor(BaseMotor): ...
class Remote:
light: ColorLight
buttons: Keypad
@@ -63,7 +68,7 @@ class ForceSensor:
class ColorLightMatrix:
def __init__(self, port: Port) -> None: ...
def on(self, color: Union[Color, List[Color]]) -> None: ...
def off(self)-> None: ...
def off(self) -> None: ...
class InfraredSensor:
def __init__(self, port: Port): ...
+4 -3
View File
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2018-2020 The Pybricks Authors
# Copyright (c) 2018-2021 The Pybricks Authors
"""Robotics module for the Pybricks API."""
@@ -100,8 +100,9 @@ class DriveBase:
"""Resets the estimated driven distance and angle to 0."""
pass
def settings(self, straight_speed, straight_acceleration, turn_rate,
turn_acceleration):
def settings(
self, straight_speed, straight_acceleration, turn_rate, turn_acceleration
):
"""Configures the speed and acceleration used
by :meth:`.straight`, :meth:`.turn`, and :meth:`.curve`.
+6 -1
View File
@@ -1,8 +1,10 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2020 The Pybricks Authors
# Copyright (c) 2020-2021 The Pybricks Authors
from typing import Optional, Tuple, overload, Union
from ._common import Control, Motor
from .parameters import Stop
class DriveBase:
distance_control: Control
@@ -32,3 +34,6 @@ class DriveBase:
) -> None: ...
def straight(self, distance: int) -> None: ...
def turn(self, angle: int) -> None: ...
def curve(
self, radius: int, angle: int, then: Stop = Stop.HOLD, wait: bool = True
) -> None: ...
+3 -2
View File
@@ -51,8 +51,9 @@ class StopWatch:
class DataLog:
"""Create a file and log data."""
def __init__(self, *headers, name='log', timestamp=True, extension='csv',
append=False):
def __init__(
self, *headers, name="log", timestamp=True, extension="csv", append=False
):
"""
Arguments: