Skip to content

Commit

Permalink
Merge pull request #425 from SpiNNakerManchester/t_man
Browse files Browse the repository at this point in the history
Full Typing of Spinnman classes
  • Loading branch information
Christian-B authored Nov 19, 2024
2 parents bc9e0eb + ddeef41 commit 50c016d
Show file tree
Hide file tree
Showing 106 changed files with 675 additions and 481 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/python_actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ jobs:
coverage-package: spinnman
flake8-packages: spinnman unittests spinnman_integration_tests
pylint-packages: spinnman
mypy-packages: spinnman unittests spinnman_integration_tests
mypy-packages: unittests spinnman_integration_tests
mypy-full_packages: spinnman
secrets: inherit
2 changes: 1 addition & 1 deletion mypy.bash
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@
utils="../SpiNNUtils/spinn_utilities"
machine="../SpiNNMachine/spinn_machine"

mypy --python-version 3.8 $utils $machine spinnman
mypy --python-version 3.8 $utils $machine spinnman unittests
25 changes: 25 additions & 0 deletions mypyd.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash

# Copyright (c) 2024 The University of Manchester
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# This bash assumes that other repositories are installed in paralled

# requires the latest mypy
# pip install --upgrade mypy

utils="../SpiNNUtils/spinn_utilities"
machine="../SpiNNMachine/spinn_machine"

mypy --python-version 3.8 --disallow-untyped-defs $utils $machine spinnman
8 changes: 4 additions & 4 deletions spinnman/board_test_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ class BoardTestConfiguration(object):
Configuration to use for a test board
"""

def __init__(self):
self.remotehost = None
self.auto_detect_bmp = None
def __init__(self) -> None:
self.remotehost: str = "UNSET"
self.auto_detect_bmp: bool = False

def set_up_remote_board(self, version: Optional[int] = None):
def set_up_remote_board(self, version: Optional[int] = None) -> None:
"""
Gets a remote board to test, returning the first that it finds.
Expand Down
4 changes: 2 additions & 2 deletions spinnman/config_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
BASE_CONFIG_FILE = "spinnman.cfg"


def unittest_setup():
def unittest_setup() -> None:
"""
Resets the configurations so only the local default configuration is
included.
Expand All @@ -34,7 +34,7 @@ def unittest_setup():
SpiNNManDataWriter.mock()


def add_spinnman_cfg():
def add_spinnman_cfg() -> None:
"""
Add the local configuration and all dependent configuration files.
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class AbstractSCPConnection(Connection, metaclass=AbstractBase):
__slots__ = ()

@abstractmethod
def is_ready_to_receive(self, timeout: float = 0):
def is_ready_to_receive(self, timeout: float = 0) -> bool:
"""
Determines if there is an SCP packet to be read without blocking.
Expand Down
6 changes: 3 additions & 3 deletions spinnman/connections/connection_listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def __init__(self, connection: Listenable[T],
self.__done = False
self.__callbacks: List[Callable[[T], None]] = []

def __run_step(self, handler: Callable[[], T]):
def __run_step(self, handler: Callable[[], T]) -> None:
"""
:param ~collections.abc.Callable handler:
"""
Expand All @@ -69,7 +69,7 @@ def __run_step(self, handler: Callable[[], T]):
callback, message)
future.add_done_callback(self.__done_callback)

def __done_callback(self, future: Future[None]):
def __done_callback(self, future: Future[None]) -> None:
"""
:param ~concurrent.futures.Future future:
"""
Expand All @@ -94,7 +94,7 @@ def run(self) -> None:
logger.warning("problem when dispatching message",
exc_info=True)

def add_callback(self, callback: Callable[[T], None]):
def add_callback(self, callback: Callable[[T], None]) -> None:
"""
Add a callback to be called when a message is received.
Expand Down
28 changes: 16 additions & 12 deletions spinnman/connections/scp_request_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
from threading import RLock
import time
from types import TracebackType
from typing import Callable, Dict, Generic, List, Optional, TypeVar, cast
from typing import (Callable, Dict, Generic, List, Optional, Set, TypeVar,
cast)
from typing_extensions import TypeAlias
from spinnman.messages.scp.enums import SCPResult
from spinnman.exceptions import SpinnmanTimeoutException, SpinnmanIOException
Expand Down Expand Up @@ -77,10 +78,11 @@ class SCPRequestPipeLine(Generic[R]):
"_retries",
"_send_time")

def __init__(self, connection: SCAMPConnection, n_channels=1,
intermediate_channel_waits=0,
n_retries=N_RETRIES, packet_timeout=SCP_TIMEOUT,
non_fail_retry_codes=None):
def __init__(self, connection: SCAMPConnection, n_channels: int = 1,
intermediate_channel_waits: int = 0,
n_retries: int = N_RETRIES,
packet_timeout: float = SCP_TIMEOUT,
non_fail_retry_codes: Optional[Set[SCPResult]] = None):
"""
:param SCAMPConnection connection:
The connection over which the communication is to take place
Expand Down Expand Up @@ -134,10 +136,11 @@ def __init__(self, connection: SCAMPConnection, n_channels=1,
# The number of packets that have been resent
self._n_resent = 0
self._n_retry_code_resent = 0
self._non_fail_retry_codes = non_fail_retry_codes
if self._non_fail_retry_codes is None:
self._non_fail_retry_codes: Set[SCPResult]
if non_fail_retry_codes is None:
self._non_fail_retry_codes = set()

else:
self._non_fail_retry_codes = non_fail_retry_codes
# self._token_bucket = TokenBucket(43750, 4375000)
# self._token_bucket = TokenBucket(3408, 700000)

Expand All @@ -159,7 +162,7 @@ def __get_next_sequence_number() -> int:

def send_request(
self, request: AbstractSCPRequest[R], callback: Optional[CB],
error_callback: ECB):
error_callback: ECB) -> None:
"""
Add an SCP request to the set to be sent.
Expand Down Expand Up @@ -260,7 +263,7 @@ def _remove_record(self, seq: int) -> None:
del self._error_callbacks[seq]
del self._retry_reason[seq]

def _single_retrieve(self, timeout: float):
def _single_retrieve(self, timeout: float) -> None:
# Receive the next response
result, seq, raw_data, offset = \
self._connection.receive_scp_response(timeout)
Expand Down Expand Up @@ -320,7 +323,8 @@ def _handle_receive_timeout(self) -> None:
for seq in to_remove:
self._remove_record(seq)

def _resend(self, seq: int, request_sent, reason: str):
def _resend(self, seq: int, request_sent: AbstractSCPRequest,
reason: str) -> None:
if self._retries[seq] <= 0:
# Report timeouts as timeout exception

Expand All @@ -346,7 +350,7 @@ def _resend(self, seq: int, request_sent, reason: str):
self._connection.send(self._request_data[seq])
self._n_resent += 1

def _do_retrieve(self, n_packets: int, timeout: float):
def _do_retrieve(self, n_packets: int, timeout: float) -> None:
"""
Receives responses until there are only n_packets responses left.
Expand Down
7 changes: 3 additions & 4 deletions spinnman/connections/token_bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class TokenBucket(object):
"""
__slots__ = ('_capacity', '_tokens', '_fill_rate', '_timestamp')

def __init__(self, tokens, fill_rate):
def __init__(self, tokens: int, fill_rate: float):
"""
:param int tokens: the total tokens in the bucket
:param float fill_rate:
Expand All @@ -38,7 +38,7 @@ def __init__(self, tokens, fill_rate):
self._fill_rate = float(fill_rate)
self._timestamp = time.time()

def consume(self, tokens, block=True):
def consume(self, tokens: int, block: bool = True) -> bool:
"""
Consume tokens from the bucket. Returns True if there were
sufficient tokens.
Expand All @@ -65,11 +65,10 @@ def consume(self, tokens, block=True):
return False

@property
def tokens(self):
def tokens(self) -> float:
"""
The number of tokens currently in the bucket.
:rtype: int
"""
if self._tokens < self._capacity:
now = time.time()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def receive_scp_response(self, timeout: Optional[float] = 1.0) -> Tuple[
result, sequence = _TWO_SHORTS.unpack_from(data, 10)
return SCPResult(result), sequence, data, 2

def __repr__(self):
def __repr__(self) -> str:
return (
f"BMPConnection("
f"boards={self._boards}, local_host={self.local_ip_address}, "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def __init__(self, remote_host: Optional[str] = None):
super().__init__(remote_host=remote_host,
remote_port=UDP_BOOT_CONNECTION_DEFAULT_PORT)

def send_boot_message(self, boot_message: SpinnakerBootMessage):
def send_boot_message(self, boot_message: SpinnakerBootMessage) -> None:
"""
Sends a SpiNNaker boot message using this connection.
Expand Down Expand Up @@ -80,7 +80,7 @@ def receive_boot_message(
data = self.receive(timeout)
return SpinnakerBootMessage.from_bytestring(data, 0)

def __repr__(self):
def __repr__(self) -> str:
return self._REPR_TEMPLATE.format(
self.local_ip_address, self.local_port,
self.remote_ip_address, self.remote_port)
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def receive_eieio_message(
return read_eieio_command_message(data, 0)
return read_eieio_data_message(data, 0)

def send_eieio_message(self, eieio_message: AbstractEIEIOMessage):
def send_eieio_message(self, eieio_message: AbstractEIEIOMessage) -> None:
"""
Sends an EIEIO message down this connection.
Expand All @@ -74,7 +74,7 @@ def send_eieio_message(self, eieio_message: AbstractEIEIOMessage):

def send_eieio_message_to(
self, eieio_message: AbstractEIEIOMessage,
ip_address: str, port: int):
ip_address: str, port: int) -> None:
"""
:param AbstractEIEIOMessage eieio_message:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ class IPAddressesConnection(UDPConnection):
"""
__slots__ = ()

def __init__(self, local_host=None,
local_port=UDP_BOOT_CONNECTION_DEFAULT_PORT):
def __init__(self, local_host: Optional[str] = None,
local_port: int = UDP_BOOT_CONNECTION_DEFAULT_PORT):
super().__init__(local_host=local_host, local_port=local_port)

def receive_ip_address(self, timeout: Optional[float] = None
Expand All @@ -44,6 +44,6 @@ def receive_ip_address(self, timeout: Optional[float] = None
return ip_address
return None

def __repr__(self):
def __repr__(self) -> str:
return f"IPAddressesConnection(local_host={self.local_ip_address}," \
f" local_port={self.local_port})"
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def chip_x(self) -> int:
def chip_y(self) -> int:
return self._chip_y

def update_chip_coordinates(self, x: int, y: int):
def update_chip_coordinates(self, x: int, y: int) -> None:
"""
Sets the coordinates without checking they are valid.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def receive_sdp_message(
data = self.receive(timeout)
return SDPMessage.from_bytestring(data, 2)

def send_sdp_message(self, sdp_message: SDPMessage):
def send_sdp_message(self, sdp_message: SDPMessage) -> None:
"""
Sends an SDP message down this connection.
Expand Down
6 changes: 3 additions & 3 deletions spinnman/connections/udp_packet_connections/udp_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def receive_with_address(self, timeout: Optional[float] = None) -> Tuple[
raise SpinnmanEOFException()
return receive_message_and_address(self._socket, timeout, _MSG_MAX)

def send(self, data: bytes):
def send(self, data: bytes) -> None:
"""
Send data down this connection.
Expand All @@ -237,7 +237,7 @@ def send(self, data: bytes):
if self.__is_closed:
raise SpinnmanEOFException()

def send_to(self, data: bytes, address: Tuple[str, int]):
def send_to(self, data: bytes, address: Tuple[str, int]) -> None:
"""
Send data down this connection.
Expand All @@ -261,7 +261,7 @@ def close(self) -> None:
self._socket.shutdown(socket.SHUT_WR)
self._socket.close()

def is_ready_to_receive(self, timeout: float = 0):
def is_ready_to_receive(self, timeout: float = 0) -> bool:
if self.__is_closed:
return True
return len(select.select([self._socket], [], [], timeout)[0]) == 1
Expand Down
5 changes: 4 additions & 1 deletion spinnman/connections/udp_packet_connections/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from spinnman.messages.sdp import SDPHeader


# Kept for spalloc_server to use
def update_sdp_header_for_udp_send(sdp_header, source_x, source_y):
def update_sdp_header_for_udp_send(
sdp_header: SDPHeader, source_x: int, source_y: int) -> None:
"""
Apply defaults to the SDP header for sending over UDP.
Expand Down
2 changes: 1 addition & 1 deletion spinnman/data/spinnman_data_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ def get_new_id(cls) -> int:
return cls.__data._app_id_tracker.get_new_id()

@classmethod
def free_id(cls, app_id: int):
def free_id(cls, app_id: int) -> None:
"""
Frees up an app_id.
Expand Down
2 changes: 1 addition & 1 deletion spinnman/data/spinnman_data_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def _soft_reset(self) -> None:
MachineDataWriter._soft_reset(self)
self._local_soft_reset()

def set_transceiver(self, transceiver: Transceiver):
def set_transceiver(self, transceiver: Transceiver) -> None:
"""
Sets the transceiver object.
Expand Down
Loading

0 comments on commit 50c016d

Please sign in to comment.