Source code for rocon_python_utils.ros.resources

#
# License: BSD
#   https://raw.github.com/robotics-in-concert/rocon_tools/license/LICENSE
#
##############################################################################
# Description
##############################################################################

"""
.. module:: ros.resources
   :platform: Unix
   :synopsis: Helpers for working with ros resource names.

This module contains helpers that lookup or collect an index of ros resource
names for various purposes.

----

"""

##############################################################################
# Imports
##############################################################################

# system
import os

# ros
import rospkg
import roslib.names

from .catkin import package_index_from_package_path

##############################################################################
# Resources
##############################################################################


[docs]def find_resource_from_string(resource, rospack=None, extension=None): ''' Convenience wrapper around roslib to find a resource (file) inside a package. This function passes off the work to find_resource once the input string is split. Pass it a shared rospack (:class:`.rospkg.RosPack`) object to accelerate the crawling across the ROS_PACKAGE_PATH when you are calling this function for many resources consecutively. .. code-block:: python rospack = rospkg.RosPack() for ros_resource_name in ['rocon_interactions/pc.interactions', 'rocon_interactions/demo.interactions'] filename = find_resource_from_string(ros_resource_name, rospack) # do something :param str resource: ros resource name (in the form package/filename) :param rospack: a caching utility to help accelerate catkin filesystem lookups :type rospack: :class:`.rospkg.RosPack` :param str extension: file name extension to look for/expect :returns: full pathname to the resource :rtype: str :raises: :exc:`.rospkg.ResourceNotFound` raised if the resource is not found or has an inappropriate extension. ''' if extension is not None: filename_extension = os.path.splitext(resource)[-1] if filename_extension == '': # no ext given resource += ".%s" % extension elif filename_extension != "." + extension and filename_extension != extension: raise rospkg.ResourceNotFound("resource with invalid filename extension specified [%s][%s]" % (resource, extension)) package, filename = roslib.names.package_resource_name(resource) if not package: raise rospkg.ResourceNotFound("resource could not be split with a valid leading package name [%s]" % (resource)) return find_resource(package, filename, rospack)
[docs]def find_resource(package, filename, rospack=None): ''' Convenience wrapper around roslib to find a resource (file) inside a package. It checks the output, and provides the appropriate error if there is one. :param str package: ros package :param str filename: some file inside the specified package :returns: absolute path to the file :rtype: str :raises: :exc:`.rospkg.ResourceNotFound` : raised if there is nothing found or multiple objects found. ''' try: resolved = roslib.packages.find_resource(package, filename, rospack=rospack) if not resolved: raise rospkg.ResourceNotFound("cannot locate [%s] in package [%s]" % (filename, package)) elif len(resolved) == 1: return resolved[0] elif len(resolved) > 1: raise rospkg.ResourceNotFound("multiple resources named [%s] in package [%s]:%s\nPlease specify full path instead" % (filename, package, ''.join(['\n- %s' % r for r in resolved]))) except rospkg.ResourceNotFound: raise rospkg.ResourceNotFound("[%s] is not a package or launch file name [%s]" % (package, package + '/' + filename)) return None
[docs]def resource_index_from_package_exports(export_tag, package_paths=None, package_whitelist=None, package_blacklist=[]): ''' Scans the package path looking for exports and grab the ones we are interested in. :param str export_tag: export tagname :param package_paths: list of package paths to scan over :type package_paths: str[] :param package_whitelist: list of packages to include (and no other) :type package_paths: str[] :param package_blacklist: list of packages to exclude :type package_paths: str[] :returns: the dictionary of resource and its absolute path :rtype: dict { resource_name : os.path } ''' package_index = _get_package_index(package_paths) resources = {} invalid_resources = {} for package in package_index.values(): if package_whitelist: if package.name not in package_whitelist: continue elif package.name in package_blacklist: continue for export in package.exports: if export.tagname == export_tag: filename_relative_path = export.content resource_name = package.name + '/' + os.path.splitext(os.path.basename(filename_relative_path))[0] resource_filename = os.path.join(os.path.dirname(package.filename), filename_relative_path) if not os.path.isfile(resource_filename): invalid_resources[resource_name] = resource_filename else: resources[resource_name] = (resource_filename, package) return (resources, invalid_resources)
def _get_package_index(package_paths): # should make use of rospkg.get_ros_paths here. # http://docs.ros.org/independent/api/rospkg/html/rospkg_environment.html ros_package_path = package_paths if package_paths else os.getenv('ROS_PACKAGE_PATH', '') ros_package_path = [x for x in ros_package_path.split(':') if x] package_index = package_index_from_package_path(ros_package_path) return package_index