From ad1c2db326527ce53225b7f31ae1c14f8ac0e368 Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Tue, 1 Dec 2020 19:36:49 +0100 Subject: [PATCH 01/15] use catkin_install_python to rewrite shebang line Signed-off-by: Mikael Arguedas --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c37b5b..6baaec7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,7 +34,7 @@ generate_messages(DEPENDENCIES std_msgs std_srvs) catkin_package() ## Install scripts -install(PROGRAMS scripts/capability_server +catkin_install_python(PROGRAMS scripts/capability_server DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) if(CATKIN_ENABLE_TESTING) From 32371b76141d6a656e6f95cf0066b2842558c8e5 Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Tue, 1 Dec 2020 19:59:42 +0100 Subject: [PATCH 02/15] fix basestring Signed-off-by: Mikael Arguedas --- src/capabilities/specs/common.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/capabilities/specs/common.py b/src/capabilities/specs/common.py index b6fc41d..8b9f3f4 100644 --- a/src/capabilities/specs/common.py +++ b/src/capabilities/specs/common.py @@ -38,6 +38,11 @@ from __future__ import print_function +try: + __basestring = basestring +except NameError: # pragma: no cover + __basestring = str + def validate_spec_name(name): """Validates a given spec name follows the 'package/spec_name' format @@ -60,7 +65,7 @@ def split_spec_name(name): :raises: AssertionError if spec name is not a str :raises: ValueError if spec name is invalid """ - assert isinstance(name, basestring), "a spec name must be a string" + assert isinstance(name, __basestring), "a spec name must be a string" split_name = name.split('/') if len(split_name) != 2 or not split_name[0] or not split_name[1]: raise ValueError("Invalid spec name '{0}', it should be of the form 'package/spec_name'".format(name)) From 94942ac4a419d8b195fc6c814e090aec2c28b45c Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 29 Apr 2021 19:57:17 +0000 Subject: [PATCH 03/15] run futurize and keep only the changes that seem relevant --- src/capabilities/client.py | 2 +- src/capabilities/discovery.py | 2 +- src/capabilities/server.py | 18 +++++++++--------- src/capabilities/specs/interface.py | 10 +++++----- src/capabilities/specs/provider.py | 2 +- test/unit/common.py | 2 +- test/unit/specs/test_interface.py | 4 ++-- test/unit/specs/test_provider.py | 2 +- test/unit/specs/test_semantic_interface.py | 2 +- test/unit/test_client.py | 3 ++- test/unit/test_server.py | 2 +- 11 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/capabilities/client.py b/src/capabilities/client.py index e1595f0..121aa8d 100644 --- a/src/capabilities/client.py +++ b/src/capabilities/client.py @@ -134,7 +134,7 @@ def wait_for_services(self, timeout=None, services=None): :returns: :py:obj:`True` is the services are available, :py:obj:`False` otherwise (timeout) :rtype: :py:obj:`bool` """ - services = self._services.keys() if services is None else services + services = list(self._services.keys()) if services is None else services assert isinstance(services, list), services for service in services: if service not in self._services: diff --git a/src/capabilities/discovery.py b/src/capabilities/discovery.py index de9b06d..d4b3db0 100644 --- a/src/capabilities/discovery.py +++ b/src/capabilities/discovery.py @@ -436,7 +436,7 @@ def names(self): :rtype: :py:obj:`list` (:py:obj:`str`) """ return list(itertools.chain( - self.interfaces.keys(), self.semantic_interfaces.keys(), self.providers.keys())) + list(self.interfaces.keys()), list(self.semantic_interfaces.keys()), list(self.providers.keys()))) @property def specs(self): diff --git a/src/capabilities/server.py b/src/capabilities/server.py index 630a241..a6f4f54 100644 --- a/src/capabilities/server.py +++ b/src/capabilities/server.py @@ -434,9 +434,9 @@ def __load_capabilities(self): spec_index.remove_provider(provider.name) self.__spec_index = spec_index # Prune spec_file_index - spec_paths = spec_index.interface_paths.values() + \ - spec_index.semantic_interface_paths.values() + \ - spec_index.provider_paths.values() + spec_paths = list(spec_index.interface_paths.values()) + \ + list(spec_index.semantic_interface_paths.values()) + \ + list(spec_index.provider_paths.values()) for package_name, package_dict in self.spec_file_index.items(): for spec_type in ['capability_interface', 'semantic_capability_interface', 'capability_provider']: package_dict[spec_type][:] = [path for path in package_dict[spec_type] if path in spec_paths] @@ -579,13 +579,13 @@ def __cleanup_graph(self): """ # Collect all running capabilities running_capabilities = [x - for x in self.__capability_instances.values() + for x in list(self.__capability_instances.values()) if x.state == 'running'] for cap in running_capabilities: if cap.started_by == USER_SERVICE_REASON: # Started by user, do not garbage collect this continue - rdepends = get_reverse_depends(cap.interface, self.__capability_instances.values()) + rdepends = get_reverse_depends(cap.interface, list(self.__capability_instances.values())) if rdepends: # Someone depends on me, do not garbage collect this rospy.logdebug("Keeping the '{0}' provider of the '{1}' interface, ".format(cap.name, cap.interface) + @@ -636,7 +636,7 @@ def __stop_capability(self, name): "which is not in the list of capability instances.") return capability = self.__capability_instances[name] - rdepends = get_reverse_depends(name, self.__capability_instances.values()) + rdepends = get_reverse_depends(name, list(self.__capability_instances.values())) for cap in rdepends: if cap.state in ['stopping', 'terminated']: # pragma: no cover # It is possible that this cap was stopped by another cap in this list @@ -685,7 +685,7 @@ def __get_providers_for_interface(self, interface, allow_semantic=False): return providers # Could be empty def __start_capability(self, capability, preferred_provider): - if capability not in self.__spec_index.interfaces.keys() + self.__spec_index.semantic_interfaces.keys(): + if capability not in list(self.__spec_index.interfaces.keys()) + list(self.__spec_index.semantic_interfaces.keys()): raise RuntimeError("Capability '{0}' not found.".format(capability)) # If no preferred provider is given, use the default preferred_provider = preferred_provider or self.__default_providers[capability] @@ -909,9 +909,9 @@ def handle_get_providers(self, req): def _handle_get_providers(self, req): if req.interface: - if req.interface not in self.__spec_index.interfaces.keys() + self.__spec_index.semantic_interfaces.keys(): + if req.interface not in list(self.__spec_index.interfaces.keys()) + list(self.__spec_index.semantic_interfaces.keys()): raise RuntimeError("Capability Interface '{0}' not found.".format(req.interface)) - providers = self.__get_providers_for_interface(req.interface, allow_semantic=req.include_semantic).keys() + providers = list(self.__get_providers_for_interface(req.interface, allow_semantic=req.include_semantic).keys()) default_provider = self.__default_providers[req.interface] else: providers = self.__spec_index.provider_names diff --git a/src/capabilities/specs/interface.py b/src/capabilities/specs/interface.py index 2f41b84..8597704 100644 --- a/src/capabilities/specs/interface.py +++ b/src/capabilities/specs/interface.py @@ -226,7 +226,7 @@ def __add_element_to_interface(name, element, group_name=None): for group in element_groups: if group in ['requires', 'provides']: elements = element_groups[group] or {} - for name, element in elements.iteritems(): + for name, element in elements.items(): __add_element_to_interface(name, element, group) else: __add_element_to_interface(group, element_groups[group]) @@ -485,7 +485,7 @@ def __init__(self, name, spec_version, description=None): def __str__(self): elements = "topics:\n" - required_and_provided = list(self.required_topics.keys() + self.provided_topics.keys()) + required_and_provided = list(list(self.required_topics.keys()) + list(self.provided_topics.keys())) both = [x for x in self.topics if x not in required_and_provided] for name, topic in self.topics.items(): if name not in both: @@ -504,7 +504,7 @@ def __str__(self): elements += "\n ".join(str(topic).splitlines()) elements += "\n" elements += " services:\n" - required_and_provided = list(self.required_services.keys() + self.provided_services.keys()) + required_and_provided = list(list(self.required_services.keys()) + list(self.provided_services.keys())) both = [x for x in self.services if x not in required_and_provided] for name, service in self.services.items(): if name not in both: @@ -523,7 +523,7 @@ def __str__(self): elements += "\n ".join(str(service).splitlines()) elements += "\n" elements += " actions:\n" - required_and_provided = list(self.required_actions.keys() + self.provided_actions.keys()) + required_and_provided = list(list(self.required_actions.keys()) + list(self.provided_actions.keys())) both = [x for x in self.actions if x not in required_and_provided] for name, action in self.actions.items(): if name not in both: @@ -542,7 +542,7 @@ def __str__(self): elements += "\n ".join(str(action).splitlines()) elements += "\n" elements += " parameters:\n" - required_and_provided = list(self.required_parameters.keys() + self.provided_parameters.keys()) + required_and_provided = list(list(self.required_parameters.keys()) + list(self.provided_parameters.keys())) both = [x for x in self.parameters if x not in required_and_provided] for name, parameter in self.parameters.items(): if name not in both: diff --git a/src/capabilities/specs/provider.py b/src/capabilities/specs/provider.py index 34622c1..3170226 100644 --- a/src/capabilities/specs/provider.py +++ b/src/capabilities/specs/provider.py @@ -197,7 +197,7 @@ def capability_provider_from_dict(spec, file_name=''): raise InvalidProvider("Invalid depends_on section, expected dict got: '{0}'".format(type(depends_on)), file_name) valid_conditionals = ['provider'] - for interface, conditions in depends_on.iteritems(): + for interface, conditions in depends_on.items(): if not isinstance(conditions, dict): raise InvalidProvider("Invalid depends_on conditional section, expected dict got: '{0}'" .format(type(conditions)), file_name) diff --git a/test/unit/common.py b/test/unit/common.py index 8849c2e..51300be 100644 --- a/test/unit/common.py +++ b/test/unit/common.py @@ -3,7 +3,7 @@ import re import sys -from StringIO import StringIO +from io import StringIO def assert_raises(exception_classes, callable_obj=None, *args, **kwargs): diff --git a/test/unit/specs/test_interface.py b/test/unit/specs/test_interface.py index 108b1b8..9aa0b27 100644 --- a/test/unit/specs/test_interface.py +++ b/test/unit/specs/test_interface.py @@ -32,7 +32,7 @@ def check_navigation(ci): ci.provided_parameters ci.required_parameters check_interface(ci) - str(ci.topics.values()[0]) + str(list(ci.topics.values())[0]) def check_all_interfaces(ci): @@ -80,7 +80,7 @@ def check_minimal(ci): def test_capability_interface_from_file_path(): default_checker = lambda x: None - for test_file, (checker, expected_exception, expected_exception_regex) in test_files_map.iteritems(): + for test_file, (checker, expected_exception, expected_exception_regex) in test_files_map.items(): checker = checker or default_checker print('running test on file ' + test_file) test_file_path = os.path.join(test_data_dir, test_file) diff --git a/test/unit/specs/test_provider.py b/test/unit/specs/test_provider.py index a883c9d..74e33a0 100644 --- a/test/unit/specs/test_provider.py +++ b/test/unit/specs/test_provider.py @@ -58,7 +58,7 @@ def check_minimal(cp): def test_capability_provider_from_file_path(): default_checker = lambda x: None print() # Keeps the output clean when doing nosetests -s - for test_file, (checker, expected_exception, expected_exception_regex) in test_files_map.iteritems(): + for test_file, (checker, expected_exception, expected_exception_regex) in test_files_map.items(): checker = checker or default_checker print('running test on file ' + test_file) test_file_path = os.path.join(test_data_dir, test_file) diff --git a/test/unit/specs/test_semantic_interface.py b/test/unit/specs/test_semantic_interface.py index e3efd66..21c0fab 100644 --- a/test/unit/specs/test_semantic_interface.py +++ b/test/unit/specs/test_semantic_interface.py @@ -48,7 +48,7 @@ def check_minimal(sci): def test_semantic_capability_interface_from_file_path(): default_checker = lambda x: None print() # Keeps the output clean when doing nosetests -s - for test_file, (checker, expected_exception, expected_exception_regex) in test_files_map.iteritems(): + for test_file, (checker, expected_exception, expected_exception_regex) in test_files_map.items(): checker = checker or default_checker print('running test on file ' + test_file) test_file_path = os.path.join(test_data_dir, test_file) diff --git a/test/unit/test_client.py b/test/unit/test_client.py index 65304bb..de3dfc0 100644 --- a/test/unit/test_client.py +++ b/test/unit/test_client.py @@ -1,4 +1,5 @@ -from common import assert_raises +from __future__ import absolute_import +from .common import assert_raises from capabilities.client import CapabilitiesClient from capabilities.client import ServiceNotAvailableException diff --git a/test/unit/test_server.py b/test/unit/test_server.py index 7e51e82..bd5efe5 100644 --- a/test/unit/test_server.py +++ b/test/unit/test_server.py @@ -60,7 +60,7 @@ def test_get_reverse_depends(): instances['foo'].depends_on = ['bar'] instances['bar'].depends_on = [] instances['baz'].depends_on = ['bar'] - result = [x.name for x in server.get_reverse_depends('bar', instances.values())] + result = [x.name for x in server.get_reverse_depends('bar', list(instances.values()))] assert sorted(['foo_pkg/foo', 'baz_pkg/baz']) == sorted(result), sorted(result) except ImportError as exc: From 9f6281a878a209e366450782724a2f2118d53663 Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Tue, 1 Dec 2020 22:49:53 +0100 Subject: [PATCH 04/15] line length Signed-off-by: Mikael Arguedas --- src/capabilities/server.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/capabilities/server.py b/src/capabilities/server.py index a6f4f54..1c7fc23 100644 --- a/src/capabilities/server.py +++ b/src/capabilities/server.py @@ -685,7 +685,9 @@ def __get_providers_for_interface(self, interface, allow_semantic=False): return providers # Could be empty def __start_capability(self, capability, preferred_provider): - if capability not in list(self.__spec_index.interfaces.keys()) + list(self.__spec_index.semantic_interfaces.keys()): + if capability not in ( + list(self.__spec_index.interfaces.keys()) + + list(self.__spec_index.semantic_interfaces.keys())): raise RuntimeError("Capability '{0}' not found.".format(capability)) # If no preferred provider is given, use the default preferred_provider = preferred_provider or self.__default_providers[capability] @@ -909,9 +911,13 @@ def handle_get_providers(self, req): def _handle_get_providers(self, req): if req.interface: - if req.interface not in list(self.__spec_index.interfaces.keys()) + list(self.__spec_index.semantic_interfaces.keys()): + if req.interface not in ( + list(self.__spec_index.interfaces.keys()) + + list(self.__spec_index.semantic_interfaces.keys())): raise RuntimeError("Capability Interface '{0}' not found.".format(req.interface)) - providers = list(self.__get_providers_for_interface(req.interface, allow_semantic=req.include_semantic).keys()) + providers = list( + self.__get_providers_for_interface( + req.interface, allow_semantic=req.include_semantic).keys()) default_provider = self.__default_providers[req.interface] else: providers = self.__spec_index.provider_names From 7de19ba1eba0df506515fd9a588ad1261549d36b Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 29 Apr 2021 20:17:19 +0000 Subject: [PATCH 05/15] remove unnecessary absolute_import --- test/unit/test_client.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/test_client.py b/test/unit/test_client.py index de3dfc0..4be785e 100644 --- a/test/unit/test_client.py +++ b/test/unit/test_client.py @@ -1,4 +1,3 @@ -from __future__ import absolute_import from .common import assert_raises from capabilities.client import CapabilitiesClient From 3ff4c8f2cebaa97d6e6fe23d9c895e800a2b943d Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Thu, 29 Apr 2021 22:43:29 +0200 Subject: [PATCH 06/15] use lists when values are removed while iterating Signed-off-by: Mikael Arguedas --- src/capabilities/server.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/capabilities/server.py b/src/capabilities/server.py index 1c7fc23..8523323 100644 --- a/src/capabilities/server.py +++ b/src/capabilities/server.py @@ -398,7 +398,7 @@ def __load_capabilities(self): package_index = package_index_from_package_path(self.__package_paths) self.spec_file_index = spec_file_index_from_package_index(package_index) # Prune packages by black and white list - for package in self.spec_file_index.keys(): + for package in list(self.spec_file_index.keys()): if self.__package_whitelist and package not in self.__package_whitelist: rospy.loginfo("Package '{0}' not in whitelist, skipping.".format(package)) del self.spec_file_index[package] @@ -991,7 +991,7 @@ def _handle_get_remappings(self, req): remappings[map_type].update(mapping) # Collapse remapping chains for mapping in remappings.values(): - for key, value in mapping.items(): + for key, value in list(mapping.items()): if value in mapping: mapping[key] = mapping[value] del mapping[value] From 8feeb1d3b0a5d3de8a3d36469c97e067f09f65ef Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Thu, 29 Apr 2021 22:59:27 +0200 Subject: [PATCH 07/15] avoid double list Signed-off-by: Mikael Arguedas --- src/capabilities/specs/interface.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/capabilities/specs/interface.py b/src/capabilities/specs/interface.py index 8597704..63d768f 100644 --- a/src/capabilities/specs/interface.py +++ b/src/capabilities/specs/interface.py @@ -485,7 +485,7 @@ def __init__(self, name, spec_version, description=None): def __str__(self): elements = "topics:\n" - required_and_provided = list(list(self.required_topics.keys()) + list(self.provided_topics.keys())) + required_and_provided = list(self.required_topics.keys()) + list(self.provided_topics.keys()) both = [x for x in self.topics if x not in required_and_provided] for name, topic in self.topics.items(): if name not in both: @@ -504,7 +504,7 @@ def __str__(self): elements += "\n ".join(str(topic).splitlines()) elements += "\n" elements += " services:\n" - required_and_provided = list(list(self.required_services.keys()) + list(self.provided_services.keys())) + required_and_provided = list(self.required_services.keys()) + list(self.provided_services.keys()) both = [x for x in self.services if x not in required_and_provided] for name, service in self.services.items(): if name not in both: @@ -523,7 +523,7 @@ def __str__(self): elements += "\n ".join(str(service).splitlines()) elements += "\n" elements += " actions:\n" - required_and_provided = list(list(self.required_actions.keys()) + list(self.provided_actions.keys())) + required_and_provided = list(self.required_actions.keys()) + list(self.provided_actions.keys()) both = [x for x in self.actions if x not in required_and_provided] for name, action in self.actions.items(): if name not in both: @@ -542,7 +542,7 @@ def __str__(self): elements += "\n ".join(str(action).splitlines()) elements += "\n" elements += " parameters:\n" - required_and_provided = list(list(self.required_parameters.keys()) + list(self.provided_parameters.keys())) + required_and_provided = list(self.required_parameters.keys()) + list(self.provided_parameters.keys()) both = [x for x in self.parameters if x not in required_and_provided] for name, parameter in self.parameters.items(): if name not in both: From 80b1e0bb1f1fcf3d4a83a4b74ee263f23cb6d17b Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Thu, 29 Apr 2021 22:59:48 +0200 Subject: [PATCH 08/15] yaml.load -> yaml.safe_load Signed-off-by: Mikael Arguedas --- src/capabilities/specs/interface.py | 6 +++--- src/capabilities/specs/provider.py | 6 +++--- src/capabilities/specs/semantic_interface.py | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/capabilities/specs/interface.py b/src/capabilities/specs/interface.py index 63d768f..a0c0be5 100644 --- a/src/capabilities/specs/interface.py +++ b/src/capabilities/specs/interface.py @@ -122,7 +122,7 @@ def capability_interface_from_file_path(file_path): :raises: :py:exc:`OSError` if the given file does not exist """ with open(os.path.abspath(file_path), 'r') as f: - return capability_interface_from_dict(yaml.load(f), file_path) + return capability_interface_from_dict(yaml.safe_load(f), file_path) def capability_interface_from_file(file_handle): @@ -136,7 +136,7 @@ def capability_interface_from_file(file_handle): :rtype: :py:class:`CapabilityInterface` :raises: :py:exc:`OSError` if the given file does not exist """ - return capability_interface_from_dict(yaml.load(file_handle.read()), file_handle.name) + return capability_interface_from_dict(yaml.safe_load(file_handle.read()), file_handle.name) def capability_interface_from_string(string, file_name=''): @@ -152,7 +152,7 @@ def capability_interface_from_string(string, file_name=''): :rtype: :py:class:`CapabilityInterface` :raises: :py:exc:`AttributeError` if the given value for string is not a str """ - return capability_interface_from_dict(yaml.load(string), file_name) + return capability_interface_from_dict(yaml.safe_load(string), file_name) def capability_interface_from_dict(spec, file_name=''): diff --git a/src/capabilities/specs/provider.py b/src/capabilities/specs/provider.py index 3170226..b857582 100644 --- a/src/capabilities/specs/provider.py +++ b/src/capabilities/specs/provider.py @@ -109,7 +109,7 @@ def capability_provider_from_file_path(file_path): :raises: :py:exc:`OSError` if the given file does not exist """ with open(os.path.abspath(file_path), 'r') as f: - return capability_provider_from_dict(yaml.load(f.read()), file_path) + return capability_provider_from_dict(yaml.safe_load(f.read()), file_path) def capability_provider_from_file(file_handle): @@ -123,7 +123,7 @@ def capability_provider_from_file(file_handle): :rtype: :py:class:`CapabilityProvider` :raises: :py:exc:`OSError` if the given file does not exist """ - return capability_provider_from_dict(yaml.load(file_handle.read()), file_handle.name) + return capability_provider_from_dict(yaml.safe_load(file_handle.read()), file_handle.name) def capability_provider_from_string(string, file_name=''): @@ -139,7 +139,7 @@ def capability_provider_from_string(string, file_name=''): :rtype: :py:class:`CapabilityProvider` :raises: :py:exc:`AttributeError` if the given value for string is not a str """ - return capability_provider_from_dict(yaml.load(string), file_name) + return capability_provider_from_dict(yaml.safe_load(string), file_name) def capability_provider_from_dict(spec, file_name=''): diff --git a/src/capabilities/specs/semantic_interface.py b/src/capabilities/specs/semantic_interface.py index 92b2ba7..cf5ce85 100644 --- a/src/capabilities/specs/semantic_interface.py +++ b/src/capabilities/specs/semantic_interface.py @@ -116,7 +116,7 @@ def semantic_capability_interface_from_file_path(file_path): :raises: :py:exc:`OSError` if the given file does not exist """ with open(os.path.abspath(file_path), 'r') as f: - return semantic_capability_interface_from_dict(yaml.load(f.read()), file_path) + return semantic_capability_interface_from_dict(yaml.safe_load(f.read()), file_path) def semantic_capability_interface_from_file(file_handle): @@ -130,7 +130,7 @@ def semantic_capability_interface_from_file(file_handle): :rtype: :py:class:`SemanticCapabilityInterface` :raises: :py:exc:`OSError` if the given file does not exist """ - return semantic_capability_interface_from_dict(yaml.load(file_handle.read()), file_handle.name) + return semantic_capability_interface_from_dict(yaml.safe_load(file_handle.read()), file_handle.name) def semantic_capability_interface_from_string(string, file_name=''): @@ -146,7 +146,7 @@ def semantic_capability_interface_from_string(string, file_name=''): :rtype: :py:class:`SemanticCapabilityInterface` :raises: :py:exc:`AttributeError` if the given value for string is not a str """ - return semantic_capability_interface_from_dict(yaml.load(string), file_name) + return semantic_capability_interface_from_dict(yaml.safe_load(string), file_name) def semantic_capability_interface_from_dict(spec, file_name=''): From 146e9911c88c78f06c8325decbed30453f94423b Mon Sep 17 00:00:00 2001 From: Stephan Wirth <1481786+stwirth@users.noreply.github.com> Date: Tue, 25 Jan 2022 11:51:48 +0100 Subject: [PATCH 09/15] Python2.7 compatible StringIO usage --- test/unit/common.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/unit/common.py b/test/unit/common.py index 51300be..84063ba 100644 --- a/test/unit/common.py +++ b/test/unit/common.py @@ -3,7 +3,12 @@ import re import sys -from io import StringIO +try: + # Python 2 + from cStringIO import StringIO +except ImportError: + # Python 3 + from io import StringIO def assert_raises(exception_classes, callable_obj=None, *args, **kwargs): From 92d1c274ca8355a3197e3987162494fe1fe89242 Mon Sep 17 00:00:00 2001 From: Stephan Wirth <1481786+stwirth@users.noreply.github.com> Date: Tue, 25 Jan 2022 12:40:50 +0100 Subject: [PATCH 10/15] Relax some test timeouts --- test/rostest/test_server/test_client.py | 2 +- test/rostest/test_server/test_ros_services.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rostest/test_server/test_client.py b/test/rostest/test_server/test_client.py index 0cae4b2..6246e82 100755 --- a/test/rostest/test_server/test_client.py +++ b/test/rostest/test_server/test_client.py @@ -32,7 +32,7 @@ def wait_for_result_to_happen(expected, initial_result, tries=10, sleep_period=1 class Test(unittest.TestCase): def test_use_and_free_capability(self): - assert wait_for_capability_server(10) + assert wait_for_capability_server(20) c = CapabilitiesClient() c.wait_for_services(timeout=3.0) # Give invalid bond id to use_capability diff --git a/test/rostest/test_server/test_ros_services.test b/test/rostest/test_server/test_ros_services.test index 1acc4fe..0abe310 100644 --- a/test/rostest/test_server/test_ros_services.test +++ b/test/rostest/test_server/test_ros_services.test @@ -17,5 +17,5 @@ 'invalid' - + From fcdae71acb9398f937652a9743fc02579fd84d25 Mon Sep 17 00:00:00 2001 From: Stephan Wirth <1481786+stwirth@users.noreply.github.com> Date: Tue, 25 Jan 2022 13:10:19 +0100 Subject: [PATCH 11/15] Relax more service timeouts --- test/rostest/test_server/test_client.py | 2 +- test/rostest/test_server/test_default_provider.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rostest/test_server/test_client.py b/test/rostest/test_server/test_client.py index 6246e82..43d552a 100755 --- a/test/rostest/test_server/test_client.py +++ b/test/rostest/test_server/test_client.py @@ -32,7 +32,7 @@ def wait_for_result_to_happen(expected, initial_result, tries=10, sleep_period=1 class Test(unittest.TestCase): def test_use_and_free_capability(self): - assert wait_for_capability_server(20) + assert wait_for_capability_server(30) c = CapabilitiesClient() c.wait_for_services(timeout=3.0) # Give invalid bond id to use_capability diff --git a/test/rostest/test_server/test_default_provider.py b/test/rostest/test_server/test_default_provider.py index 73fdb8b..bb7cf27 100755 --- a/test/rostest/test_server/test_default_provider.py +++ b/test/rostest/test_server/test_default_provider.py @@ -16,7 +16,7 @@ class Test(unittest.TestCase): def test_default_provider(self): - assert wait_for_capability_server(10) + assert wait_for_capability_server(30) call_service('/capability_server/start_capability', 'no_default_provider_pkg/Minimal', '') rospy.sleep(1) # Wait for the system to settle resp = call_service('/capability_server/get_running_capabilities') From 0d38752444ab6cf8f574ac49e6232cd3a35ec0e4 Mon Sep 17 00:00:00 2001 From: Stephan Wirth <1481786+stwirth@users.noreply.github.com> Date: Tue, 25 Jan 2022 13:24:00 +0100 Subject: [PATCH 12/15] Fix catkin_lint errors Fixes the following errors reported by catkin_lint: capabilities: error: build_export_depend 'message_runtime' is not listed in catkin_package() capabilities: error: message dependency 'std_srvs' is not listed in catkin_package() capabilities: error: message dependency 'std_msgs' is not listed in catkin_package() capabilities: error: message dependency 'std_srvs' is not listed as build_export_depend capabilities: error: message dependency 'std_msgs' is not listed as build_export_depend --- CMakeLists.txt | 2 +- package.xml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6baaec7..1464f25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,7 @@ add_service_files(FILES generate_messages(DEPENDENCIES std_msgs std_srvs) -catkin_package() +catkin_package(CATKIN_DEPENDS message_runtime std_msgs std_srvs) ## Install scripts catkin_install_python(PROGRAMS scripts/capability_server diff --git a/package.xml b/package.xml index 34a1783..739393a 100644 --- a/package.xml +++ b/package.xml @@ -25,6 +25,8 @@ std_srvs message_runtime + std_msgs + std_srvs bondpy message_runtime From 148d6297e317d40a3f6e30617e751f5fe787a5b0 Mon Sep 17 00:00:00 2001 From: Stephan Wirth <1481786+stwirth@users.noreply.github.com> Date: Thu, 27 Jan 2022 14:34:04 +0100 Subject: [PATCH 13/15] Latch READY message publishing --- src/capabilities/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/capabilities/server.py b/src/capabilities/server.py index 8523323..6bd467c 100644 --- a/src/capabilities/server.py +++ b/src/capabilities/server.py @@ -380,7 +380,7 @@ def spin(self): self.handle_get_remappings) rospy.loginfo("Capability Server Ready") - rospy.Publisher("~events", CapabilityEvent, queue_size=1000).publish( + rospy.Publisher("~events", CapabilityEvent, queue_size=1000, latch=True).publish( CapabilityEvent(type=CapabilityEvent.SERVER_READY)) rospy.spin() From 2937e75fe9bbf60db8893c6b3d8d2d9e693a0327 Mon Sep 17 00:00:00 2001 From: Stephan Wirth <1481786+stwirth@users.noreply.github.com> Date: Tue, 1 Feb 2022 13:48:49 +0100 Subject: [PATCH 14/15] Publish SERVER_READY periodically instead of latched --- src/capabilities/server.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/capabilities/server.py b/src/capabilities/server.py index 6bd467c..fac7a56 100644 --- a/src/capabilities/server.py +++ b/src/capabilities/server.py @@ -380,8 +380,11 @@ def spin(self): self.handle_get_remappings) rospy.loginfo("Capability Server Ready") - rospy.Publisher("~events", CapabilityEvent, queue_size=1000, latch=True).publish( - CapabilityEvent(type=CapabilityEvent.SERVER_READY)) + heartbeat_interval = rospy.get_param('~heartbeat_interval', 1.0) + rospy.Timer( + rospy.Duration(heartbeat_interval), + rospy.Publisher("~events", CapabilityEvent, queue_size=1000).publish( + CapabilityEvent(type=CapabilityEvent.SERVER_READY))) rospy.spin() From 6ce77e2a3a38cd119dec4bf7750c4f9a194d0020 Mon Sep 17 00:00:00 2001 From: Stephan Wirth <1481786+stwirth@users.noreply.github.com> Date: Tue, 1 Feb 2022 14:19:24 +0100 Subject: [PATCH 15/15] Fix Timer callback syntax --- src/capabilities/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/capabilities/server.py b/src/capabilities/server.py index fac7a56..bc5b8ae 100644 --- a/src/capabilities/server.py +++ b/src/capabilities/server.py @@ -383,7 +383,7 @@ def spin(self): heartbeat_interval = rospy.get_param('~heartbeat_interval', 1.0) rospy.Timer( rospy.Duration(heartbeat_interval), - rospy.Publisher("~events", CapabilityEvent, queue_size=1000).publish( + lambda event: rospy.Publisher("~events", CapabilityEvent, queue_size=1000).publish( CapabilityEvent(type=CapabilityEvent.SERVER_READY))) rospy.spin()