Skip to content

Commit

Permalink
flake8/pycodestyle cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
David Conner committed Jun 4, 2024
1 parent abc47dd commit c6baa3c
Show file tree
Hide file tree
Showing 100 changed files with 1,674 additions and 1,190 deletions.
2 changes: 2 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[flake8]
exclude = .git
max-line-length = 130
ignore = W503, D100, D105, D107 # Ignore docstring requirements for public modules, magic methods, and __init__ functions.
# For W503 - https://www.flake8rules.com/rules/W503.html and https://peps.python.org/pep-0008/#should-a-line-break-before-or-after-a-binary-operator
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2015-2023 Philipp Schillinger, Team ViGIR, Christopher Newport University
Copyright 2015-2024 Philipp Schillinger, Team ViGIR, Christopher Newport University

BSD-3-Clause

Expand All @@ -12,7 +12,7 @@ modification, are permitted provided that the following conditions are met:
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

* Neither the name of the Philipp Schillinger, Team ViGIR,
* Neither the name of the Philipp Schillinger, Team ViGIR,
Christopher Newport University nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
Expand Down
10 changes: 4 additions & 6 deletions flexbe_core/flexbe_core/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2023 Philipp Schillinger, Team ViGIR, Christopher Newport University
# Copyright 2024 Philipp Schillinger, Team ViGIR, Christopher Newport University
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
Expand Down Expand Up @@ -27,21 +27,19 @@
# POSSIBILITY OF SUCH DAMAGE.

"""
Initialization for flexbe_core.core module.
Initialization for flexbe_core package.
Please use EventState as parent class for new states
because it extends all other parent classes.
For a behavior, inherit from OperatableStateMachine as state machine.
"""
from .core import ConcurrencyContainer, EventState # noqa: F401
from .core import OperatableStateMachine, PriorityContainer # noqa: F401

from .behavior import Behavior # noqa: F401

from .behavior_library import BehaviorLibrary # noqa: F401

from .core import ConcurrencyContainer, EventState # noqa: F401
from .core import OperatableStateMachine, PriorityContainer # noqa: F401
from .logger import Logger # noqa: F401
from .state_logger import StateLogger # noqa: F401

Expand Down
21 changes: 13 additions & 8 deletions flexbe_core/flexbe_core/behavior.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python

# Copyright 2023 Philipp Schillinger, Team ViGIR, Christopher Newport University
# Copyright 2024 Philipp Schillinger, Team ViGIR, Christopher Newport University
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
Expand Down Expand Up @@ -30,18 +30,19 @@


"""This defines the superclass for all implemented behaviors."""
from flexbe_msgs.msg import BehaviorSync
from flexbe_core.core import PreemptableState, OperatableStateMachine, LockableStateMachine
from flexbe_core.core import LockableStateMachine, OperatableStateMachine, PreemptableState
from flexbe_core.logger import Logger

from flexbe_msgs.msg import BehaviorSync


class Behavior:
"""This is the superclass for all implemented behaviors."""

def __init__(self):
"""Call this superclass constructor first when overriding it with your behavior."""
self._state_machine = None
self.name = "unnamed behavior"
self.name = 'unnamed behavior'
self.beh_id = 0 # Behavior id checksum assigned by processing the file contents

self.contains = {}
Expand Down Expand Up @@ -216,7 +217,7 @@ def prepare_for_switch(self, state):
state._locked = True # make sure the state cannot transition during preparations
states = self._get_states_of_path(state.path, self._state_machine)
if states is None:
raise RuntimeError("Did not find locked state in new behavior!")
raise RuntimeError('Did not find locked state in new behavior!')
state_container = state._parent
state_container.remove_state(state) # remove from old state machine
for sm in states[1:]:
Expand All @@ -227,6 +228,7 @@ def prepare_for_switch(self, state):
self.requested_state_path = state.path # set start after switch

def get_current_states(self):
"""Get all currently active (sub-)states."""
return self._state_machine.get_deep_states()

def get_locked_state(self):
Expand All @@ -242,6 +244,7 @@ def get_locked_state(self):

@classmethod
def preempt(cls):
"""Preempt behavior."""
PreemptableState.preempt = True

# For internal use only
Expand All @@ -252,14 +255,15 @@ def _get_state_machine(self):
return self._state_machine

def _collect_contained(self, obj, path):
contain_list = {path + "/" + key: value for (key, value) in getattr(obj, 'contains', {}).items()}
contain_list = {path + '/' + key: value for (key, value) in getattr(obj, 'contains', {}).items()}
add_to_list = {}
for b_id, b_inst in contain_list.items():
add_to_list.update(self._collect_contained(b_inst, b_id))
contain_list.update(add_to_list)
return contain_list

def get_contained_behaviors(self):
"""Get contained behaviors within this behavior."""
return self._collect_contained(self, '')

def _set_typed_attribute(self, name, value):
Expand All @@ -271,13 +275,14 @@ def _set_typed_attribute(self, name, value):
elif isinstance(attr, float):
value = float(value)
elif isinstance(attr, bool):
value = (value != "0" and value.lower() != "false")
value = (value != '0' and value.lower() != 'false')
elif isinstance(attr, dict):
import yaml # pylint: disable=C0415
value = getattr(yaml, 'unsafe_load', yaml.load)(value)
setattr(self, name, value)

def set_up(self, beh_id, autonomy_level, debug):
"""Set up the behavior."""
self.beh_id = beh_id
self._autonomy_level = autonomy_level
self._debug = debug
Expand All @@ -287,7 +292,7 @@ def _get_states_of_path(self, path, container):
if len(path_elements) < 2:
return [container] # actually a state in this case
state_label = path_elements[1]
new_path = "/".join(path_elements[1:])
new_path = '/'.join(path_elements[1:])
# collect along the path and append self
if state_label in container:
childlist = self._get_states_of_path(new_path, container[state_label])
Expand Down
60 changes: 32 additions & 28 deletions flexbe_core/flexbe_core/behavior_library.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2023 Philipp Schillinger, Team ViGIR, Christopher Newport University
# Copyright 2024 Philipp Schillinger, Team ViGIR, Christopher Newport University
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
Expand Down Expand Up @@ -33,6 +33,7 @@
import zlib

from ament_index_python import get_packages_with_prefixes

from catkin_pkg.package import parse_package

from flexbe_core.logger import Logger
Expand All @@ -42,32 +43,33 @@ class BehaviorLibrary:
"""Provide access to all known behaviors."""

def __init__(self, node):
"""Initialize BehaviorLibrary instance."""
self._node = node
Logger.initialize(node)
self.parse_packages()
self.dump_packages()

def dump_packages(self):
"""Dump to screen for debugging."""
print("\n\n------------------ Available Behaviors Workspace (sorted by assigned key) ------------------", flush=True)
print('\n\n------------------ Available Behaviors Workspace (sorted by assigned key) ------------------', flush=True)
sorted_keys = list(self._behavior_lib.keys())
sorted_keys.sort()
for be_key in sorted_keys:
data = self._behavior_lib[be_key]
print(f"{be_key:10d} : {data['class']:36s} - {data['name']:36s} - {data['file']:30s} - {data['package']}")
print("-----------------------------------------------------------------------------------------\n\n", flush=True)
print('-----------------------------------------------------------------------------------------\n\n', flush=True)

def parse_packages(self):
"""Parse all ROS2 packages to update the internal behavior library."""
self._behavior_lib = {}
for pkg_name, pkg_path in get_packages_with_prefixes().items():
pkg = parse_package(os.path.join(pkg_path, 'share', pkg_name))
for export in pkg.exports:
if export.tagname == "flexbe_behaviors":
if export.tagname == 'flexbe_behaviors':
try:
self._add_behavior_manifests(os.path.join(pkg_path, 'lib', pkg_name, 'manifest'), pkg_name)
except KeyError as exc:
print(f"Error : duplicate behavior name found in {pkg_name} \n {exc}", flush=True)
print(f"Error : duplicate behavior name found in '{pkg_name}' \n {exc}", flush=True)
raise exc

def _add_behavior_manifests(self, path, pkg=None):
Expand All @@ -86,7 +88,7 @@ def _add_behavior_manifests(self, path, pkg=None):
entry_path = os.path.join(path, entry)
if os.path.isdir(entry_path):
self._add_behavior_manifests(entry_path, pkg)
elif entry.endswith(".xml") and not entry.startswith("#"):
elif entry.endswith('.xml') and not entry.startswith('#'):
try:
mrt = ET.parse(entry_path).getroot()
except ET.ParseError as exc:
Expand All @@ -95,24 +97,26 @@ def _add_behavior_manifests(self, path, pkg=None):
continue

# structure sanity check
if (mrt.tag != "behavior"
or len(mrt.findall(".//executable")) == 0
or mrt.find("executable").get("package_path") is None
or len(mrt.find("executable").get("package_path").split(".")) < 2):
if (
mrt.tag != 'behavior'
or len(mrt.findall('.//executable')) == 0
or mrt.find('executable').get('package_path') is None
or len(mrt.find('executable').get('package_path').split('.')) < 2
):
continue
exct = mrt.find("executable")
if pkg is not None and exct.get("package_path").split(".")[0] != pkg:
exct = mrt.find('executable')
if pkg is not None and exct.get('package_path').split('.')[0] != pkg:
continue # ignore if manifest not in specified package
be_key = zlib.adler32(exct.get("package_path").encode()) & 0x7fffffff
be_key = zlib.adler32(exct.get('package_path').encode()) & 0x7fffffff
if be_key in self._behavior_lib:
raise KeyError(f"Invalid behavior id key={be_key} for {exct.get('package_path')} "
raise KeyError(f"Invalid behavior id key='{be_key}' for {exct.get('package_path')} "
f"- already exists for {self._behavior_lib[be_key]['package']}")

self._behavior_lib[be_key] = {
"name": mrt.get("name"),
"package": ".".join(exct.get("package_path").split(".")[:-1]),
"file": exct.get("package_path").split(".")[-1],
"class": exct.get("class")
'name': mrt.get('name'),
'package': '.'.join(exct.get('package_path').split('.')[:-1]),
'file': exct.get('package_path').split('.')[-1],
'class': exct.get('class')
}

def get_behavior(self, be_key):
Expand All @@ -127,7 +131,7 @@ def get_behavior(self, be_key):
try:
return self._behavior_lib[be_key]
except KeyError:
Logger.logwarn(f"Did not find ID {be_key} in libary, updating...")
Logger.logwarn(f"Did not find ID '{be_key}' in libary, updating...")
self.parse_packages()
return self._behavior_lib.get(be_key, None)

Expand All @@ -140,25 +144,25 @@ def find_behavior(self, be_identifier):
@return Tuple (be_key, be_entry) corresponding to the name or (None, None) if not found.
"""
if "/" in be_identifier:
if '/' in be_identifier:
# Identifier in the form of package/Name
# where only first slash delineates package
be_split = be_identifier.split("/")
be_package, be_name = be_split[0], "/".join(be_split[1:])
be_split = be_identifier.split('/')
be_package, be_name = be_split[0], '/'.join(be_split[1:])

def __find_behavior():
return next((id, be) for (id, be)
in self._behavior_lib.items()
if be["name"] == be_name and be["package"] == be_package)
if be['name'] == be_name and be['package'] == be_package)
else:
# Accept older form of only Name, but this will return the first matching name!
be_package = None
be_name = be_identifier

def __find_behavior():
return next((id, be) for (id, be)
return next((beh_id, be) for (beh_id, be)
in self._behavior_lib.items()
if be["name"] == be_name) # Returns first matching name regardless of package
if be['name'] == be_name) # Returns first matching name regardless of package
try:
return __find_behavior()
except StopIteration:
Expand Down Expand Up @@ -196,18 +200,18 @@ def get_sourcecode_filepath(self, be_key, add_tmp=False):
return None

try:
module_path = __import__(be_entry["package"]).__path__[-1]
module_path = __import__(be_entry['package']).__path__[-1]
except ImportError:
try:
# Attempt to replace prior use of ROS 1 package finder
Logger.logwarn(f"""Cannot import behavior package '{be_entry["package"]}', """
f"""try using 'get_package_share_directory' instead""")
from ament_index_python.packages import get_package_share_directory # pylint: disable=C0415

module_path = get_package_share_directory(be_entry["package"])
module_path = get_package_share_directory(be_entry['package'])
except Exception as exc:
Logger.logerr(f"""Cannot import behavior package '{be_entry["package"]}' """)
raise exc

filename = be_entry["file"] + '.py' if not add_tmp else '_tmp.py'
filename = be_entry['file'] + '.py' if not add_tmp else '_tmp.py'
return os.path.join(module_path, filename)
29 changes: 13 additions & 16 deletions flexbe_core/flexbe_core/core/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2023 Philipp Schillinger, Team ViGIR, Christopher Newport University
# Copyright 2024 Philipp Schillinger, Team ViGIR, Christopher Newport University
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
Expand Down Expand Up @@ -27,25 +27,22 @@
# POSSIBILITY OF SUCH DAMAGE.


"""Initialize of flexbe_core.core module."""

from .preemptable_state_machine import PreemptableStateMachine # noqa: F401
from .operatable_state_machine import OperatableStateMachine # noqa: F401
from .lockable_state_machine import LockableStateMachine # noqa: F401
from .ros_state_machine import RosStateMachine # noqa: F401
from .state_machine import StateMachine # noqa: F401
"""Initialize of flexbe_core.core package."""

from .concurrency_container import ConcurrencyContainer # noqa: F401
from .priority_container import PriorityContainer # noqa: F401

from .state import State # noqa: F401
from .ros_state import RosState # noqa: F401
from .manually_transitionable_state import ManuallyTransitionableState # noqa: F401
from .event_state import EventState # noqa: F401
from .lockable_state import LockableState # noqa: F401
from .preemptable_state import PreemptableState # noqa: F401
from .lockable_state_machine import LockableStateMachine # noqa: F401
from .manually_transitionable_state import ManuallyTransitionableState # noqa: F401
from .operatable_state import OperatableState # noqa: F401
from .event_state import EventState # noqa: F401

from .operatable_state_machine import OperatableStateMachine # noqa: F401
from .preemptable_state import PreemptableState # noqa: F401
from .preemptable_state_machine import PreemptableStateMachine # noqa: F401
from .priority_container import PriorityContainer # noqa: F401
from .ros_state import RosState # noqa: F401
from .ros_state_machine import RosStateMachine # noqa: F401
from .state import State # noqa: F401
from .state_machine import StateMachine # noqa: F401
from .state_map import StateMap # noqa: F401
from .user_data import UserData # noqa: F401

Expand Down
Loading

0 comments on commit c6baa3c

Please sign in to comment.