mixins.py
Go to the documentation of this file.
1 """Mixins for reducing the amount of boilerplate in the main wrapper class."""
2 
3 from typing import Any, Tuple, Union
4 
5 import gtwrap.interface_parser as parser
6 import gtwrap.template_instantiator as instantiator
7 
8 
9 class CheckMixin:
10  """Mixin to provide various checks."""
11  # Data types that are primitive types
12  not_ptr_type: Tuple = ('int', 'double', 'bool', 'char', 'unsigned char',
13  'size_t')
14  # Ignore the namespace for these datatypes
15  ignore_namespace: Tuple = ('Matrix', 'Vector', 'Point2', 'Point3')
16  # Methods that should be ignored
17  ignore_methods: Tuple = ('pickle', )
18  # Methods that should not be wrapped directly
19  whitelist: Tuple = ('serializable', 'serialize')
20  # Datatypes that do not need to be checked in methods
21  not_check_type: list = []
22 
23  def _has_serialization(self, cls):
24  for m in cls.methods:
25  if m.name in self.whitelist:
26  return True
27  return False
28 
29  def can_be_pointer(self, arg_type: parser.Type):
30  """
31  Determine if the `arg_type` can have a pointer to it.
32 
33  E.g. `Pose3` can have `Pose3*` but
34  `Matrix` should not have `Matrix*`.
35  """
36  return (arg_type.typename.name not in self.not_ptr_type
37  and arg_type.typename.name not in self.ignore_namespace
38  and arg_type.typename.name != 'string')
39 
40  def is_shared_ptr(self, arg_type: parser.Type):
41  """
42  Determine if the `interface_parser.Type` should be treated as a
43  shared pointer in the wrapper.
44  """
45  return arg_type.is_shared_ptr
46 
47  def is_ptr(self, arg_type: parser.Type):
48  """
49  Determine if the `interface_parser.Type` should be treated as a
50  raw pointer in the wrapper.
51  """
52  return arg_type.is_ptr
53 
54  def is_ref(self, arg_type: parser.Type):
55  """
56  Determine if the `interface_parser.Type` should be treated as a
57  reference in the wrapper.
58  """
59  return arg_type.typename.name not in self.ignore_namespace and \
60  arg_type.typename.name not in self.not_ptr_type and \
61  arg_type.is_ref
62 
63  def is_class_enum(self, arg_type: parser.Type, class_: parser.Class):
64  """Check if arg_type is an enum in the class `class_`."""
65  if class_:
66  class_enums = [enum.name for enum in class_.enums]
67  return arg_type.typename.name in class_enums
68  else:
69  return False
70 
71  def is_global_enum(self, arg_type: parser.Type, class_: parser.Class):
72  """Check if arg_type is a global enum."""
73  if class_:
74  # Get the enums in the class' namespace
75  global_enums = [
76  member.name for member in class_.parent.content
77  if isinstance(member, parser.Enum)
78  ]
79  return arg_type.typename.name in global_enums
80  else:
81  return False
82 
83  def is_enum(self, arg_type: parser.Type, class_: parser.Class):
84  """Check if `arg_type` is an enum."""
85  return self.is_class_enum(arg_type, class_) or self.is_global_enum(
86  arg_type, class_)
87 
88 
90  """Mixin to provide formatting utilities."""
91 
92  ignore_namespace: tuple
93  data_type: Any
94  data_type_param: Any
95  _return_count: Any
96 
97  def _clean_class_name(self,
98  instantiated_class: instantiator.InstantiatedClass):
99  """Reformatted the C++ class name to fit Matlab defined naming
100  standards
101  """
102  if len(instantiated_class.ctors) != 0:
103  return instantiated_class.ctors[0].name
104 
105  return instantiated_class.name
106 
107  def _format_type_name(self,
108  type_name: parser.Typename,
109  separator: str = '::',
110  include_namespace: bool = True,
111  is_constructor: bool = False,
112  is_method: bool = False):
113  """
114  Args:
115  type_name: an interface_parser.Typename to reformat
116  separator: the statement to add between namespaces and typename
117  include_namespace: whether to include namespaces when reformatting
118  is_constructor: if the typename will be in a constructor
119  is_method: if the typename will be in a method
120 
121  Raises:
122  constructor and method cannot both be true
123  """
124  if is_constructor and is_method:
125  raise ValueError(
126  'Constructor and method parameters cannot both be True')
127 
128  formatted_type_name = ''
129  name = type_name.name
130 
131  if include_namespace:
132  for namespace in type_name.namespaces:
133  if name not in self.ignore_namespace and namespace != '':
134  formatted_type_name += namespace + separator
135 
136  if is_constructor:
137  formatted_type_name += self.data_type.get(name) or name
138  elif is_method:
139  formatted_type_name += self.data_type_param.get(name) or name
140  else:
141  formatted_type_name += str(name)
142 
143  if separator == "::": # C++
144  templates = []
145  for idx, _ in enumerate(type_name.instantiations):
146  template = '{}'.format(
147  self._format_type_name(type_name.instantiations[idx],
148  include_namespace=include_namespace,
149  is_constructor=is_constructor,
150  is_method=is_method))
151  templates.append(template)
152 
153  if len(templates) > 0: # If there are no templates
154  formatted_type_name += '<{}>'.format(','.join(templates))
155 
156  else:
157  for idx, _ in enumerate(type_name.instantiations):
158  formatted_type_name += '{}'.format(
159  self._format_type_name(type_name.instantiations[idx],
160  separator=separator,
161  include_namespace=False,
162  is_constructor=is_constructor,
163  is_method=is_method))
164 
165  return formatted_type_name
166 
167  def _format_return_type(self,
168  return_type: parser.function.ReturnType,
169  include_namespace: bool = False,
170  separator: str = "::"):
171  """Format return_type.
172 
173  Args:
174  return_type: an interface_parser.ReturnType to reformat
175  include_namespace: whether to include namespaces when reformatting
176  """
177  return_wrap = ''
178 
179  if self._return_count(return_type) == 1:
180  return_wrap = self._format_type_name(
181  return_type.type1.typename,
182  separator=separator,
183  include_namespace=include_namespace)
184  else:
185  return_wrap = 'pair< {type1}, {type2} >'.format(
186  type1=self._format_type_name(
187  return_type.type1.typename,
188  separator=separator,
189  include_namespace=include_namespace),
190  type2=self._format_type_name(
191  return_type.type2.typename,
192  separator=separator,
193  include_namespace=include_namespace))
194 
195  return return_wrap
196 
197  def _format_class_name(self,
198  instantiated_class: instantiator.InstantiatedClass,
199  separator: str = ''):
200  """Format a template_instantiator.InstantiatedClass name."""
201  if instantiated_class.parent == '':
202  parent_full_ns = ['']
203  else:
204  parent_full_ns = instantiated_class.parent.full_namespaces()
205 
206  parentname = "".join([separator + x
207  for x in parent_full_ns]) + separator
208 
209  class_name = parentname[2 * len(separator):]
210 
211  class_name += instantiated_class.name
212 
213  return class_name
214 
215  def _format_static_method(self,
216  static_method: parser.StaticMethod,
217  separator: str = ''):
218  """
219  Example:
220  gtsam.Point3.staticFunction()
221  """
222  method = ''
223 
224  if isinstance(static_method, parser.StaticMethod):
225  method += static_method.parent.to_cpp() + separator
226 
227  return method
228 
229  def _format_global_function(self,
230  function: Union[parser.GlobalFunction, Any],
231  separator: str = ''):
232  """Example:
233 
234  gtsamPoint3.staticFunction
235  """
236  method = ''
237 
238  if isinstance(function, parser.GlobalFunction):
239  method += "".join([separator + x for x in function.parent.full_namespaces()]) + \
240  separator
241 
242  return method[2 * len(separator):]
bool isinstance(handle obj)
Definition: pytypes.h:700
Definition: pytypes.h:1403
std::string format(const std::string &str, const std::vector< std::string > &find, const std::vector< std::string > &replace)
Container::iterator get(Container &c, Position position)
size_t len(handle h)
Get the length of a Python object.
Definition: pytypes.h:2244


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:34:56