Skip to content

Commit 5a696ce

Browse files
Add basedpyright and start making fixes
1 parent 9b7fe20 commit 5a696ce

File tree

10 files changed

+64
-89
lines changed

10 files changed

+64
-89
lines changed

.github/workflows/basic_checks.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ jobs:
156156
run: |
157157
cd tools
158158
ruff check --diff python/mbed_tools python/mbed_platformio
159+
basedpyright
159160
160161
161162
docs-check:

tools/pyproject.toml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ unit-tests = [
7373
]
7474
linters = [
7575
"ruff",
76+
"basedpyright",
7677
"SCons" # For packages imported by the PlatformIO scripts
7778
]
7879
greentea = [
@@ -207,4 +208,28 @@ max-args = 10
207208

208209
[tool.ruff.lint.flake8-annotations]
209210
# Don't require a return type annotation for __init__ in most cases
210-
mypy-init-return = true
211+
mypy-init-return = true
212+
213+
[tool.basedpyright]
214+
215+
# Don't warn about things deprecated more recently than python 3.7
216+
pythonVersion = "3.7"
217+
218+
include = [
219+
"python/mbed_tools/**",
220+
"python/mbed_platformio/**"
221+
]
222+
223+
# For right now, we can configure basedpyright in relatively permissive mode.
224+
# We will allow code where the types of things are partially unknown, as there is
225+
# lots of legacy code in that category.
226+
# Also the PlatformIO code has to work with SCons, which is fundamentally type
227+
# annotation proof, so that can likely never pass these checks.
228+
reportUnknownVariableType = false
229+
reportUnknownMemberType = false
230+
reportUnknownLambdaType = false
231+
reportMissingTypeArgument = false
232+
reportUnknownArgumentType = false
233+
reportUnknownParameterType = false
234+
reportAny = false
235+
reportExplicitAny = false

tools/python/mbed_tools/project/project.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def import_project(url: str, dst_path: Any = None, recursive: bool = False) -> p
3232
if not dst_path:
3333
dst_path = pathlib.Path(git_data["dst_path"])
3434

35-
git_utils.clone(url, dst_path)
35+
_ = git_utils.clone(url, dst_path)
3636
if recursive:
3737
libs = LibraryReferences(root=dst_path, ignore_paths=["mbed-os"])
3838
libs.fetch()

tools/python/mbed_tools/py.typed

Whitespace-only changes.

tools/python/mbed_tools/sterm/terminal.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@
1414
To start the terminal clients should call the "run" function, this is the entry point to the module.
1515
"""
1616

17+
import codecs
18+
import typing
1719
from typing import Any
1820

1921
from serial import Serial
2022
from serial.tools.miniterm import Miniterm
23+
from typing_extensions import override
2124

2225

2326
def run(port: str, baud: int, echo: bool = True) -> None:
@@ -31,7 +34,7 @@ def run(port: str, baud: int, echo: bool = True) -> None:
3134
baud: Serial baud rate.
3235
echo: Echo user input back to the console.
3336
"""
34-
term = SerialTerminal(Serial(port=port, baudrate=str(baud)), echo=echo)
37+
term = SerialTerminal(Serial(port=port, baudrate=baud), echo=echo)
3538
term.start()
3639

3740
try:
@@ -55,21 +58,23 @@ class SerialTerminal(Miniterm):
5558
def __init__(self, *args: Any, **kwargs: Any) -> None:
5659
"""Set the rx/tx encoding and special characters."""
5760
super().__init__(*args, **kwargs)
58-
self.exit_character = CTRL_C
59-
self.menu_character = CTRL_T
60-
self.reset_character = CTRL_B
61-
self.help_character = CTRL_H
61+
self.exit_character: str = CTRL_C
62+
self.menu_character: str = CTRL_T
63+
self.reset_character: str = CTRL_B
64+
self.help_character: str = CTRL_H
6265
self.set_rx_encoding("UTF-8")
6366
self.set_tx_encoding("UTF-8")
6467

6568
def reset(self) -> None:
6669
"""Send a reset signal."""
67-
self.serial.sendBreak()
70+
self.serial.send_break()
6871

72+
@override
6973
def get_help_text(self) -> str:
7074
"""Return the text displayed when the user requests help."""
7175
return HELP_TEXT
7276

77+
@override
7378
def writer(self) -> None:
7479
"""Implements terminal behaviour."""
7580
menu_active = False
@@ -79,6 +84,9 @@ def writer(self) -> None:
7984
except KeyboardInterrupt:
8085
input_key = self.exit_character
8186

87+
if input_key is None:
88+
continue
89+
8290
if (menu_active and input_key in VALID_MENU_KEYS) or (input_key == self.help_character):
8391
self.handle_menu_key(input_key)
8492
menu_active = False
@@ -103,7 +111,8 @@ def _write_transformed_char(self, text: str) -> None:
103111
for transformation in self.tx_transformations:
104112
text = transformation.tx(text)
105113

106-
self.serial.write(self.tx_encoder.encode(text))
114+
encoder = typing.cast(codecs.IncrementalEncoder, self.tx_encoder)
115+
_ = self.serial.write(encoder.encode(text))
107116

108117
def _echo_transformed_char(self, text: str) -> None:
109118
for transformation in self.tx_transformations:

tools/python/mbed_tools/targets/_internal/targets_json_parsers/accumulating_attribute_parser.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -75,23 +75,17 @@ def _targets_accumulate_hierarchy(all_targets_data: Dict[str, Any], target_name:
7575
return targets_in_order
7676

7777

78-
def _add_attribute_element(
79-
accumulator: Dict[str, Any], attribute_name: str, elements_to_add: List[Any]
80-
) -> Dict[str, Any]:
78+
def _add_attribute_element(accumulator: Dict[str, Any], attribute_name: str, elements_to_add: List[Any]) -> None:
8179
"""
8280
Adds an attribute element to an attribute.
8381
8482
Args:
8583
accumulator: a store of attributes to be updated
8684
attribute_name: name of the attribute to update
8785
elements_to_add: element to add to the attribute list
88-
89-
Returns:
90-
The accumulator object with the new elements added
9186
"""
9287
for element in elements_to_add:
9388
accumulator[attribute_name].append(element)
94-
return accumulator
9589

9690

9791
def _element_matches(element_to_remove: str, element_to_check: str) -> bool:
@@ -113,19 +107,14 @@ def _element_matches(element_to_remove: str, element_to_check: str) -> bool:
113107
return element_to_check == element_to_remove or element_to_check.startswith(f"{element_to_remove}=")
114108

115109

116-
def _remove_attribute_element(
117-
accumulator: Dict[str, Any], attribute_name: str, elements_to_remove: List[Any]
118-
) -> Dict[str, Any]:
110+
def _remove_attribute_element(accumulator: Dict[str, Any], attribute_name: str, elements_to_remove: List[Any]) -> None:
119111
"""
120112
Removes an attribute element from an attribute.
121113
122114
Args:
123115
accumulator: a store of attributes to be updated
124116
attribute_name: name of the attribute to update
125117
elements_to_remove: element to remove from the attribute list
126-
127-
Returns:
128-
The accumulator object with the desired elements removed
129118
"""
130119
existing_elements = accumulator[attribute_name]
131120
combinations_to_check = itertools.product(existing_elements, elements_to_remove)
@@ -137,7 +126,6 @@ def _remove_attribute_element(
137126

138127
for element in checked_elements_to_remove:
139128
accumulator[attribute_name].remove(element)
140-
return accumulator
141129

142130

143131
def _calculate_attribute_elements(

tools/python/mbed_tools/targets/boards.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@
44
#
55
"""Interface to the Board Database."""
66

7+
from __future__ import annotations
8+
79
import json
810
from collections.abc import Set as AbstractSet
911
from dataclasses import asdict
10-
from typing import Callable, Iterable, Iterator
12+
from typing import Callable, Iterable, Iterator, Sequence
13+
14+
from typing_extensions import override
1115

1216
from mbed_tools.targets._internal import board_database
1317
from mbed_tools.targets.board import Board
@@ -23,7 +27,7 @@ class Boards(AbstractSet):
2327
"""
2428

2529
@classmethod
26-
def from_offline_database(cls) -> "Boards":
30+
def from_offline_database(cls) -> Boards:
2731
"""
2832
Initialise with the offline board database.
2933
@@ -32,23 +36,26 @@ def from_offline_database(cls) -> "Boards":
3236
"""
3337
return cls(Board.from_offline_board_entry(b) for b in board_database.get_offline_board_data())
3438

35-
def __init__(self, boards_data: Iterable["Board"]) -> None:
39+
def __init__(self, boards_data: Iterable[Board]) -> None:
3640
"""
3741
Initialise with a list of boards.
3842
3943
Args:
4044
boards_data: iterable of board data from a board database source.
4145
"""
42-
self._boards_data = tuple(boards_data)
46+
self._boards_data: Sequence[Board] = tuple(boards_data)
4347

44-
def __iter__(self) -> Iterator["Board"]:
48+
@override
49+
def __iter__(self) -> Iterator[Board]:
4550
"""Yield an Board on each iteration."""
4651
yield from self._boards_data
4752

53+
@override
4854
def __len__(self) -> int:
4955
"""Return the number of boards."""
5056
return len(self._boards_data)
5157

58+
@override
5259
def __contains__(self, board: object) -> bool:
5360
"""
5461
Check if a board is in the collection of boards.

tools/python/mbed_tools/targets/env.py

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
import dotenv
2626

27-
dotenv.load_dotenv(dotenv.find_dotenv(usecwd=True))
27+
_ = dotenv.load_dotenv(dotenv.find_dotenv(usecwd=True))
2828

2929

3030
class Env:
@@ -51,26 +51,6 @@ def MBED_API_AUTH_TOKEN(self) -> str: # noqa: N802
5151
"""
5252
return os.getenv("MBED_API_AUTH_TOKEN", "")
5353

54-
@property
55-
def MBED_DATABASE_MODE(self) -> str: # noqa: N802
56-
"""
57-
Database mode to use when retrieving board data.
58-
59-
Mbed Targets supports an online and offline mode, which controls where to look up the board database.
60-
61-
The board lookup can be from either the online or offline database, depending
62-
on the value of an environment variable called `MBED_DATABASE_MODE`.
63-
64-
The mode can be set to one of the following:
65-
66-
- `AUTO`: the offline database is searched first, if the board isn't found the online database is searched.
67-
- `ONLINE`: the online database is always used.
68-
- `OFFLINE`: the offline database is always used.
69-
70-
If `MBED_DATABASE_MODE` is not set, it defaults to `AUTO`.
71-
"""
72-
return os.getenv("MBED_DATABASE_MODE", "AUTO")
73-
7454

7555
env = Env()
7656
"""Instance of `Env` class."""

tools/python/mbed_tools/targets/get_board.py

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,10 @@
99
"""
1010

1111
import logging
12-
from enum import Enum
1312
from typing import Callable
1413

1514
from mbed_tools.targets.board import Board
1615
from mbed_tools.targets.boards import Boards
17-
from mbed_tools.targets.env import env
18-
from mbed_tools.targets.exceptions import BoardDatabaseError, UnknownBoardError, UnsupportedModeError
1916

2017
logger = logging.getLogger(__name__)
2118

@@ -80,39 +77,4 @@ def get_board(matching: Callable) -> Board:
8077
Raises:
8178
UnknownBoard: a board matching the criteria could not be found in the board database.
8279
"""
83-
database_mode = _get_database_mode()
84-
85-
if database_mode == _DatabaseMode.OFFLINE:
86-
logger.info("Using the offline database (only) to identify boards.")
87-
return Boards.from_offline_database().get_board(matching)
88-
89-
if database_mode == _DatabaseMode.ONLINE:
90-
logger.info("Using the online database (only) to identify boards.")
91-
return Boards.from_online_database().get_board(matching)
92-
try:
93-
logger.info("Using the offline database to identify boards.")
94-
return Boards.from_offline_database().get_board(matching)
95-
except UnknownBoardError:
96-
logger.info("Unable to identify a board using the offline database, trying the online database.")
97-
try:
98-
return Boards.from_online_database().get_board(matching)
99-
except BoardDatabaseError as ex:
100-
logger.exception("Unable to access the online database to identify a board.")
101-
raise UnknownBoardError from ex
102-
103-
104-
class _DatabaseMode(Enum):
105-
"""Selected database mode."""
106-
107-
OFFLINE = 0
108-
ONLINE = 1
109-
AUTO = 2
110-
111-
112-
def _get_database_mode() -> _DatabaseMode:
113-
database_mode = env.MBED_DATABASE_MODE
114-
try:
115-
return _DatabaseMode[database_mode]
116-
except KeyError as ex:
117-
msg = f"{database_mode} is not a supported database mode."
118-
raise UnsupportedModeError(msg) from ex
80+
return Boards.from_offline_database().get_board(matching)

tools/run_python_linters.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,7 @@ echo ">> Formatting with ruff..."
3131
ruff format
3232

3333
echo ">> Linting with ruff..."
34-
ruff check --fix python/mbed_tools python/mbed_platformio
34+
ruff check --fix python/mbed_tools python/mbed_platformio
35+
36+
echo ">> Linting and type checking with basedpyright..."
37+
basedpyright

0 commit comments

Comments
 (0)