py_trees.ports_utils module

Helpers shared between py_trees.ports and py_trees.parsers.

class py_trees.ports_utils.LogLevel(*values)

Bases: Enum

Severity levels accepted by PortsLogger-compatible loggers.

DEBUG = 'debug'
ERROR = 'error'
INFO = 'info'
WARNING = 'warning'
class py_trees.ports_utils.PortsLogger(*args, **kwargs)

Bases: Protocol

Minimal logger interface used by the ports subsystem.

Any object that provides these four methods is accepted wherever the ports code takes an optional logger parameter. This is satisfied by Python’s logging.Logger, py_trees’ py_trees.logging.Logger, and typical ROS 2 loggers.

debug(msg: str) → None
error(msg: str) → None
info(msg: str) → None
warning(msg: str) → None
py_trees.ports_utils.apply_type_hints(constructor: Callable, kwargs: dict[str, Any], logger: PortsLogger | None = None, ignore: set[str] | None = None) → tuple[bool, dict[str, Any]]

Convert XML string kwargs into hinted types from the constructor signature.

Keys that are in the ignore set will be kept as-is.

  • If constructor is a class, its __init__ is inspected (excluding self).

  • Only parameters that have type annotations are converted.

  • A key with no individual type hint falls back to the constructor’s **kwargs annotation, if any (e.g. dynamic keys consumed by a **kwargs: SomeType catch-all). The catch-all is looked up by the conventional name kwargs, so one declared under another name (e.g. **options) provides no fallback.

  • An unconstrained target type (Any, object) counts as a success with the string kept, since any value satisfies it.

  • On conversion failure, the original string is preserved and a warning is printed. The function return indicates that there was a failure in one of the values.

Returns:
tuple[bool, dict[str, Any]]: Success of conversion (True if all values were successfully

converted, False if any conversion failed, a warning was also printed then), and the converted dictionary.

py_trees.ports_utils.collect_type_hints(constructor: Callable) → dict[str, Any]

Collect parameter type hints from a constructor.

When constructor is a class, the method resolution order (MRO) is walked so that a type hint declared on a parent’s __init__ is still found when the subclass forwards **kwargs to super().__init__(), and therefore does not declare the parameter itself, or declares it without an annotation.

The most-derived annotation for a given parameter name wins: walking the MRO from subclass to base and only recording the first hint seen per parameter.

Args:

constructor: A class (whose __init__ chain is inspected) or a callable.

Returns:
dict[str, Any]: Mapping of parameter name to its type annotation. Parameters

without an annotation anywhere in the hierarchy are omitted, as is self and any *args catch-all. A **kwargs catch-all is kept (typically under the key "kwargs") so callers can fall back to it for keys that don’t have their own individual type hint.

py_trees.ports_utils.convert_str_to_type(value: str, target_type: type | UnionType, logger: PortsLogger | None = None) → tuple[bool, Any]

Convert a string value to target_type (handles unions, list, tuple, enum).

py_trees.ports_utils.find_node_by_class(node: Behaviour, class_: type) → Any

Recursively search a tree for the first node instance of a class.

py_trees.ports_utils.find_node_by_name(node: Behaviour, name: str, strip_prefix: bool = False, strip_uuid: bool = False, find_all: bool = False) → Behaviour | list[Behaviour] | None

Find a node (or nodes) by name in a behavior tree.

py_trees.ports_utils.generate_node_name(explicit_name: str | None, general_name: str = '', prefix: str = '', no_uuid: bool = False) → str

Generate a node name.

Args:

explicit_name: Optional explicit name set by user. general_name: Fallback node category name. prefix: Optional dot-separated parent prefix. no_uuid: If True, do not append UUID when using general_name fallback.

py_trees.ports_utils.get_base_name(name: str, strip_uuid: bool = False) → str

Extract the base name from a fully-qualified name.

Args:

name: The fully-qualified name (e.g., “namespace1.namespace2.NodeName”). strip_uuid: Strip UUID suffix generated by generate_node_name().

py_trees.ports_utils.is_instance_of_type(value: Any, expected_type: Any) → bool

Check if a value is an instance of a specific type.

Extends Python’s isinstance() to check for generic types, such as lists.

Currently this only supports basic types (int, float, etc.) and the generic types Union and list. Add additional type support as needed.

Args:

value (Any): The value to check. expected_type (Any): The expected type.

Returns:

bool: True if the value is an instance of the expected type, False otherwise.

Raises:

NotImplementedError: If type checking for the specific generic type is not implemented.

py_trees.ports_utils.reset_blackboard_key(blackboard_client: Client, key_name: str, node_name: str = 'unknown') → None

Clear the stored value for key_name via its registered client.

py_trees.ports_utils.sanitize_name_for_blackboard_use(component: str, extra_allowed_chars: str = '') → str

Replace characters py_trees treats as separators with underscores.

py_trees.ports_utils.set_feedback_and_log(behaviour: Behaviour, *, name: str, message: str, level: LogLevel = LogLevel.INFO, logger: PortsLogger | None = None, return_only: bool = False) → str

Format message, update behaviour.feedback_message, and log at level.

py_trees.ports_utils.str_to_type(type_spec: str) → type

Resolve a fully-qualified or built-in type name into the actual type.

A fully-qualified name includes the module path, e.g. 'package.module.Type'. Built-in types can be specified by their simple name, e.g. 'int', 'str', 'list', etc. Raises ValueError if the type cannot be resolved.

py_trees.ports_utils.strip_trailing_uuid4(name: str) → str

Remove a trailing UUID4 suffix from name.

py_trees.ports_utils.uuid4_regex(at_end: bool = False) → str

Return a regex fragment matching a UUID4 string.