Skip to content

Commit

Permalink
Merge pull request #1521 from SpiNNakerManchester/t_spy
Browse files Browse the repository at this point in the history
Typing for Spynnaker
  • Loading branch information
rowleya authored Feb 11, 2025
2 parents 066a3af + dd3cae8 commit 6168092
Show file tree
Hide file tree
Showing 228 changed files with 1,795 additions and 1,281 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/python_actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ jobs:
coverage-package: spynnaker
flake8-packages: spynnaker unittests spynnaker_integration_tests proxy_integration_tests
pylint-packages: spynnaker
mypy-packages: spynnaker unittests spynnaker_integration_tests proxy_integration_tests
mypy-packages: unittests spynnaker_integration_tests proxy_integration_tests
mypy-full_packages: spynnaker
cfg_file: spynnaker
29 changes: 29 additions & 0 deletions mypyd.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/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"
man="../SpiNNMan/spinnman"
pacman="../PACMAN/pacman"
spalloc="../spalloc/spalloc_client"
fec="../SpiNNFrontEndCommon/spinn_front_end_common"

mypy --python-version 3.8 --disallow-untyped-defs $utils $machine $man $pacman $spalloc $fec spynnaker
3 changes: 3 additions & 0 deletions spynnaker/gsyn_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
import os
import spynnaker.pyNN.utilities.utility_calls as utility_calls

# TODO No use case found for this code
# mypy: disable-error-code="no-untyped-def"


def check_gsyn(gsyn1, gsyn2):
"""
Expand Down
20 changes: 11 additions & 9 deletions spynnaker/pyNN/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,8 @@ class __PynnOperations(TypedDict, total=False):
def distance(src_cell: IDMixin, tgt_cell: IDMixin,
mask: Optional[NDArray] = None,
scale_factor: float = 1.0, offset: float = 0.0,
periodic_boundaries=None) -> float:
periodic_boundaries: Optional[Tuple[
Optional[Tuple[int, int]]]] = None) -> float:
"""
Return the Euclidean distance between two cells.
Expand Down Expand Up @@ -254,7 +255,8 @@ def setup(timestep: Optional[Union[float, Literal["auto"]]] = None,
database_socket_addresses: Optional[Iterable[SocketAddress]] = None,
time_scale_factor: Optional[int] = None,
n_chips_required: Optional[int] = None,
n_boards_required: Optional[int] = None, **extra_params) -> int:
n_boards_required: Optional[int] = None,
**extra_params: Any) -> int:
"""
The main method needed to be called to make the PyNN 0.8 setup.
Needs to be called before any other function
Expand Down Expand Up @@ -391,7 +393,7 @@ def Projection(
partition_id=partition_id)


def _create_overloaded_functions(spinnaker_simulator: SpiNNaker):
def _create_overloaded_functions(spinnaker_simulator: SpiNNaker) -> None:
"""
Creates functions that the main PyNN interface supports
(given from PyNN)
Expand All @@ -417,7 +419,7 @@ def _create_overloaded_functions(spinnaker_simulator: SpiNNaker):
__pynn["record"] = pynn_common.build_record(spinnaker_simulator)


def end(_=True) -> None:
def end(_: Any = True) -> None:
"""
Cleans up the SpiNNaker machine and software
Expand Down Expand Up @@ -456,7 +458,7 @@ def list_standard_models() -> List[str]:

def set_number_of_neurons_per_core(
neuron_type: Type,
max_permitted: Optional[Union[int, Tuple[int, ...]]]):
max_permitted: Optional[Union[int, Tuple[int, ...]]]) -> None:
"""
Sets a ceiling on the number of neurons of a given model that can be
placed on a single core.
Expand Down Expand Up @@ -495,7 +497,7 @@ def set_number_of_neurons_per_core(

def connect(pre: Population, post: Population, weight: float = 0.0,
delay: Optional[float] = None, receptor_type: Optional[str] = None,
p: int = 1, rng: Optional[NumpyRNG] = None):
p: int = 1, rng: Optional[NumpyRNG] = None) -> None:
"""
Builds a projection.
Expand Down Expand Up @@ -586,7 +588,7 @@ def get_time_step() -> float:
return float(__pynn["get_time_step"]())


def initialize(cells: PopulationBase, **initial_values):
def initialize(cells: PopulationBase, **initial_values: Any) -> None:
"""
Sets cells to be initialised to the given values.
Expand Down Expand Up @@ -653,7 +655,7 @@ def record(variables: Union[str, Sequence[str]], source: PopulationBase,
annotations)


def reset(annotations: Optional[Dict[str, Any]] = None):
def reset(annotations: Optional[Dict[str, Any]] = None) -> None:
"""
Resets the simulation to t = 0.
Expand All @@ -666,7 +668,7 @@ def reset(annotations: Optional[Dict[str, Any]] = None):
__pynn["reset"](annotations)


def run(simtime: float, callbacks=None) -> float:
def run(simtime: float, callbacks: Optional[Callable] = None) -> float:
"""
The run() function advances the simulation for a given number of
milliseconds.
Expand Down
3 changes: 2 additions & 1 deletion spynnaker/pyNN/connections/ethernet_command_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ def __init__(
self.__translator = translator

def add_command_container(
self, command_container: AbstractSendMeMulticastCommandsVertex):
self,
command_container: AbstractSendMeMulticastCommandsVertex) -> None:
"""
Add a command container.
Expand Down
5 changes: 3 additions & 2 deletions spynnaker/pyNN/connections/ethernet_control_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def __init__(
label, self._translate, translate_key=False)

def add_translator(
self, label: str, translator: AbstractEthernetTranslator):
self, label: str, translator: AbstractEthernetTranslator) -> None:
"""
Add another translator that routes via the LPG.
Expand All @@ -60,7 +60,8 @@ def add_translator(
self.add_receive_no_time_callback(
label, self._translate, translate_key=False)

def _translate(self, label: str, key: int, payload: Optional[int] = None):
def _translate(self, label: str, key: int,
payload: Optional[int] = None) -> None:
translator = self.__translators[label]
if payload is None:
translator.translate_control_packet(MultiCastCommand(key))
Expand Down
23 changes: 12 additions & 11 deletions spynnaker/pyNN/connections/spif_live_spikes_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ def __init__(self, receive_labels: Optional[Iterable[str]],
self.__receiver_connection: Optional[UDPConnection] = None
self.__error_keys: Set[int] = set()

def add_receive_label(self, label: str):
def add_receive_label(self, label: str) -> None:
"""
:param str label:
"""
Expand All @@ -145,7 +145,7 @@ def add_receive_label(self, label: str):
self.__pause_stop_callbacks[label] = list()
self.__init_callbacks[label] = list()

def add_init_callback(self, label: str, init_callback: _InitCB):
def add_init_callback(self, label: str, init_callback: _InitCB) -> None:
"""
Add a callback to be called to initialise a vertex.
Expand All @@ -163,7 +163,7 @@ def add_init_callback(self, label: str, init_callback: _InitCB):

def add_receive_callback(
self, label: str, live_event_callback: _EventCB,
translate_key: bool = True):
translate_key: bool = True) -> None:
"""
Add a callback for the reception of live events from a vertex.
Expand All @@ -185,7 +185,7 @@ def add_receive_callback(
(live_event_callback, translate_key))

def add_start_resume_callback(
self, label: str, start_resume_callback: _StartStopCB):
self, label: str, start_resume_callback: _StartStopCB) -> None:
"""
Add a callback for the start and resume state of the simulation.
Expand All @@ -201,7 +201,7 @@ def add_start_resume_callback(
self.__start_resume_callbacks[label].append(start_resume_callback)

def add_pause_stop_callback(
self, label: str, pause_stop_callback: _StartStopCB):
self, label: str, pause_stop_callback: _StartStopCB) -> None:
"""
Add a callback for the pause and stop state of the simulation.
Expand All @@ -216,7 +216,7 @@ def add_pause_stop_callback(
"""
self.__pause_stop_callbacks[label].append(pause_stop_callback)

def __read_database_callback(self, db_reader: DatabaseReader):
def __read_database_callback(self, db_reader: DatabaseReader) -> None:
"""
:param DatabaseReader db_reader:
"""
Expand All @@ -238,7 +238,7 @@ def __read_database_callback(self, db_reader: DatabaseReader):
label, vertex_size, run_time_ms, machine_timestep_ms)

def __init_receivers(
self, db: DatabaseReader, vertex_sizes: Dict[str, int]):
self, db: DatabaseReader, vertex_sizes: Dict[str, int]) -> None:
# Set up a single connection for receive
if self.__receiver_connection is None:
self.__receiver_connection = UDPConnection(
Expand Down Expand Up @@ -267,7 +267,8 @@ def __handle_possible_rerun_state(self) -> None:
self.__receiver_connection.close()
self.__receiver_connection = None

def __launch_thread(self, kind: str, label: str, callback: _StartStopCB):
def __launch_thread(
self, kind: str, label: str, callback: _StartStopCB) -> None:
thread = Thread(target=callback, args=(label, self), name=(
f"{kind} callback thread for live_event_connection "
f"{self._local_port}:{self._local_ip_address}"))
Expand All @@ -294,15 +295,15 @@ def __do_stop_pause(self) -> None:
for callback in callbacks:
self.__launch_thread("pause_stop", label, callback)

def __do_receive_packet(self, packet: bytes):
def __do_receive_packet(self, packet: bytes) -> None:
# pylint: disable=broad-except
logger.debug("Received packet")
try:
self.__handle_packet(packet)
except Exception:
logger.warning("problem handling received packet", exc_info=True)

def __handle_packet(self, packet: bytes):
def __handle_packet(self, packet: bytes) -> None:
key_labels: Dict[int, List[int]] = dict()
atoms_labels: Dict[int, List[int]] = dict()
n_events = len(packet) // BYTES_PER_WORD
Expand All @@ -326,7 +327,7 @@ def __handle_packet(self, packet: bytes):
else:
c_back(label, key_labels[label_id])

def __handle_unknown_key(self, key: int):
def __handle_unknown_key(self, key: int) -> None:
if key not in self.__error_keys:
self.__error_keys.add(key)
logger.warning("Received unexpected key {}", key)
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ def __init__(self, receive_labels: Optional[Iterable[str]] = None,
live_packet_gather_label, receive_labels, send_labels,
local_host, local_port)

def send_spike(
self, label: str, neuron_id: int, send_full_keys: bool = False):
def send_spike(self, label: str, neuron_id: int,
send_full_keys: bool = False) -> None:
"""
Send a spike from a single neuron.
Expand All @@ -68,7 +68,7 @@ def send_spike(

def send_spikes(
self, label: str, neuron_ids: List[int],
send_full_keys: bool = False):
send_full_keys: bool = False) -> None:
"""
Send a number of spikes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def __init__(
live_packet_gather_label=None, send_labels=control_labels,
local_host=local_host, local_port=local_port)

def add_poisson_label(self, label: str):
def add_poisson_label(self, label: str) -> None:
"""
:param str label: The label of the Poisson source population.
"""
Expand All @@ -94,13 +94,13 @@ def __label(self, control_label: str) -> str:

def __callback_wrapper(
self, callback: _Callback, label: str,
connection: LiveEventConnection):
connection: LiveEventConnection) -> None:
callback(self.__label(label), connection)

def __init_callback_wrapper(
self, callback: _InitCallback,
label: str, vertex_size: int, run_time_ms: float,
machine_timestep_ms: float):
machine_timestep_ms: float) -> None:
callback(self.__label(label), vertex_size, run_time_ms,
machine_timestep_ms)

Expand Down Expand Up @@ -146,7 +146,7 @@ def add_pause_stop_callback(
self.__control_label(label), functools.partial(
self.__callback_wrapper, pause_stop_callback))

def set_rate(self, label: str, neuron_id: int, rate: float):
def set_rate(self, label: str, neuron_id: int, rate: float) -> None:
"""
Set the rate of a Poisson neuron within a Poisson source.
Expand All @@ -156,8 +156,8 @@ def set_rate(self, label: str, neuron_id: int, rate: float):
"""
self.set_rates(label, [(neuron_id, rate)])

def set_rates(
self, label: str, neuron_id_rates: Iterable[Tuple[int, float]]):
def set_rates(self, label: str,
neuron_id_rates: Iterable[Tuple[int, float]]) -> None:
"""
Set the rates of multiple Poisson neurons within a Poisson source.
Expand Down
6 changes: 3 additions & 3 deletions spynnaker/pyNN/data/spynnaker_data_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def get_n_projections(cls) -> int:
return len(cls.__spy_data._projections)

@classmethod
def add_projection(cls, projection: Projection):
def add_projection(cls, projection: Projection) -> None:
"""
Called by each projection to add itself to the list.
Expand Down Expand Up @@ -199,7 +199,7 @@ def get_n_populations(cls) -> int:
return len(cls.__spy_data._populations)

@classmethod
def add_population(cls, population: Population):
def add_population(cls, population: Population) -> Tuple[int, int]:
"""
Called by each population to add itself to the list.
Expand Down Expand Up @@ -237,7 +237,7 @@ def add_population(cls, population: Population):
@classmethod
def set_number_of_neurons_per_dimension_per_core(
cls, neuron_type: Type[AbstractPyNNModel],
max_permitted: Optional[Union[Tuple[int, ...]]]):
max_permitted: Optional[Union[Tuple[int, ...]]]) -> None:
"""
Sets a ceiling on the number of neurons of a given type that can be
placed on a single core for each dimension.
Expand Down
4 changes: 2 additions & 2 deletions spynnaker/pyNN/data/spynnaker_data_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def _soft_reset(self) -> None:
def set_up_timings_and_delay(
self, simulation_time_step_us: Optional[int],
time_scale_factor: Optional[float],
min_delay: Optional[Union[int, float]]):
min_delay: Optional[Union[int, float]]) -> None:
"""
:param simulation_time_step_us:
An explicitly specified time step for the simulation in
Expand All @@ -80,7 +80,7 @@ def set_up_timings_and_delay(
self.__spy_data._min_delay = None
raise

def _set_min_delay(self, min_delay: Optional[Union[int, float]]):
def _set_min_delay(self, min_delay: Optional[Union[int, float]]) -> None:
"""
Sets a min delay or accepts `None` to use simulation_time_step_ms.
Expand Down
4 changes: 2 additions & 2 deletions spynnaker/pyNN/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class SynapseRowTooBigException(SpynnakerException):
"""
Raised when a synapse row is bigger than is allowed.
"""
def __init__(self, max_size, message):
def __init__(self, max_size: int, message: str):
"""
:param max_size: the maximum permitted size of row
:param message: the exception message
Expand All @@ -90,7 +90,7 @@ def __init__(self, max_size, message):
self._max_size = max_size

@property
def max_size(self):
def max_size(self) -> int:
"""
The maximum size allowed.
"""
Expand Down
Loading

0 comments on commit 6168092

Please sign in to comment.