From fec5e1de09fbc3382292d4b3be270b7dbbc68d28 Mon Sep 17 00:00:00 2001 From: Jacob Perron Date: Mon, 24 Sep 2018 12:31:03 -0700 Subject: [PATCH] Add a common interface for describing an EventHandler A common pattern for describing event handlers has been moved to the parent class. Subclasses should implement the 'handler_description' and 'matcher_description' properties rather than implementing a describe method. --- launch/launch/event_handler.py | 35 ++++++++++++++++++- .../on_include_launch_description.py | 21 +++++------ .../launch/event_handlers/on_process_exit.py | 26 +++++--------- launch/launch/event_handlers/on_process_io.py | 17 +++------ launch/launch/event_handlers/on_shutdown.py | 15 +++----- .../event_handlers/on_state_transition.py | 13 +++---- 6 files changed, 65 insertions(+), 62 deletions(-) diff --git a/launch/launch/event_handler.py b/launch/launch/event_handler.py index f438e4ac2..4dafff960 100644 --- a/launch/launch/event_handler.py +++ b/launch/launch/event_handler.py @@ -15,7 +15,10 @@ """Module for EventHandler class.""" from typing import Callable +from typing import List from typing import Optional +from typing import Text +from typing import Tuple from .event import Event from .some_actions_type import SomeActionsType @@ -59,6 +62,8 @@ def __init__( @property def entities(self): """Getter for entities.""" + # if self.__entities is None: + # return [] return self.__entities @property @@ -75,7 +80,35 @@ def handle_once(self, value): ) self.__handle_once = value - # TODO(wjwwood): setup standard interface for describing event handlers + @property + def handler_description(self): + """ + Return the string description of the handler. + + This should be overridden. + """ + return None + + @property + def matcher_description(self): + """ + Return the string description of the matcher. + + This should be overridden. + """ + return None + + def describe(self) -> Tuple[Text, List[SomeActionsType]]: + """Return the description list with 0 as a string, and then LaunchDescriptionEntity's.""" + return ( + "{}(matcher='{}', handler='{}', handle_once={})".format( + type(self).__name__, + self.matcher_description, + self.handler_description, + self.handle_once + ), + self.entities if self.entities is not None else [] + ) def matches(self, event: Event) -> bool: """Return True if the given event should be handled by this event handler.""" diff --git a/launch/launch/event_handlers/on_include_launch_description.py b/launch/launch/event_handlers/on_include_launch_description.py index 408624821..38d0137d1 100644 --- a/launch/launch/event_handlers/on_include_launch_description.py +++ b/launch/launch/event_handlers/on_include_launch_description.py @@ -14,13 +14,10 @@ """Module for OnIncludeLaunchDescription class.""" -from typing import List from typing import Text -from typing import Tuple from ..event_handler import EventHandler from ..events import IncludeLaunchDescription -from ..launch_description_entity import LaunchDescriptionEntity from ..utilities import is_a_subclass @@ -38,12 +35,12 @@ def __init__(self, **kwargs): **kwargs, ) - def describe(self) -> Tuple[Text, List[LaunchDescriptionEntity]]: - """Return the description list with 0 as a string, and then LaunchDescriptionEntity's.""" - return ( - "OnIncludeLaunchDescription(matcher='{}', handler='{}')".format( - 'event issubclass of launch.events.IncludeLaunchDescription', - 'returns the launch_description in the event' - ), - [], - ) + @property + def handler_description(self) -> Text: + """Return the string description of the handler.""" + return 'returns the launch_description in the event' + + @property + def matcher_description(self) -> Text: + """Return the string description of the matcher.""" + return 'event issubclass of launch.events.IncludeLaunchDescription' diff --git a/launch/launch/event_handlers/on_process_exit.py b/launch/launch/event_handlers/on_process_exit.py index 60445a796..000748170 100644 --- a/launch/launch/event_handlers/on_process_exit.py +++ b/launch/launch/event_handlers/on_process_exit.py @@ -17,11 +17,9 @@ import collections from typing import Callable from typing import cast -from typing import List from typing import Optional from typing import overload from typing import Text -from typing import Tuple from ..event import Event from ..event_handler import EventHandler @@ -110,24 +108,18 @@ def handle(self, event: Event, context: LaunchContext) -> Optional[SomeActionsTy """Handle the given event.""" return self.__on_exit(cast(ProcessExited, event), context) - def describe(self) -> Tuple[Text, List[LaunchDescriptionEntity]]: - """Return the description list with 0 as a string, and then LaunchDescriptionEntity's.""" + @property + def handler_description(self) -> Text: + """Return the string description of the handler.""" + # TODO(jacobperron): revisit how to describe known actions that are passed in. + # It would be nice if the parent class could output their desciption + # via the 'entities' property. if self.__actions_on_exit: - # A list of resulting actions is already known. - return ( - "OnProcessExit(matcher='{}', handler=)".format(self.matcher_description), - self.__actions_on_exit, - ) - # A callable handler has been provided. - return ( - "OnProcessExit(matcher='{}', handler={})".format( - self.matcher_description, - self.__on_exit), - [], - ) + return '' + return '{}'.format(self.__on_exit) @property - def matcher_description(self): + def matcher_description(self) -> Text: """Return the string description of the matcher.""" if self.__target_action is None: return 'event == ProcessExited' diff --git a/launch/launch/event_handlers/on_process_io.py b/launch/launch/event_handlers/on_process_io.py index 3ae23c9b7..f2e6b9fde 100644 --- a/launch/launch/event_handlers/on_process_io.py +++ b/launch/launch/event_handlers/on_process_io.py @@ -16,16 +16,13 @@ from typing import Callable from typing import cast -from typing import List from typing import Optional from typing import Text -from typing import Tuple from ..event import Event from ..event_handler import EventHandler from ..events.process import ProcessIO from ..launch_context import LaunchContext -from ..launch_description_entity import LaunchDescriptionEntity from ..some_actions_type import SomeActionsType if False: @@ -78,8 +75,9 @@ def handle(self, event: Event, context: LaunchContext) -> Optional[SomeActionsTy return self.__on_stdin(event) return None - def describe(self) -> Tuple[Text, List[LaunchDescriptionEntity]]: - """Return the description list with 0 as a string, and then LaunchDescriptionEntity's.""" + @property + def handler_description(self) -> Text: + """Return the string description of the handler.""" handlers = [] if self.__on_stdin is not None: handlers.append("on_stdin: '{}'".format(self.__on_stdin)) @@ -88,15 +86,10 @@ def describe(self) -> Tuple[Text, List[LaunchDescriptionEntity]]: if self.__on_stderr is not None: handlers.append("on_stderr: '{}'".format(self.__on_stderr)) handlers_str = '{' + ', '.join(handlers) + '}' - return ( - "OnProcessIO(matcher='{}', handlers={})".format( - self.matcher_description, handlers_str - ), - [], - ) + return handlers_str @property - def matcher_description(self): + def matcher_description(self) -> Text: """Return the string description of the matcher.""" if self.__target_action is None: return 'event issubclass of ProcessIO' diff --git a/launch/launch/event_handlers/on_shutdown.py b/launch/launch/event_handlers/on_shutdown.py index 9db35520f..127172865 100644 --- a/launch/launch/event_handlers/on_shutdown.py +++ b/launch/launch/event_handlers/on_shutdown.py @@ -16,16 +16,13 @@ from typing import Callable from typing import cast -from typing import List from typing import Optional from typing import overload from typing import Text -from typing import Tuple from ..event import Event from ..event_handler import EventHandler from ..events import Shutdown -from ..launch_description_entity import LaunchDescriptionEntity from ..some_actions_type import SomeActionsType from ..utilities import is_a_subclass @@ -70,15 +67,11 @@ def handle(self, event: Event, context: 'LaunchContext') -> Optional[SomeActions context.extend_locals({'event': event}) return self.__on_shutdown(cast(Shutdown, event), context) - def describe(self) -> Tuple[Text, List[LaunchDescriptionEntity]]: - """Return the description list with 0 as a string, and then LaunchDescriptionEntity's.""" + @property + def handler_description(self) -> Text: + """Return the string description of the handler.""" # TODO(dhood): print known actions if they were passed in, like in OnProcessExit - return ( - "OnShutdown(matcher='{}', handler={})".format( - self.matcher_description, - self.__on_shutdown), - [], - ) + return '{}'.format(self.__on_shutdown) @property def matcher_description(self): diff --git a/launch_ros/launch_ros/event_handlers/on_state_transition.py b/launch_ros/launch_ros/event_handlers/on_state_transition.py index 7da9f4ce2..c0f89e5f5 100644 --- a/launch_ros/launch_ros/event_handlers/on_state_transition.py +++ b/launch_ros/launch_ros/event_handlers/on_state_transition.py @@ -15,14 +15,11 @@ """Module for OnStateTransition class.""" from typing import Callable -from typing import List from typing import Optional from typing import Text -from typing import Tuple from launch.event import Event from launch.event_handler import EventHandler -from launch.launch_description_entity import LaunchDescriptionEntity from launch.some_actions_type import SomeActionsType from launch.some_substitutions_type import SomeSubstitutionsType @@ -84,12 +81,10 @@ def __init__( ) self.__target_lifecycle_node = target_lifecycle_node - def describe(self) -> Tuple[Text, List[LaunchDescriptionEntity]]: - """Return the description list with 0 as a string, and then LaunchDescriptionEntity's.""" - return ( - "OnStateTransition(matcher='{}', handler=)".format(self.matcher_description), - self.entities, - ) + @property + def handler_description(self) -> Text: + """Return the string description of the handler.""" + return '' @property def matcher_description(self):