mirror of
https://github.com/pybricks/pybricks-api.git
synced 2026-07-27 19:57:02 +00:00
jedi: add new pybricks_jedi package
This package will be used in Pybricks Code to provide some intellesense operations.
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
name: pybricks_jedi
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
if: github.ref_type != 'tag'
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- run: pipx install poetry
|
||||
- run: poetry install
|
||||
working-directory: ./jedi
|
||||
- run: poetry run pytest -vv
|
||||
working-directory: ./jedi
|
||||
|
||||
publish:
|
||||
if: github.ref_type == 'tag' && startsWith(github.ref_name, 'pybricks_jedi/')
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- run: pipx install poetry
|
||||
- run: poetry install
|
||||
- run: poetry build
|
||||
- run: poetry publish
|
||||
env:
|
||||
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_PYBRICKS_JEDI_TOKEN }}
|
||||
+2
-1
@@ -26,8 +26,9 @@ build/
|
||||
build-*/
|
||||
_build/
|
||||
|
||||
# Test failure outputs
|
||||
# Tests
|
||||
######################
|
||||
.pytest_cache/
|
||||
tests/*.exp
|
||||
tests/*.out
|
||||
|
||||
|
||||
Vendored
+9
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"python.autoComplete.extraPaths": ["jedi/src"],
|
||||
"python.formatting.provider": "black",
|
||||
"python.linting.pylintEnabled": false,
|
||||
"python.linting.flake8Enabled": true,
|
||||
@@ -9,6 +10,11 @@
|
||||
"editor.defaultFormatter": "ms-python.python"
|
||||
},
|
||||
"python.languageServer": "Pylance",
|
||||
"python.testing.pytestArgs": [
|
||||
"jedi/tests"
|
||||
],
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.pytestEnabled": true,
|
||||
"files.associations": {"*.inc": "restructuredtext"},
|
||||
"restructuredtext.confPath": "${workspaceFolder}/doc/main",
|
||||
"spellright.language": [
|
||||
@@ -40,4 +46,7 @@
|
||||
"restructuredtext",
|
||||
],
|
||||
"rewrap.wrappingColumn": 78,
|
||||
"python.analysis.extraPaths": [
|
||||
"jedi/src"
|
||||
],
|
||||
}
|
||||
|
||||
+13
-1
@@ -27,6 +27,9 @@ from docutils import nodes
|
||||
from docutils.parsers.rst.directives import flag
|
||||
from docutils.parsers.rst import Directive
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.addnodes import pending_xref
|
||||
from sphinx.environment import BuildEnvironment
|
||||
from sphinx.util.nodes import make_refnode
|
||||
import toml
|
||||
|
||||
TOP_DIR = os.path.abspath(os.path.join("..", ".."))
|
||||
@@ -307,7 +310,16 @@ class AvailabilityDirective(Directive):
|
||||
]
|
||||
|
||||
|
||||
def on_missing_reference(app, env, node, contnode):
|
||||
def on_missing_reference(
|
||||
app: Sphinx, env: BuildEnvironment, node: pending_xref, contnode: nodes.Element
|
||||
) -> nodes.Element:
|
||||
# The Number type alias is on the Signals and Units page instead of on the
|
||||
# pybricks.parameters page so normal resolution doesn't work
|
||||
if node["reftype"] == "class" and node["reftarget"] == "Number":
|
||||
return make_refnode(
|
||||
app.builder, node["refdoc"], "signaltypes", "numbers", 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.
|
||||
|
||||
@@ -25,6 +25,9 @@ latex_logo = "../common/images/pybricks-logo-large.png"
|
||||
if os.environ.get("READTHEDOCS", None) == "True":
|
||||
tags.add("main") # noqa F821
|
||||
|
||||
# HACK: this allows Number type alias to be imported by Sphinx
|
||||
os.environ["SPHINX_BUILD"] = "True"
|
||||
|
||||
# Addtional configuration of the IDE docs
|
||||
if "ide" in tags.tags: # noqa F821
|
||||
_DISCLAIMER = ""
|
||||
|
||||
@@ -7,22 +7,8 @@ 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.
|
||||
.. autodata:: pybricks.parameters.Number
|
||||
:noindex:
|
||||
|
||||
Time
|
||||
~~~~~~
|
||||
|
||||
Generated
+370
@@ -0,0 +1,370 @@
|
||||
[[package]]
|
||||
name = "atomicwrites"
|
||||
version = "1.4.0"
|
||||
description = "Atomic file writes."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
version = "21.4.0"
|
||||
description = "Classes Without Boilerplate"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[package.extras]
|
||||
dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"]
|
||||
docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
|
||||
tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"]
|
||||
tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"]
|
||||
|
||||
[[package]]
|
||||
name = "black"
|
||||
version = "22.3.0"
|
||||
description = "The uncompromising code formatter."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6.2"
|
||||
|
||||
[package.dependencies]
|
||||
click = ">=8.0.0"
|
||||
mypy-extensions = ">=0.4.3"
|
||||
pathspec = ">=0.9.0"
|
||||
platformdirs = ">=2"
|
||||
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
|
||||
|
||||
[package.extras]
|
||||
colorama = ["colorama (>=0.4.3)"]
|
||||
d = ["aiohttp (>=3.7.4)"]
|
||||
jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
|
||||
uvloop = ["uvloop (>=0.15.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.1.3"
|
||||
description = "Composable command line interface toolkit"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.5"
|
||||
description = "Cross-platform colored terminal text."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "flake8"
|
||||
version = "4.0.1"
|
||||
description = "the modular source code checker: pep8 pyflakes and co"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
mccabe = ">=0.6.0,<0.7.0"
|
||||
pycodestyle = ">=2.8.0,<2.9.0"
|
||||
pyflakes = ">=2.4.0,<2.5.0"
|
||||
|
||||
[[package]]
|
||||
name = "iniconfig"
|
||||
version = "1.1.1"
|
||||
description = "iniconfig: brain-dead simple config-ini parsing"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "jedi"
|
||||
version = "0.18.1"
|
||||
description = "An autocompletion tool for Python that can be used for text editors."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
parso = ">=0.8.0,<0.9.0"
|
||||
|
||||
[package.extras]
|
||||
qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
|
||||
testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "mccabe"
|
||||
version = "0.6.1"
|
||||
description = "McCabe checker, plugin for flake8"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "mypy-extensions"
|
||||
version = "0.4.3"
|
||||
description = "Experimental type system extensions for programs checked with the mypy typechecker."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "21.3"
|
||||
description = "Core utilities for Python packages"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
|
||||
|
||||
[[package]]
|
||||
name = "parso"
|
||||
version = "0.8.3"
|
||||
description = "A Python Parser"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.extras]
|
||||
qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
|
||||
testing = ["docopt", "pytest (<6.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "pathspec"
|
||||
version = "0.9.0"
|
||||
description = "Utility library for gitignore style pattern matching of file paths."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
|
||||
|
||||
[[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 = "pluggy"
|
||||
version = "1.0.0"
|
||||
description = "plugin and hook calling mechanisms for python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.extras]
|
||||
dev = ["pre-commit", "tox"]
|
||||
testing = ["pytest", "pytest-benchmark"]
|
||||
|
||||
[[package]]
|
||||
name = "py"
|
||||
version = "1.11.0"
|
||||
description = "library with cross-python path, ini-parsing, io, code, log facilities"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "pybricks"
|
||||
version = "3.2.0b1-r1"
|
||||
description = "Documentation and user-API stubs for Pybricks MicroPython"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "^3.8"
|
||||
develop = true
|
||||
|
||||
[package.source]
|
||||
type = "directory"
|
||||
url = ".."
|
||||
|
||||
[[package]]
|
||||
name = "pycodestyle"
|
||||
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.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "pyflakes"
|
||||
version = "2.4.0"
|
||||
description = "passive checker of Python programs"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "3.0.9"
|
||||
description = "pyparsing module - Classes and methods to define and execute parsing grammars"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6.8"
|
||||
|
||||
[package.extras]
|
||||
diagrams = ["railroad-diagrams", "jinja2"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "7.1.2"
|
||||
description = "pytest: simple powerful testing with Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.dependencies]
|
||||
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
|
||||
attrs = ">=19.2.0"
|
||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||
iniconfig = "*"
|
||||
packaging = "*"
|
||||
pluggy = ">=0.12,<2.0"
|
||||
py = ">=1.8.2"
|
||||
tomli = ">=1.0.0"
|
||||
|
||||
[package.extras]
|
||||
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
|
||||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
version = "2.0.1"
|
||||
description = "A lil' TOML parser"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.2.0"
|
||||
description = "Backported and Experimental Type Hints for Python 3.7+"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = ">= 3.10, < 3.11"
|
||||
content-hash = "e2b0bd41f109d9d7b6a4a7b73e61784fe3995be07470d76cbd86b9d42ec6205b"
|
||||
|
||||
[metadata.files]
|
||||
atomicwrites = [
|
||||
{file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
|
||||
{file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
|
||||
]
|
||||
attrs = [
|
||||
{file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"},
|
||||
{file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"},
|
||||
]
|
||||
black = [
|
||||
{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"},
|
||||
]
|
||||
click = [
|
||||
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
|
||||
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
|
||||
]
|
||||
colorama = [
|
||||
{file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"},
|
||||
{file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
|
||||
]
|
||||
flake8 = [
|
||||
{file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"},
|
||||
{file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"},
|
||||
]
|
||||
iniconfig = [
|
||||
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
||||
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
|
||||
]
|
||||
jedi = [
|
||||
{file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"},
|
||||
{file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"},
|
||||
]
|
||||
mccabe = [
|
||||
{file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
|
||||
{file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
|
||||
]
|
||||
mypy-extensions = [
|
||||
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
|
||||
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
|
||||
]
|
||||
packaging = [
|
||||
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
|
||||
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
|
||||
]
|
||||
parso = [
|
||||
{file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"},
|
||||
{file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"},
|
||||
]
|
||||
pathspec = [
|
||||
{file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
|
||||
{file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
|
||||
]
|
||||
platformdirs = [
|
||||
{file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"},
|
||||
{file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"},
|
||||
]
|
||||
pluggy = [
|
||||
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
|
||||
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
|
||||
]
|
||||
py = [
|
||||
{file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
|
||||
{file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
|
||||
]
|
||||
pybricks = []
|
||||
pycodestyle = [
|
||||
{file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"},
|
||||
{file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"},
|
||||
]
|
||||
pyflakes = [
|
||||
{file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"},
|
||||
{file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"},
|
||||
]
|
||||
pyparsing = [
|
||||
{file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
|
||||
{file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
|
||||
]
|
||||
pytest = [
|
||||
{file = "pytest-7.1.2-py3-none-any.whl", hash = "sha256:13d0e3ccfc2b6e26be000cb6568c832ba67ba32e719443bfe725814d3c42433c"},
|
||||
{file = "pytest-7.1.2.tar.gz", hash = "sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"},
|
||||
]
|
||||
tomli = [
|
||||
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
|
||||
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
|
||||
]
|
||||
typing-extensions = [
|
||||
{file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"},
|
||||
{file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"},
|
||||
]
|
||||
@@ -0,0 +1,25 @@
|
||||
[tool.poetry]
|
||||
name = "pybricks_jedi"
|
||||
version = "1.0.0"
|
||||
description = "Code completion for Pybricks."
|
||||
authors = ["The Pybricks Authors"]
|
||||
license = "MIT"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">= 3.10, < 3.11"
|
||||
pybricks = { path = "../", develop = true }
|
||||
jedi = "^0.18.1"
|
||||
typing-extensions = "^4.2.0"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
pytest = "^7.1.2"
|
||||
black = "^22.3.0"
|
||||
flake8 = "^4.0.1"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
pythonpath = ["src"]
|
||||
testpaths = ["tests"]
|
||||
@@ -0,0 +1,391 @@
|
||||
from enum import IntEnum
|
||||
import json
|
||||
from typing_extensions import TypedDict, NotRequired
|
||||
import jedi
|
||||
from jedi.api.classes import Completion, Signature, ParamName
|
||||
|
||||
# Packages included in Pybricks firmware that ships with Pybricks Code.
|
||||
PYBRICKS_CODE_PACKAGES = {
|
||||
"micropython",
|
||||
"pybricks",
|
||||
"pybricks.geometry",
|
||||
"pybricks.hubs",
|
||||
"pybricks.iodevices",
|
||||
"pybricks.parameters",
|
||||
"pybricks.pupdevices",
|
||||
"pybricks.robotics",
|
||||
"pybricks.tools",
|
||||
"uerrno",
|
||||
"uio",
|
||||
"umath",
|
||||
"urandom",
|
||||
"uselect",
|
||||
"usys",
|
||||
}
|
||||
|
||||
# Subset of Python builtins included in Pybricks MicroPython.
|
||||
PYBRICKS_BUILTINS = {
|
||||
"abs",
|
||||
"all",
|
||||
"any",
|
||||
"ArithmeticError",
|
||||
"AssertionError",
|
||||
"AttributeError",
|
||||
"BaseException",
|
||||
"bin",
|
||||
"bool",
|
||||
"bytearray",
|
||||
"bytes",
|
||||
"callable",
|
||||
"chr",
|
||||
"classmethod",
|
||||
"complex",
|
||||
"dict",
|
||||
"dir",
|
||||
"divmod",
|
||||
"enumerate",
|
||||
"EOFError",
|
||||
"eval",
|
||||
"Exception",
|
||||
"exec",
|
||||
"float",
|
||||
"GeneratorExit",
|
||||
"getattr",
|
||||
"globals",
|
||||
"hasattr",
|
||||
"hash",
|
||||
"help",
|
||||
"hex",
|
||||
"id",
|
||||
"ImportError",
|
||||
"IndentationError",
|
||||
"IndexError",
|
||||
"input",
|
||||
"int",
|
||||
"isinstance",
|
||||
"issubclass",
|
||||
"iter",
|
||||
"KeyboardInterrupt",
|
||||
"KeyError",
|
||||
"len",
|
||||
"list",
|
||||
"locals",
|
||||
"LookupError",
|
||||
"map",
|
||||
"max",
|
||||
"MemoryError",
|
||||
"min",
|
||||
"NameError",
|
||||
"next",
|
||||
"NotImplementedError",
|
||||
"object",
|
||||
"oct",
|
||||
"ord",
|
||||
"OSError",
|
||||
"OverflowError",
|
||||
"pow",
|
||||
"print",
|
||||
"range",
|
||||
"repr",
|
||||
"reversed",
|
||||
"round",
|
||||
"RuntimeError",
|
||||
"set",
|
||||
"setattr",
|
||||
"slice",
|
||||
"sorted",
|
||||
"staticmethod",
|
||||
"StopIteration",
|
||||
"str",
|
||||
"sum",
|
||||
"super",
|
||||
"SyntaxError",
|
||||
"SystemExit",
|
||||
"tuple",
|
||||
"type",
|
||||
"TypeError",
|
||||
"ValueError",
|
||||
"ZeroDivisionError",
|
||||
"zip",
|
||||
}
|
||||
|
||||
# Types from monaco editor
|
||||
|
||||
|
||||
class IRange(TypedDict):
|
||||
startLineNumber: int
|
||||
startColumn: int
|
||||
endLineNumber: int
|
||||
endColumn: int
|
||||
|
||||
|
||||
class ISingleEditOperation(TypedDict):
|
||||
range: IRange
|
||||
text: str # TODO: can also be JavaScript null
|
||||
forceMoveMarkers: NotRequired[bool]
|
||||
|
||||
|
||||
class Command(TypedDict):
|
||||
id: str
|
||||
title: str
|
||||
tooltip: NotRequired[str]
|
||||
arguments: NotRequired[list]
|
||||
|
||||
|
||||
class CompletionItemKind(IntEnum):
|
||||
Method = 0
|
||||
Function = 1
|
||||
Constructor = 2
|
||||
Field = 3
|
||||
Variable = 4
|
||||
Class = 5
|
||||
Struct = 6
|
||||
Interface = 7
|
||||
Module = 8
|
||||
Property = 9
|
||||
Event = 10
|
||||
Operator = 11
|
||||
Unit = 12
|
||||
Value = 13
|
||||
Constant = 14
|
||||
Enum = 15
|
||||
EnumMember = 16
|
||||
Keyword = 17
|
||||
Text = 18
|
||||
Color = 19
|
||||
File = 20
|
||||
Reference = 21
|
||||
Customcolor = 22
|
||||
Folder = 23
|
||||
TypeParameter = 24
|
||||
User = 25
|
||||
Issue = 26
|
||||
Snippet = 27
|
||||
|
||||
|
||||
class CompletionItemTag(IntEnum):
|
||||
Deprecated = 1
|
||||
|
||||
|
||||
class CompletionItemInsertTextRule(IntEnum):
|
||||
KeepWhitespace = 1
|
||||
InsertAsSnippet = 4
|
||||
|
||||
|
||||
class CompletionItemLabel(TypedDict):
|
||||
label: str
|
||||
detail: NotRequired[str]
|
||||
description: NotRequired[str]
|
||||
|
||||
|
||||
class CompletionItemRanges(TypedDict):
|
||||
insert: IRange
|
||||
replace: IRange
|
||||
|
||||
|
||||
class CompletionItem(TypedDict):
|
||||
label: str | CompletionItemLabel
|
||||
kind: CompletionItemKind
|
||||
tags: NotRequired[list[CompletionItemTag]]
|
||||
detail: NotRequired[str]
|
||||
documentation: NotRequired[str]
|
||||
sortText: NotRequired[str]
|
||||
filterText: NotRequired[str]
|
||||
preselect: NotRequired[bool]
|
||||
insertText: str
|
||||
insertTextRules: NotRequired[CompletionItemInsertTextRule]
|
||||
range: IRange | CompletionItemRanges
|
||||
commitCharacters: NotRequired[list[str]]
|
||||
additionalTextEdits: NotRequired[list[ISingleEditOperation]]
|
||||
command: NotRequired[Command]
|
||||
|
||||
|
||||
class ParameterInformation(TypedDict):
|
||||
label: str | tuple[int, int]
|
||||
documentation: NotRequired[str]
|
||||
|
||||
|
||||
class SignatureInformation(TypedDict):
|
||||
label: str
|
||||
documentation: NotRequired[str]
|
||||
parameters: list[ParameterInformation]
|
||||
activeParameter: NotRequired[int]
|
||||
|
||||
|
||||
class SignatureHelp(TypedDict):
|
||||
signatures: list[SignatureInformation]
|
||||
activeSignature: int
|
||||
activeParameter: int
|
||||
|
||||
|
||||
def _is_pybricks(c: Completion) -> bool:
|
||||
# filter all "private" names (leading underscore)
|
||||
if (isinstance(c.name, str)) and c.name.startswith("_"):
|
||||
return False
|
||||
|
||||
if isinstance(c.full_name, str):
|
||||
# this catches things like `from __future__ import annotations`
|
||||
if c.full_name.startswith("_") and c.module_name != "__main__":
|
||||
return False
|
||||
|
||||
# filter out enum types
|
||||
if c.full_name.startswith("enum."):
|
||||
return False
|
||||
|
||||
# filter out typing types
|
||||
if c.full_name.startswith("typing."):
|
||||
return False
|
||||
|
||||
# filter out packages/modules that are not included in Pybricks firmware
|
||||
if c.type == "module" or c.type == "namespace":
|
||||
return c.full_name in PYBRICKS_CODE_PACKAGES
|
||||
|
||||
# filter subset of builtins
|
||||
if c.module_name == "builtins" and c.type != "keyword":
|
||||
return c.name in PYBRICKS_BUILTINS
|
||||
|
||||
# this is a type alias, not a real type
|
||||
if c.full_name == "pybricks.parameters.Number":
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def _map_completion_kind(type: str) -> CompletionItemKind:
|
||||
match type:
|
||||
case "module":
|
||||
return CompletionItemKind.Module
|
||||
case "class":
|
||||
return CompletionItemKind.Class
|
||||
case "instance":
|
||||
return CompletionItemKind.Variable
|
||||
case "function":
|
||||
return CompletionItemKind.Function
|
||||
case "param":
|
||||
return CompletionItemKind.Variable
|
||||
case "path":
|
||||
return CompletionItemKind.File
|
||||
case "keyword":
|
||||
return CompletionItemKind.Keyword
|
||||
case "property":
|
||||
return CompletionItemKind.Property
|
||||
case "statement":
|
||||
return CompletionItemKind.Variable
|
||||
case _:
|
||||
return CompletionItemKind.User
|
||||
|
||||
|
||||
def _map_completion_item(
|
||||
completion: Completion, line: int, column: int
|
||||
) -> CompletionItem:
|
||||
"""
|
||||
Maps a Jedi completion to a Monaco editor CompletionItem.
|
||||
|
||||
Note: All members of the CompletionItem must be directly mappable without
|
||||
PyProxy in Pyodide.
|
||||
"""
|
||||
return CompletionItem(
|
||||
insertText=completion.name_with_symbols,
|
||||
kind=_map_completion_kind(completion.type),
|
||||
label=completion.name_with_symbols,
|
||||
range=IRange(
|
||||
startLineNumber=line,
|
||||
startColumn=column - completion.get_completion_prefix_length(),
|
||||
endLineNumber=line,
|
||||
endColumn=column,
|
||||
),
|
||||
documentation=completion.docstring(),
|
||||
)
|
||||
|
||||
|
||||
def _map_parameter(param: ParamName) -> ParameterInformation:
|
||||
# NB: it is not possible to get docstring for individual parameters from jedi
|
||||
return ParameterInformation(label=param.to_string())
|
||||
|
||||
|
||||
def _map_signature(signature: Signature) -> SignatureInformation:
|
||||
optional = {} if signature.index is None else dict(activeParameter=signature.index)
|
||||
|
||||
return SignatureInformation(
|
||||
label=signature.to_string(),
|
||||
documentation=signature.docstring(),
|
||||
parameters=[_map_parameter(p) for p in signature.params],
|
||||
**optional,
|
||||
)
|
||||
|
||||
|
||||
def _map_signatures(signatures: list[Signature]) -> SignatureHelp:
|
||||
return SignatureHelp(
|
||||
signatures=[_map_signature(s) for s in signatures],
|
||||
activeSignature=0,
|
||||
activeParameter=0,
|
||||
)
|
||||
|
||||
|
||||
def initialize():
|
||||
"""
|
||||
Initialize jedi with Pybricks-specific config.
|
||||
"""
|
||||
|
||||
jedi.preload_module(
|
||||
"typing",
|
||||
"enum",
|
||||
"micropython",
|
||||
"pybricks._common",
|
||||
"pybricks.ev3dev",
|
||||
"pybricks.ev3dev.speaker",
|
||||
"pybricks.geometry",
|
||||
"pybricks.hubs",
|
||||
"pybricks.iodevices",
|
||||
"pybricks.parameters",
|
||||
"pybricks.pupdevices",
|
||||
"pybricks.robotics",
|
||||
"pybricks.tools",
|
||||
"pybricks",
|
||||
"ubuiltins",
|
||||
"uerrno",
|
||||
"uio",
|
||||
"ujson",
|
||||
"umath",
|
||||
"urandom",
|
||||
"uselect",
|
||||
"ustruct",
|
||||
"usys",
|
||||
)
|
||||
|
||||
# also preload "everything" in builtins
|
||||
jedi.Script("").complete()
|
||||
|
||||
|
||||
def complete(code: str, line: int, column: int) -> str:
|
||||
"""
|
||||
Calls jedi.Script().complete() and filters the results for Pybricks.
|
||||
|
||||
Args:
|
||||
code: The Python code to parse.
|
||||
line: The 1-based line number of the cursor position.
|
||||
column: The 1-based column number of the cursor position.
|
||||
|
||||
Returns:
|
||||
A json string containing a filtered list of completion items.
|
||||
"""
|
||||
completions = jedi.Script(code).complete(line, column - 1, fuzzy=True)
|
||||
return json.dumps(
|
||||
[_map_completion_item(c, line, column) for c in completions if _is_pybricks(c)]
|
||||
)
|
||||
|
||||
|
||||
def get_signatures(code: str, line: int, column: int) -> str:
|
||||
"""
|
||||
Calls jedi.Script().get_signatures().
|
||||
|
||||
Args:
|
||||
code: The Python code to parse.
|
||||
line: The 1-based line number of the cursor position.
|
||||
column: The 1-based column number of the cursor position.
|
||||
|
||||
Returns:
|
||||
A json string containing the signature help.
|
||||
"""
|
||||
signatures = jedi.Script(code).get_signatures(line, column - 1)
|
||||
return json.dumps(_map_signatures(signatures))
|
||||
@@ -0,0 +1,30 @@
|
||||
import pybricks_jedi
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
"""
|
||||
Allows plugins and conftest files to perform initial configuration.
|
||||
This hook is called for every plugin and initial conftest
|
||||
file after command line options have been parsed.
|
||||
"""
|
||||
|
||||
|
||||
def pytest_sessionstart(session):
|
||||
"""
|
||||
Called after the Session object has been created and
|
||||
before performing collection and entering the run test loop.
|
||||
"""
|
||||
pybricks_jedi.initialize()
|
||||
|
||||
|
||||
def pytest_sessionfinish(session, exitstatus):
|
||||
"""
|
||||
Called after whole test run finished, right before
|
||||
returning the exit status to the system.
|
||||
"""
|
||||
|
||||
|
||||
def pytest_unconfigure(config):
|
||||
"""
|
||||
called before test process is exited.
|
||||
"""
|
||||
@@ -0,0 +1,126 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
"""
|
||||
Tests for correct code completion of builtins.
|
||||
"""
|
||||
|
||||
|
||||
import json
|
||||
from pybricks_jedi import CompletionItem, complete
|
||||
|
||||
|
||||
def test_empty_code():
|
||||
code = ""
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, 1))
|
||||
# since nothing has been imported, this is just all builtins and keywords
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"abs",
|
||||
"all",
|
||||
"any",
|
||||
"ArithmeticError",
|
||||
"assert",
|
||||
"AssertionError",
|
||||
"async",
|
||||
"AttributeError",
|
||||
"await",
|
||||
"BaseException",
|
||||
"bin",
|
||||
"bool",
|
||||
"break",
|
||||
"bytearray",
|
||||
"bytes",
|
||||
"callable",
|
||||
"chr",
|
||||
"class",
|
||||
"classmethod",
|
||||
"complex",
|
||||
"continue",
|
||||
"def",
|
||||
"del",
|
||||
"dict",
|
||||
"dir",
|
||||
"divmod",
|
||||
"enumerate",
|
||||
"EOFError",
|
||||
"eval",
|
||||
"Exception",
|
||||
"exec",
|
||||
"False",
|
||||
"float",
|
||||
"for",
|
||||
"from",
|
||||
"GeneratorExit",
|
||||
"getattr",
|
||||
"global",
|
||||
"globals",
|
||||
"hasattr",
|
||||
"hash",
|
||||
"help",
|
||||
"hex",
|
||||
"id",
|
||||
"if",
|
||||
"import",
|
||||
"ImportError",
|
||||
"IndentationError",
|
||||
"IndexError",
|
||||
"input",
|
||||
"int",
|
||||
"isinstance",
|
||||
"issubclass",
|
||||
"iter",
|
||||
"KeyboardInterrupt",
|
||||
"KeyError",
|
||||
"lambda",
|
||||
"len",
|
||||
"list",
|
||||
"locals",
|
||||
"LookupError",
|
||||
"map",
|
||||
"max",
|
||||
"MemoryError",
|
||||
"min",
|
||||
"NameError",
|
||||
"next",
|
||||
"None",
|
||||
"nonlocal",
|
||||
"not",
|
||||
"NotImplementedError",
|
||||
"object",
|
||||
"oct",
|
||||
"ord",
|
||||
"OSError",
|
||||
"OverflowError",
|
||||
"pass",
|
||||
"pow",
|
||||
"print",
|
||||
"raise",
|
||||
"range",
|
||||
"repr",
|
||||
"return",
|
||||
"reversed",
|
||||
"round",
|
||||
"RuntimeError",
|
||||
"set",
|
||||
"setattr",
|
||||
"slice",
|
||||
"sorted",
|
||||
"staticmethod",
|
||||
"StopIteration",
|
||||
"str",
|
||||
"sum",
|
||||
"super",
|
||||
"SyntaxError",
|
||||
"SystemExit",
|
||||
"True",
|
||||
"try",
|
||||
"tuple",
|
||||
"type",
|
||||
"TypeError",
|
||||
"ValueError",
|
||||
"while",
|
||||
"with",
|
||||
"yield",
|
||||
"ZeroDivisionError",
|
||||
"zip",
|
||||
]
|
||||
@@ -0,0 +1,82 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
"""
|
||||
Tests for correct code completion of the CityHub class.
|
||||
"""
|
||||
|
||||
|
||||
import json
|
||||
from pybricks_jedi import CompletionItem, complete
|
||||
|
||||
IMPORT = "from pybricks.hubs import CityHub"
|
||||
CREATE_INSTANCE = "hub = CityHub()"
|
||||
|
||||
|
||||
def _create_snippet(line: str) -> str:
|
||||
"""
|
||||
Creates a code snippet::
|
||||
|
||||
from pybricks.hubs import CityHub
|
||||
hub = CityHub()
|
||||
{line}
|
||||
|
||||
Args:
|
||||
line: The value substituted for ``{line}``
|
||||
"""
|
||||
return "\n".join((IMPORT, CREATE_INSTANCE, line))
|
||||
|
||||
|
||||
def test_hub_dot():
|
||||
line = "hub."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"battery",
|
||||
"button",
|
||||
"light",
|
||||
"system",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_battery_dot():
|
||||
line = "hub.battery."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"current",
|
||||
"voltage",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_button_dot():
|
||||
line = "hub.button."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"pressed",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_light_dot():
|
||||
line = "hub.light."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"animate",
|
||||
"blink",
|
||||
"off",
|
||||
"on",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_system_dot():
|
||||
line = "hub.system."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"name",
|
||||
"reset_reason",
|
||||
"set_stop_button",
|
||||
"shutdown",
|
||||
]
|
||||
@@ -0,0 +1,254 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
"""
|
||||
Tests for correct code completion of import statements.
|
||||
"""
|
||||
|
||||
import json
|
||||
from pybricks_jedi import CompletionItem, complete
|
||||
|
||||
|
||||
def test_from():
|
||||
code = "from "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
# only modules included in Pybricks firmware should be listed
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"micropython",
|
||||
"pybricks",
|
||||
"uerrno",
|
||||
"uio",
|
||||
"umath",
|
||||
"urandom",
|
||||
"uselect",
|
||||
"usys",
|
||||
]
|
||||
|
||||
|
||||
def test_from_pybricks_import():
|
||||
code = "from pybricks import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"geometry",
|
||||
"hubs",
|
||||
"iodevices",
|
||||
"parameters",
|
||||
"pupdevices",
|
||||
"robotics",
|
||||
"tools",
|
||||
"version",
|
||||
]
|
||||
|
||||
|
||||
def test_from_pybricks_dot():
|
||||
code = "from pybricks."
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"geometry",
|
||||
"hubs",
|
||||
"iodevices",
|
||||
"parameters",
|
||||
"pupdevices",
|
||||
"robotics",
|
||||
"tools",
|
||||
]
|
||||
|
||||
|
||||
def test_from_pybricks_geometry_import():
|
||||
code = "from pybricks.geometry import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"Axis",
|
||||
"Matrix",
|
||||
"vector",
|
||||
]
|
||||
|
||||
|
||||
def test_from_pybricks_hubs_import():
|
||||
code = "from pybricks.hubs import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"CityHub",
|
||||
"EV3Brick",
|
||||
"InventorHub",
|
||||
"MoveHub",
|
||||
"PrimeHub",
|
||||
"TechnicHub",
|
||||
]
|
||||
|
||||
|
||||
def test_from_pybricks_iodevices_import():
|
||||
code = "from pybricks.iodevices import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"AnalogSensor",
|
||||
"DCMotor",
|
||||
"Ev3devSensor",
|
||||
"I2CDevice",
|
||||
"LUMPDevice",
|
||||
"LWP3Device",
|
||||
"PUPDevice",
|
||||
"UARTDevice",
|
||||
]
|
||||
|
||||
|
||||
def test_from_pybricks_parameters_import():
|
||||
code = "from pybricks.parameters import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"Button",
|
||||
"Color",
|
||||
"Direction",
|
||||
"Icon",
|
||||
"Port",
|
||||
"Side",
|
||||
"Stop",
|
||||
]
|
||||
|
||||
|
||||
def test_from_pybricks_pupdevices_import():
|
||||
code = "from pybricks.pupdevices import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"ColorDistanceSensor",
|
||||
"ColorLightMatrix",
|
||||
"ColorSensor",
|
||||
"DCMotor",
|
||||
"ForceSensor",
|
||||
"InfraredSensor",
|
||||
"Light",
|
||||
"Motor",
|
||||
"PFMotor",
|
||||
"Remote",
|
||||
"TiltSensor",
|
||||
"UltrasonicSensor",
|
||||
]
|
||||
|
||||
|
||||
def test_from_pybricks_robotics_import():
|
||||
code = "from pybricks.robotics import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"DriveBase",
|
||||
]
|
||||
|
||||
|
||||
def test_from_pybricks_tools_import():
|
||||
code = "from pybricks.tools import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"DataLog",
|
||||
"StopWatch",
|
||||
"wait",
|
||||
]
|
||||
|
||||
|
||||
def test_from_micropython_import():
|
||||
code = "from micropython import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"const",
|
||||
"kbd_intr",
|
||||
"mem_info",
|
||||
"opt_level",
|
||||
"qstr_info",
|
||||
"stack_use",
|
||||
]
|
||||
|
||||
|
||||
def test_from_uerrno_import():
|
||||
code = "from uerrno import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"EAGAIN",
|
||||
"EBUSY",
|
||||
"ECANCELED",
|
||||
"EINVAL",
|
||||
"EIO",
|
||||
"ENODEV",
|
||||
"EOPNOTSUPP",
|
||||
"EPERM",
|
||||
"errorcode",
|
||||
"ETIMEDOUT",
|
||||
]
|
||||
|
||||
|
||||
def test_from_uio_import():
|
||||
code = "from uio import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"BytesIO",
|
||||
"FileIO",
|
||||
"StringIO",
|
||||
]
|
||||
|
||||
|
||||
def test_from_umath_import():
|
||||
code = "from umath import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"acos",
|
||||
"asin",
|
||||
"atan",
|
||||
"atan2",
|
||||
"ceil",
|
||||
"copysign",
|
||||
"cos",
|
||||
"degrees",
|
||||
"e",
|
||||
"exp",
|
||||
"fabs",
|
||||
"floor",
|
||||
"fmod",
|
||||
"frexp",
|
||||
"isfinite",
|
||||
"isinfinite",
|
||||
"isnan",
|
||||
"ldexp",
|
||||
"log",
|
||||
"modf",
|
||||
"pi",
|
||||
"pow",
|
||||
"radians",
|
||||
"sin",
|
||||
"sqrt",
|
||||
"tan",
|
||||
"trunc",
|
||||
]
|
||||
|
||||
|
||||
def test_from_urandom_import():
|
||||
code = "from urandom import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"choice",
|
||||
"getrandbits",
|
||||
"randint",
|
||||
"random",
|
||||
"randrange",
|
||||
"seed",
|
||||
"uniform",
|
||||
]
|
||||
|
||||
|
||||
def test_from_uselect_import():
|
||||
code = "from uselect import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"poll",
|
||||
"Poll",
|
||||
"POLLERR",
|
||||
"POLLHUP",
|
||||
"POLLIN",
|
||||
"POLLOUT",
|
||||
]
|
||||
|
||||
|
||||
def test_from_usys_import():
|
||||
code = "from usys import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"stderr",
|
||||
"stdin",
|
||||
"stdout",
|
||||
]
|
||||
@@ -0,0 +1,327 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
"""
|
||||
Tests for correct code completion of the InventorHub class.
|
||||
"""
|
||||
|
||||
|
||||
import json
|
||||
from pybricks_jedi import SignatureHelp, complete, get_signatures, CompletionItem
|
||||
|
||||
IMPORT = "from pybricks.hubs import InventorHub"
|
||||
CREATE_INSTANCE = "hub = InventorHub()"
|
||||
|
||||
|
||||
def _create_snippet(line: str) -> str:
|
||||
"""
|
||||
Creates a code snippet::
|
||||
|
||||
from pybricks.hubs import InventorHub
|
||||
hub = InventorHub()
|
||||
{line}
|
||||
|
||||
Args:
|
||||
line: The value substituted for ``{line}``
|
||||
"""
|
||||
return "\n".join((IMPORT, CREATE_INSTANCE, line))
|
||||
|
||||
|
||||
def test_hub_dot():
|
||||
line = "hub."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"battery",
|
||||
"buttons",
|
||||
"charger",
|
||||
"display",
|
||||
"imu",
|
||||
"light",
|
||||
"speaker",
|
||||
"system",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_battery_dot():
|
||||
line = "hub.battery."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"current",
|
||||
"voltage",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_battery_dot_current():
|
||||
line = "hub.battery.current("
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == ["current() -> int"]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [None]
|
||||
|
||||
|
||||
def test_hub_dot_battery_dot_voltage():
|
||||
line = "hub.battery.voltage("
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == ["voltage() -> int"]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [None]
|
||||
|
||||
|
||||
def test_hub_dot_buttons_dot():
|
||||
line = "hub.buttons."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"pressed",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_battery_dot_pressed():
|
||||
line = "hub.buttons.pressed("
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == [
|
||||
"pressed() -> Tuple[Button]"
|
||||
]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [None]
|
||||
|
||||
|
||||
def test_hub_dot_charger_dot():
|
||||
line = "hub.charger."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"connected",
|
||||
"current",
|
||||
"status",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_charger_dot_connected():
|
||||
line = "hub.charger.connected("
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == ["connected() -> bool"]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [None]
|
||||
|
||||
|
||||
def test_hub_dot_charger_dot_current():
|
||||
line = "hub.charger.current("
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == ["current() -> int"]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [None]
|
||||
|
||||
|
||||
def test_hub_dot_display_dot():
|
||||
line = "hub.display."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"animate",
|
||||
"char",
|
||||
"image",
|
||||
"number",
|
||||
"off",
|
||||
"orientation",
|
||||
"pixel",
|
||||
"text",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_imu_dot():
|
||||
line = "hub.imu."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"acceleration",
|
||||
"angular_velocity",
|
||||
"heading",
|
||||
"reset_heading",
|
||||
"tilt",
|
||||
"up",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_light_dot():
|
||||
line = "hub.light."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"animate",
|
||||
"blink",
|
||||
"off",
|
||||
"on",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_light_dot_animate():
|
||||
line = "hub.light.animate("
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == [
|
||||
"animate(colors: Collection[Color], interval: Number) -> None",
|
||||
]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [0]
|
||||
assert [
|
||||
[p["label"] for p in s["parameters"]] for s in signatures["signatures"]
|
||||
] == [["colors: Collection[Color]", "interval: Number"]]
|
||||
|
||||
|
||||
def test_hub_dot_light_dot_animate2():
|
||||
line = "hub.light.animate([],"
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == [
|
||||
"animate(colors: Collection[Color], interval: Number) -> None",
|
||||
]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [1]
|
||||
assert [
|
||||
[p["label"] for p in s["parameters"]] for s in signatures["signatures"]
|
||||
] == [["colors: Collection[Color]", "interval: Number"]]
|
||||
|
||||
|
||||
def test_hub_dot_light_dot_blink():
|
||||
line = "hub.light.blink("
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == [
|
||||
"blink(color: Color, durations: Collection[int]) -> None",
|
||||
]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [0]
|
||||
|
||||
|
||||
def test_hub_dot_light_dot_blink2():
|
||||
line = "hub.light.blink(Color.RED,"
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == [
|
||||
"blink(color: Color, durations: Collection[int]) -> None",
|
||||
]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [1]
|
||||
|
||||
|
||||
def test_hub_dot_light_dot_on():
|
||||
line = "hub.light.on("
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == [
|
||||
"on(color: Color) -> None",
|
||||
]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [0]
|
||||
|
||||
|
||||
def test_hub_dot_speaker_dot():
|
||||
line = "hub.speaker."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"beep",
|
||||
"play_notes",
|
||||
"volume",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_speaker_dot_beep():
|
||||
line = "hub.speaker.beep("
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == [
|
||||
"beep(frequency: Number=500, duration: Number=100) -> None",
|
||||
]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [0]
|
||||
|
||||
|
||||
def test_hub_dot_speaker_dot_beep2():
|
||||
line = "hub.speaker.beep(100,"
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == [
|
||||
"beep(frequency: Number=500, duration: Number=100) -> None",
|
||||
]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [1]
|
||||
|
||||
|
||||
def test_hub_dot_speaker_dot_play_notes():
|
||||
line = "hub.speaker.play_notes("
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == [
|
||||
"play_notes(notes: Iterable[str], tempo: Number=120) -> None",
|
||||
]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [0]
|
||||
|
||||
|
||||
def test_hub_dot_speaker_dot_play_notes2():
|
||||
line = "hub.speaker.play_notes([],"
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == [
|
||||
"play_notes(notes: Iterable[str], tempo: Number=120) -> None",
|
||||
]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [1]
|
||||
|
||||
|
||||
def test_hub_dot_speaker_dot_volume():
|
||||
line = "hub.speaker.volume("
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == [
|
||||
"volume() -> int",
|
||||
"volume(volume: Number) -> None",
|
||||
]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [None, 0]
|
||||
|
||||
|
||||
def test_hub_dot_system_dot():
|
||||
line = "hub.system."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"name",
|
||||
"reset_reason",
|
||||
"set_stop_button",
|
||||
"shutdown",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_system_dot_name():
|
||||
line = "hub.system.name("
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == [
|
||||
"name() -> str",
|
||||
]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [None]
|
||||
|
||||
|
||||
def test_hub_dot_system_dot_reset_reason():
|
||||
line = "hub.system.reset_reason("
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == [
|
||||
"reset_reason() -> int",
|
||||
]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [None]
|
||||
|
||||
|
||||
def test_hub_dot_system_dot_set_stop_button():
|
||||
line = "hub.system.set_stop_button("
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == [
|
||||
"set_stop_button(button: Optional[Union[Button, Iterable[Button]]]) -> None",
|
||||
]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [0]
|
||||
|
||||
|
||||
def test_hub_dot_system_dot_shutdown():
|
||||
line = "hub.system.shutdown("
|
||||
code = _create_snippet(line)
|
||||
signatures: SignatureHelp = json.loads(get_signatures(code, 3, len(line) + 1))
|
||||
assert [s["label"] for s in signatures["signatures"]] == [
|
||||
"shutdown() -> None",
|
||||
]
|
||||
assert [s.get("activeParameter") for s in signatures["signatures"]] == [None]
|
||||
@@ -0,0 +1,93 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
"""
|
||||
Tests for correct code completion of the MoveHub class.
|
||||
"""
|
||||
|
||||
|
||||
import json
|
||||
from pybricks_jedi import CompletionItem, complete
|
||||
|
||||
IMPORT = "from pybricks.hubs import MoveHub"
|
||||
CREATE_INSTANCE = "hub = MoveHub()"
|
||||
|
||||
|
||||
def _create_snippet(line: str) -> str:
|
||||
"""
|
||||
Creates a code snippet::
|
||||
|
||||
from pybricks.hubs import MoveHub
|
||||
hub = MoveHub()
|
||||
{line}
|
||||
|
||||
Args:
|
||||
line: The value substituted for ``{line}``
|
||||
"""
|
||||
return "\n".join((IMPORT, CREATE_INSTANCE, line))
|
||||
|
||||
|
||||
def test_hub_dot():
|
||||
line = "hub."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"battery",
|
||||
"button",
|
||||
"imu",
|
||||
"light",
|
||||
"system",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_battery_dot():
|
||||
line = "hub.battery."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"current",
|
||||
"voltage",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_button_dot():
|
||||
line = "hub.button."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"pressed",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_imu_dot():
|
||||
line = "hub.imu."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"acceleration",
|
||||
"up",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_light_dot():
|
||||
line = "hub.light."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"animate",
|
||||
"blink",
|
||||
"off",
|
||||
"on",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_system_dot():
|
||||
line = "hub.system."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"name",
|
||||
"reset_reason",
|
||||
"set_stop_button",
|
||||
"shutdown",
|
||||
]
|
||||
@@ -0,0 +1,138 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
"""
|
||||
Tests for correct code completion of the PrimeHub class.
|
||||
"""
|
||||
|
||||
|
||||
import json
|
||||
from pybricks_jedi import CompletionItem, complete
|
||||
|
||||
IMPORT = "from pybricks.hubs import PrimeHub"
|
||||
CREATE_INSTANCE = "hub = PrimeHub()"
|
||||
|
||||
|
||||
def _create_snippet(line: str) -> str:
|
||||
"""
|
||||
Creates a code snippet::
|
||||
|
||||
from pybricks.hubs import PrimeHub
|
||||
hub = PrimeHub()
|
||||
{line}
|
||||
|
||||
Args:
|
||||
line: The value substituted for ``{line}``
|
||||
"""
|
||||
return "\n".join((IMPORT, CREATE_INSTANCE, line))
|
||||
|
||||
|
||||
def test_hub_dot():
|
||||
line = "hub."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"battery",
|
||||
"buttons",
|
||||
"charger",
|
||||
"display",
|
||||
"imu",
|
||||
"light",
|
||||
"speaker",
|
||||
"system",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_battery_dot():
|
||||
line = "hub.battery."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"current",
|
||||
"voltage",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_buttons_dot():
|
||||
line = "hub.buttons."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"pressed",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_charger_dot():
|
||||
line = "hub.charger."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"connected",
|
||||
"current",
|
||||
"status",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_display_dot():
|
||||
line = "hub.display."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"animate",
|
||||
"char",
|
||||
"image",
|
||||
"number",
|
||||
"off",
|
||||
"orientation",
|
||||
"pixel",
|
||||
"text",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_imu_dot():
|
||||
line = "hub.imu."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"acceleration",
|
||||
"angular_velocity",
|
||||
"heading",
|
||||
"reset_heading",
|
||||
"tilt",
|
||||
"up",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_light_dot():
|
||||
line = "hub.light."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"animate",
|
||||
"blink",
|
||||
"off",
|
||||
"on",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_speaker_dot():
|
||||
line = "hub.speaker."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"beep",
|
||||
"play_notes",
|
||||
"volume",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_system_dot():
|
||||
line = "hub.system."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"name",
|
||||
"reset_reason",
|
||||
"set_stop_button",
|
||||
"shutdown",
|
||||
]
|
||||
@@ -0,0 +1,97 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
"""
|
||||
Tests for correct code completion of the TechnicHub class.
|
||||
"""
|
||||
|
||||
|
||||
import json
|
||||
from pybricks_jedi import CompletionItem, complete
|
||||
|
||||
IMPORT = "from pybricks.hubs import TechnicHub"
|
||||
CREATE_INSTANCE = "hub = TechnicHub()"
|
||||
|
||||
|
||||
def _create_snippet(line: str) -> str:
|
||||
"""
|
||||
Creates a code snippet::
|
||||
|
||||
from pybricks.hubs import TechnicHub
|
||||
hub = TechnicHub()
|
||||
{line}
|
||||
|
||||
Args:
|
||||
line: The value substituted for ``{line}``
|
||||
"""
|
||||
return "\n".join((IMPORT, CREATE_INSTANCE, line))
|
||||
|
||||
|
||||
def test_hub_dot():
|
||||
line = "hub."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"battery",
|
||||
"button",
|
||||
"imu",
|
||||
"light",
|
||||
"system",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_battery_dot():
|
||||
line = "hub.battery."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"current",
|
||||
"voltage",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_button_dot():
|
||||
line = "hub.button."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"pressed",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_imu_dot():
|
||||
line = "hub.imu."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"acceleration",
|
||||
"angular_velocity",
|
||||
"heading",
|
||||
"reset_heading",
|
||||
"tilt",
|
||||
"up",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_light_dot():
|
||||
line = "hub.light."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"animate",
|
||||
"blink",
|
||||
"off",
|
||||
"on",
|
||||
]
|
||||
|
||||
|
||||
def test_hub_dot_system_dot():
|
||||
line = "hub.system."
|
||||
code = _create_snippet(line)
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 3, len(line) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"name",
|
||||
"reset_reason",
|
||||
"set_stop_button",
|
||||
"shutdown",
|
||||
]
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
[flake8]
|
||||
exclude = .venv/,*.pyi
|
||||
exclude = .venv/,*.pyi,jedi/
|
||||
max-line-length = 88
|
||||
ignore = E203,W503
|
||||
|
||||
|
||||
+13
-6
@@ -4,16 +4,23 @@
|
||||
"""Generic cross-platform module for typical devices like lights, displays,
|
||||
speakers, and batteries."""
|
||||
|
||||
from typing import Union, Iterable, overload, Optional, Tuple, Collection
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Union, Iterable, overload, Optional, Tuple, Collection, TYPE_CHECKING
|
||||
|
||||
from .geometry import Matrix, Axis
|
||||
from .parameters import Direction, Stop, Button, Port, Color, Side, Number
|
||||
from .parameters import Direction, Stop, Button, Port, Color, Side
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .parameters import Number
|
||||
|
||||
|
||||
class System:
|
||||
"""System control actions for a hub."""
|
||||
|
||||
def set_stop_button(self, button: Union[Button, Iterable[Button]]) -> None:
|
||||
def set_stop_button(
|
||||
self, button: Optional[Union[Button, Iterable[Button]]]
|
||||
) -> None:
|
||||
"""
|
||||
set_stop_button(button)
|
||||
|
||||
@@ -62,7 +69,7 @@ class System:
|
||||
"""
|
||||
|
||||
|
||||
class CommonDCMotor:
|
||||
class DCMotor:
|
||||
"""Generic class to control simple motors without rotation sensors, such
|
||||
as train motors."""
|
||||
|
||||
@@ -289,7 +296,7 @@ class Control:
|
||||
"""
|
||||
|
||||
|
||||
class CommonMotor(CommonDCMotor):
|
||||
class Motor(DCMotor):
|
||||
"""Generic class to control motors with built-in rotation sensors."""
|
||||
|
||||
control = Control()
|
||||
@@ -897,7 +904,7 @@ class IMU(Accelerometer):
|
||||
"""
|
||||
|
||||
def reset_heading(self, angle: Number) -> None:
|
||||
"""reset_heading(angle: Number)
|
||||
"""reset_heading(angle)
|
||||
|
||||
Resets the accumulated heading angle of the robot.
|
||||
|
||||
|
||||
+18
-11
@@ -5,18 +5,23 @@
|
||||
|
||||
from typing import Optional, Tuple, List
|
||||
|
||||
from ._common import CommonMotor
|
||||
from .parameters import Direction, Port, Color, Button
|
||||
from . import _common
|
||||
from .parameters import (
|
||||
Button as _Button,
|
||||
Color as _Color,
|
||||
Direction as _Direction,
|
||||
Port as _Port,
|
||||
)
|
||||
|
||||
|
||||
class Motor(CommonMotor):
|
||||
class Motor(_common.Motor):
|
||||
"""LEGO® MINDSTORMS® EV3 Motor."""
|
||||
|
||||
|
||||
class TouchSensor:
|
||||
"""LEGO® MINDSTORMS® EV3 Touch Sensor."""
|
||||
|
||||
def __init__(self, port: Port):
|
||||
def __init__(self, port: _Port):
|
||||
"""TouchSensor(port)
|
||||
|
||||
Arguments:
|
||||
@@ -37,14 +42,14 @@ class TouchSensor:
|
||||
class ColorSensor:
|
||||
"""LEGO® MINDSTORMS® EV3 Color Sensor."""
|
||||
|
||||
def __init__(self, port: Port):
|
||||
def __init__(self, port: _Port):
|
||||
"""ColorSensor(port)
|
||||
|
||||
Arguments:
|
||||
port (Port): Port to which the sensor is connected.
|
||||
"""
|
||||
|
||||
def color(self) -> Optional[Color]:
|
||||
def color(self) -> Optional[_Color]:
|
||||
"""color() -> Color
|
||||
|
||||
Measures the color of a surface.
|
||||
@@ -92,7 +97,7 @@ class ColorSensor:
|
||||
class InfraredSensor:
|
||||
"""LEGO® MINDSTORMS® EV3 Infrared Sensor and Beacon."""
|
||||
|
||||
def __init__(self, port: Port):
|
||||
def __init__(self, port: _Port):
|
||||
"""InfraredSensor(port)
|
||||
|
||||
Arguments:
|
||||
@@ -129,7 +134,7 @@ class InfraredSensor:
|
||||
a tuple of (``None``, ``None``) if no remote is detected.
|
||||
"""
|
||||
|
||||
def buttons(self, channel: int) -> List[Button]:
|
||||
def buttons(self, channel: int) -> List[_Button]:
|
||||
"""buttons(channel) -> List[Button]
|
||||
|
||||
Checks which buttons on the infrared remote are pressed.
|
||||
@@ -145,7 +150,7 @@ class InfraredSensor:
|
||||
|
||||
"""
|
||||
|
||||
def keypad(self) -> List[Button]:
|
||||
def keypad(self) -> List[_Button]:
|
||||
"""keypad() -> List[Button]
|
||||
|
||||
Checks which buttons on the infrared remote are pressed.
|
||||
@@ -163,7 +168,9 @@ class InfraredSensor:
|
||||
class GyroSensor:
|
||||
"""LEGO® MINDSTORMS® EV3 Gyro Sensor."""
|
||||
|
||||
def __init__(self, port: Port, positive_direction: Direction = Direction.CLOCKWISE):
|
||||
def __init__(
|
||||
self, port: _Port, positive_direction: _Direction = _Direction.CLOCKWISE
|
||||
):
|
||||
"""GyroSensor(port)
|
||||
|
||||
Arguments:
|
||||
@@ -207,7 +214,7 @@ class GyroSensor:
|
||||
class UltrasonicSensor:
|
||||
"""LEGO® MINDSTORMS® EV3 Ultrasonic Sensor."""
|
||||
|
||||
def __init__(self, port: Port):
|
||||
def __init__(self, port: _Port):
|
||||
"""UltrasonicSensor(port)
|
||||
|
||||
Arguments:
|
||||
|
||||
+47
-57
@@ -2,21 +2,11 @@
|
||||
# Copyright (c) 2018-2020 The Pybricks Authors
|
||||
|
||||
"""LEGO® Programmable Hubs."""
|
||||
from ._common import (
|
||||
Speaker,
|
||||
Battery,
|
||||
ColorLight,
|
||||
Keypad,
|
||||
LightMatrix,
|
||||
IMU,
|
||||
Charger,
|
||||
System,
|
||||
SimpleAccelerometer,
|
||||
)
|
||||
from .ev3dev._speaker import Speaker as EV3Speaker
|
||||
from .geometry import Axis
|
||||
from .media.ev3dev import Image
|
||||
from .parameters import Button
|
||||
from . import _common
|
||||
from .ev3dev import _speaker
|
||||
from .geometry import Axis as _Axis
|
||||
from .media.ev3dev import Image as _Image
|
||||
from .parameters import Button as _Button
|
||||
|
||||
|
||||
class EV3Brick:
|
||||
@@ -24,19 +14,19 @@ 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,
|
||||
)
|
||||
buttons = _common.Keypad(
|
||||
[
|
||||
_Button.LEFT,
|
||||
_Button.RIGHT,
|
||||
_Button.CENTER,
|
||||
_Button.UP,
|
||||
_Button.DOWN,
|
||||
]
|
||||
)
|
||||
screen = Image("_screen_")
|
||||
speaker = EV3Speaker()
|
||||
battery = Battery()
|
||||
light = ColorLight()
|
||||
screen = _Image("_screen_")
|
||||
speaker = _speaker.Speaker()
|
||||
battery = _common.Battery()
|
||||
light = _common.ColorLight()
|
||||
|
||||
|
||||
class MoveHub:
|
||||
@@ -44,11 +34,11 @@ class MoveHub:
|
||||
|
||||
# These class attributes are here for auto-documentation only.
|
||||
# In reality, they are instance attributes created by __init__.
|
||||
battery = Battery()
|
||||
light = ColorLight()
|
||||
imu = SimpleAccelerometer()
|
||||
system = System()
|
||||
button = Keypad((Button.CENTER,))
|
||||
battery = _common.Battery()
|
||||
light = _common.ColorLight()
|
||||
imu = _common.SimpleAccelerometer()
|
||||
system = _common.System()
|
||||
button = _common.Keypad([_Button.CENTER])
|
||||
|
||||
|
||||
class CityHub:
|
||||
@@ -56,10 +46,10 @@ class CityHub:
|
||||
|
||||
# These class attributes are here for auto-documentation only.
|
||||
# In reality, they are instance attributes created by __init__.
|
||||
battery = Battery()
|
||||
light = ColorLight()
|
||||
system = System()
|
||||
button = Keypad((Button.CENTER,))
|
||||
battery = _common.Battery()
|
||||
light = _common.ColorLight()
|
||||
system = _common.System()
|
||||
button = _common.Keypad([_Button.CENTER])
|
||||
|
||||
|
||||
class TechnicHub:
|
||||
@@ -67,13 +57,13 @@ class TechnicHub:
|
||||
|
||||
# These class attributes are here for auto-documentation only.
|
||||
# In reality, they are instance attributes created by __init__.
|
||||
battery = Battery()
|
||||
light = ColorLight()
|
||||
imu = IMU()
|
||||
system = System()
|
||||
button = Keypad((Button.CENTER,))
|
||||
battery = _common.Battery()
|
||||
light = _common.ColorLight()
|
||||
imu = _common.IMU()
|
||||
system = _common.System()
|
||||
button = _common.Keypad([_Button.CENTER])
|
||||
|
||||
def __init__(self, top_side: Axis = Axis.Z, front_side: Axis = Axis.X):
|
||||
def __init__(self, top_side: _Axis = _Axis.Z, front_side: _Axis = _Axis.X):
|
||||
"""TechnicHub(top_side=Axis.Z, front_side=Axis.X)
|
||||
|
||||
Initializes the hub. Optionally, specify how the hub is
|
||||
@@ -94,23 +84,23 @@ 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,
|
||||
)
|
||||
battery = _common.Battery()
|
||||
buttons = _common.Keypad(
|
||||
[
|
||||
_Button.LEFT,
|
||||
_Button.RIGHT,
|
||||
_Button.CENTER,
|
||||
_Button.BLUETOOTH,
|
||||
]
|
||||
)
|
||||
charger = Charger()
|
||||
light = ColorLight()
|
||||
display = LightMatrix(5, 5)
|
||||
speaker = Speaker()
|
||||
imu = IMU()
|
||||
system = System()
|
||||
charger = _common.Charger()
|
||||
light = _common.ColorLight()
|
||||
display = _common.LightMatrix(5, 5)
|
||||
speaker = _common.Speaker()
|
||||
imu = _common.IMU()
|
||||
system = _common.System()
|
||||
|
||||
def __init__(self, top_side: Axis = Axis.Z, front_side: Axis = Axis.X):
|
||||
def __init__(self, top_side: _Axis = _Axis.Z, front_side: _Axis = _Axis.X):
|
||||
"""PrimeHub(top_side=Axis.Z, front_side=Axis.X)
|
||||
|
||||
Initializes the hub. Optionally, specify how the hub is
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
|
||||
from typing import Dict, Tuple, Optional, overload
|
||||
|
||||
from ._common import CommonDCMotor
|
||||
from .parameters import Port
|
||||
from . import _common
|
||||
from .parameters import Port as _Port
|
||||
|
||||
|
||||
class PUPDevice:
|
||||
"""Powered Up motor or sensor."""
|
||||
|
||||
def __init__(self, port: Port):
|
||||
def __init__(self, port: _Port):
|
||||
"""PUPDevice(port)
|
||||
|
||||
Arguments:
|
||||
@@ -55,7 +55,7 @@ class PUPDevice:
|
||||
class LUMPDevice:
|
||||
"""Devices using the LEGO UART Messaging Protocol."""
|
||||
|
||||
def __init__(self, port: Port):
|
||||
def __init__(self, port: _Port):
|
||||
"""LUMPDevice(port)
|
||||
|
||||
Arguments:
|
||||
@@ -75,7 +75,7 @@ class LUMPDevice:
|
||||
"""
|
||||
|
||||
|
||||
class DCMotor(CommonDCMotor):
|
||||
class DCMotor(_common.DCMotor):
|
||||
"""DC Motor for LEGO® MINDSTORMS EV3."""
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ class Ev3devSensor:
|
||||
port_index: int
|
||||
"""Index of the ev3dev sysfs `lego-port`_ class."""
|
||||
|
||||
def __init__(self, port: Port):
|
||||
def __init__(self, port: _Port):
|
||||
"""Ev3devSensor(port)
|
||||
|
||||
Arguments:
|
||||
@@ -111,7 +111,7 @@ class Ev3devSensor:
|
||||
class AnalogSensor:
|
||||
"""Generic or custom analog sensor."""
|
||||
|
||||
def __init__(self, port: Port):
|
||||
def __init__(self, port: _Port):
|
||||
"""AnalogSensor(port)
|
||||
|
||||
Arguments:
|
||||
@@ -167,7 +167,7 @@ class AnalogSensor:
|
||||
class I2CDevice:
|
||||
"""Generic or custom I2C device."""
|
||||
|
||||
def __init__(self, port: Port, address: int):
|
||||
def __init__(self, port: _Port, address: int):
|
||||
"""I2CDevice(port, address)
|
||||
|
||||
Arguments:
|
||||
@@ -205,7 +205,7 @@ class I2CDevice:
|
||||
class UARTDevice:
|
||||
"""Generic UART device."""
|
||||
|
||||
def __init__(self, port: Port, baudrate: int, timeout: Optional[int] = None):
|
||||
def __init__(self, port: _Port, baudrate: int, timeout: Optional[int] = None):
|
||||
"""UARTDevice(port, baudrate, timeout=None)
|
||||
|
||||
Arguments:
|
||||
|
||||
+60
-39
@@ -6,12 +6,33 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum
|
||||
from typing import Union
|
||||
from typing import Union, TYPE_CHECKING
|
||||
import os
|
||||
|
||||
from .geometry import Matrix as _Matrix
|
||||
|
||||
from .geometry import Matrix
|
||||
if TYPE_CHECKING or os.environ["SPHINX_BUILD"] == "True":
|
||||
Number = Union[int, float]
|
||||
"""
|
||||
Numbers can be represented as integers or floating point values:
|
||||
|
||||
Number = Union[int, float]
|
||||
* 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` 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.
|
||||
|
||||
.. warning::
|
||||
The BOOST Move hub doesn't support floating point numbers due to
|
||||
limited system resources, so only integers can be used on that hub.
|
||||
"""
|
||||
|
||||
|
||||
class _PybricksEnumMeta(type(Enum)):
|
||||
@@ -163,39 +184,39 @@ class Side(_PybricksEnum):
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
+40
-38
@@ -3,25 +3,27 @@
|
||||
|
||||
"""LEGO® Powered Up motor, sensors, and lights."""
|
||||
|
||||
from typing import Collection, Optional, Union, overload, Tuple
|
||||
from __future__ import annotations
|
||||
|
||||
from ._common import (
|
||||
AmbientColorSensor,
|
||||
ColorLight,
|
||||
CommonColorSensor,
|
||||
CommonDCMotor,
|
||||
CommonMotor,
|
||||
Keypad,
|
||||
LightArray,
|
||||
from typing import TYPE_CHECKING, Collection, Optional, Union, overload, Tuple
|
||||
|
||||
from . import _common
|
||||
from .parameters import (
|
||||
Button as _Button,
|
||||
Color as _Color,
|
||||
Direction as _Direction,
|
||||
Port as _Port,
|
||||
)
|
||||
from .parameters import Button, Color, Direction, Port
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .parameters import Number as _Number
|
||||
|
||||
|
||||
class DCMotor(CommonDCMotor):
|
||||
class DCMotor(_common.DCMotor):
|
||||
"""LEGO® Powered Up motor without rotation sensors."""
|
||||
|
||||
|
||||
class Motor(CommonMotor):
|
||||
class Motor(_common.Motor):
|
||||
"""LEGO® Powered Up motor with rotation sensors."""
|
||||
|
||||
def reset_angle(self, angle: Optional[int]) -> None:
|
||||
@@ -40,21 +42,21 @@ class Motor(CommonMotor):
|
||||
class Remote:
|
||||
"""LEGO® Powered Up Bluetooth Remote Control."""
|
||||
|
||||
light = ColorLight()
|
||||
buttons = Keypad(
|
||||
light = _common.ColorLight()
|
||||
buttons = _common.Keypad(
|
||||
(
|
||||
Button.LEFT_MINUS,
|
||||
Button.RIGHT_MINUS,
|
||||
Button.LEFT,
|
||||
Button.CENTER,
|
||||
Button.RIGHT,
|
||||
Button.LEFT_PLUS,
|
||||
Button.RIGHT_PLUS,
|
||||
_Button.LEFT_MINUS,
|
||||
_Button.RIGHT_MINUS,
|
||||
_Button.LEFT,
|
||||
_Button.CENTER,
|
||||
_Button.RIGHT,
|
||||
_Button.LEFT_PLUS,
|
||||
_Button.RIGHT_PLUS,
|
||||
)
|
||||
)
|
||||
addresss: Union[str, None]
|
||||
|
||||
def __init__(self, name: str = None, timeout: int = 10000):
|
||||
def __init__(self, name: Optional[str] = None, timeout: int = 10000):
|
||||
"""Remote(name=None, timeout=10000)
|
||||
|
||||
When you instantiate this class, the hub will search for a remote
|
||||
@@ -92,7 +94,7 @@ class Remote:
|
||||
class TiltSensor:
|
||||
"""LEGO® Powered Up Tilt Sensor."""
|
||||
|
||||
def __init__(self, port: Port):
|
||||
def __init__(self, port: _Port):
|
||||
"""TiltSensor(port)
|
||||
|
||||
Arguments:
|
||||
@@ -109,10 +111,10 @@ class TiltSensor:
|
||||
"""
|
||||
|
||||
|
||||
class ColorDistanceSensor(CommonColorSensor):
|
||||
class ColorDistanceSensor(_common.CommonColorSensor):
|
||||
"""LEGO® Powered Up Color and Distance Sensor."""
|
||||
|
||||
light = ColorLight()
|
||||
light = _common.ColorLight()
|
||||
|
||||
def distance(self) -> int:
|
||||
"""distance() -> int: %
|
||||
@@ -133,8 +135,8 @@ class PFMotor(DCMotor):
|
||||
self,
|
||||
sensor: ColorDistanceSensor,
|
||||
channel: int,
|
||||
color: Color,
|
||||
positive_direction: Direction = Direction.CLOCKWISE,
|
||||
color: _Color,
|
||||
positive_direction: _Direction = _Direction.CLOCKWISE,
|
||||
):
|
||||
"""PFMotor(sensor, channel, color, positive_direction=Direction.CLOCKWISE)
|
||||
|
||||
@@ -152,18 +154,18 @@ class PFMotor(DCMotor):
|
||||
"""
|
||||
|
||||
|
||||
class ColorSensor(AmbientColorSensor):
|
||||
class ColorSensor(_common.AmbientColorSensor):
|
||||
"""LEGO® SPIKE Color Sensor."""
|
||||
|
||||
lights = LightArray(3)
|
||||
lights = _common.LightArray(3)
|
||||
|
||||
|
||||
class UltrasonicSensor:
|
||||
"""LEGO® SPIKE Color Sensor."""
|
||||
|
||||
lights = LightArray(3)
|
||||
lights = _common.LightArray(3)
|
||||
|
||||
def __init__(self, port: Port):
|
||||
def __init__(self, port: _Port):
|
||||
"""UltrasonicSensor(port)
|
||||
|
||||
Arguments:
|
||||
@@ -197,7 +199,7 @@ class UltrasonicSensor:
|
||||
class ForceSensor:
|
||||
"""LEGO® SPIKE Force Sensor."""
|
||||
|
||||
def __init__(self, port: Port):
|
||||
def __init__(self, port: _Port):
|
||||
"""ForceSensor(port)
|
||||
|
||||
Arguments:
|
||||
@@ -222,7 +224,7 @@ class ForceSensor:
|
||||
Movement up to approximately 8.00 mm.
|
||||
"""
|
||||
|
||||
def pressed(self, force=3) -> bool:
|
||||
def pressed(self, force: _Number = 3) -> bool:
|
||||
"""pressed(force=3) -> bool
|
||||
|
||||
Checks if the sensor button is pressed.
|
||||
@@ -253,7 +255,7 @@ class ColorLightMatrix:
|
||||
LEGO® SPIKE 3x3 Color Light Matrix.
|
||||
"""
|
||||
|
||||
def __init__(self, port: Port):
|
||||
def __init__(self, port: _Port):
|
||||
"""ColorLightMatrix(port)
|
||||
|
||||
Arguments:
|
||||
@@ -262,7 +264,7 @@ class ColorLightMatrix:
|
||||
"""
|
||||
...
|
||||
|
||||
def on(self, color: Union[Color, Collection[Color]]) -> None:
|
||||
def on(self, color: Union[_Color, Collection[_Color]]) -> None:
|
||||
"""on(colors)
|
||||
|
||||
Turns the lights on.
|
||||
@@ -286,7 +288,7 @@ class ColorLightMatrix:
|
||||
class InfraredSensor:
|
||||
"""LEGO® Powered Up Infrared Sensor."""
|
||||
|
||||
def __init__(self, port: Port):
|
||||
def __init__(self, port: _Port):
|
||||
"""InfraredSensor(port)
|
||||
|
||||
Arguments:
|
||||
@@ -326,14 +328,14 @@ class InfraredSensor:
|
||||
class Light:
|
||||
"""LEGO® Powered Up Light."""
|
||||
|
||||
def __init__(self, port: Port):
|
||||
def __init__(self, port: _Port):
|
||||
"""Light(port)
|
||||
|
||||
Arguments:
|
||||
port (Port): Port to which the device is connected.
|
||||
"""
|
||||
|
||||
def on(self, brightness: int = 100) -> None:
|
||||
def on(self, brightness: _Number = 100) -> None:
|
||||
"""on(brightness=100)
|
||||
|
||||
Turns on the light at the specified brightness.
|
||||
|
||||
+24
-17
@@ -3,10 +3,15 @@
|
||||
|
||||
"""Robotics module for the Pybricks API."""
|
||||
|
||||
from typing import Tuple, Optional, overload
|
||||
from __future__ import annotations
|
||||
|
||||
from ._common import Control, CommonMotor as Motor
|
||||
from .parameters import Stop, Number
|
||||
from typing import Tuple, Optional, overload, TYPE_CHECKING
|
||||
|
||||
from . import _common
|
||||
from .parameters import Stop as _Stop
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .parameters import Number as _Number
|
||||
|
||||
|
||||
class DriveBase:
|
||||
@@ -26,7 +31,7 @@ class DriveBase:
|
||||
|
||||
"""
|
||||
|
||||
distance_control = Control()
|
||||
distance_control = _common.Control()
|
||||
"""The traveled distance and drive speed are controlled by a PID
|
||||
controller. You can use this attribute to change its settings.
|
||||
See the :ref:`motor control <settings>` attribute for an overview of
|
||||
@@ -34,7 +39,7 @@ class DriveBase:
|
||||
functionality, but the settings apply to every millimeter driven by the
|
||||
drive base, instead of degrees turned by one motor."""
|
||||
|
||||
heading_control = Control()
|
||||
heading_control = _common.Control()
|
||||
"""The robot turn angle and turn rate are controlled by a PID
|
||||
controller. You can use this attribute to change its settings.
|
||||
See the :ref:`motor control <settings>` attribute for an overview of
|
||||
@@ -45,10 +50,10 @@ class DriveBase:
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
left_motor: Motor,
|
||||
right_motor: Motor,
|
||||
wheel_diameter: Number,
|
||||
axle_track: Number,
|
||||
left_motor: _common.Motor,
|
||||
right_motor: _common.Motor,
|
||||
wheel_diameter: _Number,
|
||||
axle_track: _Number,
|
||||
):
|
||||
"""DriveBase(left_motor, right_motor, wheel_diameter, axle_track)
|
||||
|
||||
@@ -62,7 +67,7 @@ class DriveBase:
|
||||
both wheels touch the ground.
|
||||
"""
|
||||
|
||||
def drive(self, speed: Number, turn_rate: Number) -> None:
|
||||
def drive(self, speed: _Number, turn_rate: _Number) -> None:
|
||||
"""drive(speed, turn_rate)
|
||||
|
||||
Starts driving at the specified speed and turn rate. Both values are
|
||||
@@ -113,10 +118,10 @@ class DriveBase:
|
||||
@overload
|
||||
def settings(
|
||||
self,
|
||||
straight_speed: Optional[Number],
|
||||
straight_acceleration: Optional[Number],
|
||||
turn_rate: Optional[Number],
|
||||
turn_acceleration: Optional[Number],
|
||||
straight_speed: Optional[_Number],
|
||||
straight_acceleration: Optional[_Number],
|
||||
turn_rate: Optional[_Number],
|
||||
turn_acceleration: Optional[_Number],
|
||||
) -> None:
|
||||
...
|
||||
|
||||
@@ -142,7 +147,7 @@ class DriveBase:
|
||||
deceleration of the robot.
|
||||
"""
|
||||
|
||||
def straight(self, distance, then=Stop.HOLD, wait=True) -> None:
|
||||
def straight(self, distance: _Number, then=_Stop.HOLD, wait=True) -> None:
|
||||
"""straight(distance, then=Stop.HOLD, wait=True)
|
||||
|
||||
Drives straight for a given distance and then stops.
|
||||
@@ -154,7 +159,7 @@ class DriveBase:
|
||||
with the rest of the program.
|
||||
"""
|
||||
|
||||
def turn(self, angle, then=Stop.HOLD, wait=True) -> None:
|
||||
def turn(self, angle: _Number, then=_Stop.HOLD, wait=True) -> None:
|
||||
"""turn(angle, then=Stop.HOLD, wait=True)
|
||||
|
||||
Turns in place by a given angle and then stops.
|
||||
@@ -166,7 +171,9 @@ class DriveBase:
|
||||
with the rest of the program.
|
||||
"""
|
||||
|
||||
def curve(self, radius, angle, then=Stop.HOLD, wait=True) -> None:
|
||||
def curve(
|
||||
self, radius: _Number, angle: _Number, then=_Stop.HOLD, wait=True
|
||||
) -> None:
|
||||
"""curve(radius, angle, then=Stop.HOLD, wait=True)
|
||||
|
||||
Drives an arc along a circle of a given radius, by a given angle.
|
||||
|
||||
@@ -25,14 +25,6 @@ This module implements pseudo-random number generators.
|
||||
from typing import Any, Optional, Sequence, overload
|
||||
|
||||
|
||||
[
|
||||
"random",
|
||||
"uniform",
|
||||
]
|
||||
|
||||
# bookkeeping
|
||||
|
||||
|
||||
def seed(a: Optional[int] = None) -> None:
|
||||
"""
|
||||
Initialize the random number generator.
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
This module provides a subset of the standard Python ``sys`` module.
|
||||
"""
|
||||
|
||||
from uio import FileIO
|
||||
from uio import FileIO as _FileIO
|
||||
|
||||
# REVISIT: most functions are excluded since they aren't useful for Pybricks
|
||||
|
||||
stdin: FileIO = FileIO()
|
||||
stdin: _FileIO = _FileIO()
|
||||
"""
|
||||
Stream object (:class:`uio.FileIO`) that receives input from a connected
|
||||
terminal, if any.
|
||||
@@ -25,7 +25,7 @@ Also see :func:`micropython.kbd_intr` to disable ``KeyboardInterrupt`` if you
|
||||
are passing binary data via ``stdin``.
|
||||
"""
|
||||
|
||||
stdout: FileIO = FileIO()
|
||||
stdout: _FileIO = _FileIO()
|
||||
"""
|
||||
Stream object (:class:`uio.FileIO`) that sends output to a connected terminal,
|
||||
if any.
|
||||
@@ -34,7 +34,7 @@ Reading may modify newline characters. Use ``usys.stdout.buffer`` instead if
|
||||
this is undesirable.
|
||||
"""
|
||||
|
||||
stderr: FileIO = FileIO()
|
||||
stderr: _FileIO = _FileIO()
|
||||
"""
|
||||
Alias for :data:`stdout`.
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user