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 re 
 44   
 45  import roslib.packages 
 46  import roslib.stack_manifest 
 47   
 48  import rospkg 
 49   
 50  ROS_ROOT = rospkg.environment.ROS_ROOT 
 51  ROS_PACKAGE_PATH = rospkg.environment.ROS_PACKAGE_PATH 
 52   
 53  STACK_FILE = 'stack.xml' 
 54  ROS_STACK = 'ros' 
 55   
 56   
57 -class ROSStackException(Exception):
58 pass
59 60
61 -class InvalidROSStackException(ROSStackException):
62 pass
63 64
65 -def stack_of(pkg, env=None):
66 """ 67 @param env: override environment variables 68 @type env: {str: str} 69 @return: name of stack that pkg is in, or None if pkg is not part of a stack 70 @rtype: str 71 @raise roslib.packages.InvalidROSPkgException: if pkg cannot be located 72 """ 73 if env is None: 74 env = os.environ 75 pkg_dir = roslib.packages.get_pkg_dir(pkg, ros_root=env[ROS_ROOT], ros_package_path=env.get(ROS_PACKAGE_PATH, None)) 76 d = pkg_dir 77 while d and os.path.dirname(d) != d: 78 stack_file = os.path.join(d, STACK_FILE) 79 if os.path.exists(stack_file): 80 # TODO: need to resolve issues regarding whether the 81 # stack.xml or the directory defines the stack name 82 return os.path.basename(d) 83 d = os.path.dirname(d)
84 85
86 -def get_stack_dir(stack, env=None):
87 """ 88 Get the directory of a ROS stack. This will initialize an internal 89 cache and return cached results if possible. 90 91 This routine is not thread-safe to os.environ changes. 92 93 @param env: override environment variables 94 @type env: {str: str} 95 @param stack: name of ROS stack to locate on disk 96 @type stack: str 97 @return: directory of stack. 98 @rtype: str 99 @raise InvalidROSStackException: if stack cannot be located. 100 """ 101 _init_rosstack(env=env) 102 try: 103 return _rosstack.get_path(stack) 104 except rospkg.ResourceNotFound: 105 # preserve old signature 106 raise InvalidROSStackException(stack)
107 108 109 _rosstack = None 110 _ros_paths = None 111 112
113 -def _init_rosstack(env=None):
114 global _rosstack, _ros_paths 115 if env is None: 116 env = os.environ 117 ros_paths = rospkg.get_ros_paths(env) 118 if ros_paths != _ros_paths: 119 _ros_paths = ros_paths 120 _rosstack = rospkg.RosStack(ros_paths)
121 122
123 -def list_stacks(env=None):
124 """ 125 Get list of all ROS stacks. This uses an internal cache. 126 127 This routine is not thread-safe to os.environ changes. 128 129 @param env: override environment variables 130 @type env: {str: str} 131 @return: complete list of stacks names in ROS environment 132 @rtype: [str] 133 """ 134 _init_rosstack(env=env) 135 return _rosstack.list()
136 137
138 -def list_stacks_by_path(path, stacks=None, cache=None):
139 """ 140 List ROS stacks within the specified path. 141 142 Optionally, a cache dictionary can be provided, which will be 143 updated with the stack->path mappings. list_stacks_by_path() does 144 NOT returned cached results -- it only updates the cache. 145 146 @param path: path to list stacks in 147 @type path: str 148 @param stacks: list of stacks to append to. If stack is 149 already present in stacks, it will be ignored. 150 @type stacks: [str] 151 @param cache: (optional) stack path cache to update. Maps stack name to directory path. 152 @type cache: {str: str} 153 @return: complete list of stack names in ROS environment. Same as stacks parameter. 154 @rtype: [str] 155 """ 156 if stacks is None: 157 stacks = [] 158 MANIFEST_FILE = rospkg.MANIFEST_FILE 159 basename = os.path.basename 160 for d, dirs, files in os.walk(path, topdown=True): 161 if STACK_FILE in files: 162 stack = basename(d) 163 if stack not in stacks: 164 stacks.append(stack) 165 if cache is not None: 166 cache[stack] = d 167 del dirs[:] 168 continue # leaf 169 elif MANIFEST_FILE in files: 170 del dirs[:] 171 continue # leaf 172 elif 'rospack_nosubdirs' in files: 173 del dirs[:] 174 continue # leaf 175 # remove hidden dirs (esp. .svn/.git) 176 [dirs.remove(di) for di in dirs if di[0] == '.'] 177 for sub_d in dirs: 178 # followlinks=True only available in Python 2.6, so we 179 # have to implement manually 180 sub_p = os.path.join(d, sub_d) 181 if os.path.islink(sub_p): 182 stacks.extend(list_stacks_by_path(sub_p, cache=cache)) 183 return stacks
184 185 186 # #2022
187 -def expand_to_packages(names, env=None):
188 """ 189 Expand names into a list of packages. Names can either be of packages or stacks. 190 191 @param names: names of stacks or packages 192 @type names: [str] 193 @return: ([packages], [not_found]). expand_packages() returns two 194 lists. The first is of packages names. The second is a list of 195 names for which no matching stack or package was found. Lists may have duplicates. 196 @rtype: ([str], [str]) 197 """ 198 if env is None: 199 env = os.environ 200 ros_paths = rospkg.get_ros_paths(env) 201 rospack = rospkg.RosPack(ros_paths) 202 rosstack = rospkg.RosStack(ros_paths) 203 return rospkg.expand_to_packages(names, rospack, rosstack)
204 205
206 -def get_stack_version(stack, env=None):
207 """ 208 @param env: override environment variables 209 @type env: {str: str} 210 211 @return: version number of stack, or None if stack is unversioned. 212 @rtype: str 213 """ 214 _init_rosstack(env=env) 215 return _rosstack.get_stack_version(stack)
216 217
218 -def get_stack_version_by_dir(stack_dir):
219 """ 220 Get stack version where stack_dir points to root directory of stack. 221 222 @param env: override environment variables 223 @type env: {str: str} 224 225 @return: version number of stack, or None if stack is unversioned. 226 @rtype: str 227 """ 228 # REP 109: check for <version> tag first, then CMakeLists.txt 229 manifest_filename = os.path.join(stack_dir, STACK_FILE) 230 if os.path.isfile(manifest_filename): 231 m = roslib.stack_manifest.parse_file(manifest_filename) 232 if m.version: 233 return m.version 234 235 cmake_filename = os.path.join(stack_dir, 'CMakeLists.txt') 236 if os.path.isfile(cmake_filename): 237 with open(cmake_filename) as f: 238 return _get_cmake_version(f.read()) 239 else: 240 return None
241 242
243 -def _get_cmake_version(text):
244 for l in text.split('\n'): 245 if l.strip().startswith('rosbuild_make_distribution'): 246 x_re = re.compile(r'[()]') 247 lsplit = x_re.split(l.strip()) 248 if len(lsplit) < 2: 249 raise ReleaseException("couldn't find version number in CMakeLists.txt:\n\n%s" % l) 250 return lsplit[1]
251