Package roswtf :: Module context
[frames] | no frames]

Source Code for Module roswtf.context

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2009, Willow Garage, Inc. 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  # 
 10  #  * Redistributions of source code must retain the above copyright 
 11  #    notice, this list of conditions and the following disclaimer. 
 12  #  * Redistributions in binary form must reproduce the above 
 13  #    copyright notice, this list of conditions and the following 
 14  #    disclaimer in the documentation and/or other materials provided 
 15  #    with the distribution. 
 16  #  * Neither the name of Willow Garage, Inc. nor the names of its 
 17  #    contributors may be used to endorse or promote products derived 
 18  #    from this software without specific prior written permission. 
 19  # 
 20  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 21  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 22  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 23  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 24  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 25  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 26  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 28  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 29  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 30  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 31  # POSSIBILITY OF SUCH DAMAGE. 
 32  # 
 33  # Revision $Id: context.py 7871 2010-01-14 18:55:53Z kwc $ 
 34   
 35  """ 
 36  L{WtfContext} object, which is commonly used throughout the roswtf 
 37  APIs to pass state. 
 38  """ 
 39   
 40  import os 
 41  import sys 
 42   
 43  import roslib.manifest 
 44  import roslib.packages 
 45  import roslib.stacks 
 46  import roslib.rosenv 
 47  import roslib.rospack 
 48  import roslib.substitution_args 
 49   
 50  import roslaunch.depends 
 51   
 52  from roswtf.model import WtfWarning 
53 54 -class WtfException(Exception):
55 """ 56 Base exception class of roswtf-related issues. 57 """ 58 pass
59
60 -class WtfContext(object):
61 """ 62 WtfContext stores common state about the ROS filesystem and online 63 environment. The primary use of this is for convenience (not 64 having to load this state manually) and performance (not having to 65 do the same calculation repeatedly). 66 """ 67 __slots__ = ['pkg', 'pkg_dir', 'pkgs', 68 'stack', 'stack_dir', 'stacks', 69 'manifest_file', 'manifest', 70 'env', 'ros_root', 'ros_package_path', 'pythonpath', 71 'ros_master_uri', 72 'roslaunch_uris', 73 'ros_bindeps_path', 74 'ros_boost_root', 75 'launch_files', 76 'launch_file_deps', 77 'launch_file_missing_deps', 78 'system_state', 79 'service_providers', 80 'topics', 'services', 81 'nodes', 'uri_node_map', 82 'expected_edges', 83 'actual_edges', 84 'unconnected_subscriptions', 85 'use_sim_time', 86 'warnings', 'errors'] 87
88 - def __init__(self):
89 # main package we are running 90 self.pkg = None 91 self.pkg_dir = None 92 # main stack we are running 93 self.stack = None 94 self.stack_dir = None 95 96 # - list of all packages involved in this check 97 self.pkgs = [] 98 # - list of all stacks involved in this check 99 self.stacks = [] 100 101 # manifest location of package that we are running 102 self.manifest_file = None 103 # manifest of package that we are running 104 self.manifest = None 105 106 # environment variables 107 self.env = {} 108 109 # provide these for convenience 110 self.ros_root = None 111 self.ros_package_path = None 112 self.pythonpath = None 113 self.ros_bindeps_path = None 114 self.ros_boost_root = None 115 116 # launch file that is being run 117 self.launch_files = None 118 self.launch_file_deps = None 119 self.launch_file_missing_deps = None 120 121 # online state 122 self.roslaunch_uris = None 123 self.system_state = None #master.getSystemState 124 self.topics = None 125 self.services = None 126 self.service_providers = None #names of nodes with services 127 self.nodes = None 128 self.uri_node_map = {} 129 self.expected_edges = None 130 self.actual_edges = None 131 self.unconnected_subscriptions = None 132 self.use_sim_time = None 133 134 # warnings that we have collected so far 135 self.warnings = [] 136 # errors that we have collected so far 137 self.errors = []
138
139 - def as_dictionary(self):
140 """ 141 @return: dictionary representation of context, which is 142 useful for producing error messages 143 @rtype: dict 144 """ 145 return dict((s, getattr(self, s)) for s in self.__slots__)
146 147 @staticmethod
148 - def from_roslaunch(roslaunch_files, env=os.environ):
149 """ 150 @param roslaunch_file: roslaunch_file to load from 151 @type roslaunch_file: str 152 """ 153 # can't go any further if launch file doesn't validate 154 l, c = roslaunch.XmlLoader(), roslaunch.ROSLaunchConfig() 155 for f in roslaunch_files: 156 try: 157 l.load(f, c, verbose=False) 158 except roslaunch.RLException, e: 159 raise WtfException("Unable to load roslaunch file [%s]: %s"%(f, str(e))) 160 161 ctx = WtfContext() 162 ctx.launch_files = roslaunch_files 163 _load_roslaunch(ctx, roslaunch_files) 164 # ctx.pkg and ctx.stack initialized by _load_roslaunch 165 _load_pkg(ctx, ctx.pkg) 166 if ctx.stack: 167 _load_stack(ctx, ctx.stack) 168 _load_env(ctx, env) 169 return ctx
170 171 @staticmethod
172 - def from_stack(stack, env=os.environ):
173 """ 174 Initialize WtfContext from stack. 175 @param stack: stack name 176 @type stack: str 177 @raise WtfException: if context state cannot be initialized 178 """ 179 ctx = WtfContext() 180 _load_stack(ctx, stack) 181 try: 182 ctx.pkgs = roslib.stacks.packages_of(stack) 183 except roslib.stacks.InvalidROSStackException: 184 # this should be handled elsewhere 185 ctx.pkgs = [] 186 _load_env(ctx, env) 187 return ctx
188 189 @staticmethod
190 - def from_package(pkg, env=os.environ):
191 """ 192 Initialize WtfContext from package name. 193 194 @param pkg: package name 195 @type pkg: str 196 @raise WtfException: if context state cannot be initialized 197 """ 198 ctx = WtfContext() 199 _load_pkg(ctx, pkg) 200 stack = roslib.stacks.stack_of(pkg) 201 if stack: 202 _load_stack(ctx, stack) 203 _load_env(ctx, env) 204 return ctx
205 206 @staticmethod
207 - def from_env(env=os.environ):
208 """ 209 Initialize WtfContext from environment. 210 211 @raise WtfException: if context state cannot be initialized 212 """ 213 ctx = WtfContext() 214 _load_env(ctx, env) 215 return ctx
216
217 -def _load_roslaunch(ctx, roslaunch_files):
218 """ 219 Utility for initializing WtfContext state from roslaunch file 220 """ 221 try: 222 base_pkg, file_deps, missing = roslaunch.depends.roslaunch_deps(roslaunch_files) 223 ctx.pkg = base_pkg 224 ctx.launch_file_deps = file_deps 225 ctx.launch_file_missing_deps = missing 226 except roslib.substitution_args.SubstitutionException, se: 227 raise WtfException("Cannot load roslaunch file(s): "+str(se)) 228 except roslaunch.depends.RoslaunchDepsException, e: 229 raise WtfException(str(e))
230
231 -def _load_pkg(ctx, pkg):
232 """ 233 Utility for initializing WtfContext state 234 @raise WtfException: if context state cannot be initialized 235 """ 236 ctx.pkg = pkg 237 ctx.pkgs = [pkg] + roslib.rospack.rospack_depends(pkg) 238 try: 239 ctx.pkg_dir = roslib.packages.get_pkg_dir(pkg) 240 ctx.manifest_file = roslib.manifest.manifest_file(pkg) 241 ctx.manifest = roslib.manifest.parse_file(roslib.manifest.manifest_file(pkg)) 242 except roslib.packages.InvalidROSPkgException: 243 raise WtfException("Cannot locate manifest file for package [%s]"%pkg) 244 except roslib.manifest.ManifestException, e: 245 raise WtfException("Package [%s] has an invalid manifest: %s"%(pkg, e))
246
247 -def _load_stack(ctx, stack):
248 """ 249 Utility for initializing WtfContext state 250 @raise WtfException: if context state cannot be initialized 251 """ 252 try: 253 ctx.stack = stack 254 ctx.stacks = [stack] + roslib.rospack.rosstack_depends(stack) 255 try: 256 ctx.stack_dir = roslib.stacks.get_stack_dir(stack) 257 except roslib.stacks.InvalidROSStackException: 258 raise WtfException("[%s] appears to be a stack, but it's not on your ROS_PACKAGE_PATH"%stack) 259 except roslib.stacks.InvalidROSStackException: 260 raise WtfException("[%s] appears to be a stack, but it's not on your ROS_PACKAGE_PATH"%stack)
261
262 263 -def _load_env(ctx,env):
264 """ 265 Utility for initializing WtfContext state 266 267 @raise WtfException: if context state cannot be initialized 268 """ 269 ctx.env = env 270 try: 271 ctx.ros_root = env[roslib.rosenv.ROS_ROOT] 272 except KeyError: 273 raise WtfException("ROS_ROOT is not set") 274 ctx.ros_package_path = env.get(roslib.rosenv.ROS_PACKAGE_PATH, None) 275 ctx.pythonpath = env.get('PYTHONPATH', None) 276 ctx.ros_master_uri = env.get(roslib.rosenv.ROS_MASTER_URI, None) 277 ctx.ros_bindeps_path = env.get(roslib.rosenv.ROS_BINDEPS_PATH, None) 278 ctx.ros_boost_root = env.get(roslib.rosenv.ROS_BOOST_ROOT, None)
279