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

Source Code for Module roslib.names

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2008, 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$ 
 34   
 35  """ 
 36  Warning: do not use this library.  It is unstable and most of the routines 
 37  here have been superceded by other libraries (e.g. genmsg).  These 
 38  routines will likely be *deleted* in future releases. 
 39  """ 
 40   
 41  import os 
 42  import sys 
 43   
 44  #TODO: deprecate PRN_SEPARATOR 
 45  PRN_SEPARATOR = '/' 
 46  TYPE_SEPARATOR = PRN_SEPARATOR #alias 
 47  SEP = '/' 
 48  GLOBALNS = '/' 
 49  PRIV_NAME = '~' 
 50  REMAP = ":=" 
 51  ANYTYPE = '*' 
 52   
 53  if sys.hexversion > 0x03000000: #Python3 
54 - def isstring(s):
55 return isinstance(s, str) #Python 3.x
56 else:
57 - def isstring(s):
58 """ 59 Small helper version to check an object is a string in a way that works 60 for both Python 2 and 3 61 """ 62 return isinstance(s, basestring) #Python 2.x
63
64 -def get_ros_namespace(env=None, argv=None):
65 """ 66 @param env: environment dictionary (defaults to os.environ) 67 @type env: dict 68 @param argv: command-line arguments (defaults to sys.argv) 69 @type argv: [str] 70 @return: ROS namespace of current program 71 @rtype: str 72 """ 73 #we force command-line-specified namespaces to be globally scoped 74 if argv is None: 75 argv = sys.argv 76 for a in argv: 77 if a.startswith('__ns:='): 78 return make_global_ns(a[len('__ns:='):]) 79 if env is None: 80 env = os.environ 81 return make_global_ns(env.get('ROS_NAMESPACE', GLOBALNS))
82
83 -def make_caller_id(name):
84 """ 85 Resolve a local name to the caller ID based on ROS environment settings (i.e. ROS_NAMESPACE) 86 87 @param name: local name to calculate caller ID from, e.g. 'camera', 'node' 88 @type name: str 89 @return: caller ID based on supplied local name 90 @rtype: str 91 """ 92 return make_global_ns(ns_join(get_ros_namespace(), name))
93
94 -def make_global_ns(name):
95 """ 96 Convert name to a global name with a trailing namespace separator. 97 98 @param name: ROS resource name. Cannot be a ~name. 99 @type name: str 100 @return str: name as a global name, e.g. 'foo' -> '/foo/'. 101 This does NOT resolve a name. 102 @rtype: str 103 @raise ValueError: if name is a ~name 104 """ 105 if is_private(name): 106 raise ValueError("cannot turn [%s] into a global name"%name) 107 if not is_global(name): 108 name = SEP + name 109 if name[-1] != SEP: 110 name = name + SEP 111 return name
112
113 -def is_global(name):
114 """ 115 Test if name is a global graph resource name. 116 117 @param name: must be a legal name in canonical form 118 @type name: str 119 @return: True if name is a globally referenced name (i.e. /ns/name) 120 @rtype: bool 121 """ 122 return name and name[0] == SEP
123
124 -def is_private(name):
125 """ 126 Test if name is a private graph resource name. 127 128 @param name: must be a legal name in canonical form 129 @type name: str 130 @return bool: True if name is a privately referenced name (i.e. ~name) 131 """ 132 return name and name[0] == PRIV_NAME
133
134 -def namespace(name):
135 """ 136 Get the namespace of name. The namespace is returned with a 137 trailing slash in order to favor easy concatenation and easier use 138 within the global context. 139 140 @param name: name to return the namespace of. Must be a legal 141 name. NOTE: an empty name will return the global namespace. 142 @type name: str 143 @return str: Namespace of name. For example, '/wg/node1' returns '/wg/'. The 144 global namespace is '/'. 145 @rtype: str 146 @raise ValueError: if name is invalid 147 """ 148 "map name to its namespace" 149 if name is None: 150 raise ValueError('name') 151 if not isstring(name): 152 raise TypeError('name') 153 if not name: 154 return SEP 155 elif name[-1] == SEP: 156 name = name[:-1] 157 return name[:name.rfind(SEP)+1] or SEP
158
159 -def ns_join(ns, name):
160 """ 161 Join a namespace and name. If name is unjoinable (i.e. ~private or 162 /global) it will be returned without joining 163 164 @param ns: namespace ('/' and '~' are both legal). If ns is the empty string, name will be returned. 165 @type ns: str 166 @param name str: a legal name 167 @return str: name concatenated to ns, or name if it is 168 unjoinable. 169 @rtype: str 170 """ 171 if is_private(name) or is_global(name): 172 return name 173 if ns == PRIV_NAME: 174 return PRIV_NAME + name 175 if not ns: 176 return name 177 if ns[-1] == SEP: 178 return ns + name 179 return ns + SEP + name
180
181 -def load_mappings(argv):
182 """ 183 Load name mappings encoded in command-line arguments. This will filter 184 out any parameter assignment mappings (see roslib.param.load_param_mappings()). 185 186 @param argv: command-line arguments 187 @type argv: [str] 188 @return: name->name remappings. 189 @rtype: dict {str: str} 190 """ 191 mappings = {} 192 for arg in argv: 193 if REMAP in arg: 194 try: 195 src, dst = [x.strip() for x in arg.split(REMAP)] 196 if src and dst: 197 if len(src) > 1 and src[0] == '_' and src[1] != '_': 198 #ignore parameter assignment mappings 199 pass 200 else: 201 mappings[src] = dst 202 except: 203 sys.stderr.write("ERROR: Invalid remapping argument '%s'\n"%arg) 204 return mappings
205 206 ####################################################################### 207 # RESOURCE NAMES 208 # resource names refer to entities in a file system 209
210 -def resource_name(res_pkg_name, name, my_pkg=None):
211 """ 212 Convert package name + resource into a fully qualified resource name 213 214 @param res_pkg_name: name of package resource is located in 215 @type res_pkg_name: str 216 @param name: resource base name 217 @type name: str 218 @param my_pkg: name of package resource is being referred to 219 in. If specified, name will be returned in local form if 220 res_pkg_name is my_pkg 221 @type my_pkg: str 222 @return: name for resource 223 @rtype: str 224 """ 225 if res_pkg_name != my_pkg: 226 return res_pkg_name+PRN_SEPARATOR+name 227 return name
228
229 -def resource_name_base(name):
230 """ 231 pkg/typeName -> typeName, typeName -> typeName 232 233 Convert fully qualified resource name into the package-less resource name 234 @param name: package resource name, e.g. 'std_msgs/String' 235 @type name: str 236 @return: resource name sans package-name scope 237 @rtype: str 238 """ 239 240 return name[name.rfind(PRN_SEPARATOR)+1:]
241
242 -def resource_name_package(name):
243 """ 244 pkg/typeName -> pkg, typeName -> None 245 246 @param name: package resource name, e.g. 'std_msgs/String' 247 @type name: str 248 @return: package name of resource 249 @rtype: str 250 """ 251 252 if not PRN_SEPARATOR in name: 253 return None 254 return name[:name.find(PRN_SEPARATOR)]
255
256 -def package_resource_name(name):
257 """ 258 Split a name into its package and resource name parts, e.g. 'std_msgs/String -> std_msgs, String' 259 260 @param name: package resource name, e.g. 'std_msgs/String' 261 @type name: str 262 @return: package name, resource name 263 @rtype: str 264 @raise ValueError: if name is invalid 265 """ 266 if PRN_SEPARATOR in name: 267 val = tuple(name.split(PRN_SEPARATOR)) 268 if len(val) != 2: 269 raise ValueError("invalid name [%s]"%name) 270 else: 271 return val 272 else: 273 return '', name
274
275 -def _is_safe_name(name, type_name):
276 #windows long-file name length is 255 277 if not isstring(name) or not name or len(name) > 255: 278 return False 279 return is_legal_resource_name(name)
280 281 ################################################################################ 282 # NAME VALIDATORS 283 284 import re 285 #ascii char followed by (alphanumeric, _, /) 286 RESOURCE_NAME_LEGAL_CHARS_P = re.compile('^[A-Za-z][\w_\/]*$') 303 304 #~,/, or ascii char followed by (alphanumeric, _, /) 305 NAME_LEGAL_CHARS_P = re.compile('^[\~\/A-Za-z][\w_\/]*$') 324 325 BASE_NAME_LEGAL_CHARS_P = re.compile('^[A-Za-z][\w_]*$') #ascii char followed by (alphanumeric, _) 335 336 BASE_RESOURCE_NAME_LEGAL_CHARS_P = re.compile('^[A-Za-z][\w_]*$') #ascii char followed by (alphanumeric, _) 347
348 -def canonicalize_name(name):
349 """ 350 Put name in canonical form. Extra slashes '//' are removed and 351 name is returned without any trailing slash, e.g. /foo/bar 352 @param name: ROS name 353 @type name: str 354 """ 355 if not name or name == SEP: 356 return name 357 elif name[0] == SEP: 358 return '/' + '/'.join([x for x in name.split(SEP) if x]) 359 else: 360 return '/'.join([x for x in name.split(SEP) if x])
361
362 -def resolve_name(name, namespace_, remappings=None):
363 """ 364 Resolve a ROS name to its global, canonical form. Private ~names 365 are resolved relative to the node name. 366 367 @param name: name to resolve. 368 @type name: str 369 @param namespace_: node name to resolve relative to. 370 @type namespace_: str 371 @param remappings: Map of resolved remappings. Use None to indicate no remapping. 372 @return: Resolved name. If name is empty/None, resolve_name 373 returns parent namespace_. If namespace_ is empty/None, 374 @rtype: str 375 """ 376 if not name: #empty string resolves to parent of the namespace_ 377 return namespace(namespace_) 378 379 name = canonicalize_name(name) 380 if name[0] == SEP: #global name 381 resolved_name = name 382 elif is_private(name): #~name 383 # #3044: be careful not to accidentally make rest of name global 384 resolved_name = canonicalize_name(namespace_ + SEP + name[1:]) 385 else: #relative 386 resolved_name = namespace(namespace_) + name 387 388 #Mappings override general namespace-based resolution 389 # - do this before canonicalization as remappings are meant to 390 # match the name as specified in the code 391 if remappings and resolved_name in remappings: 392 return remappings[resolved_name] 393 else: 394 return resolved_name
395
396 -def anonymous_name(id):
397 """ 398 Generate a ROS-legal 'anonymous' name 399 400 @param id: prefix for anonymous name 401 @type id: str 402 """ 403 import socket, random 404 name = "%s_%s_%s_%s"%(id, socket.gethostname(), os.getpid(), random.randint(0, sys.maxsize)) 405 # RFC 952 allows hyphens, IP addrs can have '.'s, both 406 # of which are illegal for ROS names. For good 407 # measure, screen ipv6 ':'. 408 name = name.replace('.', '_') 409 name = name.replace('-', '_') 410 return name.replace(':', '_')
411