00001
00002
00003
00004
00005 '''rtshell
00006
00007 Copyright (C) 2009-2014
00008 Geoffrey Biggs
00009 RT-Synthesis Research Group
00010 Intelligent Systems Research Institute,
00011 National Institute of Advanced Industrial Science and Technology (AIST),
00012 Japan
00013 All rights reserved.
00014 Licensed under the Eclipse Public License -v 1.0 (EPL)
00015 http://www.opensource.org/licenses/eclipse-1.0.txt
00016
00017 Implementation of the command to display component information.
00018
00019 '''
00020
00021
00022 import optparse
00023 import os
00024 import os.path
00025 import rtctree.exceptions
00026 import rtctree.tree
00027 import rtctree.path
00028 import rtctree.utils
00029 import SDOPackage
00030 import sys
00031 import traceback
00032
00033 import path
00034 import rts_exceptions
00035 import rtshell
00036
00037
00038 def format_port(port, comp, start_indent=0, use_colour=True, long=0):
00039 result = []
00040 indent = start_indent
00041 if long > 0:
00042 tag = '-'
00043 else:
00044 tag = '+'
00045 name_string = rtctree.utils.build_attr_string('bold',
00046 supported=use_colour) + port.name + \
00047 rtctree.utils.build_attr_string('reset', supported=use_colour)
00048 result.append('{0}{1}: {2}'.format(tag.rjust(indent), port.porttype,
00049 name_string))
00050 if long > 0:
00051 indent += 2
00052 keys = port.properties.keys()
00053 keys.sort()
00054 pad_length = max([len(key) for key in keys]) + 2
00055 for key in keys:
00056 result.append('{0}{1}{2}'.format(''.ljust(indent),
00057 key.ljust(pad_length), port.properties[key]))
00058 if port.porttype == 'CorbaPort' and port.interfaces:
00059 for intf in port.interfaces:
00060 result.append('{0}Interface:'.format(''.ljust(indent)))
00061 pad_length = 15
00062 indent += 2
00063 result.append('{0}{1}{2}'.format(''.ljust(indent),
00064 'Instance name'.ljust(pad_length),
00065 intf.instance_name))
00066 result.append('{0}{1}{2}'.format(''.ljust(indent),
00067 'Type name'.ljust(pad_length),
00068 intf.type_name))
00069 result.append('{0}{1}{2}'.format(''.ljust(indent),
00070 'Polarity'.ljust(pad_length),
00071 intf.polarity_as_string(add_colour=use_colour)))
00072 indent -= 2
00073 num_conns = len(port.connections)
00074 for conn in port.connections:
00075 if long > 1:
00076 tag2 = '-'
00077 else:
00078 tag2 = '+'
00079 dest_ports = []
00080 for name, p in conn.ports:
00081
00082 if not p:
00083 dest_ports.append(name)
00084 num_conns -= 1
00085
00086 elif not comp.get_port_by_ref(p.object):
00087 dest_ports.append(name)
00088 num_conns -= 1
00089 if dest_ports:
00090 result.append('{0}Connected to {1}'.format(
00091 tag2.rjust(indent), rtctree.utils.build_attr_string('bold',
00092 supported=use_colour) + dest_ports[0] + \
00093 rtctree.utils.build_attr_string('reset',
00094 supported=use_colour)))
00095 if len(dest_ports) > 1:
00096 for dp in dest_ports[1:]:
00097 result.append('{0}{1}{2}'.format(''.ljust(indent),
00098 ''.ljust(14),
00099 rtctree.utils.build_attr_string('bold',
00100 supported=use_colour) + dp + \
00101 rtctree.utils.build_attr_string('reset',
00102 supported=use_colour)))
00103 if long > 1:
00104 indent += 2
00105 keys = [k for k in conn.properties.keys() \
00106 if not k.endswith('inport_ref') \
00107 if not k.endswith('inport_ior')]
00108 pad_length = max([len('Name')] + \
00109 [len(key) for key in keys]) + 2
00110 result.append('{0}{1}{2}'.format(''.ljust(indent),
00111 'Name'.ljust(pad_length), conn.name))
00112 result.append('{0}{1}{2}'.format(''.ljust(indent),
00113 'ID'.ljust(pad_length), conn.id))
00114 for key in keys:
00115 result.append('{0}{1}{2}'.format(''.ljust(indent),
00116 key.ljust(pad_length),
00117 conn.properties[key]))
00118 indent -= 2
00119 if num_conns > 0:
00120 if num_conns > 1:
00121 plural = 's'
00122 else:
00123 plural = ''
00124 result.append('{0}({1} other connection{2})'.format(\
00125 ''.rjust(indent), num_conns, plural))
00126 indent -= 2
00127 return result
00128
00129
00130 def find_composite_comp(tree, member, inst_name):
00131 def get_fp(mgr, args):
00132 for c in mgr.components:
00133 if c.instance_name == inst_name:
00134 return c.full_path_str
00135 return None
00136 def is_correct_mgr(node):
00137 has_member = False
00138 has_inst_name = False
00139 for c in node.components:
00140 if c.instance_name == inst_name:
00141 has_inst_name = True
00142 elif c.instance_name == member.instance_name:
00143 has_member = True
00144 return has_member and has_inst_name
00145 return tree.iterate(get_fp, filter=['is_manager', is_correct_mgr])
00146
00147
00148 def format_composite(comp, tree, start_indent=0, use_colour=True, long=0):
00149 result = []
00150 indent = start_indent
00151 for o in comp.organisations:
00152 if not o.sdo_id:
00153 sdo_id = 'Unknown'
00154 else:
00155 sdo_id = o.sdo_id
00156 id_str = rtctree.utils.build_attr_string('bold',
00157 supported=use_colour) + sdo_id + \
00158 rtctree.utils.build_attr_string('reset',
00159 supported=use_colour)
00160 if long > 0:
00161 tag = '-'
00162 else:
00163 tag = '+'
00164 result.append('{0}Composition {1}'.format(tag.rjust(indent),
00165 id_str))
00166 if long > 0:
00167 indent += 2
00168 padding = 8
00169 result.append('{0}{1}{2}'.format(''.ljust(indent),
00170 'ID'.ljust(padding), o.org_id))
00171 for m in o.members:
00172 c_path = find_composite_comp(tree, comp, m)
00173 if c_path:
00174 result.append('{0}{1}{2}'.format(''.ljust(indent),
00175 'Member'.ljust(padding), c_path[0]))
00176 else:
00177 result.append('{0}{1}{2}'.format(''.ljust(indent),
00178 'Member'.ljust(padding), 'Unknown'))
00179 indent -= 2
00180 return result
00181
00182
00183 def format_comp_member(comp, tree, start_indent=0, use_colour=True, long=0):
00184 result = []
00185 indent = start_indent
00186 for po in comp.parent_organisations:
00187 if not po.sdo_id:
00188 sdo_id = 'Unknown'
00189 else:
00190 sdo_id = po.sdo_id
00191 id_str = rtctree.utils.build_attr_string('bold',
00192 supported=use_colour) + sdo_id + \
00193 rtctree.utils.build_attr_string('reset',
00194 supported=use_colour)
00195 if long > 0:
00196 tag = '-'
00197 else:
00198 tag = '+'
00199 result.append('{0}Parent composition {1}'.format(tag.rjust(indent),
00200 id_str))
00201 if long > 0:
00202 indent += 2
00203 padding = 6
00204 result.append('{0}{1}{2}'.format(''.ljust(indent),
00205 'ID'.ljust(padding), po.org_id))
00206 composite_path = find_composite_comp(tree, comp, po.sdo_id)
00207 if composite_path:
00208 result.append('{0}{1}{2}'.format(''.ljust(indent),
00209 'Path'.ljust(padding), composite_path[0]))
00210 else:
00211 result.append('{0}{1}{2}'.format(''.ljust(indent),
00212 'Path'.ljust(padding), 'Unknown'))
00213 indent -= 2
00214 return result
00215
00216
00217 def format_ec(ec, start_indent=0, use_colour=True, long=0):
00218 result = []
00219 indent = start_indent
00220 handle_str = rtctree.utils.build_attr_string('bold',
00221 supported=use_colour) + str(ec.handle) + \
00222 rtctree.utils.build_attr_string('reset',
00223 supported=use_colour)
00224 if long > 0:
00225 result.append('{0}Execution Context {1}'.format(\
00226 '-'.rjust(indent), handle_str))
00227 padding = 7
00228 indent += 2
00229 result.append('{0}{1}{2}'.format(''.ljust(indent),
00230 'State'.ljust(padding),
00231 ec.running_as_string(add_colour=use_colour)))
00232 result.append('{0}{1}{2}'.format(''.ljust(indent),
00233 'Kind'.ljust(padding),
00234 ec.kind_as_string(add_colour=use_colour)))
00235 result.append('{0}{1}{2}'.format(''.ljust(indent),
00236 'Rate'.ljust(padding), ec.rate))
00237 if ec.owner_name:
00238 result.append('{0}{1}{2}'.format(''.ljust(indent),
00239 'Owner'.ljust(padding), ec.owner_name))
00240 if ec.participant_names:
00241 if long > 1:
00242 result.append('{0}{1}'.format('-'.rjust(indent),
00243 'Participants'.ljust(padding)))
00244 indent += 2
00245 for pn in ec.participant_names:
00246 result.append('{0}{1}'.format(''.ljust(indent),
00247 pn))
00248 indent -= 2
00249 else:
00250 result.append('{0}{1}'.format('+'.rjust(indent),
00251 'Participants'.ljust(padding)))
00252 if ec.properties:
00253 if long > 1:
00254 result.append('{0}{1}'.format('-'.rjust(indent),
00255 'Extra properties'.ljust(padding)))
00256 indent += 2
00257 keys = ec.properties.keys()
00258 keys.sort()
00259 pad_length = max([len(key) for key in keys]) + 2
00260 for key in keys:
00261 result.append('{0}{1}{2}'.format(''.ljust(indent),
00262 key.ljust(pad_length), ec.properties[key]))
00263 indent -= 2
00264 else:
00265 result.append('{0}{1}'.format('+'.rjust(indent),
00266 'Extra properties'.ljust(padding)))
00267 indent -= 2
00268 else:
00269 result.append('{0}Execution Context {1}'.format(\
00270 '+'.rjust(indent), handle_str))
00271 return result
00272
00273
00274 def format_component(comp, tree, use_colour=True, long=0):
00275 result = []
00276 result.append('{0} {1}'.format(comp.name,
00277 comp.get_state_string(add_colour=use_colour)))
00278
00279 indent = 2
00280 profile_items = [('Category', comp.category),
00281 ('Description', comp.description),
00282 ('Instance name', comp.instance_name),
00283 ('Type name', comp.type_name),
00284 ('Vendor', comp.vendor),
00285 ('Version', comp.version)]
00286 if comp.parent:
00287 profile_items.append(('Parent', comp.parent_object))
00288 if comp.is_composite:
00289 if comp.is_composite_member:
00290 profile_items.append(('Type', 'Composite composite member'))
00291 else:
00292 profile_items.append(('Type', 'Composite'))
00293 elif comp.is_composite_member:
00294 profile_items.append(('Type', 'Monolithic composite member'))
00295 else:
00296 profile_items.append(('Type', 'Monolithic'))
00297 pad_length = max([len(item[0]) for item in profile_items]) + 2
00298 for item in profile_items:
00299 result.append('{0}{1}{2}'.format(''.ljust(indent),
00300 item[0].ljust(pad_length),
00301 item[1]))
00302
00303 if comp.properties:
00304 if long > 1:
00305 result.append('{0}Extra properties:'.format(''.ljust(indent)))
00306 indent += 2
00307 extra_props = comp.properties
00308 keys = extra_props.keys()
00309 keys.sort()
00310 pad_length = max([len(key) for key in keys]) + 2
00311 for key in keys:
00312 result.append('{0}{1}{2}'.format(''.ljust(indent),
00313 key.ljust(pad_length),
00314 extra_props[key]))
00315 else:
00316 result.append('{0}{1}'.format('+'.rjust(indent),
00317 'Extra properties'))
00318 indent -= 2
00319
00320 if comp.is_composite:
00321 result += format_composite(comp, tree, start_indent=indent,
00322 use_colour=use_colour, long=long)
00323 if comp.is_composite_member:
00324 result += format_comp_member(comp, tree, start_indent=indent,
00325 use_colour=use_colour, long=long)
00326 for ec in comp.owned_ecs:
00327 result += format_ec(ec, start_indent=indent,
00328 use_colour=use_colour, long=long)
00329 for p in comp.ports:
00330 result += format_port(p, comp, start_indent=indent,
00331 use_colour=use_colour, long=long)
00332
00333 return result
00334
00335
00336 def format_manager(mgr, use_colour=True, long=0):
00337 def add_profile_entry(dest, title, key):
00338 if key in mgr.profile:
00339 dest.append('{0}: {1}'.format(title, mgr.profile[key]))
00340 else:
00341 print >>sys.stderr, '{0}: Warning: "{1}" profile entry is \
00342 missing. Possible version conflict between rtshell and OpenRTM-aist.'.format(\
00343 sys.argv[0], key)
00344
00345 result = []
00346 add_profile_entry(result, 'Name', 'name')
00347 add_profile_entry(result, 'Instance name', 'instance_name')
00348 add_profile_entry(result, 'Process ID', 'pid')
00349 add_profile_entry(result, 'Naming format', 'naming_formats')
00350 add_profile_entry(result, 'Refstring path', 'refstring_path')
00351 add_profile_entry(result, 'Components precreate', 'components.precreate')
00352 result.append('Modules:')
00353 add_profile_entry(result, ' Load path', 'modules.load_path')
00354 add_profile_entry(result, ' Config path', 'modules.config_path')
00355 add_profile_entry(result, ' Preload', 'modules.preload')
00356 add_profile_entry(result, ' Init function prefix',
00357 'modules.init_func_prefix')
00358 add_profile_entry(result, ' Init function suffix',
00359 'modules.init_func_suffix')
00360 add_profile_entry(result, ' Download allowed',
00361 'modules.download_allowed')
00362 add_profile_entry(result, ' Absolute path allowed',
00363 'modules.abs_path_allowed')
00364 result.append('OS:')
00365 add_profile_entry(result, ' Version', 'os.version')
00366 add_profile_entry(result, ' Architecture', 'os.arch')
00367 add_profile_entry(result, ' Release', 'os.release')
00368 add_profile_entry(result, ' Host name', 'os.hostname')
00369 add_profile_entry(result, ' Name', 'os.name')
00370
00371 result.append('Loaded modules:')
00372 for lm in mgr.loaded_modules:
00373 result.append(' Filepath: {0}'.format(lm['file_path']))
00374
00375 result.append('Loadable modules:')
00376 for lm in mgr.loadable_modules:
00377 result.append(' {0}'.format(lm['module_file_path']))
00378
00379 return result
00380
00381
00382 def cat_target(cmd_path, full_path, options, tree=None):
00383 use_colour = rtctree.utils.colour_supported(sys.stdout)
00384
00385 path, port = rtctree.path.parse_path(full_path)
00386 if not path[-1]:
00387
00388 trailing_slash = True
00389 path = path[:-1]
00390 else:
00391 trailing_slash = False
00392
00393 if not tree:
00394 if options.long > 0:
00395
00396 filter = []
00397 else:
00398 filter = [path]
00399 tree = rtctree.tree.RTCTree(paths=path, filter=filter)
00400
00401 if not tree.has_path(path):
00402 raise rts_exceptions.NoSuchObjectError(cmd_path)
00403 object = tree.get_node(path)
00404 if port:
00405 if not object.is_component:
00406 raise rts_exceptions.NotAComponentError(cmd_path)
00407 if trailing_slash:
00408 raise rts_exceptions.NoSuchObjectError(cmd_path)
00409 p = object.get_port_by_name(port)
00410 if not p:
00411 raise rts_exceptions.PortNotFoundError(path, port)
00412 return format_port(p, object, start_indent=0,
00413 use_colour=use_colour, long=options.long)
00414 else:
00415 if object.is_component:
00416 if trailing_slash:
00417 raise rts_exceptions.NoSuchObjectError(cmd_path)
00418 return format_component(object, tree, use_colour=use_colour,
00419 long=options.long)
00420 elif object.is_manager:
00421 return format_manager(object, use_colour=use_colour,
00422 long=options.long)
00423 elif object.is_zombie:
00424 raise rts_exceptions.ZombieObjectError(cmd_path)
00425 else:
00426 raise rts_exceptions.NoSuchObjectError(cmd_path)
00427
00428
00429 def main(argv=None, tree=None):
00430 usage = '''Usage: %prog [options] [path]
00431 Display information about a manager or component.'''
00432 version = rtshell.RTSH_VERSION
00433 parser = optparse.OptionParser(usage=usage, version=version)
00434 parser.add_option('-l', dest='long', action='count', default=0,
00435 help='Show more information. Specify multiple times for even '\
00436 'more information. [Default: False]')
00437 parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
00438 default=False,
00439 help='Output verbose information. [Default: %default]')
00440
00441 if argv:
00442 sys.argv = [sys.argv[0]] + argv
00443 try:
00444 options, args = parser.parse_args()
00445 except optparse.OptionError, e:
00446 print >>sys.stderr, 'OptionError:', e
00447 return 1, []
00448
00449 if not args:
00450
00451 print >>sys.stderr, '{0}: Cannot cat a directory.'.format(
00452 os.path.basename(sys.argv[0]))
00453 return 1, []
00454 elif len(args) == 1:
00455 cmd_path = args[0]
00456 else:
00457 print >>sys.stderr, usage
00458 return 1, []
00459 full_path = path.cmd_path_to_full_path(cmd_path)
00460
00461 result = []
00462 try:
00463 result = cat_target(cmd_path, full_path, options, tree=tree)
00464 except Exception, e:
00465 if options.verbose:
00466 traceback.print_exc()
00467 print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e)
00468 return 1, []
00469 return 0, result
00470
00471
00472
00473