objectutils.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # Software License Agreement (BSD License)
3 #
4 # Copyright (c) 2012, 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 from rosbridge_library.internal import ros_loader
35 import inspect
36 
37 # Keep track of atomic types and special types
38 atomics = ['bool', 'byte','int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64', 'float32', 'float64', 'string']
39 specials = ['time', 'duration']
40 
41 def get_typedef(type):
42  """ A typedef is a dict containing the following fields:
43  - string type
44  - string[] fieldnames
45  - string[] fieldtypes
46  - int[] fieldarraylen
47  - string[] examples
48  - string[] constnames
49  - string[] constvalues
50  get_typedef will return a typedef dict for the specified message type """
51  if type in atomics:
52  # Atomics don't get a typedef
53  return None
54 
55  if type in specials:
56  # Specials get their type def mocked up
57  return _get_special_typedef(type)
58 
59  # Fetch an instance and return its typedef
60  instance = ros_loader.get_message_instance(type)
61  return _get_typedef(instance)
62 
63 def get_service_request_typedef(servicetype):
64  """ Returns a typedef dict for the service request class for the specified service type """
65  # Get an instance of the service request class and return its typedef
66  instance = ros_loader.get_service_request_instance(servicetype)
67  return _get_typedef(instance)
68 
70  """ Returns a typedef dict for the service response class for the specified service type """
71  # Get an instance of the service response class and return its typedef
72  instance = ros_loader.get_service_response_instance(servicetype)
73  return _get_typedef(instance)
74 
76  """ Returns a list of typedef dicts for this type and all contained type fields """
77  # Just go straight into the recursive method
78  return _get_typedefs_recursive(type, [])
79 
81  """ Returns a list of typedef dicts for this type and all contained type fields """
82  # Get an instance of the service request class and get its typedef
83  instance = ros_loader.get_service_request_instance(servicetype)
84  typedef = _get_typedef(instance)
85 
86  # Return the list of sub-typedefs
87  return _get_subtypedefs_recursive(typedef, [])
88 
90  """ Returns a list of typedef dicts for this type and all contained type fields """
91  # Get an instance of the service response class and get its typedef
92  instance = ros_loader.get_service_response_instance(servicetype)
93  typedef = _get_typedef(instance)
94 
95  # Return the list of sub-typedefs
96  return _get_subtypedefs_recursive(typedef, [])
97 
99  """ Returns the full text (similar to `gendeps --cat`) for the specified message type """
100  # Get an instance of the service response class and get its typedef
101  try:
102  instance = ros_loader.get_message_instance(type)
103  return instance._full_text
104  except Exception:
105  return ""
106 
107 def _get_typedef(instance):
108  """ Gets a typedef dict for the specified instance """
109  if instance is None or not hasattr(instance, "__slots__") or not hasattr(instance, "_slot_types"):
110  return None
111 
112  fieldnames = []
113  fieldtypes = []
114  fieldarraylen = []
115  examples = []
116  constnames = []
117  constvalues = []
118  for i in range(len(instance.__slots__)):
119  # Pull out the name
120  name = instance.__slots__[i]
121  fieldnames.append(name)
122 
123  # Pull out the type and determine whether it's an array
124  field_type = instance._slot_types[i]
125  arraylen = -1
126  if field_type[-1:]==']':
127  if field_type[-2:-1]=='[':
128  arraylen = 0
129  field_type = field_type[:-2]
130  else:
131  split = field_type.find('[')
132  arraylen = int(field_type[split+1:-1])
133  field_type = field_type[:split]
134  fieldarraylen.append(arraylen)
135 
136  # Get the fully qualified type
137  field_instance = getattr(instance, name)
138  fieldtypes.append(_type_name(field_type, field_instance))
139 
140  # Set the example as appropriate
141  example = field_instance
142  if arraylen>=0:
143  example = []
144  elif field_type not in atomics:
145  example = {}
146  examples.append(str(example))
147 
148  # Add pseudo constants names and values filtering members
149  attributes = inspect.getmembers(instance)
150  for attribute in attributes:
151  if attribute[0] not in instance.__slots__ and not attribute[0].startswith('_') and not inspect.isroutine(attribute[1]):
152  constnames.append(str(attribute[0]))
153  constvalues.append(str(attribute[1]))
154 
155  typedef = {
156  "type" : _type_name_from_instance(instance),
157  "fieldnames" : fieldnames,
158  "fieldtypes" : fieldtypes,
159  "fieldarraylen" : fieldarraylen,
160  "examples" : examples,
161  "constnames" : constnames,
162  "constvalues" : constvalues
163  }
164 
165  return typedef
166 
168  example = None
169  if type=="time" or type=="duration":
170  example = {
171  "type": type,
172  "fieldnames": ["secs", "nsecs"],
173  "fieldtypes": ["int32", "int32"],
174  "fieldarraylen": [-1, -1],
175  "examples": [ "0", "0" ],
176  "constnames": [],
177  "constvalues": []
178  }
179  return example
180 
181 def _get_typedefs_recursive(type, typesseen):
182  """ returns the type def for this type as well as the type defs for any fields within the type """
183  if type in typesseen:
184  # Don't put a type if it's already been seen
185  return []
186 
187  # Note that we have now seen this type
188  typesseen.append(type)
189 
190  # Get the typedef for this type and make sure it's not None
191  typedef = get_typedef(type)
192 
193  return _get_subtypedefs_recursive(typedef, typesseen)
194 
195 def _get_subtypedefs_recursive(typedef, typesseen):
196  if typedef is None:
197  return []
198 
199  # Create the list of subtypes and get the typedefs for fields
200  typedefs = [ typedef ]
201  for fieldtype in typedef["fieldtypes"]:
202  typedefs = typedefs + _get_typedefs_recursive(fieldtype, typesseen)
203 
204  return typedefs
205 
206 def _type_name(type, instance):
207  """ given a short type, and an object instance of that type,
208  determines and returns the fully qualified type """
209  # The fully qualified type of atomic and special types is just their original name
210  if type in atomics or type in specials:
211  return type
212 
213  # If the instance is a list, then we can get no more information from the instance.
214  # However, luckily, the 'type' field for list types is usually already inflated to the full type.
215  if isinstance(instance, list):
216  return type
217 
218  # Otherwise, the type will come from the module and class name of the instance
219  return _type_name_from_instance(instance)
220 
222  mod = instance.__module__
223  type = mod[0:mod.find('.')]+"/"+instance.__class__.__name__
224  return type
225 
def _type_name(type, instance)
Definition: objectutils.py:206
def _get_special_typedef(type)
Definition: objectutils.py:167
def _get_typedef(instance)
Definition: objectutils.py:107
def get_service_request_typedef_recursive(servicetype)
Definition: objectutils.py:80
def get_service_request_typedef(servicetype)
Definition: objectutils.py:63
def get_service_response_typedef(servicetype)
Definition: objectutils.py:69
def _type_name_from_instance(instance)
Definition: objectutils.py:221
def _get_subtypedefs_recursive(typedef, typesseen)
Definition: objectutils.py:195
def get_service_response_typedef_recursive(servicetype)
Definition: objectutils.py:89
def get_typedef(type)
Definition: objectutils.py:41
def _get_typedefs_recursive(type, typesseen)
Definition: objectutils.py:181
def get_typedef_full_text(type)
Definition: objectutils.py:98
def get_typedef_recursive(type)
Definition: objectutils.py:75


rosapi
Author(s): Jonathan Mace
autogenerated on Wed Jun 3 2020 03:55:16