From 3a5e71584874d6cc86a17a106ba806a90f50e3a5 Mon Sep 17 00:00:00 2001 From: Varun Agrawal Date: Thu, 22 Jul 2021 11:51:22 -0400 Subject: [PATCH] Squashed 'wrap/' changes from d9ae5ce03..571c23952 571c23952 Merge pull request #119 from borglab/feature/remove-loguru 0e5178251 remove loguru as a dependency 5b76595cf fix type info and do some refactoring git-subtree-dir: wrap git-subtree-split: 571c2395242e33dfd0596a240fbcb87775b9ba0c --- gtwrap/interface_parser/classes.py | 14 ++-- gtwrap/interface_parser/function.py | 2 +- gtwrap/interface_parser/type.py | 6 +- gtwrap/matlab_wrapper/mixins.py | 109 +++++++++++++--------------- gtwrap/matlab_wrapper/wrapper.py | 7 +- gtwrap/template_instantiator.py | 11 ++- requirements.txt | 1 - tests/test_matlab_wrapper.py | 6 -- 8 files changed, 68 insertions(+), 88 deletions(-) diff --git a/gtwrap/interface_parser/classes.py b/gtwrap/interface_parser/classes.py index 3e6a0fc3c..11317962d 100644 --- a/gtwrap/interface_parser/classes.py +++ b/gtwrap/interface_parser/classes.py @@ -10,7 +10,7 @@ Parser classes and rules for parsing C++ classes. Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellaert """ -from typing import Iterable, List, Union +from typing import Any, Iterable, List, Union from pyparsing import Literal, Optional, ZeroOrMore # type: ignore @@ -48,12 +48,12 @@ class Method: args_list, t.is_const)) def __init__(self, - template: str, + template: Union[Template, Any], name: str, return_type: ReturnType, args: ArgumentList, is_const: str, - parent: Union[str, "Class"] = ''): + parent: Union["Class", Any] = ''): self.template = template self.name = name self.return_type = return_type @@ -98,7 +98,7 @@ class StaticMethod: name: str, return_type: ReturnType, args: ArgumentList, - parent: Union[str, "Class"] = ''): + parent: Union["Class", Any] = ''): self.name = name self.return_type = return_type self.args = args @@ -129,7 +129,7 @@ class Constructor: def __init__(self, name: str, args: ArgumentList, - parent: Union["Class", str] = ''): + parent: Union["Class", Any] = ''): self.name = name self.args = args @@ -167,7 +167,7 @@ class Operator: return_type: ReturnType, args: ArgumentList, is_const: str, - parent: Union[str, "Class"] = ''): + parent: Union["Class", Any] = ''): self.name = name self.operator = operator self.return_type = return_type @@ -284,7 +284,7 @@ class Class: properties: List[Variable], operators: List[Operator], enums: List[Enum], - parent: str = '', + parent: Any = '', ): self.template = template self.is_virtual = is_virtual diff --git a/gtwrap/interface_parser/function.py b/gtwrap/interface_parser/function.py index 995aba10e..9fe1f56f0 100644 --- a/gtwrap/interface_parser/function.py +++ b/gtwrap/interface_parser/function.py @@ -169,7 +169,7 @@ class GlobalFunction: return_type: ReturnType, args_list: ArgumentList, template: Template, - parent: str = ''): + parent: Any = ''): self.name = name self.return_type = return_type self.args = args_list diff --git a/gtwrap/interface_parser/type.py b/gtwrap/interface_parser/type.py index 0b9be6501..49315cc56 100644 --- a/gtwrap/interface_parser/type.py +++ b/gtwrap/interface_parser/type.py @@ -12,7 +12,7 @@ Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellae # pylint: disable=unnecessary-lambda, expression-not-assigned -from typing import Iterable, List, Union +from typing import List, Sequence, Union from pyparsing import (Forward, Optional, Or, ParseResults, # type: ignore delimitedList) @@ -49,12 +49,12 @@ class Typename: def __init__(self, t: ParseResults, - instantiations: Iterable[ParseResults] = ()): + instantiations: Sequence[ParseResults] = ()): self.name = t[-1] # the name is the last element in this list self.namespaces = t[:-1] if instantiations: - if isinstance(instantiations, Iterable): + if isinstance(instantiations, Sequence): self.instantiations = instantiations # type: ignore else: self.instantiations = instantiations.asList() diff --git a/gtwrap/matlab_wrapper/mixins.py b/gtwrap/matlab_wrapper/mixins.py index 061cea283..217801ff3 100644 --- a/gtwrap/matlab_wrapper/mixins.py +++ b/gtwrap/matlab_wrapper/mixins.py @@ -1,5 +1,7 @@ """Mixins for reducing the amount of boilerplate in the main wrapper class.""" +from typing import Any, Tuple, Union + import gtwrap.interface_parser as parser import gtwrap.template_instantiator as instantiator @@ -7,13 +9,14 @@ import gtwrap.template_instantiator as instantiator class CheckMixin: """Mixin to provide various checks.""" # Data types that are primitive types - not_ptr_type = ['int', 'double', 'bool', 'char', 'unsigned char', 'size_t'] + not_ptr_type: Tuple = ('int', 'double', 'bool', 'char', 'unsigned char', + 'size_t') # Ignore the namespace for these datatypes - ignore_namespace = ['Matrix', 'Vector', 'Point2', 'Point3'] + ignore_namespace: Tuple = ('Matrix', 'Vector', 'Point2', 'Point3') # Methods that should be ignored - ignore_methods = ['pickle'] + ignore_methods: Tuple = ('pickle', ) # Methods that should not be wrapped directly - whitelist = ['serializable', 'serialize'] + whitelist: Tuple = ('serializable', 'serialize') # Datatypes that do not need to be checked in methods not_check_type: list = [] @@ -23,7 +26,7 @@ class CheckMixin: return True return False - def is_shared_ptr(self, arg_type): + def is_shared_ptr(self, arg_type: parser.Type): """ Determine if the `interface_parser.Type` should be treated as a shared pointer in the wrapper. @@ -33,7 +36,7 @@ class CheckMixin: and arg_type.typename.name not in self.ignore_namespace and arg_type.typename.name != 'string') - def is_ptr(self, arg_type): + def is_ptr(self, arg_type: parser.Type): """ Determine if the `interface_parser.Type` should be treated as a raw pointer in the wrapper. @@ -43,7 +46,7 @@ class CheckMixin: and arg_type.typename.name not in self.ignore_namespace and arg_type.typename.name != 'string') - def is_ref(self, arg_type): + def is_ref(self, arg_type: parser.Type): """ Determine if the `interface_parser.Type` should be treated as a reference in the wrapper. @@ -55,7 +58,14 @@ class CheckMixin: class FormatMixin: """Mixin to provide formatting utilities.""" - def _clean_class_name(self, instantiated_class): + + ignore_namespace: tuple + data_type: Any + data_type_param: Any + _return_count: Any + + def _clean_class_name(self, + instantiated_class: instantiator.InstantiatedClass): """Reformatted the C++ class name to fit Matlab defined naming standards """ @@ -65,23 +75,23 @@ class FormatMixin: return instantiated_class.name def _format_type_name(self, - type_name, - separator='::', - include_namespace=True, - constructor=False, - method=False): + type_name: parser.Typename, + separator: str = '::', + include_namespace: bool = True, + is_constructor: bool = False, + is_method: bool = False): """ Args: type_name: an interface_parser.Typename to reformat separator: the statement to add between namespaces and typename include_namespace: whether to include namespaces when reformatting - constructor: if the typename will be in a constructor - method: if the typename will be in a method + is_constructor: if the typename will be in a constructor + is_method: if the typename will be in a method Raises: constructor and method cannot both be true """ - if constructor and method: + if is_constructor and is_method: raise ValueError( 'Constructor and method parameters cannot both be True') @@ -93,9 +103,9 @@ class FormatMixin: if name not in self.ignore_namespace and namespace != '': formatted_type_name += namespace + separator - if constructor: + if is_constructor: formatted_type_name += self.data_type.get(name) or name - elif method: + elif is_method: formatted_type_name += self.data_type_param.get(name) or name else: formatted_type_name += name @@ -106,8 +116,8 @@ class FormatMixin: template = '{}'.format( self._format_type_name(type_name.instantiations[idx], include_namespace=include_namespace, - constructor=constructor, - method=method)) + is_constructor=is_constructor, + is_method=is_method)) templates.append(template) if len(templates) > 0: # If there are no templates @@ -119,15 +129,15 @@ class FormatMixin: self._format_type_name(type_name.instantiations[idx], separator=separator, include_namespace=False, - constructor=constructor, - method=method)) + is_constructor=is_constructor, + is_method=is_method)) return formatted_type_name def _format_return_type(self, - return_type, - include_namespace=False, - separator="::"): + return_type: parser.function.ReturnType, + include_namespace: bool = False, + separator: str = "::"): """Format return_type. Args: @@ -154,18 +164,15 @@ class FormatMixin: return return_wrap - def _format_class_name(self, instantiated_class, separator=''): + def _format_class_name(self, + instantiated_class: instantiator.InstantiatedClass, + separator: str = ''): """Format a template_instantiator.InstantiatedClass name.""" if instantiated_class.parent == '': parent_full_ns = [''] else: parent_full_ns = instantiated_class.parent.full_namespaces() - # class_name = instantiated_class.parent.name - # - # if class_name != '': - # class_name += separator - # - # class_name += instantiated_class.name + parentname = "".join([separator + x for x in parent_full_ns]) + separator @@ -175,10 +182,12 @@ class FormatMixin: return class_name - def _format_static_method(self, static_method, separator=''): - """Example: - - gtsamPoint3.staticFunction + def _format_static_method(self, + static_method: parser.StaticMethod, + separator: str = ''): + """ + Example: + gtsam.Point3.staticFunction() """ method = '' @@ -188,35 +197,17 @@ class FormatMixin: return method[2 * len(separator):] - def _format_instance_method(self, instance_method, separator=''): + def _format_global_function(self, + function: Union[parser.GlobalFunction, Any], + separator: str = ''): """Example: gtsamPoint3.staticFunction """ method = '' - if isinstance(instance_method, instantiator.InstantiatedMethod): - method_list = [ - separator + x - for x in instance_method.parent.parent.full_namespaces() - ] - method += "".join(method_list) + separator - - method += instance_method.parent.name + separator - method += instance_method.original.name - method += "<" + instance_method.instantiations.to_cpp() + ">" - - return method[2 * len(separator):] - - def _format_global_method(self, static_method, separator=''): - """Example: - - gtsamPoint3.staticFunction - """ - method = '' - - if isinstance(static_method, parser.GlobalFunction): - method += "".join([separator + x for x in static_method.parent.full_namespaces()]) + \ + if isinstance(function, parser.GlobalFunction): + method += "".join([separator + x for x in function.parent.full_namespaces()]) + \ separator return method[2 * len(separator):] diff --git a/gtwrap/matlab_wrapper/wrapper.py b/gtwrap/matlab_wrapper/wrapper.py index b040d2731..97945f73a 100755 --- a/gtwrap/matlab_wrapper/wrapper.py +++ b/gtwrap/matlab_wrapper/wrapper.py @@ -11,8 +11,6 @@ import textwrap from functools import partial, reduce from typing import Dict, Iterable, List, Union -from loguru import logger - import gtwrap.interface_parser as parser import gtwrap.template_instantiator as instantiator from gtwrap.matlab_wrapper.mixins import CheckMixin, FormatMixin @@ -200,7 +198,7 @@ class MatlabWrapper(CheckMixin, FormatMixin): check_type = self._format_type_name( arg.ctype.typename, separator='.', - constructor=not wrap_datatypes) + is_constructor=not wrap_datatypes) var_arg_wrap += " && isa(varargin{{{num}}},'{data_type}')".format( num=i, data_type=check_type) @@ -1090,11 +1088,10 @@ class MatlabWrapper(CheckMixin, FormatMixin): if method.instantiations: # method_name += '<{}>'.format( # self._format_type_name(method.instantiations)) - # method_name = self._format_instance_method(method, '::') method = method.to_cpp() elif isinstance(method, parser.GlobalFunction): - method_name = self._format_global_method(method, '::') + method_name = self._format_global_function(method, '::') method_name += method.name else: diff --git a/gtwrap/template_instantiator.py b/gtwrap/template_instantiator.py index 87729cfa6..0cda93d5d 100644 --- a/gtwrap/template_instantiator.py +++ b/gtwrap/template_instantiator.py @@ -4,7 +4,7 @@ import itertools from copy import deepcopy -from typing import Iterable, List +from typing import Any, Iterable, List, Sequence import gtwrap.interface_parser as parser @@ -214,17 +214,17 @@ class InstantiatedMethod(parser.Method): } """ def __init__(self, - original, + original: parser.Method, instantiations: Iterable[parser.Typename] = ()): self.original = original self.instantiations = instantiations - self.template = '' + self.template: Any = '' self.is_const = original.is_const self.parent = original.parent # Check for typenames if templated. # This way, we can gracefully handle both templated and non-templated methods. - typenames = self.original.template.typenames if self.original.template else [] + typenames: Sequence = self.original.template.typenames if self.original.template else [] self.name = instantiate_name(original.name, self.instantiations) self.return_type = instantiate_return_type( original.return_type, @@ -348,13 +348,12 @@ class InstantiatedClass(parser.Class): return "{virtual}Class {cpp_class} : {parent_class}\n"\ "{ctors}\n{static_methods}\n{methods}\n{operators}".format( virtual="virtual " if self.is_virtual else '', - name=self.name, cpp_class=self.to_cpp(), parent_class=self.parent, ctors="\n".join([repr(ctor) for ctor in self.ctors]), - methods="\n".join([repr(m) for m in self.methods]), static_methods="\n".join([repr(m) for m in self.static_methods]), + methods="\n".join([repr(m) for m in self.methods]), operators="\n".join([repr(op) for op in self.operators]) ) diff --git a/requirements.txt b/requirements.txt index dd24ea4ed..a7181b271 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,2 @@ pyparsing pytest -loguru \ No newline at end of file diff --git a/tests/test_matlab_wrapper.py b/tests/test_matlab_wrapper.py index fad4de16a..112750721 100644 --- a/tests/test_matlab_wrapper.py +++ b/tests/test_matlab_wrapper.py @@ -11,8 +11,6 @@ import os.path as osp import sys import unittest -from loguru import logger - sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__)))) from gtwrap.matlab_wrapper import MatlabWrapper @@ -44,10 +42,6 @@ class TestWrap(unittest.TestCase): # Create the `actual/matlab` directory os.makedirs(self.MATLAB_ACTUAL_DIR, exist_ok=True) - # set the log level to INFO by default - logger.remove() # remove the default sink - logger.add(sys.stderr, format="{time} {level} {message}", level="INFO") - def compare_and_diff(self, file): """ Compute the comparison between the expected and actual file,