port_types.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- Python -*-
00003 # -*- coding: utf-8 -*-
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 Classes and functions for managing port types.
00018 
00019 '''
00020 
00021 
00022 import re
00023 import rtctree.path
00024 
00025 import comp_mgmt
00026 import fmt
00027 import rts_exceptions
00028 
00029 
00030 ###############################################################################
00031 ## Class for managing port specifications.
00032 
00033 class PortSpec(object):
00034     def __init__(self, name, type, target, input=True, formatter=None,
00035             type_name='', raw='', *args, **kwargs):
00036         super(PortSpec, self).__init__()
00037         self._formatter = formatter
00038         self._input = input
00039         self._name = name
00040         self._raw_specs = [raw]
00041         self._targets = [target]
00042         self._type = type
00043         self._type_name = type_name
00044 
00045     def __str__(self):
00046         if self._formatter:
00047             fmt_str = '#{0}'.format(self._formatter)
00048         else:
00049             fmt_str = ''
00050         result = ''
00051         for t in self._targets:
00052             result += '{0}.{1}{2},'.format(rtctree.path.format_path(t),
00053                     self._name, fmt_str)
00054         return result[:-1]
00055 
00056     @property
00057     def formatter(self):
00058         '''Get the port's formatter function.'''
00059         return self._formatter
00060 
00061     @property
00062     def input(self):
00063         '''If the port is an input port or not.'''
00064         return self._input
00065 
00066     @property
00067     def name(self):
00068         '''The name of the port.'''
00069         return self._name
00070 
00071     @property
00072     def output(self):
00073         '''If the port is an output port or not.'''
00074         return not self._input
00075 
00076     @property
00077     def raw(self):
00078         '''The raw port specifications that created this PortSpec.'''
00079         return self._raw_specs
00080 
00081     @property
00082     def targets(self):
00083         '''The target ports of this port, as [(path, port_name), ...].'''
00084         return self._targets
00085 
00086     @property
00087     def type(self):
00088         '''The port's data type constructor function.'''
00089         return self._type
00090 
00091     @property
00092     def type_name(self):
00093         '''The port's data type name.'''
00094         return self._type_name
00095 
00096     def add_target(self, target, raw=''):
00097         '''Add an additional target for this port.'''
00098         self._targets.append(target)
00099         self._raw_specs.append(raw)
00100 
00101 
00102 ###############################################################################
00103 ## Functions for building port specifications.
00104 
00105 def make_port_specs(ports, modmgr, tree):
00106     '''Create a list of PortSpec objects matching the ports given.
00107 
00108     The ports are searched for in the given RTCTree, and PortSpec objects are
00109     created matching them. The component holding each port is found, then the
00110     port object matching the given port name is found. A PortSpec is given
00111     matching its data type and with the reverse direction. If the target port
00112     is an InPort, a PortSpec for an OutPort will be created, and vice versa.
00113 
00114     @param ports The paths to the target ports. Each must be a tuple of
00115                  (path, port, name, formatter) where path is a list of path
00116                  components in the format used by rtctree.
00117     @param modmgr The ModuleMgr object to use to evaluate the format
00118                   expression.
00119     @param tree An RTCTree to search for the ports in.
00120 
00121     '''
00122     result = {}
00123     index = 0
00124     for (rtc, port, name, form, raw) in ports:
00125         port_obj = comp_mgmt.find_port(rtc, port, tree)
00126         if port_obj.porttype == 'DataInPort':
00127             input = False
00128         elif port_obj.porttype == 'DataOutPort':
00129             input = True
00130         else:
00131             raise rts_exceptions.BadPortTypeError(rtc, port)
00132         if name is None:
00133             if input:
00134                 name = 'input{0}'.format(index)
00135             else:
00136                 name = 'output{0}'.format(index)
00137             index += 1
00138         data_type = port_obj.properties['dataport.data_type']
00139         # Strip the IDL header and version if present
00140         if data_type.startswith('IDL:'):
00141             data_type = data_type[4:]
00142         colon = data_type.rfind(':')
00143         if colon != -1:
00144             data_type = data_type[:colon]
00145         port_cons = modmgr.find_class(data_type)
00146         if form:
00147             # Look up the formatter in one of the user-provided modules
00148             formatter = fmt.import_formatter(form, modmgr)
00149         else:
00150             formatter = None
00151         if name in result:
00152             # Already have a port with this name so add a target
00153             if (input != result[name].input or
00154                     port_cons != result[name].type or
00155                     formatter != result[name].formatter):
00156                 raise rts_exceptions.SameNameDiffSpecError(raw)
00157             result[name].add_target((rtc, port), raw=raw)
00158         else:
00159             result[name] = (PortSpec(name, port_cons, (rtc, port), input=input,
00160                 formatter=formatter,
00161                 type_name=port_obj.properties['dataport.data_type'], raw=raw))
00162     return result.values()
00163 
00164 
00165 def parse_targets(targets):
00166     '''Parse target ports, as specified on the command line.
00167 
00168     Parses target ports specified onto the command line into a tuple of
00169     (path, port, name, formatter, target), where path is in the rtctree
00170     format.
00171 
00172     @param targets A list of target ports, as strings. Each string should
00173                    be in the format "path:port.name#formatter", e.g.
00174                    "/localhost/blurg.host_cxt/comp0.rtc:input.stuff#print_stuff".
00175                    The name component is optional; if it is not present,
00176                    neither should the '.' character be. The formatter
00177                    component is optional; if it is not present, neither
00178                    should the '#' character be. A name is not required
00179                    to use a formatter.
00180 
00181     '''
00182     regex = re.compile(r'^(?P<path>[:\-\w/.\(\)]+?)(?:\.(?P<name>\w+))?(?:#(?P<form>[\w.]+))?$')
00183     result = []
00184     for t in targets:
00185         m = regex.match(t)
00186         if not m:
00187             raise rts_exceptions.BadPortSpecError(t)
00188         raw_path, name, formatter = m.groups()
00189         path, port = rtctree.path.parse_path(raw_path)
00190         if not port or not path[-1]:
00191             raise rts_exceptions.BadPortSpecError(t)
00192         result.append((path, port, name, formatter, t))
00193     return result
00194 
00195 
00196 def require_all_input(port_specs):
00197     '''Checks that all ports in the specification are inputs.
00198 
00199     Raises a @ref PortNotInputError exception if any ports are output.
00200 
00201     @param port_specs A list of @ref PortSpec objects.
00202 
00203     '''
00204     for p in port_specs:
00205         if not p.input:
00206             raise rts_exceptions.PortNotInputError(p.name)
00207 
00208 
00209 def require_all_output(port_specs):
00210     '''Checks that all ports in the specification are outputs.
00211 
00212     Raises a @ref PortNotOutputError exception if any ports are output.
00213 
00214     @param port_specs A list of @ref PortSpec objects.
00215 
00216     '''
00217     for p in port_specs:
00218         if not p.output:
00219             raise rts_exceptions.PortNotOutputError(p.name)
00220 


rtshell
Author(s): Geoffrey Biggs
autogenerated on Fri Aug 28 2015 12:55:12