added type hinting to core.emane functions

This commit is contained in:
Blake Harnden 2020-01-14 16:27:08 -08:00
parent 49f09a25cc
commit fa095431fb
9 changed files with 147 additions and 108 deletions

View file

@ -1,6 +1,8 @@
"""
EMANE Bypass model for CORE
"""
from typing import List
from core.config import ConfigGroup, Configuration
from core.emane import emanemodel
from core.emulator.enumerations import ConfigDataTypes
@ -29,11 +31,11 @@ class EmaneBypassModel(emanemodel.EmaneModel):
phy_config = []
@classmethod
def load(cls, emane_prefix):
def load(cls, emane_prefix: str) -> None:
# ignore default logic
pass
# override config groups
@classmethod
def config_groups(cls):
def config_groups(cls) -> List[ConfigGroup]:
return [ConfigGroup("Bypass Parameters", 1, 1)]

View file

@ -4,11 +4,13 @@ commeffect.py: EMANE CommEffect model for CORE
import logging
import os
from typing import Dict, List
from lxml import etree
from core.config import ConfigGroup
from core.config import ConfigGroup, Configuration
from core.emane import emanemanifest, emanemodel
from core.nodes.interface import CoreInterface
from core.xml import emanexml
try:
@ -20,7 +22,7 @@ except ImportError:
logging.debug("compatible emane python bindings not installed")
def convert_none(x):
def convert_none(x: float) -> int:
"""
Helper to use 0 for None values.
"""
@ -45,19 +47,21 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
external_config = []
@classmethod
def load(cls, emane_prefix):
def load(cls, emane_prefix: str) -> None:
shim_xml_path = os.path.join(emane_prefix, "share/emane/manifest", cls.shim_xml)
cls.config_shim = emanemanifest.parse(shim_xml_path, cls.shim_defaults)
@classmethod
def configurations(cls):
def configurations(cls) -> List[Configuration]:
return cls.config_shim
@classmethod
def config_groups(cls):
def config_groups(cls) -> List[ConfigGroup]:
return [ConfigGroup("CommEffect SHIM Parameters", 1, len(cls.configurations()))]
def build_xml_files(self, config, interface=None):
def build_xml_files(
self, config: Dict[str, str], interface: CoreInterface = None
) -> None:
"""
Build the necessary nem and commeffect XMLs in the given path.
If an individual NEM has a nonstandard config, we need to build
@ -109,14 +113,14 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
def linkconfig(
self,
netif,
bw=None,
delay=None,
loss=None,
duplicate=None,
jitter=None,
netif2=None,
):
netif: CoreInterface,
bw: float = None,
delay: float = None,
loss: float = None,
duplicate: float = None,
jitter: float = None,
netif2: CoreInterface = None,
) -> None:
"""
Generate CommEffect events when a Link Message is received having
link parameters.

View file

@ -6,6 +6,7 @@ import logging
import os
import threading
from collections import OrderedDict
from typing import TYPE_CHECKING, Dict, List, Set, Tuple, Type
from core import utils
from core.config import ConfigGroup, Configuration, ModelManager
@ -19,8 +20,15 @@ from core.emane.rfpipe import EmaneRfPipeModel
from core.emane.tdma import EmaneTdmaModel
from core.emulator.enumerations import ConfigDataTypes, RegisterTlvs
from core.errors import CoreCommandError, CoreError
from core.nodes.base import CoreNode
from core.nodes.interface import CoreInterface
from core.nodes.network import CtrlNet
from core.xml import emanexml
if TYPE_CHECKING:
from core.emulator.session import Session
try:
from emane.events import EventService
from emane.events import LocationEvent
@ -57,7 +65,7 @@ class EmaneManager(ModelManager):
EVENTCFGVAR = "LIBEMANEEVENTSERVICECONFIG"
DEFAULT_LOG_LEVEL = 3
def __init__(self, session):
def __init__(self, session: "Session") -> None:
"""
Creates a Emane instance.
@ -86,7 +94,9 @@ class EmaneManager(ModelManager):
self.event_device = None
self.emane_check()
def getifcconfig(self, node_id, interface, model_name):
def getifcconfig(
self, node_id: int, interface: CoreInterface, model_name: str
) -> Dict[str, str]:
"""
Retrieve interface configuration or node configuration if not provided.
@ -129,11 +139,11 @@ class EmaneManager(ModelManager):
return config
def config_reset(self, node_id=None):
def config_reset(self, node_id: int = None) -> None:
super().config_reset(node_id)
self.set_configs(self.emane_config.default_values())
def emane_check(self):
def emane_check(self) -> None:
"""
Check if emane is installed and load models.
@ -157,7 +167,7 @@ class EmaneManager(ModelManager):
except CoreCommandError:
logging.info("emane is not installed")
def deleteeventservice(self):
def deleteeventservice(self) -> None:
if self.service:
for fd in self.service._readFd, self.service._writeFd:
if fd >= 0:
@ -168,7 +178,7 @@ class EmaneManager(ModelManager):
self.service = None
self.event_device = None
def initeventservice(self, filename=None, shutdown=False):
def initeventservice(self, filename: str = None, shutdown: bool = False) -> None:
"""
Re-initialize the EMANE Event service.
The multicast group and/or port may be configured.
@ -186,7 +196,7 @@ class EmaneManager(ModelManager):
logging.error(
"invalid emane event service device provided: %s", self.event_device
)
return False
return
# make sure the event control network is in place
eventnet = self.session.add_remove_control_net(
@ -205,9 +215,7 @@ class EmaneManager(ModelManager):
except EventServiceException:
logging.exception("error instantiating emane EventService")
return True
def load_models(self, emane_models):
def load_models(self, emane_models: List[Type[EmaneModel]]) -> None:
"""
Load EMANE models and make them available.
"""
@ -219,7 +227,7 @@ class EmaneManager(ModelManager):
emane_model.load(emane_prefix)
self.models[emane_model.name] = emane_model
def add_node(self, emane_net):
def add_node(self, emane_net: EmaneNet) -> None:
"""
Add EMANE network object to this manager.
@ -233,7 +241,7 @@ class EmaneManager(ModelManager):
)
self._emane_nets[emane_net.id] = emane_net
def getnodes(self):
def getnodes(self) -> Set[CoreNode]:
"""
Return a set of CoreNodes that are linked to an EMANE network,
e.g. containers having one or more radio interfaces.
@ -245,7 +253,7 @@ class EmaneManager(ModelManager):
nodes.add(netif.node)
return nodes
def setup(self):
def setup(self) -> int:
"""
Setup duties for EMANE manager.
@ -303,7 +311,7 @@ class EmaneManager(ModelManager):
self.check_node_models()
return EmaneManager.SUCCESS
def startup(self):
def startup(self) -> int:
"""
After all the EMANE networks have been added, build XML files
and start the daemons.
@ -347,7 +355,7 @@ class EmaneManager(ModelManager):
return EmaneManager.SUCCESS
def poststartup(self):
def poststartup(self) -> None:
"""
Retransmit location events now that all NEMs are active.
"""
@ -367,7 +375,7 @@ class EmaneManager(ModelManager):
x, y, z = netif.node.position.get()
emane_node.setnemposition(netif, x, y, z)
def reset(self):
def reset(self) -> None:
"""
Remove all EMANE networks from the dictionary, reset port numbers and
nem id counters
@ -382,7 +390,7 @@ class EmaneManager(ModelManager):
"emane_transform_port", 8200
)
def shutdown(self):
def shutdown(self) -> None:
"""
stop all EMANE daemons
"""
@ -394,7 +402,7 @@ class EmaneManager(ModelManager):
self.stopdaemons()
self.stopeventmonitor()
def buildxml(self):
def buildxml(self) -> None:
"""
Build XML files required to run EMANE on each node.
NEMs run inside containers using the control network for passing
@ -410,7 +418,7 @@ class EmaneManager(ModelManager):
self.buildnemxml()
self.buildeventservicexml()
def check_node_models(self):
def check_node_models(self) -> None:
"""
Associate EMANE model classes with EMANE network nodes.
"""
@ -438,7 +446,7 @@ class EmaneManager(ModelManager):
model_class = self.models[model_name]
emane_node.setmodel(model_class, config)
def nemlookup(self, nemid):
def nemlookup(self, nemid) -> Tuple[EmaneNet, CoreInterface]:
"""
Look for the given numerical NEM ID and return the first matching
EMANE network and NEM interface.
@ -456,7 +464,7 @@ class EmaneManager(ModelManager):
return emane_node, netif
def numnems(self):
def numnems(self) -> int:
"""
Return the number of NEMs emulated locally.
"""
@ -466,7 +474,7 @@ class EmaneManager(ModelManager):
count += len(emane_node.netifs())
return count
def buildplatformxml(self, ctrlnet):
def buildplatformxml(self, ctrlnet: CtrlNet) -> None:
"""
Build a platform.xml file now that all nodes are configured.
"""
@ -480,7 +488,7 @@ class EmaneManager(ModelManager):
self, ctrlnet, emane_node, nemid, platform_xmls
)
def buildnemxml(self):
def buildnemxml(self) -> None:
"""
Builds the nem, mac, and phy xml files for each EMANE network.
"""
@ -488,7 +496,7 @@ class EmaneManager(ModelManager):
emane_net = self._emane_nets[key]
emanexml.build_xml_files(self, emane_net)
def buildeventservicexml(self):
def buildeventservicexml(self) -> None:
"""
Build the libemaneeventservice.xml file if event service options
were changed in the global config.
@ -520,7 +528,7 @@ class EmaneManager(ModelManager):
)
)
def startdaemons(self):
def startdaemons(self) -> None:
"""
Start one EMANE daemon per node having a radio.
Add a control network even if the user has not configured one.
@ -596,7 +604,7 @@ class EmaneManager(ModelManager):
self.session.distributed.execute(lambda x: x.remote_cmd(emanecmd, cwd=path))
logging.info("host emane daemon running: %s", emanecmd)
def stopdaemons(self):
def stopdaemons(self) -> None:
"""
Kill the appropriate EMANE daemons.
"""
@ -623,7 +631,7 @@ class EmaneManager(ModelManager):
except CoreCommandError:
logging.exception("error shutting down emane daemons")
def installnetifs(self):
def installnetifs(self) -> None:
"""
Install TUN/TAP virtual interfaces into their proper namespaces
now that the EMANE daemons are running.
@ -633,7 +641,7 @@ class EmaneManager(ModelManager):
logging.info("emane install netifs for node: %d", key)
emane_node.installnetifs()
def deinstallnetifs(self):
def deinstallnetifs(self) -> None:
"""
Uninstall TUN/TAP virtual interfaces.
"""
@ -641,7 +649,7 @@ class EmaneManager(ModelManager):
emane_node = self._emane_nets[key]
emane_node.deinstallnetifs()
def doeventmonitor(self):
def doeventmonitor(self) -> bool:
"""
Returns boolean whether or not EMANE events will be monitored.
"""
@ -649,7 +657,7 @@ class EmaneManager(ModelManager):
# generate the EMANE events when nodes are moved
return self.session.options.get_config_bool("emane_event_monitor")
def genlocationevents(self):
def genlocationevents(self) -> bool:
"""
Returns boolean whether or not EMANE events will be generated.
"""
@ -660,7 +668,7 @@ class EmaneManager(ModelManager):
tmp = not self.doeventmonitor()
return tmp
def starteventmonitor(self):
def starteventmonitor(self) -> None:
"""
Start monitoring EMANE location events if configured to do so.
"""
@ -681,7 +689,7 @@ class EmaneManager(ModelManager):
self.eventmonthread.daemon = True
self.eventmonthread.start()
def stopeventmonitor(self):
def stopeventmonitor(self) -> None:
"""
Stop monitoring EMANE location events.
"""
@ -697,7 +705,7 @@ class EmaneManager(ModelManager):
self.eventmonthread.join()
self.eventmonthread = None
def eventmonitorloop(self):
def eventmonitorloop(self) -> None:
"""
Thread target that monitors EMANE location events.
"""
@ -724,7 +732,7 @@ class EmaneManager(ModelManager):
threading.currentThread().getName(),
)
def handlelocationevent(self, rxnemid, eid, data):
def handlelocationevent(self, rxnemid: int, eid: int, data: str) -> None:
"""
Handle an EMANE location event.
"""
@ -747,7 +755,9 @@ class EmaneManager(ModelManager):
logging.debug("emane location event: %s,%s,%s", lat, lon, alt)
self.handlelocationeventtoxyz(txnemid, lat, lon, alt)
def handlelocationeventtoxyz(self, nemid, lat, lon, alt):
def handlelocationeventtoxyz(
self, nemid: int, lat: float, lon: float, alt: float
) -> bool:
"""
Convert the (NEM ID, lat, long, alt) from a received location event
into a node and x,y,z coordinate values, sending a Node Message.
@ -800,11 +810,11 @@ class EmaneManager(ModelManager):
# don"t use node.setposition(x,y,z) which generates an event
node.position.set(x, y, z)
node_data = node.data(message_type=0, lat=str(lat), lon=str(lon), alt=str(alt))
node_data = node.data(message_type=0, lat=lat, lon=lon, alt=alt)
self.session.broadcast_node(node_data)
return True
def emanerunning(self, node):
def emanerunning(self, node: CoreNode) -> bool:
"""
Return True if an EMANE process associated with the given node is running,
False otherwise.
@ -827,7 +837,7 @@ class EmaneGlobalModel:
name = "emane"
bitmap = None
def __init__(self, session):
def __init__(self, session: "Session") -> None:
self.session = session
self.nem_config = [
Configuration(
@ -840,7 +850,7 @@ class EmaneGlobalModel:
self.emulator_config = None
self.parse_config()
def parse_config(self):
def parse_config(self) -> None:
emane_prefix = self.session.options.get_config(
"emane_prefix", default=DEFAULT_EMANE_PREFIX
)
@ -862,10 +872,10 @@ class EmaneGlobalModel:
),
)
def configurations(self):
def configurations(self) -> List[Configuration]:
return self.emulator_config + self.nem_config
def config_groups(self):
def config_groups(self) -> List[ConfigGroup]:
emulator_len = len(self.emulator_config)
config_len = len(self.configurations())
return [
@ -873,7 +883,7 @@ class EmaneGlobalModel:
ConfigGroup("NEM Parameters", emulator_len + 1, config_len),
]
def default_values(self):
def default_values(self) -> Dict[str, str]:
return OrderedDict(
[(config.id, config.default) for config in self.configurations()]
)

View file

@ -1,4 +1,5 @@
import logging
from typing import Dict, List
from core.config import Configuration
from core.emulator.enumerations import ConfigDataTypes
@ -13,12 +14,12 @@ except ImportError:
logging.debug("compatible emane python bindings not installed")
def _type_value(config_type):
def _type_value(config_type: str) -> ConfigDataTypes:
"""
Convert emane configuration type to core configuration value.
:param str config_type: emane configuration type
:return:
:return: core config type
"""
config_type = config_type.upper()
if config_type == "DOUBLE":
@ -28,7 +29,7 @@ def _type_value(config_type):
return ConfigDataTypes[config_type]
def _get_possible(config_type, config_regex):
def _get_possible(config_type: str, config_regex: str) -> List[str]:
"""
Retrieve possible config value options based on emane regexes.
@ -47,7 +48,7 @@ def _get_possible(config_type, config_regex):
return []
def _get_default(config_type_name, config_value):
def _get_default(config_type_name: str, config_value: List[str]) -> str:
"""
Convert default configuration values to one used by core.
@ -72,7 +73,7 @@ def _get_default(config_type_name, config_value):
return config_default
def parse(manifest_path, defaults):
def parse(manifest_path: str, defaults: Dict[str, str]) -> List[Configuration]:
"""
Parses a valid emane manifest file and converts the provided configuration values into ones used by core.

View file

@ -3,12 +3,14 @@ Defines Emane Models used within CORE.
"""
import logging
import os
from typing import Dict, List
from core.config import ConfigGroup, Configuration
from core.emane import emanemanifest
from core.emulator.enumerations import ConfigDataTypes
from core.errors import CoreError
from core.location.mobility import WirelessModel
from core.nodes.interface import CoreInterface
from core.xml import emanexml
@ -45,7 +47,7 @@ class EmaneModel(WirelessModel):
config_ignore = set()
@classmethod
def load(cls, emane_prefix):
def load(cls, emane_prefix: str) -> None:
"""
Called after being loaded within the EmaneManager. Provides configured emane_prefix for
parsing xml files.
@ -63,7 +65,7 @@ class EmaneModel(WirelessModel):
cls.phy_config = emanemanifest.parse(phy_xml_path, cls.phy_defaults)
@classmethod
def configurations(cls):
def configurations(cls) -> List[Configuration]:
"""
Returns the combination all all configurations (mac, phy, and external).
@ -73,7 +75,7 @@ class EmaneModel(WirelessModel):
return cls.mac_config + cls.phy_config + cls.external_config
@classmethod
def config_groups(cls):
def config_groups(cls) -> List[ConfigGroup]:
"""
Returns the defined configuration groups.
@ -89,10 +91,12 @@ class EmaneModel(WirelessModel):
ConfigGroup("External Parameters", phy_len + 1, config_len),
]
def build_xml_files(self, config, interface=None):
def build_xml_files(
self, config: Dict[str, str], interface: CoreInterface = None
) -> None:
"""
Builds xml files for this emane model. Creates a nem.xml file that points to both mac.xml and phy.xml
definitions.
Builds xml files for this emane model. Creates a nem.xml file that points to
both mac.xml and phy.xml definitions.
:param dict config: emane model configuration for the node and interface
:param interface: interface for the emane node
@ -127,7 +131,7 @@ class EmaneModel(WirelessModel):
phy_file = os.path.join(self.session.session_dir, phy_name)
emanexml.create_phy_xml(self, config, phy_file, server)
def post_startup(self):
def post_startup(self) -> None:
"""
Logic to execute after the emane manager is finished with startup.
@ -135,7 +139,7 @@ class EmaneModel(WirelessModel):
"""
logging.debug("emane model(%s) has no post setup tasks", self.name)
def update(self, moved, moved_netifs):
def update(self, moved: bool, moved_netifs: List[CoreInterface]) -> None:
"""
Invoked from MobilityModel when nodes are moved; this causes
emane location events to be generated for the nodes in the moved
@ -143,7 +147,7 @@ class EmaneModel(WirelessModel):
:param bool moved: were nodes moved
:param list moved_netifs: interfaces that were moved
:return:
:return: nothing
"""
try:
wlan = self.session.get_node(self.id)
@ -153,14 +157,14 @@ class EmaneModel(WirelessModel):
def linkconfig(
self,
netif,
bw=None,
delay=None,
loss=None,
duplicate=None,
jitter=None,
netif2=None,
):
netif: CoreInterface,
bw: float = None,
delay: float = None,
loss: float = None,
duplicate: float = None,
jitter: float = None,
netif2: CoreInterface = None,
) -> None:
"""
Invoked when a Link Message is received. Default is unimplemented.

View file

@ -15,7 +15,7 @@ class EmaneIeee80211abgModel(emanemodel.EmaneModel):
mac_xml = "ieee80211abgmaclayer.xml"
@classmethod
def load(cls, emane_prefix):
def load(cls, emane_prefix: str) -> None:
cls.mac_defaults["pcrcurveuri"] = os.path.join(
emane_prefix, "share/emane/xml/models/mac/ieee80211abg/ieee80211pcr.xml"
)

View file

@ -4,9 +4,18 @@ share the same MAC+PHY model.
"""
import logging
from typing import TYPE_CHECKING, Dict, List, Optional, Type
from core.emulator.distributed import DistributedServer
from core.emulator.enumerations import LinkTypes, NodeTypes, RegisterTlvs
from core.nodes.base import CoreNetworkBase
from core.nodes.interface import CoreInterface
if TYPE_CHECKING:
from core.emulator.session import Session
from core.location.mobility import WirelessModel
WirelessModelType = Type[WirelessModel]
try:
from emane.events import LocationEvent
@ -29,7 +38,14 @@ class EmaneNet(CoreNetworkBase):
type = "wlan"
is_emane = True
def __init__(self, session, _id=None, name=None, start=True, server=None):
def __init__(
self,
session: "Session",
_id: int = None,
name: str = None,
start: bool = True,
server: DistributedServer = None,
) -> None:
super().__init__(session, _id, name, start, server)
self.conf = ""
self.up = False
@ -39,20 +55,20 @@ class EmaneNet(CoreNetworkBase):
def linkconfig(
self,
netif,
bw=None,
delay=None,
loss=None,
duplicate=None,
jitter=None,
netif2=None,
):
netif: CoreInterface,
bw: float = None,
delay: float = None,
loss: float = None,
duplicate: float = None,
jitter: float = None,
netif2: CoreInterface = None,
) -> None:
"""
The CommEffect model supports link configuration.
"""
if not self.model:
return
return self.model.linkconfig(
self.model.linkconfig(
netif=netif,
bw=bw,
delay=delay,
@ -62,19 +78,19 @@ class EmaneNet(CoreNetworkBase):
netif2=netif2,
)
def config(self, conf):
def config(self, conf: str) -> None:
self.conf = conf
def shutdown(self):
def shutdown(self) -> None:
pass
def link(self, netif1, netif2):
def link(self, netif1: CoreInterface, netif2: CoreInterface) -> None:
pass
def unlink(self, netif1, netif2):
def unlink(self, netif1: CoreInterface, netif2: CoreInterface) -> None:
pass
def updatemodel(self, config):
def updatemodel(self, config: Dict[str, str]) -> None:
if not self.model:
raise ValueError("no model set to update for node(%s)", self.id)
logging.info(
@ -82,7 +98,7 @@ class EmaneNet(CoreNetworkBase):
)
self.model.set_configs(config, node_id=self.id)
def setmodel(self, model, config):
def setmodel(self, model: "WirelessModelType", config: Dict[str, str]) -> None:
"""
set the EmaneModel associated with this node
"""
@ -96,14 +112,14 @@ class EmaneNet(CoreNetworkBase):
self.mobility = model(session=self.session, _id=self.id)
self.mobility.update_config(config)
def setnemid(self, netif, nemid):
def setnemid(self, netif: CoreInterface, nemid: int) -> None:
"""
Record an interface to numerical ID mapping. The Emane controller
object manages and assigns these IDs for all NEMs.
"""
self.nemidmap[netif] = nemid
def getnemid(self, netif):
def getnemid(self, netif: CoreInterface) -> Optional[int]:
"""
Given an interface, return its numerical ID.
"""
@ -112,7 +128,7 @@ class EmaneNet(CoreNetworkBase):
else:
return self.nemidmap[netif]
def getnemnetif(self, nemid):
def getnemnetif(self, nemid: int) -> Optional[CoreInterface]:
"""
Given a numerical NEM ID, return its interface. This returns the
first interface that matches the given NEM ID.
@ -122,13 +138,13 @@ class EmaneNet(CoreNetworkBase):
return netif
return None
def netifs(self, sort=True):
def netifs(self, sort: bool = True) -> List[CoreInterface]:
"""
Retrieve list of linked interfaces sorted by node number.
"""
return sorted(self._netif.values(), key=lambda ifc: ifc.node.id)
def installnetifs(self):
def installnetifs(self) -> None:
"""
Install TAP devices into their namespaces. This is done after
EMANE daemons have been started, because that is their only chance
@ -159,7 +175,7 @@ class EmaneNet(CoreNetworkBase):
x, y, z = netif.node.position.get()
self.setnemposition(netif, x, y, z)
def deinstallnetifs(self):
def deinstallnetifs(self) -> None:
"""
Uninstall TAP devices. This invokes their shutdown method for
any required cleanup; the device may be actually removed when
@ -170,7 +186,9 @@ class EmaneNet(CoreNetworkBase):
netif.shutdown()
netif.poshook = None
def setnemposition(self, netif, x, y, z):
def setnemposition(
self, netif: CoreInterface, x: float, y: float, z: float
) -> None:
"""
Publish a NEM location change event using the EMANE event service.
"""
@ -191,7 +209,7 @@ class EmaneNet(CoreNetworkBase):
event.append(nemid, latitude=lat, longitude=lon, altitude=alt)
self.session.emane.service.publish(0, event)
def setnempositions(self, moved_netifs):
def setnempositions(self, moved_netifs: List[CoreInterface]) -> None:
"""
Several NEMs have moved, from e.g. a WaypointMobilityModel
calculation. Generate an EMANE Location Event having several

View file

@ -15,7 +15,7 @@ class EmaneRfPipeModel(emanemodel.EmaneModel):
mac_xml = "rfpipemaclayer.xml"
@classmethod
def load(cls, emane_prefix):
def load(cls, emane_prefix: str) -> None:
cls.mac_defaults["pcrcurveuri"] = os.path.join(
emane_prefix, "share/emane/xml/models/mac/rfpipe/rfpipepcr.xml"
)

View file

@ -27,7 +27,7 @@ class EmaneTdmaModel(emanemodel.EmaneModel):
config_ignore = {schedule_name}
@classmethod
def load(cls, emane_prefix):
def load(cls, emane_prefix: str) -> None:
cls.mac_defaults["pcrcurveuri"] = os.path.join(
emane_prefix,
"share/emane/xml/models/mac/tdmaeventscheduler/tdmabasemodelpcr.xml",
@ -43,7 +43,7 @@ class EmaneTdmaModel(emanemodel.EmaneModel):
),
)
def post_startup(self):
def post_startup(self) -> None:
"""
Logic to execute after the emane manager is finished with startup.