Skip to content

Commit

Permalink
Add a _DummyNetwork class to designate "uninitialized" networks.
Browse files Browse the repository at this point in the history
This class can replace the dummy "None" value for attribute
initializations, which can then be properly typed as Network to avoid
static type checking errors.

Switch to that new initialization in the NmtBase class as an example.

This has the benefit of not needing `self.network is not None` checks
at run-time wherever a method or attribute access is used, but still
satisfies static type checking.  When hitting such a code path at
run-time, of course it will lead to an exception because the
attributes required in the Network methods are not set.  But that is a
case of wrong API usage (accessing a network without associating it
first), which a static checker cannot detect reliably.  The dummy
class could be modified to provide a better exception message if
desired, but this is just a minimal proof of concept so far.
  • Loading branch information
acolomb committed Aug 7, 2024
1 parent d1c28e5 commit 2645ee3
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 2 deletions.
7 changes: 7 additions & 0 deletions canopen/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,13 @@ def __len__(self) -> int:
return len(self.nodes)


class _DummyNetwork(Network):
"""Empty network implementation as a placeholder before actual initialization."""

def __init__(self, bus: Optional[can.BusABC] = None):
"""Do not initialize attributes, by skipping the parent constructor."""


class PeriodicMessageTask:
"""
Task object to transmit a message periodically using python-can's
Expand Down
10 changes: 8 additions & 2 deletions canopen/nmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@
import logging
import struct
import time
from typing import Callable, Optional
from typing import Callable, Optional, TYPE_CHECKING

from canopen.network import _DummyNetwork

if TYPE_CHECKING:
from canopen.network import Network


logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -45,7 +51,7 @@ class NmtBase:

def __init__(self, node_id: int):
self.id = node_id
self.network = None
self.network: Network = _DummyNetwork()
self._state = 0

def on_command(self, can_id, data, timestamp):
Expand Down

0 comments on commit 2645ee3

Please sign in to comment.