Package roslib :: Module stacks
[frames] | no frames]

Source Code for Module roslib.stacks

  1  #! /usr/bin/env python 
  2  # Software License Agreement (BSD License) 
  3  # 
  4  # Copyright (c) 2008, Willow Garage, Inc. 
  5  # All rights reserved. 
  6  # 
  7  # Redistribution and use in source and binary forms, with or without 
  8  # modification, are permitted provided that the following conditions 
  9  # are met: 
 10  # 
 11  #  * Redistributions of source code must retain the above copyright 
 12  #    notice, this list of conditions and the following disclaimer. 
 13  #  * Redistributions in binary form must reproduce the above 
 14  #    copyright notice, this list of conditions and the following 
 15  #    disclaimer in the documentation and/or other materials provided 
 16  #    with the distribution. 
 17  #  * Neither the name of Willow Garage, Inc. nor the names of its 
 18  #    contributors may be used to endorse or promote products derived 
 19  #    from this software without specific prior written permission. 
 20  # 
 21  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 22  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 23  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 24  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 25  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 26  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 27  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 28  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 29  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 30  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 31  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 32  # POSSIBILITY OF SUCH DAMAGE. 
 33  # 
 34  # Revision $Id$ 
 35   
 36  """ 
 37  Warning: do not use this library.  It is unstable and most of the routines 
 38  here have been superceded by other libraries (e.g. rospkg).  These 
 39  routines will likely be *deleted* in future releases. 
 40  """ 
 41   
 42  import os 
 43  import sys 
 44  import re 
 45   
 46  import roslib.packages 
 47  import roslib.stack_manifest 
 48   
 49  import rospkg 
 50   
 51  ROS_ROOT=rospkg.environment.ROS_ROOT 
 52  ROS_PACKAGE_PATH=rospkg.environment.ROS_PACKAGE_PATH 
 53   
 54  STACK_FILE = 'stack.xml' 
 55  ROS_STACK = 'ros' 
 56   
57 -class ROSStackException(Exception): pass
58 -class InvalidROSStackException(ROSStackException): pass
59
60 -def stack_of(pkg, env=None):
61 """ 62 @param env: override environment variables 63 @type env: {str: str} 64 @return: name of stack that pkg is in, or None if pkg is not part of a stack 65 @rtype: str 66 @raise roslib.packages.InvalidROSPkgException: if pkg cannot be located 67 """ 68 if env is None: 69 env = os.environ 70 pkg_dir = roslib.packages.get_pkg_dir(pkg, ros_root=env[ROS_ROOT], ros_package_path=env.get(ROS_PACKAGE_PATH, None)) 71 d = pkg_dir 72 while d and os.path.dirname(d) != d: 73 stack_file = os.path.join(d, STACK_FILE) 74 if os.path.exists(stack_file): 75 #TODO: need to resolve issues regarding whether the 76 #stack.xml or the directory defines the stack name 77 return os.path.basename(d) 78 d = os.path.dirname(d)
79
80 -def get_stack_dir(stack, env=None):
81 """ 82 Get the directory of a ROS stack. This will initialize an internal 83 cache and return cached results if possible. 84 85 This routine is not thread-safe to os.environ changes. 86 87 @param env: override environment variables 88 @type env: {str: str} 89 @param stack: name of ROS stack to locate on disk 90 @type stack: str 91 @return: directory of stack. 92 @rtype: str 93 @raise InvalidROSStackException: if stack cannot be located. 94 """ 95 _init_rosstack(env=env) 96 try: 97 return _rosstack.get_path(stack) 98 except rospkg.ResourceNotFound: 99 # preserve old signature 100 raise InvalidROSStackException(stack)
101 102 _rosstack = None 103 _ros_paths = None 104
105 -def _init_rosstack(env=None):
106 global _rosstack, _ros_paths 107 if env is None: 108 env = os.environ 109 ros_paths = rospkg.get_ros_paths(env) 110 if ros_paths != _ros_paths: 111 _ros_paths = ros_paths 112 _rosstack = rospkg.RosStack(ros_paths)
113
114 -def list_stacks(env=None):
115 """ 116 Get list of all ROS stacks. This uses an internal cache. 117 118 This routine is not thread-safe to os.environ changes. 119 120 @param env: override environment variables 121 @type env: {str: str} 122 @return: complete list of stacks names in ROS environment 123 @rtype: [str] 124 """ 125 _init_rosstack(env=env) 126 return _rosstack.list()
127
128 -def list_stacks_by_path(path, stacks=None, cache=None):
129 """ 130 List ROS stacks within the specified path. 131 132 Optionally, a cache dictionary can be provided, which will be 133 updated with the stack->path mappings. list_stacks_by_path() does 134 NOT returned cached results -- it only updates the cache. 135 136 @param path: path to list stacks in 137 @type path: str 138 @param stacks: list of stacks to append to. If stack is 139 already present in stacks, it will be ignored. 140 @type stacks: [str] 141 @param cache: (optional) stack path cache to update. Maps stack name to directory path. 142 @type cache: {str: str} 143 @return: complete list of stack names in ROS environment. Same as stacks parameter. 144 @rtype: [str] 145 """ 146 if stacks is None: 147 stacks = [] 148 MANIFEST_FILE = rospkg.MANIFEST_FILE 149 basename = os.path.basename 150 for d, dirs, files in os.walk(path, topdown=True): 151 if STACK_FILE in files: 152 stack = basename(d) 153 if stack not in stacks: 154 stacks.append(stack) 155 if cache is not None: 156 cache[stack] = d 157 del dirs[:] 158 continue #leaf 159 elif MANIFEST_FILE in files: 160 del dirs[:] 161 continue #leaf 162 elif 'rospack_nosubdirs' in files: 163 del dirs[:] 164 continue #leaf 165 # remove hidden dirs (esp. .svn/.git) 166 [dirs.remove(di) for di in dirs if di[0] == '.'] 167 for sub_d in dirs: 168 # followlinks=True only available in Python 2.6, so we 169 # have to implement manually 170 sub_p = os.path.join(d, sub_d) 171 if os.path.islink(sub_p): 172 stacks.extend(list_stacks_by_path(sub_p, cache=cache)) 173 return stacks
174 175 # #2022
176 -def expand_to_packages(names, env=None):
177 """ 178 Expand names into a list of packages. Names can either be of packages or stacks. 179 180 @param names: names of stacks or packages 181 @type names: [str] 182 @return: ([packages], [not_found]). expand_packages() returns two 183 lists. The first is of packages names. The second is a list of 184 names for which no matching stack or package was found. Lists may have duplicates. 185 @rtype: ([str], [str]) 186 """ 187 if env is None: 188 env = os.environ 189 ros_paths = rospkg.get_ros_paths(env) 190 rospack = rospkg.RosPack(ros_paths) 191 rosstack = rospkg.RosStack(ros_paths) 192 return rospkg.expand_to_packages(names, rospack, rosstack)
193
194 -def get_stack_version(stack, env=None):
195 """ 196 @param env: override environment variables 197 @type env: {str: str} 198 199 @return: version number of stack, or None if stack is unversioned. 200 @rtype: str 201 """ 202 _init_rosstack(env=env) 203 return _rosstack.get_stack_version(stack)
204
205 -def get_stack_version_by_dir(stack_dir):
206 """ 207 Get stack version where stack_dir points to root directory of stack. 208 209 @param env: override environment variables 210 @type env: {str: str} 211 212 @return: version number of stack, or None if stack is unversioned. 213 @rtype: str 214 """ 215 # REP 109: check for <version> tag first, then CMakeLists.txt 216 manifest_filename = os.path.join(stack_dir, STACK_FILE) 217 if os.path.isfile(manifest_filename): 218 m = roslib.stack_manifest.parse_file(manifest_filename) 219 if m.version: 220 return m.version 221 222 cmake_filename = os.path.join(stack_dir, 'CMakeLists.txt') 223 if os.path.isfile(cmake_filename): 224 with open(cmake_filename) as f: 225 return _get_cmake_version(f.read()) 226 else: 227 return None
228
229 -def _get_cmake_version(text):
230 for l in text.split('\n'): 231 if l.strip().startswith('rosbuild_make_distribution'): 232 x_re = re.compile(r'[()]') 233 lsplit = x_re.split(l.strip()) 234 if len(lsplit) < 2: 235 raise ReleaseException("couldn't find version number in CMakeLists.txt:\n\n%s"%l) 236 return lsplit[1]
237