Skip to content
Open

Typed #160

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
recursive-include dali py.typed
8 changes: 5 additions & 3 deletions dali/address.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
7.2.2. Decoding of event messages is currently not implemented.
"""

from __future__ import annotations

from dali.exceptions import IncompatibleFrame


Expand Down Expand Up @@ -261,7 +263,7 @@ class GearShort(GearAddress):
address.
"""

def __init__(self, address):
def __init__(self, address: int) -> None:
if not isinstance(address, int):
raise ValueError("address must be an integer")
if address < 0 or address > 63:
Expand Down Expand Up @@ -305,7 +307,7 @@ class DeviceShort(DeviceAddress):
address.
"""

def __init__(self, address: int):
def __init__(self, address: int) -> None:
if not isinstance(address, int):
raise ValueError("address must be an integer")
if address < 0 or address > 63:
Expand Down Expand Up @@ -379,7 +381,7 @@ def __str__(self):
class _AddressedInstance(Instance):
_flags = None

def __init__(self, value):
def __init__(self, value: int) -> None:
if not isinstance(value, int):
raise ValueError("value must be an integer")
if value < 0 or value > 31:
Expand Down
9 changes: 6 additions & 3 deletions dali/command.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"""Declaration of base types for dali commands and their responses."""

from __future__ import annotations

from enum import IntEnum
from typing import Any
from dali import address
from dali import frame
from dali.exceptions import MissingResponse
Expand Down Expand Up @@ -46,17 +49,17 @@ class Response:
_expected = False
_error_acceptable = False

def __init__(self, val):
def __init__(self, val: frame.BackwardFrame | None) -> None:
if val is not None and not isinstance(val, frame.BackwardFrame):
raise TypeError("Response must be passed None or a BackwardFrame")
self._value = val

@property
def raw_value(self):
def raw_value(self) -> frame.BackwardFrame | None:
return self._value

@property
def value(self):
def value(self) -> Any:
if self._value is None and self._expected:
raise MissingResponse()
if self._value and self._value.error and not self._error_acceptable:
Expand Down
8 changes: 5 additions & 3 deletions dali/device/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class _StandardDeviceCommand(_DeviceCommand):
"""
_opcode = None

def __init__(self, device):
def __init__(self, device: address.Address | int) -> None:
if self._opcode is None:
raise NotImplementedError

Expand Down Expand Up @@ -514,7 +514,9 @@ class _StandardInstanceCommand(_DeviceCommand):

_opcode = None

def __init__(self, device, instance):
def __init__(
self, device: address.Address | int, instance: address.Instance
) -> None:
if self._opcode is None:
raise NotImplementedError

Expand Down Expand Up @@ -784,7 +786,7 @@ def __str__(self):


class _SpecialDeviceCommandOneParam(_SpecialDeviceCommand):
def __init__(self, param):
def __init__(self, param: int) -> None:
if not isinstance(param, int):
raise ValueError("parameter must be an integer")
if param < 0 or param > 255:
Expand Down
10 changes: 6 additions & 4 deletions dali/device/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,27 +69,29 @@ class DeviceInstanceTypeMapper:
through the `from_frame()` method.
"""

def __init__(self, initial=None):
def __init__(
self, initial: Optional[dict[tuple[int, int], int]] = None
) -> None:
"""
Creates a new DeviceInstanceTypeMapper object, optionally with
preloaded mappings as defined by `initial`.

:param initial: A dict of data to preload into the mapping
"""
self._mapping: dict[(int, int), int] = {}
self._mapping: dict[tuple[int, int], int] = {}
if initial:
self._mapping = initial

@property
def mapping(self) -> dict[(int, int), int]:
def mapping(self) -> dict[tuple[int, int], int]:
return self._mapping

def autodiscover(
self,
addresses: int | tuple[int, int] | Iterable[int] = (0, 63),
quiescent_settle: float = 0.2,
status_attempts: int = 3,
) -> Generator[Command, Response, None]:
) -> Generator[Command, Optional[Response], None]:
"""
A generator sequence to scan a DALI bus for control device instances,
and query their types. This information is stored within this
Expand Down
2 changes: 1 addition & 1 deletion dali/device/occupancy.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def from_event_data(cls, event_data: int):
return OccupancyEvent

@property
def event_data(self):
def event_data(self) -> EventData:
return self._extra_data

def _set_event_data(
Expand Down
Empty file added dali/device/py.typed
Empty file.
Empty file added dali/driver/py.typed
Empty file.
6 changes: 4 additions & 2 deletions dali/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

###############################################################################
# general
###############################################################################
Expand Down Expand Up @@ -50,7 +52,7 @@ class DALISequenceError(DALIError):
class ProgramShortAddressFailure(DALIError):
"""A device did not accept programming of its short address."""

def __init__(self, address):
def __init__(self, address: int) -> None:
self.address = address


Expand Down Expand Up @@ -125,7 +127,7 @@ class TransmissionError(DriverError):
``error_code`` is the interface-specific reason for the rejection.
"""

def __init__(self, error_code):
def __init__(self, error_code: int) -> None:
self.error_code = error_code
super().__init__(
f"Frame transmission rejected, error code {error_code}"
Expand Down
8 changes: 5 additions & 3 deletions dali/gear/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
or DTR0, the abbreviation has been kept in capitals.
"""

from __future__ import annotations

from dali import command
from dali import address
from dali import frame
Expand Down Expand Up @@ -61,7 +63,7 @@ class _StandardCommand(_GearCommand):
_cmdval = None
_hasparam = False

def __init__(self, destination, *args):
def __init__(self, destination: address.Address | int, *args: int) -> None:
if self._cmdval is None:
raise NotImplementedError

Expand Down Expand Up @@ -155,7 +157,7 @@ class DAPC(_GearCommand):
be respected.
"""

def __init__(self, destination, power):
def __init__(self, destination: address.Address | int, power: int | str) -> None:
if power == "OFF":
power = 0

Expand Down Expand Up @@ -1003,7 +1005,7 @@ class _SpecialCommand(_GearCommand):
_hasparam = False
_cmdval = None

def __init__(self, *args):
def __init__(self, *args: int) -> None:
if self._hasparam:
if len(args) != 1:
raise TypeError(
Expand Down
Empty file added dali/gear/py.typed
Empty file.
2 changes: 1 addition & 1 deletion dali/gear/sequences.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@


def SetDT8ColourValueTc(
address: GearAddress,
address: GearAddress | int,
tc_mired: int,
) -> Generator[command.Command, Optional[command.Response], None]:
"""
Expand Down
10 changes: 8 additions & 2 deletions dali/memory/location.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from __future__ import annotations

from collections import namedtuple
from collections.abc import Generator
from enum import Enum, auto
from typing import Any, Optional

from dali import device, gear
from dali import command, device, gear
from dali.address import Address, DeviceAddress, DeviceShort, GearAddress, GearShort
from dali.exceptions import (
LatchingNotSupported,
Expand Down Expand Up @@ -165,7 +167,11 @@ def last_address(self, addr):
la = yield from self.LastAddress.read(addr)
return la

def read_all(self, addr: Address, use_latch: bool = True):
def read_all(
self, addr: Address, use_latch: bool = True
) -> Generator[
command.Command, Optional[command.Response], dict[type[MemoryValue], Any]
]:
"""Read all available memory values from this memory bank.

If the memory bank has a latch, the latch is set during the
Expand Down
Empty file added dali/memory/py.typed
Empty file.
Empty file added dali/py.typed
Empty file.
28 changes: 22 additions & 6 deletions dali/sequences.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@
# Sequences may raise exceptions, which the driver should pass to the
# caller.

from __future__ import annotations

from collections.abc import Iterable
from typing import Generator, Optional

from dali import command
from dali.exceptions import DALISequenceError, ProgramShortAddressFailure

from dali.gear.general import *
from dali.address import Broadcast, Short
from dali.address import Broadcast, GearAddress, Short


class sleep:
Expand All @@ -30,7 +36,7 @@ class sleep:
Yielded during a sequence to request that the caller wait for at
least the specified length of time in seconds
"""
def __init__(self, delay):
def __init__(self, delay: float) -> None:
self.delay = delay


Expand All @@ -42,7 +48,12 @@ class progress:
both. The amount of progress is just an indication and there is
no guarantee that it will not decrease as well as increase.
"""
def __init__(self, message=None, completed=None, size=None):
def __init__(
self,
message: str | None = None,
completed: int | None = None,
size: int | None = None,
) -> None:
self.message = message
self.completed = completed
self.size = size
Expand All @@ -54,7 +65,9 @@ def __str__(self):
return f"Progress: {self.completed}/{self.size}"


def QueryDeviceTypes(addr):
def QueryDeviceTypes(
addr: GearAddress,
) -> Generator[command.Command, Optional[command.Response], list[int]]:
"""Obtain a list of part 2xx device types supported by control gear
"""
r = yield QueryDeviceType(addr)
Expand Down Expand Up @@ -147,8 +160,11 @@ def _find_next(low, high):
return (yield from _find_next(midpoint + 1, high))


def Commissioning(available_addresses=None, readdress=False,
dry_run=False):
def Commissioning(
available_addresses: Iterable[int] | None = None,
readdress: bool = False,
dry_run: bool = False,
) -> Generator[command.Command, Optional[command.Response], None]:
"""Assign short addresses to control gear

If available_addresses is passed, only the specified addresses
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ classifiers =

[options]
python_requires = >=3.10
include_package_data = True
packages =
dali
dali.device
Expand Down
Loading