@@ -83,6 +83,34 @@ def duration_value_ms(self) -> Any:
8383 return self .get_input (self .INPUT_DURATION_MS_PORT )
8484
8585
86+ class EchoCtorArgs (BehaviourWithPorts ):
87+ """Behaviour that tests interpreting constructor type hints for type coercion from XML ports."""
88+
89+ @classmethod
90+ def input_ports (cls ) -> dict :
91+ return {"in" : PortInformation (data_type = str , required = False )} # not used here
92+
93+ @classmethod
94+ def output_ports (cls ) -> dict :
95+ return {"out" : PortInformation (data_type = str , required = False )} # not used here
96+
97+ def __init__ (self , name : str , greeting : str , times : float | None , flag : bool , ** kwargs : Any ) -> None :
98+ super ().__init__ (name , ** kwargs )
99+ self .greeting = greeting
100+ self .times = times
101+ self .flag = flag
102+
103+
104+ class EchoCtorArgsChild (EchoCtorArgs ):
105+ """
106+ Behaviour that tests interpreting constructor type hints for type coercion from XML ports,
107+ but from its parent class.
108+ """
109+
110+ def __init__ (self , ** kwargs ):
111+ super ().__init__ (** kwargs )
112+
113+
86114@dataclass
87115class RobotData :
88116 type : str
@@ -471,25 +499,37 @@ def test_ctor_args_passed_as_kwargs(self) -> None:
471499 Values are automatically converted based on the type hints in the constructor.
472500 """
473501
474- class EchoCtorArgs (BehaviourWithPorts ):
475- @classmethod
476- def input_ports (cls ) -> dict :
477- return {"in" : PortInformation (data_type = str , required = False )} # not used here
502+ xml = """<root main_tree_to_execute="Main">
503+ <BehaviorTree ID="Main">
504+ <Sequence>
505+ <EchoCtorArgs name="E1" greeting="hello" times="3" flag="true"/>
506+ </Sequence>
507+ </BehaviorTree>
508+ </root>"""
478509
479- @ classmethod
480- def output_ports ( cls ) -> dict :
481- return { "out" : PortInformation ( data_type = str , required = False )} # not used here
510+ with tempfile . NamedTemporaryFile ( delete = False , mode = "w" , suffix = ".xml" ) as tf :
511+ tf . write ( xml )
512+ path = tf . name
482513
483- def __init__ (self , name : str , greeting : str , times : float | None , flag : bool , ** kwargs : Any ) -> None :
484- super ().__init__ (name , ** kwargs )
485- self .greeting = greeting
486- self .times = times
487- self .flag = flag
514+ root = parse_behaviour_tree_xml (path , logger = StdoutLogger ())
515+ node = find_node_by_class (root , EchoCtorArgs )
516+ self .assertIsNotNone (node )
517+ self .assertEqual (node .greeting , "hello" )
518+ self .assertEqual (node .times , 3.0 )
519+ self .assertEqual (node .flag , True )
520+
521+ os .unlink (path )
522+
523+ def test_ctor_args_passed_as_kwargs_in_parent_class (self ) -> None :
524+ """
525+ Non-port XML attributes must be passed as constructor kwargs.
526+ Values are automatically converted based on the type hints in the parent class constructor.
527+ """
488528
489529 xml = """<root main_tree_to_execute="Main">
490530 <BehaviorTree ID="Main">
491531 <Sequence>
492- <EchoCtorArgs name="E1" greeting="hello" times="3" flag="true"/>
532+ <EchoCtorArgsChild name="E1" greeting="hello" times="3" flag="true"/>
493533 </Sequence>
494534 </BehaviorTree>
495535 </root>"""
@@ -499,7 +539,7 @@ def __init__(self, name: str, greeting: str, times: float | None, flag: bool, **
499539 path = tf .name
500540
501541 root = parse_behaviour_tree_xml (path , logger = StdoutLogger ())
502- node = find_node_by_class (root , EchoCtorArgs )
542+ node = find_node_by_class (root , EchoCtorArgsChild )
503543 self .assertIsNotNone (node )
504544 self .assertEqual (node .greeting , "hello" )
505545 self .assertEqual (node .times , 3.0 )
0 commit comments