diff --git a/b_asic/GUI/arrow.py b/b_asic/GUI/arrow.py index cbf9ae4a9aad21f0b84fa1ca3bea827e68ed4d7c..fb5bb9d8d282d9a708fe35e3bba97fae1b3320b4 100644 --- a/b_asic/GUI/arrow.py +++ b/b_asic/GUI/arrow.py @@ -46,7 +46,7 @@ class Arrow(QGraphicsPathItem): window: "SFGMainWindow", signal: Signal | None = None, parent=None, - ): + ) -> None: super().__init__(parent) self._source_port_button = source_port_button if signal is None: @@ -58,7 +58,7 @@ class Arrow(QGraphicsPathItem): self._source_port_button.moved.connect(self.update_arrow) self._destination_port_button.moved.connect(self.update_arrow) - def contextMenuEvent(self, event): + def contextMenuEvent(self, event) -> None: """ Open right-click menu. @@ -111,7 +111,7 @@ class Arrow(QGraphicsPathItem): """The destination InputPort.""" return cast("InputPort", self._destination_port_button.port) - def set_source_operation(self, source: "Operation"): + def set_source_operation(self, source: "Operation") -> None: """ Set operation of the source DragButton. @@ -122,7 +122,7 @@ class Arrow(QGraphicsPathItem): """ self._source_port_button._operation_button.operation = source - def set_destination_operation(self, destination: "Operation"): + def set_destination_operation(self, destination: "Operation") -> None: """ Set operation of the destination DragButton. @@ -133,7 +133,7 @@ class Arrow(QGraphicsPathItem): """ self._destination_port_button._operation_button.operation = destination - def remove(self): + def remove(self) -> None: """Remove line and connections to signals etc.""" self.signal.remove_destination() self.signal.remove_source() @@ -165,7 +165,7 @@ class Arrow(QGraphicsPathItem): del self._window._arrow_ports[self] - def update_arrow(self): + def update_arrow(self) -> None: """ Update coordinates for arrow. diff --git a/b_asic/GUI/drag_button.py b/b_asic/GUI/drag_button.py index 6d20abeb00e14a3fa6056dd5371ee1c598194aba..4817961134516531bc046efe49a726fb5b924bc9 100644 --- a/b_asic/GUI/drag_button.py +++ b/b_asic/GUI/drag_button.py @@ -17,6 +17,7 @@ from b_asic.GUI.properties_window import PropertiesWindow from b_asic.gui_utils.decorators import decorate_class, handle_error from b_asic.operation import Operation from b_asic.port import InputPort +from b_asic.types import TypeName if TYPE_CHECKING: from qtpy.QtWidgets import QGraphicsTextItem @@ -54,7 +55,7 @@ class DragButton(QPushButton): show_name: bool, window: "SFGMainWindow", parent=None, - ): + ) -> None: self.name = operation.name or operation.graph_id self._ports: list[PortButton] = [] self.show_name = show_name @@ -70,7 +71,7 @@ class DragButton(QPushButton): self.label = None super().__init__(parent) - def contextMenuEvent(self, event): + def contextMenuEvent(self, event) -> None: menu = QMenu() properties = QAction("Properties") menu.addAction(properties) @@ -90,7 +91,7 @@ class DragButton(QPushButton): self._properties_window = PropertiesWindow(self, self._window) self._properties_window.show() - def type_name(self): + def type_name(self) -> TypeName: """Return the type name of the underlying operation.""" return self.operation.type_name() @@ -105,7 +106,7 @@ class DragButton(QPushButton): """ self.label = label - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: if event.button() == Qt.MouseButton.LeftButton: self._m_press = True pos = event.pos() @@ -119,7 +120,7 @@ class DragButton(QPushButton): """Return a list of PortButtons.""" return self._ports - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: if event.buttons() == Qt.MouseButton.LeftButton and self._m_press: self._m_drag = True self.move(self.mapToParent(event.pos() - self._mouse_press_pos)) @@ -133,7 +134,7 @@ class DragButton(QPushButton): self._window._update() super().mouseMoveEvent(event) - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: self._m_press = False if self._m_drag: if self._mouse_press_pos is not None: @@ -156,7 +157,7 @@ class DragButton(QPushButton): self._window._update() super().mouseReleaseEvent(event) - def _flip(self, event=None): + def _flip(self, event=None) -> None: self._flipped = not self._flipped for pb in self._ports: if isinstance(pb.port, InputPort): @@ -169,7 +170,7 @@ class DragButton(QPushButton): self._window._update() - def _toggle_button(self, pressed=False): + def _toggle_button(self, pressed=False) -> None: self.pressed = not pressed self.setStyleSheet( f"background-color: {'white' if not self.pressed else 'grey'};" @@ -185,7 +186,7 @@ class DragButton(QPushButton): self.setIcon(QIcon(path_to_image)) self.setIconSize(QSize(MINBUTTONSIZE, MINBUTTONSIZE)) - def is_flipped(self): + def is_flipped(self) -> bool: """Return True if the button is flipped (inputs to the right).""" return self._flipped @@ -215,7 +216,7 @@ class DragButton(QPushButton): for arrow in self._window._arrow_ports: arrow.update() - def remove(self, event=None): + def remove(self, event=None) -> None: """Remove button/operation from signal flow graph.""" self._window._logger.info( "Removing operation with name %s", self.operation.name @@ -261,10 +262,10 @@ class DragButton(QPushButton): if self.operation in self._window._drag_buttons: del self._window._drag_buttons[self.operation] - def add_ports(self): + def add_ports(self) -> None: """Add ports to button.""" - def _determine_port_distance(opheight, ports): + def _determine_port_distance(opheight, ports: int) -> list[float]: """ Determine the distance between each port on the side of an operation. The method returns the distance that each port should have from 0. diff --git a/b_asic/GUI/gui_interface.py b/b_asic/GUI/gui_interface.py index c6cd7776be7a987e27350e65333dfebead5d2064..46ea3c8676b93115b91046dce366881a9c383bca 100644 --- a/b_asic/GUI/gui_interface.py +++ b/b_asic/GUI/gui_interface.py @@ -9,7 +9,7 @@ from qtpy import QtCore, QtWidgets class Ui_main_window: - def setupUi(self, main_window): + def setupUi(self, main_window) -> None: main_window.setObjectName("main_window") main_window.setEnabled(True) main_window.resize(897, 633) @@ -206,7 +206,7 @@ class Ui_main_window: self.core_operations_list.setCurrentRow(-1) QtCore.QMetaObject.connectSlotsByName(main_window) - def retranslateUi(self, main_window): + def retranslateUi(self, main_window) -> None: _translate = QtCore.QCoreApplication.translate main_window.setWindowTitle(_translate("main_window", "B-ASIC")) self.operation_box.setTitle(_translate("main_window", "Operations")) diff --git a/b_asic/GUI/main_window.py b/b_asic/GUI/main_window.py index a0dfe2989d36232ecc47806f2b3278ade9bd1b84..6c084e802086c0304bafb8cba8d11f37e1b8a887 100644 --- a/b_asic/GUI/main_window.py +++ b/b_asic/GUI/main_window.py @@ -71,7 +71,7 @@ QCoreApplication.setApplicationVersion(__version__) @decorate_class(handle_error) class SFGMainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self._logger = logging.getLogger(__name__) self._window = self @@ -347,7 +347,7 @@ class SFGMainWindow(QMainWindow): positions[op.graph_id][-1] if op.graph_id in positions else None, ) - def connect_ports(ports: Sequence[InputPort]): + def connect_ports(ports: Sequence[InputPort]) -> None: for port in ports: for signal in port.signals: sources = [ @@ -381,7 +381,7 @@ class SFGMainWindow(QMainWindow): self._sfg_dict[sfg.name] = sfg self.update() - def _create_recent_file_actions_and_menus(self): + def _create_recent_file_actions_and_menus(self) -> None: for _ in range(self._max_recent_files): recent_file_action = QAction(self._ui.recent_sfg) recent_file_action.setVisible(False) @@ -393,7 +393,7 @@ class SFGMainWindow(QMainWindow): self._update_recent_file_list() - def _toggle_fullscreen(self, event=None): + def _toggle_fullscreen(self, event=None) -> None: """Toggle full screen mode.""" if self.isFullScreen(): self.showNormal() @@ -402,7 +402,7 @@ class SFGMainWindow(QMainWindow): self.showFullScreen() self._fullscreen_action.setIcon(get_icon("full-screen-exit")) - def _update_recent_file_list(self): + def _update_recent_file_list(self) -> None: settings = QSettings() rfp = cast(deque, settings.value("SFG/recentFiles")) if rfp: @@ -417,10 +417,10 @@ class SFGMainWindow(QMainWindow): for i in range(dequelen, self._max_recent_files): self._recent_files_actions[i].setVisible(False) - def _open_recent_file(self, action): + def _open_recent_file(self, action) -> None: self._load_from_file(action.data().filePath()) - def _add_recent_file(self, module): + def _add_recent_file(self, module) -> None: settings = QSettings() rfp = cast(deque, settings.value("SFG/recentFiles")) if rfp: @@ -649,7 +649,7 @@ class SFGMainWindow(QMainWindow): return self._add_namespace(module) - def _add_namespace(self, module: str): + def _add_namespace(self, module: str) -> None: spec = importlib.util.spec_from_file_location( f"{QFileInfo(module).fileName()}", module ) @@ -658,7 +658,7 @@ class SFGMainWindow(QMainWindow): self.add_operations_from_namespace(namespace, self._ui.custom_operations_list) - def _update(self): + def _update(self) -> None: self._scene.update() self._graphics_view.update() @@ -882,7 +882,7 @@ class SFGMainWindow(QMainWindow): operation._toggle_button(pressed=True) self.update_statusbar("Unselected all operations") - def _zoom_to_fit(self, event=None): + def _zoom_to_fit(self, event=None) -> None: """Zoom to fit SFGs in window.""" self._graphics_view.fitInView( self._scene.sceneRect(), Qt.AspectRatioMode.KeepAspectRatio @@ -904,7 +904,7 @@ class SFGMainWindow(QMainWindow): self._thread[sfg].finished.connect(self._thread[sfg].deleteLater) self._thread[sfg].start() - def _show_plot_window(self, sim: Simulation): + def _show_plot_window(self, sim: Simulation) -> None: """Show the simulation results window.""" self._plot[sim] = PlotWindow(sim.results, sfg_name=sim.sfg.name) self._plot[sim].show() diff --git a/b_asic/GUI/port_button.py b/b_asic/GUI/port_button.py index c90166d08391fe31101959072bbe56a66395875f..ddd3cb233f2f15051afddb8b6fa5e012fd666112 100644 --- a/b_asic/GUI/port_button.py +++ b/b_asic/GUI/port_button.py @@ -31,7 +31,7 @@ class PortButton(QPushButton): connectionRequested = Signal(QPushButton) moved = Signal() - def __init__(self, name: str, operation_button: "DragButton", port: "Port"): + def __init__(self, name: str, operation_button: "DragButton", port: "Port") -> None: super().__init__(name, parent=operation_button) self.pressed = False self._window = operation_button._window @@ -50,25 +50,25 @@ class PortButton(QPushButton): """Operation associated with PortButton.""" return self._operation_button.operation - def contextMenuEvent(self, event): + def contextMenuEvent(self, event) -> None: menu = QMenu() menu.addAction("Connect", lambda: self.connectionRequested.emit(self)) menu.exec_(self.cursor().pos()) - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: if event.button() == Qt.MouseButton.LeftButton: self._window._mouse_pressed = True self.select_port(event.modifiers()) super().mousePressEvent(event) - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: if event.button() == Qt.MouseButton.LeftButton and self._window._mouse_pressed: self._window._mouse_pressed = False if self._window._mouse_dragging: self._window._mouse_dragging = False super().mouseReleaseEvent(event) - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: if self._window._mouse_pressed: self._window._mouse_dragging = True self._window._starting_port = self @@ -78,20 +78,20 @@ class PortButton(QPushButton): drag.exec() super().mouseMoveEvent(event) - def dragEnterEvent(self, event): + def dragEnterEvent(self, event) -> None: event.acceptProposedAction() self.update() super().dragEnterEvent(event) - def dragLeaveEvent(self, event): + def dragLeaveEvent(self, event) -> None: self.update() super().dragLeaveEvent(event) - def dragMoveEvent(self, event): + def dragMoveEvent(self, event) -> None: event.acceptProposedAction() super().dragMoveEvent(event) - def dropEvent(self, event): + def dropEvent(self, event) -> None: event.acceptProposedAction() if self != self._window._starting_port: self.select_port(Qt.KeyboardModifier.ControlModifier) @@ -99,13 +99,13 @@ class PortButton(QPushButton): self.update() super().dropEvent(event) - def _toggle_port(self, pressed: bool = False): + def _toggle_port(self, pressed: bool = False) -> None: self.pressed = not pressed self.setStyleSheet( f"background-color: {'white' if not self.pressed else 'grey'}" ) - def select_port(self, modifiers=None): + def select_port(self, modifiers=None) -> None: """ Select the port taking *modifiers* into account. diff --git a/b_asic/GUI/precedence_graph_window.py b/b_asic/GUI/precedence_graph_window.py index 0d151ceeb4c2d9243f9b76286c26d55c85019d83..61fcac3ae8324da50d3d055102bbe1beacc88889 100644 --- a/b_asic/GUI/precedence_graph_window.py +++ b/b_asic/GUI/precedence_graph_window.py @@ -18,7 +18,7 @@ class PrecedenceGraphWindow(QDialog): pc = Signal() - def __init__(self, window): + def __init__(self, window) -> None: super().__init__() self._window = window self._check_box_dict = {} @@ -31,7 +31,7 @@ class PrecedenceGraphWindow(QDialog): self._dialog_layout.addWidget(self._show_precedence_graph_button) self.setLayout(self._dialog_layout) - def add_sfg_to_dialog(self): + def add_sfg_to_dialog(self) -> None: if not self._window._sfg_dict: self.accept() self.pc.emit() @@ -56,7 +56,7 @@ class PrecedenceGraphWindow(QDialog): check_box = next(iter(self._check_box_dict.keys())) check_box.setChecked(True) - def show_precedence_graph(self): + def show_precedence_graph(self) -> None: for check_box, sfg in self._check_box_dict.items(): if check_box.isChecked(): self._window._logger.info( diff --git a/b_asic/GUI/properties_window.py b/b_asic/GUI/properties_window.py index aedb07ccfffea979b052af22e6680394494b733e..c3a64bcbf274cb437e321b7f27f8affcdaed914e 100644 --- a/b_asic/GUI/properties_window.py +++ b/b_asic/GUI/properties_window.py @@ -19,7 +19,7 @@ from qtpy.QtWidgets import ( class PropertiesWindow(QDialog): - def __init__(self, operation, main_window): + def __init__(self, operation, main_window) -> None: super().__init__() self.operation = operation self._window = main_window @@ -143,7 +143,7 @@ class PropertiesWindow(QDialog): self._vertical_layout.addWidget(self._ok_button) self.setLayout(self._vertical_layout) - def save_properties(self): + def save_properties(self) -> None: self._window._logger.info( "Saving properties of operation: %s", self.operation.name ) diff --git a/b_asic/GUI/select_sfg_window.py b/b_asic/GUI/select_sfg_window.py index a3ac58bfaba9dc723be51f0502cec916e16a84af..17b6d2b1b380ed647c826a7c0fdef77c2a8cfa68 100644 --- a/b_asic/GUI/select_sfg_window.py +++ b/b_asic/GUI/select_sfg_window.py @@ -14,7 +14,7 @@ if TYPE_CHECKING: class SelectSFGWindow(QDialog): ok = Signal() - def __init__(self, window: "SFGMainWindow"): + def __init__(self, window: "SFGMainWindow") -> None: super().__init__() self._window = window self.setWindowFlags(Qt.WindowTitleHint | Qt.WindowCloseButtonHint) @@ -41,7 +41,7 @@ class SelectSFGWindow(QDialog): self.accept() self.ok.emit() - def save_properties(self): + def save_properties(self) -> None: self.sfg = self._window._sfg_dict[self._sfg_combo_box.currentText()] self.accept() self.ok.emit() diff --git a/b_asic/GUI/signal_generator_input.py b/b_asic/GUI/signal_generator_input.py index 86c423bd3ab6bc55ec3543411c9a980e88033f12..b5169f0fb0df8b6ed410a88ee1fc30cc334faecc 100644 --- a/b_asic/GUI/signal_generator_input.py +++ b/b_asic/GUI/signal_generator_input.py @@ -29,7 +29,7 @@ from b_asic.signal_generator import ( class SignalGeneratorInput(QGridLayout): """Abstract class for graphically configuring and generating signal generators.""" - def __init__(self, logger, *args, **kwargs): + def __init__(self, logger, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self._logger = logger @@ -37,7 +37,13 @@ class SignalGeneratorInput(QGridLayout): """Return the SignalGenerator based on the graphical input.""" raise NotImplementedError - def _parse_number(self, string, _type, name, default): + def _parse_number( + self, + string, + _type: type[float] | type[int] | type[complex], + name, + default: float, + ) -> float | int | complex: string = string.strip() try: if not string: @@ -60,7 +66,7 @@ class DelayInput(SignalGeneratorInput): have a single delay parameter. """ - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.delay_label = QLabel("Delay") self.addWidget(self.delay_label, 0, 0) @@ -98,7 +104,7 @@ class ZeroPadInput(SignalGeneratorInput): :class:`~b_asic.signal_generators.ZeroPad` signal generator. """ - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.input_label = QLabel("Input") self.addWidget(self.input_label, 0, 0) @@ -127,7 +133,7 @@ class FromFileInput(SignalGeneratorInput): :class:`~b_asic.signal_generators.FromFile` signal generator. """ - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.file_label = QLabel("Browse") self.addWidget(self.file_label, 0, 0) @@ -140,7 +146,7 @@ class FromFileInput(SignalGeneratorInput): def get_generator(self) -> SignalGenerator: return FromFile(self.file_browser.text()) - def get_input_file(self, i, file_browser): + def get_input_file(self, i, file_browser) -> None: module, accepted = QFileDialog().getOpenFileName() file_browser.setText(module) return @@ -152,7 +158,7 @@ class SinusoidInput(SignalGeneratorInput): :class:`~b_asic.signal_generators.Sinusoid` signal generator. """ - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.frequency_label = QLabel("Frequency") self.addWidget(self.frequency_label, 0, 0) @@ -180,7 +186,7 @@ class GaussianInput(SignalGeneratorInput): :class:`~b_asic.signal_generators.Gaussian` signal generator. """ - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.scale_label = QLabel("Standard deviation") self.addWidget(self.scale_label, 0, 0) @@ -214,7 +220,7 @@ class UniformInput(SignalGeneratorInput): :class:`~b_asic.signal_generators.Uniform` signal generator. """ - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.low_label = QLabel("Lower bound") self.addWidget(self.low_label, 0, 0) @@ -246,7 +252,7 @@ class ConstantInput(SignalGeneratorInput): :class:`~b_asic.signal_generators.Constant` signal generator. """ - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.constant_label = QLabel("Constant") self.addWidget(self.constant_label, 0, 0) diff --git a/b_asic/GUI/simulate_sfg_window.py b/b_asic/GUI/simulate_sfg_window.py index 47836e68e9325a4ef81c2509f6e065bb0c0d54fb..b8ce6b0bc843bfcef7345b770e29f88b8dd9246a 100644 --- a/b_asic/GUI/simulate_sfg_window.py +++ b/b_asic/GUI/simulate_sfg_window.py @@ -30,7 +30,7 @@ class SimulateSFGWindow(QDialog): simulate = Signal() - def __init__(self, window): + def __init__(self, window) -> None: super().__init__() self._window = window self._properties = {} diff --git a/b_asic/GUI/simulation_worker.py b/b_asic/GUI/simulation_worker.py index 3dd357bb378b7de705f582c782e90e22abde2b2a..b7468d31c854f70e815e31536a3bf6bd1bc969a4 100644 --- a/b_asic/GUI/simulation_worker.py +++ b/b_asic/GUI/simulation_worker.py @@ -24,12 +24,12 @@ class SimulationWorker(QObject): finished = Signal(Simulation) - def __init__(self, sfg: SFG, properties): + def __init__(self, sfg: SFG, properties) -> None: super().__init__() self._sfg = sfg self._props = properties - def start_simulation(self): + def start_simulation(self) -> None: """Start simulation and emit signal when finished.""" simulation = Simulation(self._sfg, input_providers=self._props["input_values"]) simulation.run_for( diff --git a/b_asic/GUI/util_dialogs.py b/b_asic/GUI/util_dialogs.py index 20b628710578efa154864f3c3b95cdda0752ad63..4ebd98b65c61f2cff001ff2751f8533d0cae2a6f 100644 --- a/b_asic/GUI/util_dialogs.py +++ b/b_asic/GUI/util_dialogs.py @@ -70,7 +70,7 @@ _QUESTIONS = { class KeybindingsWindow(QDialog): - def __init__(self, window): + def __init__(self, window) -> None: super().__init__() self._window = window self.setWindowFlags(Qt.WindowTitleHint | Qt.WindowCloseButtonHint) @@ -81,7 +81,7 @@ class KeybindingsWindow(QDialog): self.add_information_to_layout() - def add_information_to_layout(self): + def add_information_to_layout(self) -> None: information_layout = QVBoxLayout() title_label = QLabel("B-ASIC / Better ASIC Toolbox") @@ -112,7 +112,7 @@ class KeybindingsWindow(QDialog): class FaqWindow(QDialog): - def __init__(self, window): + def __init__(self, window) -> None: super().__init__() self._window = window self.setWindowFlags(Qt.WindowTitleHint | Qt.WindowCloseButtonHint) @@ -127,7 +127,7 @@ class FaqWindow(QDialog): self._scroll_area.setWidget(self) self._scroll_area.setWidgetResizable(True) - def _add_question_to_layout(self, question, answer): + def _add_question_to_layout(self, question, answer) -> None: question_layout = QVBoxLayout() answer_layout = QHBoxLayout() diff --git a/b_asic/architecture.py b/b_asic/architecture.py index ee0e46b3535d6b33f376c789f1c906d25ebdb67f..6e4083268873ff35e49afb5ce0d9821941128423 100644 --- a/b_asic/architecture.py +++ b/b_asic/architecture.py @@ -9,6 +9,7 @@ from io import TextIOWrapper from itertools import chain from typing import ( Literal, + NoReturn, cast, ) @@ -52,7 +53,7 @@ class HardwareBlock: __slots__ = "_entity_name" _entity_name: str | None - def __init__(self, entity_name: str | None = None): + def __init__(self, entity_name: str | None = None) -> None: self._entity_name: str | None = None if entity_name is not None: self.set_entity_name(entity_name) @@ -156,7 +157,7 @@ class Resource(HardwareBlock): def __init__( self, process_collection: ProcessCollection, entity_name: str | None = None - ): + ) -> None: if not len(process_collection): raise ValueError("Do not create Resource with empty ProcessCollection") super().__init__(entity_name=entity_name) @@ -165,10 +166,10 @@ class Resource(HardwareBlock): self._output_count = -1 self._assignment: list[ProcessCollection] | None = None - def __repr__(self): + def __repr__(self) -> str: return self.entity_name - def __iter__(self): + def __iter__(self) -> Iterator[ProcessCollection]: return iter(self._collection) def _digraph(self, fontname: str = "Times New Roman") -> Digraph: @@ -285,7 +286,7 @@ class Resource(HardwareBlock): def is_assigned(self) -> bool: return self._assignment is not None - def assign(self, strategy: Literal["left_edge"] = "left_edge"): + def assign(self, strategy: Literal["left_edge"] = "left_edge") -> NoReturn: """ Perform assignment of processes to resource. @@ -322,7 +323,7 @@ class Resource(HardwareBlock): def operation_type(self) -> type[MemoryProcess] | type[Operation]: raise NotImplementedError("ABC Resource does not implement operation_type") - def add_process(self, proc: Process, assign=False): + def add_process(self, proc: Process, assign=False) -> None: """ Add a :class:`~b_asic.process.Process` to this :class:`Resource`. @@ -352,7 +353,7 @@ class Resource(HardwareBlock): else: self._assignment = None - def remove_process(self, proc: Process, assign: bool = False): + def remove_process(self, proc: Process, assign: bool = False) -> None: """ Remove a :class:`~b_asic.process.Process` from this :class:`Resource`. @@ -402,7 +403,7 @@ class ProcessingElement(Resource): process_collection: ProcessCollection, entity_name: str | None = None, assign: bool = True, - ): + ) -> None: super().__init__(process_collection=process_collection, entity_name=entity_name) if not isinstance(process_collection, ProcessCollection): @@ -512,7 +513,7 @@ class Memory(Resource): write_ports: int | None = None, total_ports: int | None = None, assign: bool = False, - ): + ) -> None: super().__init__(process_collection=process_collection, entity_name=entity_name) if not all( isinstance(operator, MemoryProcess) @@ -631,7 +632,7 @@ of :class:`~b_asic.architecture.ProcessingElement` memories: Memory | Iterable[Memory], entity_name: str = "arch", direct_interconnects: ProcessCollection | None = None, - ): + ) -> None: super().__init__(entity_name) pe_names = [pe._entity_name for pe in processing_elements] diff --git a/b_asic/codegen/vhdl/__init__.py b/b_asic/codegen/vhdl/__init__.py index 29612c3cc13153d9edc871be05d775b779547e4d..0811d5bced0b6cf207a12847a1ff8864d9d1a766 100644 --- a/b_asic/codegen/vhdl/__init__.py +++ b/b_asic/codegen/vhdl/__init__.py @@ -15,7 +15,7 @@ def write( *, end: str = "\n", start: str | None = None, -): +) -> None: r""" Write text to a VHDL file. @@ -42,7 +42,7 @@ def write( f.write(f"{VHDL_TAB * indent_level}{text}{end}") -def write_lines(f: TextIO, lines: list[tuple[int, str] | tuple[int, str, str]]): +def write_lines(f: TextIO, lines: list[tuple[int, str] | tuple[int, str, str]]) -> None: """ Write provided lines to a VHDL file. diff --git a/b_asic/codegen/vhdl/architecture.py b/b_asic/codegen/vhdl/architecture.py index 6af890c54389c10bc1070d74070b4602de1afcd0..9e21062a046d14a4d70c8c0efe90d8a680f4203d 100644 --- a/b_asic/codegen/vhdl/architecture.py +++ b/b_asic/codegen/vhdl/architecture.py @@ -30,7 +30,7 @@ def memory_based_storage( quartus_ram_style: ( Literal["M4K", "M9K", "M10K", "M20K", "M144K", "MLAB", "logic"] | None ) = None, -): +) -> None: """ Generate the VHDL architecture for a memory-based storage architecture. @@ -585,7 +585,7 @@ def register_based_storage( total_ports: int, sync_rst: bool = False, async_rst: bool = False, -): +) -> None: architecture_name = "rtl" schedule_time = len(forward_backward_table) diff --git a/b_asic/codegen/vhdl/common.py b/b_asic/codegen/vhdl/common.py index 0ab12c145dd51a0833f0b924f0f199a206b3d610..9bd5b203a69a9d377725cc1065afa09a8e2c0d18 100644 --- a/b_asic/codegen/vhdl/common.py +++ b/b_asic/codegen/vhdl/common.py @@ -10,7 +10,7 @@ from typing import Any, Literal, TextIO from b_asic.codegen.vhdl import write, write_lines -def b_asic_preamble(f: TextIO): +def b_asic_preamble(f: TextIO) -> None: """ Write a standard BASIC VHDL preamble comment. @@ -49,7 +49,7 @@ def ieee_header( f: TextIO, std_logic_1164: bool = True, numeric_std: bool = True, -): +) -> None: """ Write the standard IEEE VHDL use header. @@ -84,7 +84,7 @@ def signal_declaration( quartus_ram_style: ( Literal["M4K", "M9K", "M10K", "M20K", "M144K", "MLAB", "logic"] | None ) = None, -): +) -> None: """ Create a VHDL signal declaration. @@ -143,7 +143,7 @@ def alias_declaration( signal_type: str, value: str | None = None, name_pad: int | None = None, -): +) -> None: name_pad = name_pad or 0 write(f, 1, f"alias {name:<{name_pad}} : {signal_type} is {value};") @@ -154,7 +154,7 @@ def constant_declaration( signal_type: str, value: Any, name_pad: int | None = None, -): +) -> None: """ Write a VHDL constant declaration with a name, a type and a value. @@ -179,7 +179,7 @@ def type_declaration( f: TextIO, name: str, alias: str, -): +) -> None: """ Write a VHDL type declaration with a name tied to an alias. @@ -200,7 +200,7 @@ def process_prologue( sensitivity_list: str, indent: int = 1, name: str | None = None, -): +) -> None: """ Write the prologue of a regular VHDL process with a user provided sensitivity list. @@ -229,7 +229,7 @@ def process_epilogue( sensitivity_list: str | None = None, indent: int = 1, name: str | None = None, -): +) -> None: """ Write the epilogue of a regular VHDL process. @@ -258,7 +258,7 @@ def synchronous_process_prologue( clk: str, indent: int = 1, name: str | None = None, -): +) -> None: """ Write the prologue of a regular VHDL synchronous process with a single clock object. @@ -287,7 +287,7 @@ def synchronous_process_epilogue( clk: str | None = None, indent: int = 1, name: str | None = None, -): +) -> None: """ Write the epilogue of a regular VHDL synchronous process with a single clock. @@ -316,7 +316,7 @@ def synchronous_process( body: str, indent: int = 1, name: str | None = None, -): +) -> None: """ Write a regular VHDL synchronous process with a single clock. @@ -349,7 +349,7 @@ def synchronous_memory( read_ports: set[tuple[str, str, str]], write_ports: set[tuple[str, str, str]], name: str | None = None, -): +) -> None: """ Infer a VHDL synchronous reads and writes. @@ -396,7 +396,7 @@ def asynchronous_read_memory( read_ports: set[tuple[str, str, str]], write_ports: set[tuple[str, str, str]], name: str | None = None, -): +) -> None: """ Infer a VHDL memory with synchronous writes and asynchronous reads. diff --git a/b_asic/codegen/vhdl/entity.py b/b_asic/codegen/vhdl/entity.py index a230c1688799c3d306c80b5508feb6c173477a80..d080d07804ea0e393277660aad53f30aaf957aad 100644 --- a/b_asic/codegen/vhdl/entity.py +++ b/b_asic/codegen/vhdl/entity.py @@ -12,7 +12,7 @@ from b_asic.resources import ProcessCollection def memory_based_storage( f: TextIO, entity_name: str, collection: ProcessCollection, word_length: int -): +) -> None: # Check that this is a ProcessCollection of (Plain)MemoryVariables is_memory_variable = all( isinstance(process, MemoryVariable) for process in collection @@ -80,5 +80,5 @@ def memory_based_storage( def register_based_storage( f: TextIO, entity_name: str, collection: ProcessCollection, word_length: int -): +) -> None: memory_based_storage(f, entity_name, collection, word_length) diff --git a/b_asic/core_operations.py b/b_asic/core_operations.py index af8139a50f2b48b8a674ac1710e9f72896de5fd9..9f7203aa3fb5208413d774bcf077a8a56cec6a96 100644 --- a/b_asic/core_operations.py +++ b/b_asic/core_operations.py @@ -4,6 +4,8 @@ B-ASIC Core Operations Module. Contains some of the most commonly used mathematical operations. """ +from typing import NoReturn + from numpy import abs as np_abs from numpy import conjugate, sqrt @@ -36,7 +38,7 @@ class Constant(AbstractOperation): is_linear = True is_constant = True - def __init__(self, value: Num = 0, name: Name = ""): + def __init__(self, value: Num = 0, name: Name = "") -> None: """ Construct a Constant operation with the given value. """ @@ -53,7 +55,7 @@ class Constant(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("c") - def evaluate(self): + def evaluate(self) -> Num: return self.param("value") @property @@ -169,7 +171,7 @@ class Addition(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """ Construct an Addition operation. """ @@ -187,7 +189,7 @@ class Addition(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("add") - def evaluate(self, a, b): + def evaluate(self, a, b) -> Num: return a + b @@ -247,7 +249,7 @@ class Subtraction(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """ Construct a Subtraction operation. """ @@ -265,7 +267,7 @@ class Subtraction(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("sub") - def evaluate(self, a, b): + def evaluate(self, a, b) -> Num: return a - b @@ -337,7 +339,7 @@ class AddSub(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """ Construct an Addition/Subtraction operation. """ @@ -356,7 +358,7 @@ class AddSub(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("addsub") - def evaluate(self, a, b): + def evaluate(self, a, b) -> Num: return a + b if self.is_add else a - b @property @@ -439,7 +441,7 @@ class Multiplication(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """Construct a Multiplication operation.""" super().__init__( input_count=2, @@ -455,7 +457,7 @@ class Multiplication(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("mul") - def evaluate(self, a, b): + def evaluate(self, a, b) -> Num: return a * b @property @@ -519,7 +521,7 @@ class Division(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """Construct a Division operation.""" super().__init__( input_count=2, @@ -535,7 +537,7 @@ class Division(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("div") - def evaluate(self, a, b): + def evaluate(self, a, b) -> Num: if b == 0: return float("inf") return a / b @@ -603,7 +605,7 @@ class Min(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """Construct a Min operation.""" super().__init__( input_count=2, @@ -619,7 +621,7 @@ class Min(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("min") - def evaluate(self, a, b): + def evaluate(self, a, b) -> Num: if isinstance(a, complex) or isinstance(b, complex): raise ValueError("core_operations.Min does not support complex numbers.") return min(a, b) @@ -683,7 +685,7 @@ class Max(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """Construct a Max operation.""" super().__init__( input_count=2, @@ -699,7 +701,7 @@ class Max(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("max") - def evaluate(self, a, b): + def evaluate(self, a, b) -> Num: if isinstance(a, complex) or isinstance(b, complex): raise ValueError("core_operations.Max does not support complex numbers.") return max(a, b) @@ -743,7 +745,7 @@ class SquareRoot(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """Construct a SquareRoot operation.""" super().__init__( input_count=1, @@ -759,7 +761,7 @@ class SquareRoot(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("sqrt") - def evaluate(self, a): + def evaluate(self, a) -> Num: return sqrt(complex(a)) @@ -801,7 +803,7 @@ class ComplexConjugate(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """Construct a ComplexConjugate operation.""" super().__init__( input_count=1, @@ -817,7 +819,7 @@ class ComplexConjugate(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("conj") - def evaluate(self, a): + def evaluate(self, a) -> Num: return conjugate(a) @@ -859,7 +861,7 @@ class Absolute(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """Construct an Absolute operation.""" super().__init__( input_count=1, @@ -875,7 +877,7 @@ class Absolute(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("abs") - def evaluate(self, a): + def evaluate(self, a) -> Num: return np_abs(a) @@ -934,7 +936,7 @@ class ConstantMultiplication(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """Construct a ConstantMultiplication operation with the given value.""" super().__init__( input_count=1, @@ -951,7 +953,7 @@ class ConstantMultiplication(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("cmul") - def evaluate(self, a): + def evaluate(self, a) -> Num: return a * self.param("value") @property @@ -1022,7 +1024,7 @@ class Butterfly(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """Construct a Butterfly operation.""" super().__init__( input_count=2, @@ -1038,7 +1040,7 @@ class Butterfly(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("bfly") - def evaluate(self, a, b): + def evaluate(self, a, b) -> Num: return a + b, a - b @@ -1106,7 +1108,7 @@ class MAD(AbstractOperation): latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, do_add: bool = True, - ): + ) -> None: """Construct a MAD operation.""" super().__init__( input_count=3, @@ -1123,7 +1125,7 @@ class MAD(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("mad") - def evaluate(self, a, b, c): + def evaluate(self, a, b, c) -> Num: return a * b + c if self.do_add else a * b @property @@ -1188,7 +1190,7 @@ class MADS(AbstractOperation): latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, do_addsub: bool = True, - ): + ) -> None: """Construct a MADS operation.""" super().__init__( input_count=3, @@ -1206,7 +1208,7 @@ class MADS(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("mads") - def evaluate(self, a, b, c): + def evaluate(self, a, b, c) -> Num: if self.is_add: if self.do_addsub: return a + b * c @@ -1293,7 +1295,7 @@ class SymmetricTwoportAdaptor(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """Construct a SymmetricTwoportAdaptor operation.""" super().__init__( input_count=2, @@ -1310,7 +1312,7 @@ class SymmetricTwoportAdaptor(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("sym2p") - def evaluate(self, a, b): + def evaluate(self, a, b) -> Num: tmp = self.value * (b - a) return b + tmp, a + tmp @@ -1380,7 +1382,7 @@ class Reciprocal(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """Construct a Reciprocal operation.""" super().__init__( input_count=1, @@ -1396,7 +1398,7 @@ class Reciprocal(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("rec") - def evaluate(self, a): + def evaluate(self, a) -> Num: if a == 0: return float("inf") return 1 / a @@ -1459,7 +1461,7 @@ class RightShift(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """Construct a RightShift operation with the given value.""" super().__init__( input_count=1, @@ -1476,7 +1478,7 @@ class RightShift(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("rshift") - def evaluate(self, a): + def evaluate(self, a) -> Num: return a * 2 ** (-self.param("value")) @property @@ -1551,7 +1553,7 @@ class LeftShift(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """Construct a RightShift operation with the given value.""" super().__init__( input_count=1, @@ -1568,7 +1570,7 @@ class LeftShift(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("lshift") - def evaluate(self, a): + def evaluate(self, a) -> Num: return a * 2 ** (self.param("value")) @property @@ -1644,7 +1646,7 @@ class Shift(AbstractOperation): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """Construct a Shift operation with the given value.""" super().__init__( input_count=1, @@ -1661,7 +1663,7 @@ class Shift(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("shift") - def evaluate(self, a): + def evaluate(self, a) -> Num: return a * 2 ** (self.param("value")) @property @@ -1694,7 +1696,7 @@ class DontCare(AbstractOperation): is_linear = True - def __init__(self, name: Name = ""): + def __init__(self, name: Name = "") -> None: """Construct a DontCare operation.""" super().__init__( input_count=0, @@ -1708,7 +1710,7 @@ class DontCare(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("dontcare") - def evaluate(self): + def evaluate(self) -> int: return 0 @property @@ -1770,7 +1772,7 @@ class Sink(AbstractOperation): is_linear = True - def __init__(self, name: Name = ""): + def __init__(self, name: Name = "") -> None: """Construct a Sink operation.""" super().__init__( input_count=1, @@ -1784,7 +1786,7 @@ class Sink(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("sink") - def evaluate(self): + def evaluate(self) -> NoReturn: raise NotImplementedError @property diff --git a/b_asic/graph_component.py b/b_asic/graph_component.py index f0a1b2121841584ef40f032745906fbaf8282df1..94c437a94d56ea4fc5b60a04741e61b77dcbbb07 100644 --- a/b_asic/graph_component.py +++ b/b_asic/graph_component.py @@ -124,7 +124,7 @@ class AbstractGraphComponent(GraphComponent): _graph_id: GraphID _parameters: dict[str, Any] - def __init__(self, name: Name = Name("")): + def __init__(self, name: Name = Name("")) -> None: """Construct a graph component.""" self._name = Name(name) self._graph_id = GraphID("") diff --git a/b_asic/gui_utils/about_window.py b/b_asic/gui_utils/about_window.py index 62763c530ac99d31dca530f3f95ca63397d58234..20535a7edfd4d92bb7f18208546ad29101d1a03c 100644 --- a/b_asic/gui_utils/about_window.py +++ b/b_asic/gui_utils/about_window.py @@ -26,7 +26,7 @@ from b_asic._version import __version__ class AboutWindow(QDialog): """About window.""" - def __init__(self, window): + def __init__(self, window) -> None: super().__init__() self._window = window self.setWindowFlags(Qt.WindowTitleHint | Qt.WindowCloseButtonHint) @@ -37,7 +37,7 @@ class AboutWindow(QDialog): self._add_information_to_layout() - def _hover_text(self, url): + def _hover_text(self, url) -> None: # self.setWindowTitle(url) # When removing mouse, the title gets "B-ASIC Scheduler". # Where does THAT come from? @@ -46,7 +46,7 @@ class AboutWindow(QDialog): else: QToolTip.hideText() - def _add_information_to_layout(self): + def _add_information_to_layout(self) -> None: # |1 Title |2 | # | License | Logo | <- layout12 # | Version | | @@ -118,7 +118,7 @@ class AboutWindow(QDialog): # ONLY FOR DEBUG below -def show_about_window(): +def show_about_window() -> None: """Simply show the about window.""" app = QApplication(sys.argv) window = AboutWindow(QDialog) diff --git a/b_asic/gui_utils/color_button.py b/b_asic/gui_utils/color_button.py index b47a248bfbb39d54b83b1d1db4b19fe2c6c82322..c72dc6c7cf1b2f50cb465bc6bd6da3def2a6f777 100644 --- a/b_asic/gui_utils/color_button.py +++ b/b_asic/gui_utils/color_button.py @@ -23,7 +23,7 @@ class ColorButton(QPushButton): _color: None | QColor _color_changed = Signal(QColor) - def __init__(self, color: QColor, *args, **kwargs): + def __init__(self, color: QColor, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self._color = None diff --git a/b_asic/gui_utils/icons.py b/b_asic/gui_utils/icons.py index 96d0e00255cb2ac70605e11d1d2fdc25300679d2..7f4f5743dcea805a7cb35f7f8192508b66e5d11f 100644 --- a/b_asic/gui_utils/icons.py +++ b/b_asic/gui_utils/icons.py @@ -1,7 +1,12 @@ """B-ASIC icons.""" +from typing import TYPE_CHECKING + import qtawesome +if TYPE_CHECKING: + from qtpy.QtGui import QIcon + ICONS = { "save": "mdi6.content-save", "save-as": "mdi6.content-save-edit", @@ -39,7 +44,7 @@ ICONS = { } -def get_icon(name): +def get_icon(name: str) -> "QIcon": """Return icon for given name.""" info = ICONS[name] if isinstance(info, str): diff --git a/b_asic/gui_utils/mpl_window.py b/b_asic/gui_utils/mpl_window.py index 2a3500114c4bb511f3d8259c82fdd3f717a4bf68..a7bc9cf3af5f6eb1ac02edd4df25bb1bc790caa1 100644 --- a/b_asic/gui_utils/mpl_window.py +++ b/b_asic/gui_utils/mpl_window.py @@ -1,5 +1,6 @@ """MPLWindow is a dialog that provides an Axes for plotting in.""" +from matplotlib.axes import Axes from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qtagg import NavigationToolbar2QT as NavigationToolbar from matplotlib.figure import Figure @@ -12,7 +13,7 @@ class MPLWindow(QDialog): Dialog for plotting Matplotlib things. """ - def __init__(self, title: str = "B-ASIC", subplots=(1, 1)): + def __init__(self, title: str = "B-ASIC", subplots=(1, 1)) -> None: super().__init__() self.setWindowFlags( Qt.WindowTitleHint @@ -35,8 +36,8 @@ class MPLWindow(QDialog): self._dialog_layout.addWidget(self._plot_canvas) @property - def axes(self): + def axes(self) -> Axes | list[Axes]: return self._plot_axes - def redraw(self): + def redraw(self) -> None: self._plot_canvas.draw() diff --git a/b_asic/gui_utils/plot_window.py b/b_asic/gui_utils/plot_window.py index 242203326b0d50ad239365640c75de509dbc748b..2c2367c7528c936d7bfcadc014de4e13d27d9c30 100644 --- a/b_asic/gui_utils/plot_window.py +++ b/b_asic/gui_utils/plot_window.py @@ -47,7 +47,7 @@ class PlotWindow(QWidget): self, sim_result: Mapping[ResultKey, Sequence[Num]], sfg_name: str | None = None, - ): + ) -> None: super().__init__() self.setWindowFlags( Qt.WindowTitleHint @@ -194,32 +194,32 @@ class PlotWindow(QWidget): # self.plotcanvas.draw() self._auto_redraw = True - def _legend_checkbox_change(self, check_state): + def _legend_checkbox_change(self, check_state) -> None: self._legend.set(visible=(check_state == Qt.CheckState.Checked)) if self._auto_redraw: if check_state == Qt.CheckState.Checked: self._legend = self._plot_axes.legend() self._plot_canvas.draw() - def _button_all_click(self, event): + def _button_all_click(self, event) -> None: self._auto_redraw = False for x in range(self._checklist.count()): self._checklist.item(x).setCheckState(Qt.CheckState.Checked) self._auto_redraw = True self._update_legend() - def _update_legend(self): + def _update_legend(self) -> None: self._legend = self._plot_axes.legend() self._plot_canvas.draw() - def _button_none_click(self, event): + def _button_none_click(self, event) -> None: self._auto_redraw = False for x in range(self._checklist.count()): self._checklist.item(x).setCheckState(Qt.CheckState.Unchecked) self._auto_redraw = True self._update_legend() - def _item_change(self, listitem): + def _item_change(self, listitem) -> None: key = listitem.text() if listitem.checkState() == Qt.CheckState.Checked: self._plot_axes.add_line(self._lines[key]) @@ -228,7 +228,7 @@ class PlotWindow(QWidget): if self._auto_redraw: self._update_legend() - def _relim(self, event=None): + def _relim(self, event=None) -> None: self._plot_axes.relim(True) self._plot_axes.autoscale(True) self._plot_axes.autoscale(axis="x", tight=True) @@ -238,7 +238,7 @@ class PlotWindow(QWidget): def start_simulation_dialog( sim_results: dict[str, list[complex]], sfg_name: str | None = None -): +) -> None: """ Display the simulation results window. diff --git a/b_asic/operation.py b/b_asic/operation.py index f4388b70c4450048a32ab8bfa71ca323da139be1..304b22ddc6e67a1b34805c5cc3aa5fed029f5f51 100644 --- a/b_asic/operation.py +++ b/b_asic/operation.py @@ -467,7 +467,7 @@ class AbstractOperation(Operation, AbstractGraphComponent): latency: int | None = None, latency_offsets: dict[str, int] | None = None, execution_time: int | None = None, - ): + ) -> None: """ Construct an operation with the given input/output count. diff --git a/b_asic/port.py b/b_asic/port.py index f2b3737469b08472232e3d41e5e8938f85a7e8e0..669868475b1355b54f6d962238fb4f6746c6122a 100644 --- a/b_asic/port.py +++ b/b_asic/port.py @@ -141,7 +141,7 @@ class AbstractPort(Port): operation: "Operation", index: int, latency_offset: int | None = None, - ): + ) -> None: """Construct a port of the given operation at the given port index.""" self._operation = operation self._index = index @@ -160,11 +160,11 @@ class AbstractPort(Port): return self._latency_offset @latency_offset.setter - def latency_offset(self, latency_offset: int | None): + def latency_offset(self, latency_offset: int | None) -> None: self._latency_offset = latency_offset @property - def name(self): + def name(self) -> str: return f"{self.operation.graph_id}.{self.index}" @@ -281,7 +281,7 @@ class InputPort(AbstractPort): __slots__ = ("_source_signal",) _source_signal: Signal | None - def __init__(self, operation: "Operation", index: int): + def __init__(self, operation: "Operation", index: int) -> None: """Construct an InputPort.""" super().__init__(operation, index) self._source_signal = None @@ -378,7 +378,7 @@ class OutputPort(AbstractPort, SignalSourceProvider): __slots__ = ("_destination_signals",) _destination_signals: list[Signal] - def __init__(self, operation: "Operation", index: int): + def __init__(self, operation: "Operation", index: int) -> None: """Construct an OutputPort.""" super().__init__(operation, index) self._destination_signals = [] diff --git a/b_asic/process.py b/b_asic/process.py index 27263a8daf1ef47b4945a119ce3cd88d9f014d78..551722bdee195bc7aee72d87b0e1373f9d94521f 100644 --- a/b_asic/process.py +++ b/b_asic/process.py @@ -29,7 +29,7 @@ class Process: _execution_time: int _name: str - def __init__(self, start_time: int, execution_time: int, name: str = ""): + def __init__(self, start_time: int, execution_time: int, name: str = "") -> None: self._start_time = start_time self._execution_time = execution_time self._name = name @@ -95,7 +95,7 @@ class OperatorProcess(Process): start_time: int, operation: Operation, name: str | None = None, - ): + ) -> None: execution_time = operation.execution_time if execution_time is None: raise ValueError( @@ -147,7 +147,7 @@ class MemoryProcess(Process): write_time: int, life_times: list[int], name: str = "", - ): + ) -> None: pass self._life_times = life_times super().__init__( @@ -222,7 +222,7 @@ class MemoryProcess(Process): ) return short_process, long_process - def _add_life_time(self, life_time: int): + def _add_life_time(self, life_time: int) -> None: """ Add a lifetime to this :class:`~b_asic.process.MultiReadProcess` set of lifetimes. @@ -242,7 +242,7 @@ class MemoryProcess(Process): self._life_times.append(life_time) self._execution_time = max(self.life_times) - def _remove_life_time(self, life_time: int): + def _remove_life_time(self, life_time: int) -> None: """ Remove a lifetime from this :class:`~b_asic.process.MultiReadProcess` set of lifetimes. @@ -295,7 +295,7 @@ class MemoryVariable(MemoryProcess): write_port: OutputPort, reads: dict[InputPort, int], name: str | None = None, - ): + ) -> None: self._read_ports = list(reads.keys()) self._reads = reads self._write_port = write_port @@ -385,7 +385,7 @@ class PlainMemoryVariable(MemoryProcess): write_port: int, reads: dict[int, int], name: str | None = None, - ): + ) -> None: self._read_ports = list(reads.keys()) self._write_port = write_port self._reads = reads diff --git a/b_asic/quantization.py b/b_asic/quantization.py index f53b1e943e97cd54915d5dfcd08902166331b4ce..38c96aba45d2f4d2d431566b9f8040bfc78c3a2e 100644 --- a/b_asic/quantization.py +++ b/b_asic/quantization.py @@ -50,7 +50,7 @@ def quantize( integer_bits: int = 1, quantization: Quantization = Quantization.TRUNCATION, overflow: Overflow = Overflow.TWOS_COMPLEMENT, -): +) -> Num: r""" Quantize *value* assuming two's complement representation. diff --git a/b_asic/resources.py b/b_asic/resources.py index b41c3a7ff65c9a6a5bd43c41ab5166c6c4d9e721..e8531cb3b55043aaa3e93e217a813057c3253c77 100644 --- a/b_asic/resources.py +++ b/b_asic/resources.py @@ -9,7 +9,7 @@ import itertools import re import sys from collections import Counter, defaultdict -from collections.abc import Iterable +from collections.abc import Iterable, Iterator from functools import reduce from math import floor, log2 from typing import TYPE_CHECKING, Literal, TypeVar, Union @@ -231,7 +231,7 @@ class _ForwardBackwardEntry: back_edge_to: dict[int, int] | None = None, back_edge_from: dict[int, int] | None = None, outputs_from: int | None = None, - ): + ) -> None: """ Single entry in a _ForwardBackwardTable. @@ -265,7 +265,7 @@ class _ForwardBackwardEntry: class _ForwardBackwardTable: - def __init__(self, collection: "ProcessCollection"): + def __init__(self, collection: "ProcessCollection") -> None: """ Forward-Backward allocation table for ProcessCollections. @@ -322,7 +322,7 @@ class _ForwardBackwardTable: s = {proc for e in self.table for proc in e.outputs} return len(self._collection - s) == 0 - def _do_forward_allocation(self): + def _do_forward_allocation(self) -> None: """ Forward all Processes as far as possible in the register chain. @@ -355,7 +355,7 @@ class _ForwardBackwardTable: else: self.table[(time + 1) % rows].regs[reg_idx + 1] = reg - def _do_single_backward_allocation(self): + def _do_single_backward_allocation(self) -> None: """ Perform backward allocation of Processes in the allocation table. """ @@ -399,16 +399,16 @@ class _ForwardBackwardTable: "Can't backward allocate any variable. This should not happen." ) - def __getitem__(self, key): + def __getitem__(self, key) -> _ForwardBackwardEntry: return self.table[key] - def __iter__(self): + def __iter__(self) -> Iterator[_ForwardBackwardEntry]: yield from self.table - def __len__(self): + def __len__(self) -> int: return len(self.table) - def __str__(self): + def __str__(self) -> str: # ANSI escape codes for coloring in the forward-backward table string GREEN_BACKGROUND_ANSI = "\u001b[42m" BROWN_BACKGROUND_ANSI = "\u001b[43m" @@ -509,7 +509,7 @@ class ProcessCollection: collection: Iterable[Process], schedule_time: int, cyclic: bool = False, - ): + ) -> None: self._collection = list(collection) self._schedule_time = schedule_time self._cyclic = cyclic @@ -522,10 +522,10 @@ class ProcessCollection: def schedule_time(self) -> int: return self._schedule_time - def __len__(self): + def __len__(self) -> int: return len(self.collection) - def add_process(self, process: Process): + def add_process(self, process: Process) -> None: """ Add a :class:`~b_asic.process.Process`. @@ -538,7 +538,7 @@ class ProcessCollection: raise ValueError("Process already in ProcessCollection") self.collection.append(process) - def remove_process(self, process: Process): + def remove_process(self, process: Process) -> None: """ Remove a :class:`~b_asic.process.Process`. @@ -580,7 +580,7 @@ class ProcessCollection: show_markers: bool = True, row: int | None = None, allow_excessive_lifetimes: bool = False, - ): + ) -> Axes: """ Plot lifetime diagram. @@ -1887,13 +1887,13 @@ class ProcessCollection: # SVG is valid HTML. This is useful for e.g. sphinx-gallery _repr_html_ = _repr_svg_ - def __repr__(self): + def __repr__(self) -> str: return ( f"ProcessCollection({self._collection}, {self._schedule_time}," f" {self._cyclic})" ) - def __iter__(self): + def __iter__(self) -> Iterator[Process]: return iter(self._collection) def _ilp_graph_color_assignment( @@ -2098,7 +2098,7 @@ class ProcessCollection: input_sync: bool = True, adr_mux_size: int | None = None, adr_pipe_depth: int | None = None, - ): + ) -> None: """ Generate VHDL code for memory-based storage of processes (MemoryVariables). @@ -2279,7 +2279,7 @@ class ProcessCollection: read_ports: int = 1, write_ports: int = 1, total_ports: int = 2, - ): + ) -> None: """ Generate VHDL code for register-based storage of processes (MemoryVariables). @@ -2447,7 +2447,7 @@ class ProcessCollection: return dict(sorted(Counter(accesses).items())) - def show_port_accesses(self, title: str = ""): + def show_port_accesses(self, title: str = "") -> None: """ Show read, write, and total accesses. @@ -2462,7 +2462,7 @@ class ProcessCollection: fig.suptitle(title) fig.show() # type: ignore - def plot_port_accesses(self, axes): + def plot_port_accesses(self, axes) -> None: """ Plot read, write, and total accesses. @@ -2484,7 +2484,7 @@ class ProcessCollection: ax.yaxis.set_major_locator(MaxNLocator(integer=True, min_n_ticks=1)) ax.set_xlim(-0.5, self.schedule_time - 0.5) - def from_name(self, name: str): + def from_name(self, name: str) -> Process: """ Get a :class:`~b_asic.process.Process` from its name. @@ -2501,8 +2501,7 @@ class ProcessCollection: name_to_proc = {p.name: p for p in self.collection} if name in name_to_proc: return name_to_proc[name] - else: - raise KeyError(f"{name} not in {self}") + raise KeyError(f"{name} not in {self}") def total_execution_times(self) -> dict[int, int]: c: Counter[int] = Counter() @@ -2515,7 +2514,7 @@ class ProcessCollection: return dict(sorted(c.items())) - def show_total_execution_times(self, title: str = ""): + def show_total_execution_times(self, title: str = "") -> None: """ Show total execution time for each time slot. @@ -2530,7 +2529,7 @@ class ProcessCollection: fig.suptitle(title) fig.show() # type: ignore - def plot_total_execution_times(self, ax): + def plot_total_execution_times(self, ax) -> None: """ Plot total execution times for each time slot. diff --git a/b_asic/schedule.py b/b_asic/schedule.py index 95b126fd07d1386505816f0cd936459ea1be3188..b591a6a8e9b7b9380af8bd538eeaf4e365d8563c 100644 --- a/b_asic/schedule.py +++ b/b_asic/schedule.py @@ -49,7 +49,7 @@ _LATENCY_COLOR: tuple[float, ...] = tuple(float(c / 255) for c in LATENCY_COLOR) _SIGNAL_COLOR: tuple[float, ...] = tuple(float(c / 255) for c in SIGNAL_COLOR) -def _laps_default(): +def _laps_default() -> int: """ Return the default value for _laps. @@ -58,7 +58,7 @@ def _laps_default(): return 0 -def _y_locations_default(): +def _y_locations_default() -> None: """ Return the default value for _y_locations. @@ -105,7 +105,7 @@ class Schedule: cyclic: bool = False, start_times: dict[GraphID, int] | None = None, laps: dict[GraphID, int] | None = None, - ): + ) -> None: """Construct a Schedule from an SFG.""" if not isinstance(sfg, SFG): raise TypeError("An SFG must be provided") @@ -824,7 +824,7 @@ class Schedule: def _get_minimum_height( self, operation_height: float = 1.0, operation_gap: float = OPERATION_GAP - ): + ) -> float: max_pos_graph_id = max(self._y_locations, key=self._y_locations.get) return self._get_y_plot_location( max_pos_graph_id, operation_height, operation_gap diff --git a/b_asic/scheduler.py b/b_asic/scheduler.py index 742d8cda912c59b3784dcadda3bff80ad7d6990e..8373480602acf9a0842f886551a5744630cc3bdd 100644 --- a/b_asic/scheduler.py +++ b/b_asic/scheduler.py @@ -58,7 +58,7 @@ class Scheduler(ABC): input_times: dict["GraphID", int] | None = None, output_delta_times: dict["GraphID", int] | None = None, sort_y_location: bool = True, - ): + ) -> None: self._op_laps = {} if input_times is not None: @@ -812,7 +812,7 @@ class ListScheduler(Scheduler): used_op_types = self._schedule._sfg.get_used_operation_types() - def find_type_from_type_name(type_name): + def find_type_from_type_name(type_name: TypeName) -> type[Operation]: for op_type in used_op_types: if op_type.type_name() == type_name: return op_type @@ -1040,7 +1040,7 @@ class RecursiveListScheduler(ListScheduler): return False return True - def _get_recursive_priority_table(self): + def _get_recursive_priority_table(self) -> list[tuple["GraphID", int]]: ready_ops = [ op_id for op_id in self._remaining_recursive_ops @@ -1274,7 +1274,7 @@ class ILPScheduler(Scheduler): def __init__( self, solver: pulp.LpSolver | None = None, sort_y_location: bool = True - ): + ) -> None: self._solver = solver self._sort_y_location = sort_y_location diff --git a/b_asic/scheduler_gui/_preferences.py b/b_asic/scheduler_gui/_preferences.py index abe72305134495b565f8a8ad3443d9721f06db77..3b854b9121d170c950f08a8b556f18a26ff3eacd 100644 --- a/b_asic/scheduler_gui/_preferences.py +++ b/b_asic/scheduler_gui/_preferences.py @@ -30,7 +30,7 @@ class ColorDataType: current_color: QColor = SIGNAL_INACTIVE, changed: bool = False, name: str = "", - ): + ) -> None: self.current_color = current_color self.DEFAULT = DEFAULT self.changed = changed @@ -69,7 +69,7 @@ class FontDataType: italic: bool = False, bold: bool = False, changed: bool = False, - ): + ) -> None: self.current_font = current_font self.DEFAULT = DEFAULT self.DEFAULT_COLOR = DEFAULT_COLOR @@ -85,7 +85,7 @@ FONT = FontDataType( ) -def read_from_settings(settings: QSettings): +def read_from_settings(settings: QSettings) -> None: FONT.current_font = QFont( settings.value("font", defaultValue=FONT.DEFAULT.toString(), type=str) ) @@ -157,7 +157,7 @@ def read_from_settings(settings: QSettings): ) -def write_to_settings(settings: QSettings): +def write_to_settings(settings: QSettings) -> None: settings.setValue("font", FONT.current_font.toString()) settings.setValue("font_size", FONT.size) settings.setValue("font_color", FONT.color) @@ -184,7 +184,7 @@ def write_to_settings(settings: QSettings): ) -def reset_color_settings(settings: QSettings): +def reset_color_settings(settings: QSettings) -> None: LATENCY_COLOR_TYPE.changed = False ACTIVE_COLOR_TYPE.changed = False SIGNAL_WARNING_COLOR_TYPE.changed = False diff --git a/b_asic/scheduler_gui/axes_item.py b/b_asic/scheduler_gui/axes_item.py index 5630aa15996013726d9228e364d867a1451b628d..d99280fd8ec98f29a45ab9bc40db07f15de18a8a 100644 --- a/b_asic/scheduler_gui/axes_item.py +++ b/b_asic/scheduler_gui/axes_item.py @@ -71,7 +71,7 @@ class AxesItem(QGraphicsItemGroup): width_padding: float = 0.6, height_padding: float = 0.5, parent: QGraphicsItem | None = None, - ): + ) -> None: """ Class for an AxesItem. diff --git a/b_asic/scheduler_gui/main_window.py b/b_asic/scheduler_gui/main_window.py index 5dae5fdaa4f558aa887b1177e371646b480b61b9..ef12541df96b3066376a9f5ed82cb1cd96e1b4ce 100644 --- a/b_asic/scheduler_gui/main_window.py +++ b/b_asic/scheduler_gui/main_window.py @@ -32,7 +32,7 @@ from qtpy.QtCore import ( Qt, Slot, ) -from qtpy.QtGui import QCloseEvent, QColor, QPalette, QTransform +from qtpy.QtGui import QCloseEvent, QColor, QPalette, QTransform, QWheelEvent from qtpy.QtWidgets import ( QAbstractButton, QAction, @@ -120,7 +120,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): _recent_files_actions: list[QAction] _recent_file_paths: deque[str] - def __init__(self): + def __init__(self) -> None: """Initialize Scheduler-GUI.""" super().__init__() self._schedule = None @@ -305,7 +305,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): else: # Cancelled self.update_statusbar("Cancelled") - def wheelEvent(self, event) -> None: + def wheelEvent(self, event: QWheelEvent) -> None: """Zoom in or out using mouse wheel if control is pressed.""" delta = event.angleDelta().y() / 2500 new_zoom = 1.0 + delta @@ -320,6 +320,8 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): elif modifiers == Qt.KeyboardModifier.ControlModifier: self.view.scale(new_zoom, new_zoom) + event.ignore() + @Slot() def _load_schedule_from_pyfile(self) -> None: """SLOT() for SIGNAL(menu_load_from_file.triggered).""" @@ -348,7 +350,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self._load_from_file(abs_path_filename) - def _load_from_file(self, abs_path_filename): + def _load_from_file(self, abs_path_filename) -> None: """ Import from Python-file. @@ -529,7 +531,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): return self._open_schedule_file(abs_path_filename) - def _open_schedule_file(self, abs_path_filename: str): + def _open_schedule_file(self, abs_path_filename: str) -> None: """Open a saved schedule (*.bsc-file), which is a pickled Schedule.""" self._file_name = abs_path_filename self._add_recent_file(abs_path_filename) @@ -564,7 +566,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): else: self.splitter.moveSplitter(max_, 1) - def _toggle_file_loaded(self, enable: bool): + def _toggle_file_loaded(self, enable: bool) -> None: self.menu_save.setEnabled(enable) self.menu_save_as.setEnabled(enable) @@ -691,7 +693,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): else: event.ignore() - def _open_about_window(self, event=None): + def _open_about_window(self, event=None) -> None: self.about_page = AboutWindow(self) self.about_page.show() @@ -908,7 +910,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): else: log.error("'Operator' not found in info table. It may have been renamed.") - def _create_recent_file_actions_and_menus(self): + def _create_recent_file_actions_and_menus(self) -> None: for _ in range(self._max_recent_files): recent_file_action = QAction(self.menu_Recent_Schedule) recent_file_action.setVisible(False) @@ -920,7 +922,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self._update_recent_file_list() - def _update_operation_types(self): + def _update_operation_types(self) -> None: self.menu_view_execution_times.setEnabled(True) for action in self.menu_view_execution_times.actions(): self.menu_view_execution_times.removeAction(action) @@ -944,12 +946,12 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self.menu_view_total_execution_times_of_type.addAction(type_action) @Slot() - def open_preferences_dialog(self): + def open_preferences_dialog(self) -> None: """Open the preferences dialog to customize fonts, colors, and settings.""" self._preferences_dialog = PreferencesDialog(self) self._preferences_dialog.show() - def load_preferences(self): + def load_preferences(self) -> None: """Load the last saved preferences from settings.""" settings = QSettings() LATENCY_COLOR_TYPE.current_color = QColor( @@ -1054,10 +1056,10 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): ) @Slot(str) - def _show_execution_times_for_type(self, type_name): + def _show_execution_times_for_type(self, type_name) -> None: self._execution_time_plot(type_name) - def _closed_execution_times_for_type(self, type_name): + def _closed_execution_times_for_type(self, type_name) -> None: self._execution_time_plot_dialogs[type_name] = None def _execution_time_plot(self, type_name: str) -> None: @@ -1070,7 +1072,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self._update_execution_times_for_type(type_name) self._execution_time_plot_dialogs[type_name].show() - def _update_execution_times_for_type(self, type_name): + def _update_execution_times_for_type(self, type_name) -> None: if self._execution_time_plot_dialogs[type_name]: self._execution_time_plot_dialogs[type_name].axes.clear() self._schedule.get_operations().get_by_type_name(type_name).plot( @@ -1079,10 +1081,10 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self._execution_time_plot_dialogs[type_name].redraw() @Slot(str) - def _show_total_execution_times_for_type(self, type_name): + def _show_total_execution_times_for_type(self, type_name) -> None: self._total_execution_time_plot(type_name) - def _closed_total_execution_times_for_type(self, type_name): + def _closed_total_execution_times_for_type(self, type_name) -> None: self._total_execution_time_plot_dialogs[type_name] = None def _total_execution_time_plot(self, type_name: str) -> None: @@ -1095,7 +1097,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self._update_total_execution_times_for_type(type_name) self._total_execution_time_plot_dialogs[type_name].show() - def _update_total_execution_times_for_type(self, type_name): + def _update_total_execution_times_for_type(self, type_name) -> None: if self._total_execution_time_plot_dialogs[type_name]: self._total_execution_time_plot_dialogs[type_name].axes.clear() self._schedule.get_operations().get_by_type_name( @@ -1105,7 +1107,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): ) self._total_execution_time_plot_dialogs[type_name].redraw() - def _show_execution_times_for_variables(self): + def _show_execution_times_for_variables(self) -> None: self._execution_time_for_variables = MPLWindow("Execution times for variables") self._execution_time_for_variables.finished.connect( self._execution_times_for_variables_closed @@ -1113,7 +1115,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self._update_execution_times_for_variables() self._execution_time_for_variables.show() - def _update_execution_times_for_variables(self): + def _update_execution_times_for_variables(self) -> None: if self._execution_time_for_variables: self._execution_time_for_variables.axes.clear() self._schedule.get_memory_variables().plot( @@ -1122,10 +1124,10 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self._execution_time_for_variables.redraw() @Slot() - def _execution_times_for_variables_closed(self): + def _execution_times_for_variables_closed(self) -> None: self._execution_time_for_variables = None - def _show_total_execution_times_for_variables(self): + def _show_total_execution_times_for_variables(self) -> None: self._total_execution_time_for_variables = MPLWindow( "Total execution times for variables" ) @@ -1135,7 +1137,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self._update_total_execution_times_for_variables() self._total_execution_time_for_variables.show() - def _update_total_execution_times_for_variables(self): + def _update_total_execution_times_for_variables(self) -> None: if self._total_execution_time_for_variables: self._total_execution_time_for_variables.axes.clear() self._schedule.get_memory_variables().plot_total_execution_times( @@ -1144,10 +1146,10 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self._total_execution_time_for_variables.redraw() @Slot() - def _total_execution_times_for_variables_closed(self): + def _total_execution_times_for_variables_closed(self) -> None: self._total_execution_time_for_variables = None - def _show_ports_accesses_for_storage(self): + def _show_ports_accesses_for_storage(self) -> None: self._ports_accesses_for_storage = MPLWindow( "Port accesses for storage", subplots=(3, 1) ) @@ -1172,7 +1174,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): @Slot() @Slot(str) - def _schedule_changed(self, type_name: str | None = None): + def _schedule_changed(self, type_name: str | None = None) -> None: self._update_execution_times_for_variables() self._update_ports_accesses_for_storage() for key, dialog in self._execution_time_plot_dialogs.items(): @@ -1183,7 +1185,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): if dialog: self._update_total_execution_times_for_type(key) - def _update_recent_file_list(self): + def _update_recent_file_list(self) -> None: settings = QSettings() rfp = cast(deque, settings.value("scheduler/recentFiles")) if rfp: @@ -1198,13 +1200,13 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): for i in range(dequelen, self._max_recent_files): self._recent_files_actions[i].setVisible(False) - def _open_recent_file(self, action): + def _open_recent_file(self, action) -> None: if action.data().filePath().endswith(".bsc"): self._open_schedule_file(action.data().filePath()) else: self._load_from_file(action.data().filePath()) - def _add_recent_file(self, filename): + def _add_recent_file(self, filename) -> None: settings = QSettings() rfp = cast(deque, settings.value("scheduler/recentFiles")) if rfp: @@ -1217,17 +1219,17 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self._update_recent_file_list() - def _zoom_to_fit(self, event=None): + def _zoom_to_fit(self, event=None) -> None: """Zoom to fit schedule in window keeping aspect ratio.""" self.view.fitInView(self._scene.sceneRect(), Qt.AspectRatioMode.KeepAspectRatio) - def _zoom_to_fit_no_aspect(self, event=None): + def _zoom_to_fit_no_aspect(self, event=None) -> None: """Zoom to fit schedule in window ignoring aspect ratio.""" self.view.fitInView( self._scene.sceneRect(), Qt.AspectRatioMode.IgnoreAspectRatio ) - def _reset_aspect_ratio(self, event=None): + def _reset_aspect_ratio(self, event=None) -> None: """Reset the aspect ratio.""" self.view.setTransform(QTransform()) self.view.scale(self._scale, self._scale) @@ -1248,7 +1250,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self._show_port_numbers = self.action_show_port_numbers.isChecked() self._graph.set_port_numbers(self._show_port_numbers) - def _toggle_fullscreen(self, event=None): + def _toggle_fullscreen(self, event=None) -> None: """Toggle full screen mode.""" if self.isFullScreen(): self.showNormal() diff --git a/b_asic/scheduler_gui/operation_item.py b/b_asic/scheduler_gui/operation_item.py index 04f1ccbe51a0b8751ef12cdce62c5ad2db09e920..02f8de0772413a9d99ce3f28d50d4396ff3a6729 100644 --- a/b_asic/scheduler_gui/operation_item.py +++ b/b_asic/scheduler_gui/operation_item.py @@ -72,7 +72,7 @@ class OperationItem(QGraphicsItemGroup): operation: Operation, parent: "SchedulerItem", height: float = OPERATION_HEIGHT, - ): + ) -> None: """ Construct a OperationItem. @@ -229,12 +229,12 @@ class OperationItem(QGraphicsItemGroup): self._label_item.prepareGeometryChange() self._label_item.setBrush(color) - def set_show_port_numbers(self, port_number: bool = True): + def set_show_port_numbers(self, port_number: bool = True) -> None: """Set if port numbers are shown.""" for item in self._port_number_items: item.setVisible(port_number) - def set_port_active(self, key: str): + def set_port_active(self, key: str) -> None: """Set the port as active, i.e., draw it in special colors.""" item = cast(QPointF, self._ports[key]["item"]) if ACTIVE_COLOR_TYPE.changed: @@ -248,7 +248,7 @@ class OperationItem(QGraphicsItemGroup): item.setBrush(self._port_filling_brush_active) item.setPen(self._port_outline_pen_active) - def set_port_inactive(self, key: str, warning: bool = False): + def set_port_inactive(self, key: str, warning: bool = False) -> None: """Set the port as inactive, i.e., draw it in standard colors.""" item = cast(QPointF, self._ports[key]["item"]) item.setBrush( @@ -352,7 +352,7 @@ class OperationItem(QGraphicsItemGroup): self.set_inactive() - def _open_context_menu(self): + def _open_context_menu(self) -> None: """Create and open context menu.""" menu = QMenu() swap = QAction(get_icon("swap"), "Swap") @@ -390,8 +390,8 @@ class OperationItem(QGraphicsItemGroup): def _total_execution_time_plot(self, event=None) -> None: self._parent._total_execution_time_plot(self._operation.type_name()) - def _move_asap(self, event=None): + def _move_asap(self, event=None) -> None: self._parent.schedule.move_operation_asap(self._operation.graph_id) - def _move_alap(self, event=None): + def _move_alap(self, event=None) -> None: self._parent.schedule.move_operation_alap(self._operation.graph_id) diff --git a/b_asic/scheduler_gui/preferences_dialog.py b/b_asic/scheduler_gui/preferences_dialog.py index 441e9f27d3834f9ccd0fe366112ba34958274eff..abcc35acf19a2602baa01bd71d0b886d9a94d5ed 100644 --- a/b_asic/scheduler_gui/preferences_dialog.py +++ b/b_asic/scheduler_gui/preferences_dialog.py @@ -38,7 +38,7 @@ from b_asic.scheduler_gui._preferences import ( class PreferencesDialog(QWidget): - def __init__(self, parent): + def __init__(self, parent) -> None: super().__init__() self._parent = parent self.setWindowTitle("Preferences") @@ -212,7 +212,7 @@ class PreferencesDialog(QWidget): else: self._font_size_input.setText(str(FONT.size)) - def set_font_size_clicked(self): + def set_font_size_clicked(self) -> None: """ Set the font size to the specified size and update the font. """ @@ -244,7 +244,7 @@ class PreferencesDialog(QWidget): button.pressed.connect(lambda: self.color_button_clicked(color)) return button - def italic_font_clicked(self): + def italic_font_clicked(self) -> None: """ Toggle the font style to italic if not already italic, otherwise remove italic. """ @@ -256,7 +256,7 @@ class PreferencesDialog(QWidget): self._italic_button.set_color(QColor("snow")) self.update_font() - def bold_font_clicked(self): + def bold_font_clicked(self) -> None: """ Toggle the font style to bold if not already bold, otherwise unbold. """ @@ -355,7 +355,7 @@ class PreferencesDialog(QWidget): self.match_dialog_font() self._parent.update_statusbar("Preferences Updated") - def reset_font_clicked(self): + def reset_font_clicked(self) -> None: """ Reset the font settings. """ @@ -385,7 +385,7 @@ class PreferencesDialog(QWidget): else: self._boldbutton.set_color(QColor("snow")) - def update_font(self): + def update_font(self) -> None: """Update font preferences based on current Font settings.""" settings = QSettings() FONT.changed = not ( @@ -401,7 +401,7 @@ class PreferencesDialog(QWidget): settings.sync() self._parent.load_preferences() - def font_color_clicked(self): + def font_color_clicked(self) -> None: """Select a font color and update preferences.""" settings = QSettings() color = QColorDialog.getColor(FONT.color, self, "Select font color") @@ -412,7 +412,7 @@ class PreferencesDialog(QWidget): settings.sync() self._parent._graph._font_color_change(FONT.color) - def reset_color_clicked(self): + def reset_color_clicked(self) -> None: """Reset the color settings.""" settings = QSettings() reset_color_settings(settings) @@ -423,7 +423,7 @@ class PreferencesDialog(QWidget): self._parent._graph._signals.reopen.emit() self._parent.load_preferences() - def reset_all_clicked(self): + def reset_all_clicked(self) -> None: """Reset both the color and the font settings.""" self.reset_color_clicked() self.reset_font_clicked() diff --git a/b_asic/scheduler_gui/scheduler_event.py b/b_asic/scheduler_gui/scheduler_event.py index e75ad85bccd91f7bb7c9571d0a58bd890a7fa425..230b94edb9b55c7fa160b51f3e557545cbeaa6e0 100644 --- a/b_asic/scheduler_gui/scheduler_event.py +++ b/b_asic/scheduler_gui/scheduler_event.py @@ -49,7 +49,7 @@ class SchedulerEvent: _schedule: Schedule _old_op_position: int = -1 - def __init__(self, parent: QGraphicsItem | None = None): + def __init__(self, parent: QGraphicsItem | None = None) -> None: super().__init__(parent=parent) self._signals = self.Signals() @@ -150,7 +150,7 @@ class SchedulerEvent: coordinate system of the parent object. """ - def update_pos(operation_item, dx, dy): + def update_pos(operation_item, dx, dy) -> None: pos_x = operation_item.x() + dx if self.is_component_valid_pos(operation_item, pos_x): pos_y = operation_item.y() + dy * (OPERATION_GAP + OPERATION_HEIGHT) @@ -252,7 +252,7 @@ class SchedulerEvent: horizontally in x-axis scale steps. """ - def update_pos(timeline_item, dx): + def update_pos(timeline_item, dx) -> None: pos = timeline_item.x() + dx if self.is_valid_delta_time(self._delta_time + dx): timeline_item.setX(pos) diff --git a/b_asic/scheduler_gui/scheduler_item.py b/b_asic/scheduler_gui/scheduler_item.py index cd370f31b425960d6926cc5aeab93a3803a5c5b0..543ed8d8b8604b7f55505012fd82c6151f376150 100644 --- a/b_asic/scheduler_gui/scheduler_item.py +++ b/b_asic/scheduler_gui/scheduler_item.py @@ -71,7 +71,7 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): warnings: bool = True, show_port_numbers: bool = False, parent: QGraphicsItem | None = None, - ): + ) -> None: """ Construct a SchedulerItem. @@ -168,13 +168,13 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): for signal in self._signal_dict[item]: signal.update_path() - def _get_all_signals(self): + def _get_all_signals(self) -> set[SignalItem]: s = set() for signals in self._signal_dict.values(): s.update(signals) return s - def set_warnings(self, warnings: bool = True): + def set_warnings(self, warnings: bool = True) -> None: """ Set warnings for long execution times. @@ -189,7 +189,7 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): for signal in self._get_all_signals(): signal.set_inactive() - def set_port_numbers(self, port_numbers: bool = True): + def set_port_numbers(self, port_numbers: bool = True) -> None: """ Set if port numbers are shown. @@ -329,10 +329,10 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): self._redraw_all_lines() self._update_axes() - def _execution_time_plot(self, type_name: str): + def _execution_time_plot(self, type_name: str) -> None: self._signals.execution_time_plot.emit(type_name) - def _total_execution_time_plot(self, type_name: str): + def _total_execution_time_plot(self, type_name: str) -> None: self._signals.total_execution_time_plot.emit(type_name) def _redraw_all(self) -> None: diff --git a/b_asic/scheduler_gui/signal_item.py b/b_asic/scheduler_gui/signal_item.py index 0b8edbdf607735111b7c289e936128b86213995c..98c674cfa22bfb71609b3d54263f89dae7446926 100644 --- a/b_asic/scheduler_gui/signal_item.py +++ b/b_asic/scheduler_gui/signal_item.py @@ -56,7 +56,7 @@ class SignalItem(QGraphicsPathItem): dest_operation: OperationItem, signal: Signal, parent: "SchedulerItem", - ): + ) -> None: super().__init__(parent=parent) self._src_operation = src_operation self._dest_operation = dest_operation diff --git a/b_asic/scheduler_gui/ui_main_window.py b/b_asic/scheduler_gui/ui_main_window.py index cf0af8d455f4118958768ffe36160305909b57d7..0622cd10b8f3657abe5585567ddd7c8689c0b555 100644 --- a/b_asic/scheduler_gui/ui_main_window.py +++ b/b_asic/scheduler_gui/ui_main_window.py @@ -25,7 +25,7 @@ from qtpy.QtWidgets import ( class Ui_MainWindow: - def setupUi(self, MainWindow): + def setupUi(self, MainWindow) -> None: if not MainWindow.objectName(): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 600) @@ -389,7 +389,7 @@ class Ui_MainWindow: # setupUi - def retranslateUi(self, MainWindow): + def retranslateUi(self, MainWindow) -> None: self.menu_load_from_file.setText( QCoreApplication.translate( "MainWindow", "&Import schedule from file...", None diff --git a/b_asic/signal.py b/b_asic/signal.py index 76f909e7c6f3d9f2b9e1ceec31488e64df5ab0aa..17a9d6f4eabcfb4a05c98c883932ff7bade6de38 100644 --- a/b_asic/signal.py +++ b/b_asic/signal.py @@ -48,7 +48,7 @@ class Signal(AbstractGraphComponent): destination: Union["InputPort", "Signal", "Operation"] | None = None, bits: int | None = None, name: Name = Name(""), - ): + ) -> None: """Construct a Signal.""" super().__init__(Name(name)) self._source = None diff --git a/b_asic/signal_flow_graph.py b/b_asic/signal_flow_graph.py index fd90cf4b3425faa1de357c01cca5aac6db13244a..431664e0dc55967b56a84a4b4225b63875154587 100644 --- a/b_asic/signal_flow_graph.py +++ b/b_asic/signal_flow_graph.py @@ -51,7 +51,7 @@ class GraphIDGenerator: _next_id_number: defaultdict[TypeName, GraphIDNumber] - def __init__(self, id_number_offset: GraphIDNumber = GraphIDNumber(0)): + def __init__(self, id_number_offset: GraphIDNumber = GraphIDNumber(0)) -> None: """Construct a GraphIDGenerator.""" self._next_id_number = defaultdict(lambda: id_number_offset) @@ -127,7 +127,7 @@ class SFG(AbstractOperation): id_number_offset: GraphIDNumber = GraphIDNumber(0), name: Name = Name(""), input_sources: Sequence[SignalSourceProvider | None] | None = None, - ): + ) -> None: input_signal_count = 0 if input_signals is None else len(input_signals) input_operation_count = 0 if inputs is None else len(inputs) output_signal_count = 0 if output_signals is None else len(output_signals) @@ -332,7 +332,7 @@ class SFG(AbstractOperation): # doc-string inherited. return TypeName("sfg") - def evaluate(self, *args): + def evaluate(self, *args) -> Num | list[Num] | None: result = self.evaluate_outputs(args) n = len(result) return None if n == 0 else result[0] if n == 1 else result @@ -854,19 +854,19 @@ class SFG(AbstractOperation): def _insert_operation_after_operation( self, output_operation: Operation, new_operation: Operation - ): + ) -> None: for output in output_operation.outputs: self._insert_operation_after_outputport(output, new_operation.copy()) def _insert_operation_before_operation( self, input_operation: Operation, new_operation: Operation - ): + ) -> None: for port in input_operation.inputs: self._insert_operation_before_inputport(port, new_operation.copy()) def _insert_operation_after_outputport( self, output_port: OutputPort, new_operation: Operation - ): + ) -> None: # Make copy as list will be updated signal_list = output_port.signals[:] for signal in signal_list: @@ -875,18 +875,22 @@ class SFG(AbstractOperation): def _insert_operation_before_inputport( self, input_port: InputPort, new_operation: Operation - ): + ) -> None: # Make copy as list will be updated input_port.signals[0].set_destination(new_operation) new_operation.output(0).add_signal(Signal(destination=input_port)) - def _insert_operation_before_signal(self, signal: Signal, new_operation: Operation): + def _insert_operation_before_signal( + self, signal: Signal, new_operation: Operation + ) -> None: output_port = signal.source output_port.remove_signal(signal) Signal(output_port, new_operation) signal.set_source(new_operation) - def _insert_operation_after_signal(self, signal: Signal, new_operation: Operation): + def _insert_operation_after_signal( + self, signal: Signal, new_operation: Operation + ) -> None: input_port = signal.destination input_port.remove_signal(signal) Signal(new_operation, input_port) diff --git a/b_asic/simulation.py b/b_asic/simulation.py index 62a2799ad207336aa33ce269829da310db06af4d..31d488789524408b7f2e286f61f1ed96a12cd268 100644 --- a/b_asic/simulation.py +++ b/b_asic/simulation.py @@ -48,7 +48,7 @@ class Simulation: self, sfg: SFG, input_providers: Sequence[InputProvider | None] | None = None, - ): + ) -> None: """Construct a Simulation of an SFG.""" if not isinstance(sfg, SFG): raise TypeError("An SFG must be provided") diff --git a/b_asic/special_operations.py b/b_asic/special_operations.py index 7da24a76b15aaaaa91b0acb49f7d5a327387309d..29b1a38c818cc33e868d7af38c2ead2741a74942 100644 --- a/b_asic/special_operations.py +++ b/b_asic/special_operations.py @@ -33,7 +33,7 @@ class Input(AbstractOperation): is_linear = True is_constant = False - def __init__(self, name: Name = ""): + def __init__(self, name: Name = "") -> None: """Construct an Input operation.""" super().__init__( input_count=0, @@ -48,7 +48,7 @@ class Input(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("in") - def evaluate(self): + def evaluate(self) -> Num: return self.param("value") @property @@ -119,7 +119,7 @@ class Output(AbstractOperation): self, src0: SignalSourceProvider | None = None, name: Name = Name(""), - ): + ) -> None: """Construct an Output operation.""" super().__init__( input_count=1, @@ -134,7 +134,7 @@ class Output(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("out") - def evaluate(self, _): + def evaluate(self, _) -> None: return None def get_plot_coordinates( @@ -183,7 +183,7 @@ class Delay(AbstractOperation): src0: SignalSourceProvider | None = None, initial_value: Num = 0, name: Name = Name(""), - ): + ) -> None: """Construct a Delay operation.""" super().__init__( input_count=1, @@ -198,7 +198,7 @@ class Delay(AbstractOperation): def type_name(cls) -> TypeName: return TypeName("t") - def evaluate(self, a): + def evaluate(self, a) -> Num: return self.param("initial_value") def current_output( diff --git a/pyproject.toml b/pyproject.toml index 78f0680b771e2f192fe4d89a8005d95bacecef10..6e21aa834169d6d87f5c72227afdbfa52ebc47c8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -98,7 +98,7 @@ ignore_missing_imports = true precision = 2 [tool.ruff] -exclude = ["examples", "docs_sphinx"] +exclude = ["examples", "docs_sphinx", "b_asic/scheduler_gui/ui_main_window.py"] [tool.ruff.lint] select = [ @@ -148,7 +148,7 @@ ignore = [ ] [tool.ruff.lint.per-file-ignores] -"test/*" = ["D1", "D401", "PERF401"] +"test/*" = ["D1", "D401", "PERF401", "ANN"] "b_asic/scheduler_gui/ui_main_window.py" = ["D100"] [tool.codespell]