diff --git a/src/pybricks/__init__.py b/src/pybricks/__init__.py index ffceb7b..7b24417 100644 --- a/src/pybricks/__init__.py +++ b/src/pybricks/__init__.py @@ -1,7 +1,4 @@ -from typing import Tuple - - -version: Tuple[str, str, str] = ( +version: tuple[str, str, str] = ( "hub", "3.X.YbZ", "v3.X.YbZ-GIT_HASH on DATE", diff --git a/src/pybricks/_common.py b/src/pybricks/_common.py index 649e775..4e0cebd 100644 --- a/src/pybricks/_common.py +++ b/src/pybricks/_common.py @@ -6,24 +6,16 @@ speakers, and batteries.""" from __future__ import annotations -from typing import ( - Union, - Iterable, - overload, - Optional, - Tuple, - Collection, - Set, - TYPE_CHECKING, -) +from typing import TYPE_CHECKING, overload -from .tools import Matrix -from .parameters import Axis, Direction, Stop, Button, Port, Color, Side +from .parameters import Direction, Stop if TYPE_CHECKING: - from typing import Any, Awaitable, TypeVar + from collections.abc import Awaitable, Collection, Iterable + from typing import Any, TypeVar - from .parameters import Number + from .parameters import Axis, Button, Color, Number, Port, Side + from .tools import Matrix _T_co = TypeVar("_T_co", covariant=True) @@ -36,9 +28,9 @@ if TYPE_CHECKING: class MaybeAwaitableInt(int, Awaitable[int]): ... - class MaybeAwaitableTuple(Tuple[_T_co], Awaitable[Tuple[_T_co]]): ... + class MaybeAwaitableTuple(tuple[_T_co], Awaitable[tuple[_T_co]]): ... - class MaybeAwaitableSet(Set[_T_co], Awaitable[Set[_T_co]]): ... + class MaybeAwaitableSet(set[_T_co], Awaitable[set[_T_co]]): ... class MaybeAwaitableColor(Color, Awaitable[Color]): ... @@ -48,9 +40,7 @@ if TYPE_CHECKING: class System: """System control actions for a hub.""" - def set_stop_button( - self, button: Optional[Union[Button, Iterable[Button]]] - ) -> None: + def set_stop_button(self, button: Button | Iterable[Button] | None) -> None: """ set_stop_button(button) @@ -188,12 +178,12 @@ class DCMotor: def settings(self, max_voltage: Number) -> None: ... @overload - def settings(self) -> Tuple[int]: ... + def settings(self) -> tuple[int]: ... def settings(self, *args): """ settings(max_voltage) - settings() -> Tuple[int] + settings() -> tuple[int] Configures motor settings. If no arguments are given, this returns the current values. @@ -218,18 +208,18 @@ class Control: @overload def limits( self, - speed: Optional[Number] = None, - acceleration: Optional[Number] = None, - torque: Optional[Number] = None, + speed: Number | None = None, + acceleration: Number | None = None, + torque: Number | None = None, ) -> None: ... @overload - def limits(self) -> Tuple[int, int, int]: ... + def limits(self) -> tuple[int, int, int]: ... def limits(self, *args): """ limits(speed, acceleration, torque) - limits() -> Tuple[int, int, int] + limits() -> tuple[int, int, int] Configures the maximum speed, acceleration, and torque. @@ -252,19 +242,19 @@ class Control: @overload def pid( self, - kp: Optional[Number] = None, - ki: Optional[Number] = None, - kd: Optional[Number] = None, - integral_deadzone: Optional[Number] = None, - integral_rate: Optional[Number] = None, + kp: Number | None = None, + ki: Number | None = None, + kd: Number | None = None, + integral_deadzone: Number | None = None, + integral_rate: Number | None = None, ) -> None: ... @overload - def pid(self) -> Tuple[int, int, int, int, int]: ... + def pid(self) -> tuple[int, int, int, int, int]: ... def pid(self, *args): """pid(kp, ki, kd, integral_deadzone, integral_rate) - pid() -> Tuple[int, int, int, int, int] + pid() -> tuple[int, int, int, int, int] Gets or sets the PID values for position and speed control. @@ -287,15 +277,15 @@ class Control: @overload def target_tolerances( - self, speed: Optional[Number] = None, position: Optional[Number] = None + self, speed: Number | None = None, position: Number | None = None ) -> None: ... @overload - def target_tolerances(self) -> Tuple[int, int]: ... + def target_tolerances(self) -> tuple[int, int]: ... def target_tolerances(self, *args): """target_tolerances(speed, position) - target_tolerances() -> Tuple[int, int] + target_tolerances() -> tuple[int, int] Gets or sets the tolerances that say when a maneuver is done. @@ -311,15 +301,15 @@ class Control: @overload def stall_tolerances( - self, speed: Optional[Number] = None, time: Optional[Number] = None + self, speed: Number | None = None, time: Number | None = None ) -> None: ... @overload - def stall_tolerances(self) -> Tuple[int, int]: ... + def stall_tolerances(self) -> tuple[int, int]: ... def stall_tolerances(self, speed, time): """stall_tolerances(speed, time) - stall_tolerances() -> Tuple[int, int] + stall_tolerances() -> tuple[int, int] Gets or sets stalling tolerances. @@ -337,8 +327,8 @@ class Control: class Model: """Class to interact with motor state observer and settings.""" - def state(self) -> Tuple[float, float, float, bool]: - """state() -> Tuple[float, float, float, bool] + def state(self) -> tuple[float, float, float, bool]: + """state() -> tuple[float, float, float, bool] Gets the estimated angle, speed, current, and stall state of the motor, using a simulation model that mimics the real motor. @@ -364,7 +354,7 @@ class Model: def settings(self, speed, time): """settings(values) - settings() -> Tuple + settings() -> tuple Gets or sets model settings as a tuple of integers. If no arguments are given, this will return the current values. This method is mainly used @@ -374,7 +364,7 @@ class Model: .. _model settings: https://docs.pybricks.com/projects/pbio/en/latest/struct__pbio__observer__settings__t.html Arguments: - values (Tuple): Tuple with `model settings`_. + values (tuple): Tuple with `model settings`_. """ @@ -394,7 +384,7 @@ class Motor(DCMotor): self, port: Port, positive_direction: Direction = Direction.CLOCKWISE, - gears: Optional[Union[Collection[int], Collection[Collection[int]]]] = None, + gears: Collection[int] | Collection[Collection[int]] | None = None, reset_angle: bool = True, profile: Number = None, ): @@ -480,7 +470,7 @@ class Motor(DCMotor): The load torque. """ - def reset_angle(self, angle: Optional[Number]) -> None: + def reset_angle(self, angle: Number | None) -> None: """ reset_angle(angle) @@ -577,7 +567,7 @@ class Motor(DCMotor): self, speed: Number, then: Stop = Stop.COAST, - duty_limit: Optional[Number] = None, + duty_limit: Number | None = None, ) -> MaybeAwaitableInt: """ run_until_stalled(speed, then=Stop.COAST, duty_limit=None) -> int: deg @@ -773,9 +763,7 @@ class ExternalColorLight: class LightArray3: """Control an array of three single-color lights.""" - def on( - self, brightness: Union[Number, Tuple[Number, Number, Number]] - ) -> MaybeAwaitable: + def on(self, brightness: Number | tuple[Number, Number, Number]) -> MaybeAwaitable: """on(brightness) Turns on the lights at the specified brightness. @@ -798,7 +786,7 @@ class LightArray4(LightArray3): """Control an array of four single-color lights.""" def on( - self, brightness: Union[Number, Tuple[Number, Number, Number, Number]] + self, brightness: Number | tuple[Number, Number, Number, Number] ) -> MaybeAwaitable: """on(brightness) @@ -926,8 +914,8 @@ class Keypad: def __init__(self, active_buttons): ... - def pressed(self) -> Set[Button]: - """pressed() -> Set[Button] + def pressed(self) -> set[Button]: + """pressed() -> set[Button] Checks which buttons are currently pressed. @@ -999,8 +987,8 @@ class Charger: class SimpleAccelerometer: """Get measurements from an accelerometer.""" - def acceleration(self) -> Tuple[int, int, int]: - """acceleration() -> Tuple[int, int, int]: mm/s² + def acceleration(self) -> tuple[int, int, int]: + """acceleration() -> tuple[int, int, int]: mm/s² Gets the acceleration of the device. @@ -1018,8 +1006,8 @@ class SimpleAccelerometer: ``Side.FRONT`` or ``Side.BACK``. """ - def tilt(self) -> Tuple[int, int]: - """tilt() -> Tuple[int, int] + def tilt(self) -> tuple[int, int]: + """tilt() -> tuple[int, int] Gets the pitch and roll angles. This is relative to the :ref:`user-specified neutral orientation `. @@ -1049,8 +1037,8 @@ class IMU: ``Side.FRONT`` or ``Side.BACK``. """ - def tilt(self, calibrated: bool = True) -> Tuple[int, int]: - """tilt(calibrated=True) -> Tuple[int, int] + def tilt(self, calibrated: bool = True) -> tuple[int, int]: + """tilt(calibrated=True) -> tuple[int, int] Gets the pitch and roll angles. This is relative to the :ref:`user-specified neutral orientation `. @@ -1124,27 +1112,27 @@ class IMU: angular_velocity_threshold: float = None, acceleration_threshold: float = None, heading_correction: float = None, - angular_velocity_bias: Tuple[float, float, float] = None, - angular_velocity_scale: Tuple[float, float, float] = None, - acceleration_correction: Tuple[float, float, float, float, float, float] = None, + angular_velocity_bias: tuple[float, float, float] = None, + angular_velocity_scale: tuple[float, float, float] = None, + acceleration_correction: tuple[float, float, float, float, float, float] = None, ) -> None: ... @overload def settings( self, - ) -> Tuple[ + ) -> tuple[ float, float, float, - Tuple[float, float, float], - Tuple[float, float, float], - Tuple[float, float, float, float, float, float], + tuple[float, float, float], + tuple[float, float, float], + tuple[float, float, float, float, float, float], ]: ... def settings(self, *args): """ settings(*, angular_velocity_threshold, acceleration_threshold, heading_correction, angular_velocity_bias, angular_velocity_scale, acceleration_correction) - settings() -> Tuple + settings() -> tuple Configures the IMU settings. If no arguments are given, this returns the current values. Use keyword arguments for each value diff --git a/src/pybricks/ev3devices.py b/src/pybricks/ev3devices.py index a73d341..471398d 100644 --- a/src/pybricks/ev3devices.py +++ b/src/pybricks/ev3devices.py @@ -5,29 +5,20 @@ from __future__ import annotations -from typing import Optional, Tuple, List +from typing import TYPE_CHECKING from . import _common -from .parameters import ( - Button as _Button, - Color as _Color, - Direction as _Direction, - Port as _Port, -) - -from typing import ( - TYPE_CHECKING, -) +from .parameters import Direction if TYPE_CHECKING: from ._common import ( - MaybeAwaitableColor, MaybeAwaitableBool, + MaybeAwaitableColor, MaybeAwaitableInt, MaybeAwaitableSet, MaybeAwaitableTuple, ) - from .parameters import Number, Port + from .parameters import Button, Port class Motor(_common.Motor): @@ -37,7 +28,7 @@ class Motor(_common.Motor): class TouchSensor: """LEGO® MINDSTORMS® EV3 Touch Sensor.""" - def __init__(self, port: _Port): + def __init__(self, port: Port): """TouchSensor(port) Arguments: @@ -58,7 +49,7 @@ class TouchSensor: class ColorSensor: """LEGO® MINDSTORMS® EV3 Color Sensor.""" - def __init__(self, port: _Port): + def __init__(self, port: Port): """ColorSensor(port) Arguments: @@ -99,7 +90,7 @@ class ColorSensor: """ def rgb(self) -> MaybeAwaitableTuple[int, int, int]: - """rgb() -> Tuple[int, int, int] + """rgb() -> tuple[int, int, int] Measures the reflection of a surface using a red, green, and then a blue light. @@ -113,7 +104,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: @@ -133,10 +124,10 @@ class InfraredSensor: """ - def beacon(self, channel: int) -> MaybeAwaitableTuple[Optional[int], Optional[int]]: + def beacon(self, channel: int) -> MaybeAwaitableTuple[int | None, int | None]: """ - beacon(channel) -> Tuple[int, int] - beacon(channel) -> Tuple[None, None] + beacon(channel) -> tuple[int, int] + beacon(channel) -> tuple[None, None] Measures the relative distance and angle between the remote and the infrared sensor. @@ -150,8 +141,8 @@ class InfraredSensor: a tuple of (``None``, ``None``) if no remote is detected. """ - def buttons(self, channel: int) -> MaybeAwaitableSet[_Button]: - """buttons(channel) -> Set[Button] + def buttons(self, channel: int) -> MaybeAwaitableSet[Button]: + """buttons(channel) -> set[Button] Checks which buttons on the infrared remote are pressed. @@ -166,8 +157,8 @@ class InfraredSensor: """ - def keypad(self) -> MaybeAwaitableSet[_Button]: - """keypad() -> Set[Button] + def keypad(self) -> MaybeAwaitableSet[Button]: + """keypad() -> set[Button] Checks which buttons on the infrared remote are pressed. @@ -184,7 +175,7 @@ class InfraredSensor: class GyroSensor: """LEGO® MINDSTORMS® EV3 Gyro Sensor.""" - def __init__(self, port: _Port, direction: _Direction = _Direction.CLOCKWISE): + def __init__(self, port: Port, direction: Direction = Direction.CLOCKWISE): """GyroSensor(port) Arguments: @@ -228,7 +219,7 @@ class GyroSensor: class UltrasonicSensor: """LEGO® MINDSTORMS® EV3 Ultrasonic Sensor.""" - def __init__(self, port: _Port): + def __init__(self, port: Port): """UltrasonicSensor(port) Arguments: @@ -268,3 +259,15 @@ class UltrasonicSensor: ``True`` if ultrasonic sounds are detected, ``False`` if not. """ + + +# Hide type-only names from jedi completions in the module namespace. +if TYPE_CHECKING: + del Button + del Direction + del MaybeAwaitableBool + del MaybeAwaitableColor + del MaybeAwaitableInt + del MaybeAwaitableSet + del MaybeAwaitableTuple + del Port diff --git a/src/pybricks/hubs.py b/src/pybricks/hubs.py index e64fb72..6930664 100644 --- a/src/pybricks/hubs.py +++ b/src/pybricks/hubs.py @@ -3,10 +3,14 @@ """LEGO® Programmable Hubs.""" +from __future__ import annotations + +from typing import TYPE_CHECKING + from . import _common from .ev3dev import _speaker from .media.ev3dev import Image as _Image -from .parameters import Button as _Button, Axis +from .parameters import Axis, Button as _Button class EV3Brick: @@ -178,5 +182,6 @@ class InventorHub(PrimeHub): """LEGO® MINDSTORMS Inventor Hub.""" -# HACK: hide from jedi -del Axis +# Hide type-only names from jedi completions in the module namespace. +if TYPE_CHECKING: + del Axis diff --git a/src/pybricks/iodevices.py b/src/pybricks/iodevices.py index 8507132..63d8516 100644 --- a/src/pybricks/iodevices.py +++ b/src/pybricks/iodevices.py @@ -5,20 +5,19 @@ from __future__ import annotations -from typing import Tuple, Optional, overload, TYPE_CHECKING +from typing import TYPE_CHECKING, overload from . import _common -from .parameters import Port as _Port if TYPE_CHECKING: from ._common import MaybeAwaitable, MaybeAwaitableBytes, MaybeAwaitableTuple - from .parameters import Number + from .parameters import Number, Port class PUPDevice: """Powered Up motor or sensor.""" - def __init__(self, port: _Port): + def __init__(self, port: Port): """PUPDevice(port) Arguments: @@ -26,7 +25,7 @@ class PUPDevice: """ def info(self) -> dict: - """info() -> Dict + """info() -> dict Gets information about the device. @@ -43,7 +42,7 @@ class PUPDevice: """ def read(self, mode: int) -> MaybeAwaitableTuple: - """read(mode) -> Tuple + """read(mode) -> tuple Reads values from a given mode. @@ -65,7 +64,7 @@ class PUPDevice: support reading (e.g. a DC motor or light). """ - def write(self, mode: int, data: Tuple) -> MaybeAwaitable: + def write(self, mode: int, data: tuple) -> MaybeAwaitable: """write(mode, data) Writes values to the device. Only selected UART devices and modes @@ -116,7 +115,7 @@ class DCMotor(_common.DCMotor): class AnalogSensor: """Generic or custom analog sensor.""" - def __init__(self, port: _Port, custom: bool = False): + def __init__(self, port: Port, custom: bool = False): """AnalogSensor(port, custom=False) Arguments: @@ -190,7 +189,7 @@ class I2CDevice: def __init__( self, - port: _Port, + port: Port, address: int, custom: bool = False, power_pin: int = 0, @@ -212,17 +211,15 @@ class I2CDevice: """ @overload - def read( - self, reg: Optional[int] = None, length: int = 1 - ) -> MaybeAwaitableBytes: ... + def read(self, reg: int | None = None, length: int = 1) -> MaybeAwaitableBytes: ... @overload def read( - self, reg: Optional[int] = None, length: int = 1, map: callable = ... + self, reg: int | None = None, length: int = 1, map: callable = ... ) -> MaybeAwaitable: ... def read( - self, reg: Optional[int] = None, length: int = 1, map=None + self, reg: int | None = None, length: int = 1, map=None ) -> MaybeAwaitableBytes: """read(reg=None, length=1) -> bytes read(reg=None, length=1, map=callable) -> Any @@ -244,7 +241,7 @@ class I2CDevice: """ def write( - self, reg: Optional[int] = None, data: Optional[bytes] = None + self, reg: int | None = None, data: bytes | None = None ) -> MaybeAwaitable: """write(reg=None, data=None) @@ -273,9 +270,9 @@ class UARTDevice: def __init__( self, - port: _Port, + port: Port, baudrate: int = 115200, - timeout: Optional[int] = None, + timeout: int | None = None, power_pin: int = 0, ): """UARTDevice(port, baudrate=115200, timeout=None, power_pin=0) @@ -516,7 +513,7 @@ class XboxController: def __init__( self, joystick_deadzone: int = 10, - name: Optional[str] = None, + name: str | None = None, timeout: int = 10000, connect: bool = True, ): @@ -559,8 +556,8 @@ class XboxController: OSError: If the controller is not connected. """ - def state(self) -> Tuple: - """state() -> Tuple + def state(self) -> tuple: + """state() -> tuple Gets all raw controller input values as a single tuple. This gives access to values not exposed by the other methods. @@ -576,8 +573,8 @@ class XboxController: OSError: If the controller is not connected. """ - def joystick_left(self) -> Tuple[int, int]: - """joystick_left() -> Tuple + def joystick_left(self) -> tuple[int, int]: + """joystick_left() -> tuple Gets the left joystick position as percentages between -100% and 100%. The center position is (0, 0). A square deadzone is applied: @@ -590,8 +587,8 @@ class XboxController: OSError: If the controller is not connected. """ - def joystick_right(self) -> Tuple[int, int]: - """joystick_right() -> Tuple + def joystick_right(self) -> tuple[int, int]: + """joystick_right() -> tuple Gets the right joystick position as percentages between -100% and 100%. The center position is (0, 0). A square deadzone is applied: @@ -604,8 +601,8 @@ class XboxController: OSError: If the controller is not connected. """ - def triggers(self) -> Tuple[int, int]: - """triggers() -> Tuple + def triggers(self) -> tuple[int, int]: + """triggers() -> tuple Gets the left and right trigger positions as percentages between 0% and 100%. @@ -651,7 +648,7 @@ class XboxController: def rumble( self, - power: Number | Tuple[Number, Number, Number, Number] = 100, + power: Number | tuple[Number, Number, Number, Number] = 100, duration: int = 200, count: int = 1, delay: int = 100, @@ -686,9 +683,10 @@ class XboxController: """ -# hide from jedi +# Hide type-only names from jedi completions in the module namespace. if TYPE_CHECKING: del MaybeAwaitable del MaybeAwaitableBytes del MaybeAwaitableTuple del Number + del Port diff --git a/src/pybricks/messaging.py b/src/pybricks/messaging.py index 32fdfa9..68f3565 100644 --- a/src/pybricks/messaging.py +++ b/src/pybricks/messaging.py @@ -7,26 +7,13 @@ Classes to send and receive messages from another device. from __future__ import annotations - -from typing import ( - abstractmethod, - Callable, - Generic, - Iterable, - List, - Optional, - overload, - Sequence, - Tuple, - TYPE_CHECKING, - TypeVar, - Union, -) +from abc import abstractmethod +from typing import TYPE_CHECKING, Generic, TypeVar, overload if TYPE_CHECKING: - from ._common import ( - MaybeAwaitable, - ) + from collections.abc import Callable, Iterable, Sequence + + from ._common import MaybeAwaitable T = TypeVar("T") @@ -42,7 +29,7 @@ class BLERadio: def __init__( self, - broadcast_channel: Optional[int] = None, + broadcast_channel: int | None = None, observe_channels: Sequence[int] = [], ): """BLERadio(broadcast_channel=None, observe_channels=[]) @@ -62,13 +49,11 @@ class BLERadio: @overload def broadcast( - self, data: Iterable[Union[bool, int, float, str, bytes]] + self, data: Iterable[bool | int | float | str | bytes] ) -> MaybeAwaitable: ... @overload - def broadcast( - self, data: Union[bool, int, float, str, bytes] - ) -> MaybeAwaitable: ... + def broadcast(self, data: bool | int | float | str | bytes) -> MaybeAwaitable: ... def broadcast(self, data: object) -> MaybeAwaitable: """broadcast(data) @@ -105,12 +90,15 @@ class BLERadio: def observe( self, channel: int - ) -> Optional[ - Union[ - Tuple[Union[bool, int, float, str, bytes], ...], - Union[bool, int, float, str, bytes], - ] - ]: + ) -> ( + tuple[bool | int | float | str | bytes, ...] + | bool + | int + | float + | str + | bytes + | None + ): """observe(channel) -> bool | int | float | str | bytes | tuple | None Retrieves the last observed data for a given channel. @@ -174,8 +162,8 @@ class Mailbox(Generic[T]): self, name: str, connection: Connection, - encode: Optional[Callable[[T], bytes]] = None, - decode: Optional[Callable[[bytes], T]] = None, + encode: Callable[[T], bytes] | None = None, + decode: Callable[[bytes], T] | None = None, ): """Mailbox(name, connection, encode=None, decode=None) @@ -210,7 +198,7 @@ class Mailbox(Generic[T]): """ return "" - def send(self, value: T, brick: Optional[str] = None) -> None: + def send(self, value: T, brick: str | None = None) -> None: """send(value, brick=None) Sends a value to this mailbox on connected devices. @@ -393,7 +381,7 @@ class AppData: initialization. After that, all methods may be used while multi-tasking. """ - def __init__(self, modes: List[Tuple[int, int]]): + def __init__(self, modes: list[tuple[int, int]]): """AppData(modes) Arguments: @@ -410,7 +398,7 @@ class AppData: ValueError: If any mode number appears more than once. """ - def get_bytes(self, mode: int, index: Optional[int] = None) -> Union[bytes, int]: + def get_bytes(self, mode: int, index: int | None = None) -> bytes | int: """get_bytes(mode, index=None) -> bytes | int Gets data received from the host for the given mode. @@ -462,6 +450,10 @@ class AppData: """ +# Hide type-only names from jedi completions in the module namespace. if TYPE_CHECKING: + del Callable + del Iterable del MaybeAwaitable + del Sequence del T diff --git a/src/pybricks/nxtdevices.py b/src/pybricks/nxtdevices.py index a0f6112..50790ee 100644 --- a/src/pybricks/nxtdevices.py +++ b/src/pybricks/nxtdevices.py @@ -5,31 +5,21 @@ from __future__ import annotations -from typing import Optional, Tuple, List - -from . import _common - -from typing import ( - TYPE_CHECKING, -) - -if TYPE_CHECKING: - from ._common import ( - MaybeAwaitableInt, - MaybeAwaitableFloat, - MaybeAwaitableTuple, - ) - from .parameters import Number, Port - -from .parameters import Port, Color - +from typing import TYPE_CHECKING from . import _common from ._common import ColorLight, CommonColorSensor from .iodevices import AnalogSensor +if TYPE_CHECKING: + from collections.abc import Callable -from typing import Callable, Optional, Tuple + from ._common import ( + MaybeAwaitableFloat, + MaybeAwaitableInt, + MaybeAwaitableTuple, + ) + from .parameters import Color, Port class Motor(_common.Motor): @@ -92,7 +82,7 @@ class ColorSensor(CommonColorSensor): light = ColorLight() - def rgb(self) -> Tuple[int, int, int]: + def rgb(self) -> tuple[int, int, int]: """Measures the reflection of a surface using a red, green, and then a blue light. @@ -237,7 +227,7 @@ class EnergyMeter: """ def input(self) -> MaybeAwaitableTuple[int, int, int]: - """input() -> Tuple[int, int, int] + """input() -> tuple[int, int, int] Measures the electrical signals at the input (bottom) side of the energy meter. It measures the voltage applied to it and the @@ -252,7 +242,7 @@ class EnergyMeter: """ def output(self) -> MaybeAwaitableTuple[int, int, int]: - """output() -> Tuple[int, int, int] + """output() -> tuple[int, int, int] Measures the electrical signals at the output (top) side of the energy meter. It measures the voltage applied to the external @@ -270,7 +260,7 @@ class EnergyMeter: class VernierAdapter(AnalogSensor): """LEGO® MINDSTORMS® Education NXT/EV3 Adapter for Vernier Sensors.""" - def __init__(self, port: Port, conversion: Optional[Callable[[int], float]] = None): + def __init__(self, port: Port, conversion: Callable[[int], float] | None = None): """VernierAdapter(port, conversion=None) Arguments: @@ -315,3 +305,16 @@ class VernierAdapter(AnalogSensor): Returns: Converted sensor value. """ + + +# Hide type-only names from jedi completions in the module namespace. +if TYPE_CHECKING: + del AnalogSensor + del Callable + del Color + del ColorLight + del CommonColorSensor + del MaybeAwaitableFloat + del MaybeAwaitableInt + del MaybeAwaitableTuple + del Port diff --git a/src/pybricks/parameters.py b/src/pybricks/parameters.py index d781671..ca0d45d 100644 --- a/src/pybricks/parameters.py +++ b/src/pybricks/parameters.py @@ -5,14 +5,14 @@ from __future__ import annotations -from enum import Enum -from typing import Union, TYPE_CHECKING import os +from enum import Enum +from typing import TYPE_CHECKING from .tools import Matrix as _Matrix, vector as _vector if TYPE_CHECKING or os.environ.get("SPHINX_BUILD") == "True": - Number = Union[int, float] + Number = int | float """ Numbers can be represented as integers or floating point values: diff --git a/src/pybricks/pupdevices.py b/src/pybricks/pupdevices.py index 470f454..c7f7ab3 100644 --- a/src/pybricks/pupdevices.py +++ b/src/pybricks/pupdevices.py @@ -5,13 +5,15 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Collection, Optional, Union +from typing import TYPE_CHECKING from . import _common from .iodevices import LWP3Device -from .parameters import Button, Color, Direction +from .parameters import Button, Direction if TYPE_CHECKING: + from collections.abc import Collection + from ._common import ( MaybeAwaitable, MaybeAwaitableBool, @@ -19,7 +21,7 @@ if TYPE_CHECKING: MaybeAwaitableInt, MaybeAwaitableTuple, ) - from .parameters import Number, Port + from .parameters import Color, Number, Port class DCMotor(_common.DCMotor): @@ -44,7 +46,7 @@ class Motor(_common.Motor): self, port: Port, positive_direction: Direction = Direction.CLOCKWISE, - gears: Optional[Union[Collection[int], Collection[Collection[int]]]] = None, + gears: Collection[int] | Collection[Collection[int]] | None = None, reset_angle: bool = True, profile: Number = None, ): @@ -82,7 +84,7 @@ class Motor(_common.Motor): motor type will be selected automatically (about 11 degrees). """ - def reset_angle(self, angle: Optional[Number] = None) -> None: + def reset_angle(self, angle: Number | None = None) -> None: """reset_angle(angle=None) Sets the accumulated rotation angle of the motor to a desired value. @@ -114,11 +116,11 @@ class Remote(LWP3Device): Button.RIGHT_PLUS, ) ) - address: Union[str, None] + address: str | None def __init__( self, - name: Optional[str] = None, + name: str | None = None, timeout: int = 10000, connect: bool = True, ): @@ -148,7 +150,7 @@ class TechnicMoveHub(LWP3Device): def __init__( self, - name: Optional[str] = None, + name: str | None = None, timeout: int = 10000, connect: bool = True, ): @@ -191,7 +193,7 @@ class MarioHub(LWP3Device): def __init__( self, - name: Optional[str] = None, + name: str | None = None, timeout: int = 10000, connect: bool = True, ): @@ -263,7 +265,7 @@ class DuploTrain(LWP3Device): def __init__( self, - name: Optional[str] = None, + name: str | None = None, timeout: int = 10000, connect: bool = True, ): @@ -362,7 +364,7 @@ class TiltSensor: """ def tilt(self) -> MaybeAwaitableTuple[int, int]: - """tilt() -> Tuple[int, int]: deg + """tilt() -> tuple[int, int]: deg Measures the tilt relative to the horizontal plane. @@ -566,7 +568,7 @@ class ColorLightMatrix: """ ... - def on(self, color: Union[Color, Collection[Color]]) -> MaybeAwaitable: + def on(self, color: Color | Collection[Color]) -> MaybeAwaitable: """on(colors) Turns the lights on. @@ -653,9 +655,10 @@ class Light: Turns off the light.""" -# HACK: exclude from jedi +# Hide type-only names from jedi completions in the module namespace. if TYPE_CHECKING: del Button + del Collection del Color del Direction del LWP3Device diff --git a/src/pybricks/robotics.py b/src/pybricks/robotics.py index 18f1f77..d89916e 100644 --- a/src/pybricks/robotics.py +++ b/src/pybricks/robotics.py @@ -5,13 +5,13 @@ from __future__ import annotations -from typing import Tuple, Union, Optional, overload, TYPE_CHECKING +from typing import TYPE_CHECKING, overload from . import _common from .parameters import Stop if TYPE_CHECKING: - from ._common import Motor, MaybeAwaitable + from ._common import MaybeAwaitable, Motor from .parameters import Number @@ -120,8 +120,8 @@ class DriveBase: Accumulated angle since last reset. """ - def state(self) -> Tuple[int, int, int, int]: - """state() -> Tuple[int, int, int, int] + def state(self) -> tuple[int, int, int, int]: + """state() -> tuple[int, int, int, int] Gets the state of the robot. @@ -150,22 +150,22 @@ class DriveBase: @overload def settings( self, - straight_speed: Optional[Number] = None, - straight_acceleration: Optional[Union[Number, Tuple[Number, Number]]] = None, - turn_rate: Optional[Number] = None, - turn_acceleration: Optional[Union[Number, Tuple[Number, Number]]] = None, + straight_speed: Number | None = None, + straight_acceleration: Number | tuple[Number, Number] | None = None, + turn_rate: Number | None = None, + turn_acceleration: Number | tuple[Number, Number] | None = None, ) -> None: ... @overload def settings( self, - ) -> Tuple[int, Union[int, Tuple[int, int]], int, Union[int, Tuple[int, int]]]: ... + ) -> tuple[int, int | tuple[int, int], int, int | tuple[int, int]]: ... def settings(self, *args): """ settings(straight_speed, straight_acceleration, turn_rate, turn_acceleration) - settings() -> Tuple[int, int, int, int] - settings() -> Tuple[int, Tuple[int, int], int, Tuple[int, int]] + settings() -> tuple[int, int, int, int] + settings() -> tuple[int, tuple[int, int], int, tuple[int, int]] Configures the drive base speed and acceleration. @@ -183,13 +183,13 @@ class DriveBase: Arguments: straight_speed (Number, mm/s): Straight-line speed of the robot. - straight_acceleration (Number or Tuple[Number, Number], mm/s²): + straight_acceleration (Number or tuple[Number, Number], mm/s²): Straight-line acceleration and deceleration of the robot. Provide a single value to use the same acceleration and deceleration. Provide a tuple with two values to set them separately. turn_rate (Number, deg/s): Turn rate of the robot. - turn_acceleration (Number or Tuple[Number, Number], deg/s²): + turn_acceleration (Number or tuple[Number, Number], deg/s²): Angular acceleration and deceleration of the robot. Provide a single value to use the same acceleration and deceleration. Provide a tuple with two values to set them @@ -332,7 +332,7 @@ class Car: def __init__( self, steer_motor: Motor, - drive_motors: Motor | Tuple[Motor, ...], + drive_motors: Motor | tuple[Motor, ...], torque_limit: Number = 100, ): """Car(steer_motor, drive_motors, torque_limit=100) @@ -390,9 +390,9 @@ class Car: """ -# HACK: hide from jedi +# Hide type-only names from jedi completions in the module namespace. if TYPE_CHECKING: + del MaybeAwaitable del Motor del Number - del MaybeAwaitable del Stop diff --git a/src/pybricks/tools.py b/src/pybricks/tools.py index ff02af3..acdd41e 100644 --- a/src/pybricks/tools.py +++ b/src/pybricks/tools.py @@ -5,9 +5,12 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Optional, Sequence, Tuple, overload, Coroutine +from typing import TYPE_CHECKING, overload if TYPE_CHECKING: + from collections.abc import Coroutine, Sequence + from typing import Any + from ._common import MaybeAwaitable, MaybeAwaitableTuple from .parameters import Number @@ -143,7 +146,7 @@ class Matrix: original.""" @property - def shape(self) -> Tuple[int, int]: + def shape(self) -> tuple[int, int]: """Returns a tuple (``m``, ``n``), where ``m`` is the number of rows and ``n`` is the number of columns. """ @@ -211,7 +214,7 @@ def cross(a: Matrix, b: Matrix) -> Matrix: """ -def read_input_byte(last: bool = False, chr: bool = False) -> Optional[int | str]: +def read_input_byte(last: bool = False, chr: bool = False) -> int | str | None: """ read_input_byte() -> int | str | None @@ -254,7 +257,7 @@ def hub_menu(*symbols: int | str) -> int | str: def multitask(*coroutines: Coroutine, race=False) -> MaybeAwaitableTuple: """ - multitask(coroutine1, coroutine2, ...) -> Tuple + multitask(coroutine1, coroutine2, ...) -> tuple Runs multiple coroutines concurrently. This creates a new coroutine that can be used like any other, including in another ``multitask`` statement. @@ -272,7 +275,7 @@ def multitask(*coroutines: Coroutine, race=False) -> MaybeAwaitableTuple: """ -def run_task(coroutine: Coroutine) -> Optional[bool]: +def run_task(coroutine: Coroutine) -> bool | None: """ run_task(coroutine) -> bool | None @@ -290,8 +293,11 @@ def run_task(coroutine: Coroutine) -> Optional[bool]: """ -# HACK: hide from jedi +# Hide type-only names from jedi completions in the module namespace. if TYPE_CHECKING: - del Number + del Any + del Coroutine del MaybeAwaitable del MaybeAwaitableTuple + del Number + del Sequence