mirror of
https://github.com/pybricks/pybricks-api.git
synced 2026-09-12 01:24:17 +00:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ccc60c177 | ||
|
|
93c4fcc884 | ||
|
|
aa72605e99 | ||
|
|
8ee725722f | ||
|
|
236bda5f31 | ||
|
|
36ee3bd9ef | ||
|
|
16a0621e03 |
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 3.2.0c2 - 2022-12-20
|
||||
## 3.2.0 - 2022-12-20
|
||||
|
||||
### Changed
|
||||
- Changed module TOC headings to make it easier to find things.
|
||||
|
||||
@@ -4,6 +4,15 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 1.7.0 - 2022-12-28
|
||||
|
||||
### Added
|
||||
- Added `update_user_modules()` function for filtering on user modules.
|
||||
|
||||
### Fixed
|
||||
- Fixed code completion for builtin types.
|
||||
- Fixed code completion for names starting with `_`.
|
||||
|
||||
## 1.6.0 - 2022-12-09
|
||||
|
||||
### Changed
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "pybricks_jedi"
|
||||
version = "1.6.0"
|
||||
version = "1.7.0"
|
||||
description = "Code completion for Pybricks."
|
||||
authors = ["The Pybricks Authors <team@pybricks.com>"]
|
||||
license = "MIT"
|
||||
|
||||
@@ -2,6 +2,7 @@ import io
|
||||
import json
|
||||
import re
|
||||
from enum import IntEnum
|
||||
from typing import Iterable
|
||||
|
||||
import docstring_parser
|
||||
import jedi
|
||||
@@ -31,90 +32,153 @@ PYBRICKS_CODE_PACKAGES = {
|
||||
|
||||
# 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",
|
||||
"builtins.abs",
|
||||
"builtins.all",
|
||||
"builtins.any",
|
||||
"builtins.ArithmeticError",
|
||||
"builtins.AssertionError",
|
||||
"builtins.AttributeError",
|
||||
"builtins.BaseException",
|
||||
"builtins.bin",
|
||||
"builtins.bool",
|
||||
"builtins.bytearray",
|
||||
"builtins.bytes",
|
||||
"builtins.callable",
|
||||
"builtins.chr",
|
||||
"builtins.classmethod",
|
||||
"builtins.complex",
|
||||
"builtins.dict",
|
||||
"builtins.dir",
|
||||
"builtins.divmod",
|
||||
"builtins.enumerate",
|
||||
"builtins.EOFError",
|
||||
"builtins.eval",
|
||||
"builtins.Exception",
|
||||
"builtins.exec",
|
||||
"builtins.float",
|
||||
"builtins.GeneratorExit",
|
||||
"builtins.getattr",
|
||||
"builtins.globals",
|
||||
"builtins.hasattr",
|
||||
"builtins.hash",
|
||||
"builtins.help",
|
||||
"builtins.hex",
|
||||
"builtins.id",
|
||||
"builtins.ImportError",
|
||||
"builtins.IndentationError",
|
||||
"builtins.IndexError",
|
||||
"builtins.input",
|
||||
"builtins.int",
|
||||
"builtins.isinstance",
|
||||
"builtins.issubclass",
|
||||
"builtins.iter",
|
||||
"builtins.KeyboardInterrupt",
|
||||
"builtins.KeyError",
|
||||
"builtins.len",
|
||||
"builtins.list",
|
||||
"builtins.locals",
|
||||
"builtins.LookupError",
|
||||
"builtins.map",
|
||||
"builtins.max",
|
||||
"builtins.MemoryError",
|
||||
"builtins.min",
|
||||
"builtins.NameError",
|
||||
"builtins.next",
|
||||
"builtins.NotImplementedError",
|
||||
"builtins.object",
|
||||
"builtins.oct",
|
||||
"builtins.ord",
|
||||
"builtins.OSError",
|
||||
"builtins.OverflowError",
|
||||
"builtins.pow",
|
||||
"builtins.print",
|
||||
"builtins.range",
|
||||
"builtins.repr",
|
||||
"builtins.reversed",
|
||||
"builtins.round",
|
||||
"builtins.RuntimeError",
|
||||
"builtins.set",
|
||||
"builtins.setattr",
|
||||
"builtins.slice",
|
||||
"builtins.sorted",
|
||||
"builtins.staticmethod",
|
||||
"builtins.StopIteration",
|
||||
"builtins.str",
|
||||
"builtins.sum",
|
||||
"builtins.super",
|
||||
"builtins.SyntaxError",
|
||||
"builtins.SystemExit",
|
||||
"builtins.tuple",
|
||||
"builtins.type",
|
||||
"builtins.TypeError",
|
||||
"builtins.ValueError",
|
||||
"builtins.ZeroDivisionError",
|
||||
"builtins.zip",
|
||||
"builtins.bytearray.append",
|
||||
"builtins.bytearray.extend",
|
||||
"builtins.dict.clear",
|
||||
"builtins.dict.copy",
|
||||
"builtins.dict.fromkeys",
|
||||
"builtins.dict.get",
|
||||
"builtins.dict.items",
|
||||
"builtins.dict.keys",
|
||||
"builtins.dict.pop",
|
||||
"builtins.dict.popitem",
|
||||
"builtins.dict.setdefault",
|
||||
"builtins.dict.update",
|
||||
"builtins.dict.values",
|
||||
"builtins.int.from_bytes",
|
||||
"builtins.int.to_bytes",
|
||||
"builtins.list.append",
|
||||
"builtins.list.clear",
|
||||
"builtins.list.copy",
|
||||
"builtins.list.count",
|
||||
"builtins.list.extend",
|
||||
"builtins.list.index",
|
||||
"builtins.list.insert",
|
||||
"builtins.list.pop",
|
||||
"builtins.list.remove",
|
||||
"builtins.list.reverse",
|
||||
"builtins.list.sort",
|
||||
"builtins.str.count",
|
||||
"builtins.str.endswith",
|
||||
"builtins.str.find",
|
||||
"builtins.str.format",
|
||||
"builtins.str.index",
|
||||
"builtins.str.isalpha",
|
||||
"builtins.str.isdigit",
|
||||
"builtins.str.islower",
|
||||
"builtins.str.isspace",
|
||||
"builtins.str.isupper",
|
||||
"builtins.str.join",
|
||||
"builtins.str.lower",
|
||||
"builtins.str.lstrip",
|
||||
"builtins.str.replace",
|
||||
"builtins.str.rfind",
|
||||
"builtins.str.rindex",
|
||||
"builtins.str.rsplit",
|
||||
"builtins.str.rstrip",
|
||||
"builtins.str.split",
|
||||
"builtins.str.startswith",
|
||||
"builtins.str.strip",
|
||||
"builtins.str.upper",
|
||||
"builtins.tuple.count",
|
||||
"builtins.tuple.index",
|
||||
}
|
||||
|
||||
PYBRICKS_BUILTINS_NO_FULLNAME = {"items", "values"}
|
||||
|
||||
PYBRICKS_TYPING = {
|
||||
"typing.MutableSequence.append",
|
||||
"typing.MutableSequence.extend",
|
||||
"typing.MutableMapping.pop",
|
||||
"typing.Mapping.get",
|
||||
}
|
||||
|
||||
MICROPY_NOT_SUPPORTED_DUNDER = {"__doc__", "__package__"}
|
||||
|
||||
user_modules = set()
|
||||
|
||||
# Types from monaco editor
|
||||
|
||||
|
||||
@@ -243,10 +307,14 @@ class SignatureHelp(TypedDict):
|
||||
|
||||
def _is_pybricks(c: Completion) -> bool:
|
||||
# filter all "private" names (leading underscore)
|
||||
if (isinstance(c.name, str)) and c.name.startswith("_"):
|
||||
return False
|
||||
if c.name is not None:
|
||||
if c.name.startswith("_") and c.module_name != "__main__":
|
||||
return False
|
||||
|
||||
if isinstance(c.full_name, str):
|
||||
if c.name in MICROPY_NOT_SUPPORTED_DUNDER:
|
||||
return False
|
||||
|
||||
if c.full_name is not None:
|
||||
# this catches things like `from __future__ import annotations`
|
||||
if c.full_name.startswith("_") and c.module_name != "__main__":
|
||||
return False
|
||||
@@ -256,16 +324,19 @@ def _is_pybricks(c: Completion) -> bool:
|
||||
return False
|
||||
|
||||
# filter out typing types
|
||||
if c.full_name.startswith("typing."):
|
||||
if c.full_name.startswith("typing.") and c.full_name not in PYBRICKS_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
|
||||
return c.full_name in PYBRICKS_CODE_PACKAGES or c.full_name in user_modules
|
||||
|
||||
# filter subset of builtins
|
||||
if c.module_name == "builtins" and c.type != "keyword":
|
||||
return c.name in PYBRICKS_BUILTINS
|
||||
if c.full_name is None:
|
||||
return c.name in PYBRICKS_BUILTINS_NO_FULLNAME
|
||||
|
||||
return c.full_name in PYBRICKS_BUILTINS
|
||||
|
||||
# this is a type alias, not a real type
|
||||
if c.full_name == "pybricks.parameters.Number":
|
||||
@@ -473,3 +544,15 @@ def get_signatures(code: str, line: int, column: int) -> str:
|
||||
"""
|
||||
signatures = jedi.Script(code).get_signatures(line, column - 1)
|
||||
return json.dumps(_map_signatures(signatures))
|
||||
|
||||
|
||||
def update_user_modules(names: Iterable[str]) -> None:
|
||||
"""
|
||||
Updates the set of user module names used for filtering.
|
||||
|
||||
Args:
|
||||
names:
|
||||
An iterable of module names.
|
||||
"""
|
||||
user_modules.clear()
|
||||
user_modules.update(names)
|
||||
|
||||
@@ -7,6 +7,9 @@ Tests for correct code completion of builtins.
|
||||
|
||||
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from pybricks_jedi import CompletionItem, complete
|
||||
|
||||
|
||||
@@ -123,4 +126,144 @@ def test_empty_code():
|
||||
"yield",
|
||||
"ZeroDivisionError",
|
||||
"zip",
|
||||
"__name__",
|
||||
]
|
||||
|
||||
|
||||
FUNCTION_PARAMS = [
|
||||
pytest.param(
|
||||
"''.",
|
||||
[
|
||||
"count",
|
||||
"endswith",
|
||||
"find",
|
||||
"format",
|
||||
"index",
|
||||
"isalpha",
|
||||
"isdigit",
|
||||
"islower",
|
||||
"isspace",
|
||||
"isupper",
|
||||
"join",
|
||||
"lower",
|
||||
"lstrip",
|
||||
"replace",
|
||||
"rfind",
|
||||
"rindex",
|
||||
"rsplit",
|
||||
"rstrip",
|
||||
"split",
|
||||
"startswith",
|
||||
"strip",
|
||||
"upper",
|
||||
],
|
||||
),
|
||||
pytest.param(
|
||||
"str().",
|
||||
[
|
||||
"count",
|
||||
"endswith",
|
||||
"find",
|
||||
"format",
|
||||
"index",
|
||||
"isalpha",
|
||||
"isdigit",
|
||||
"islower",
|
||||
"isspace",
|
||||
"isupper",
|
||||
"join",
|
||||
"lower",
|
||||
"lstrip",
|
||||
"replace",
|
||||
"rfind",
|
||||
"rindex",
|
||||
"rsplit",
|
||||
"rstrip",
|
||||
"split",
|
||||
"startswith",
|
||||
"strip",
|
||||
"upper",
|
||||
],
|
||||
),
|
||||
pytest.param("(0).", ["from_bytes", "to_bytes"]),
|
||||
pytest.param("int().", ["from_bytes", "to_bytes"]),
|
||||
pytest.param(
|
||||
"{}.",
|
||||
[
|
||||
"clear",
|
||||
"copy",
|
||||
"fromkeys",
|
||||
"get",
|
||||
"items",
|
||||
"keys",
|
||||
"pop",
|
||||
"popitem",
|
||||
"setdefault",
|
||||
"update",
|
||||
"values",
|
||||
],
|
||||
),
|
||||
pytest.param(
|
||||
"dict().",
|
||||
[
|
||||
"clear",
|
||||
"copy",
|
||||
"fromkeys",
|
||||
"get",
|
||||
"items",
|
||||
"keys",
|
||||
"pop",
|
||||
"popitem",
|
||||
"setdefault",
|
||||
"update",
|
||||
"values",
|
||||
],
|
||||
),
|
||||
pytest.param(
|
||||
"[].",
|
||||
[
|
||||
"append",
|
||||
"clear",
|
||||
"copy",
|
||||
"count",
|
||||
"extend",
|
||||
"index",
|
||||
"insert",
|
||||
"pop",
|
||||
"remove",
|
||||
"reverse",
|
||||
"sort",
|
||||
],
|
||||
),
|
||||
pytest.param(
|
||||
"list().",
|
||||
[
|
||||
"append",
|
||||
"clear",
|
||||
"copy",
|
||||
"count",
|
||||
"extend",
|
||||
"index",
|
||||
"insert",
|
||||
"pop",
|
||||
"remove",
|
||||
"reverse",
|
||||
"sort",
|
||||
],
|
||||
),
|
||||
pytest.param("().", ["count", "index"]),
|
||||
pytest.param("tuple().", ["count", "index"]),
|
||||
pytest.param("bytearray().", ["append", "extend"]),
|
||||
pytest.param("bytes().", []),
|
||||
pytest.param("b''.", []),
|
||||
pytest.param("float().", []),
|
||||
pytest.param("(0.0).", []),
|
||||
pytest.param("complex().", []),
|
||||
pytest.param("type().", []),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("code,attributes", FUNCTION_PARAMS)
|
||||
def test_get_completion_for_builtins(code: str, attributes: list[str]):
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == attributes
|
||||
|
||||
@@ -6,7 +6,9 @@ Tests for correct code completion of import statements.
|
||||
"""
|
||||
|
||||
import json
|
||||
from pybricks_jedi import CompletionItem, complete
|
||||
|
||||
import pytest
|
||||
from pybricks_jedi import CompletionItem, complete, update_user_modules
|
||||
|
||||
|
||||
def test_from():
|
||||
@@ -27,6 +29,32 @@ def test_from():
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user_modules():
|
||||
update_user_modules(["jedi", "pytest"])
|
||||
yield
|
||||
update_user_modules([])
|
||||
|
||||
|
||||
def test_from_with_user_modules(user_modules):
|
||||
code = "from "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"jedi",
|
||||
"micropython",
|
||||
"pybricks",
|
||||
"pytest",
|
||||
"uerrno",
|
||||
"uio",
|
||||
"ujson",
|
||||
"umath",
|
||||
"urandom",
|
||||
"uselect",
|
||||
"ustruct",
|
||||
"usys",
|
||||
]
|
||||
|
||||
|
||||
def test_from_pybricks_import():
|
||||
code = "from pybricks import "
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import json
|
||||
from pybricks_jedi import CompletionItem, complete
|
||||
|
||||
|
||||
def test_get_completion_for_private_globals():
|
||||
code = """
|
||||
_X = 0
|
||||
|
||||
_
|
||||
"""
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 4, 2))
|
||||
assert [c["insertText"] for c in completions] == ["_X", "__name__"]
|
||||
|
||||
|
||||
def test_get_completion_for_private_attributes():
|
||||
code = """
|
||||
class X:
|
||||
def __init__(self):
|
||||
self.public = 0
|
||||
self._protected = 0
|
||||
self.__private = 0
|
||||
|
||||
x = X()
|
||||
|
||||
x.
|
||||
"""
|
||||
completions: list[CompletionItem] = json.loads(complete(code, 10, 3))
|
||||
assert [c["insertText"] for c in completions] == [
|
||||
"public",
|
||||
"_protected",
|
||||
"__init__",
|
||||
]
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
<!-- refer to https://keepachangelog.com/en/1.0.0/ for guidance -->
|
||||
|
||||
## 2.7.0 - 2022-12-20
|
||||
|
||||
### Changed
|
||||
- Updated docs to v3.2.0c2.
|
||||
|
||||
## 2.6.0 - 2022-12-09
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@pybricks/ide-docs",
|
||||
"version": "2.6.0",
|
||||
"version": "2.7.0",
|
||||
"description": "Special build of Pybricks API docs for embedding in an IDE.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "pybricks"
|
||||
version = "3.2.0c2"
|
||||
version = "3.2.0"
|
||||
description = "Documentation and user-API stubs for Pybricks MicroPython"
|
||||
authors = ["The Pybricks Authors <dev@pybricks.com>"]
|
||||
maintainers = ["Laurens Valk <laurens@pybricks.com>", "David Lechner <david@pybricks.com>" ]
|
||||
|
||||
@@ -1074,8 +1074,9 @@ def round(*args):
|
||||
truncate trailing zeros. To print numbers nicely, format strings instead::
|
||||
|
||||
# print two decimal places
|
||||
print('my number: %.2f' % number) print('my number:
|
||||
{:.2f}'.format(number))
|
||||
print('my number: %.2f' % number)
|
||||
print('my number: {:.2f}'.format(number))
|
||||
print(f'my number: {number:.2f}')
|
||||
|
||||
Arguments:
|
||||
number (float): The number to be rounded.
|
||||
|
||||
Reference in New Issue
Block a user