vppapigen: remove python2 support
[vpp.git] / src / tools / vppapigen / vppapigen.py
index 94696ae..80097a1 100755 (executable)
@@ -1,14 +1,16 @@
 #!/usr/bin/python3
 
-from __future__ import print_function
 import ply.lex as lex
 import ply.yacc as yacc
 import sys
 import argparse
+import keyword
 import logging
 import binascii
 import os
 
+log = logging.getLogger('vppapigen')
+
 # Ensure we don't leave temporary files around
 sys.dont_write_bytecode = True
 
@@ -134,10 +136,6 @@ class Service():
         self.stream = stream
         self.events = [] if events is None else events
 
-    def __repr__(self):
-        return "Service(caller={!r}, reply={!r}, events={!r}, stream={!r})".\
-            format(self.caller, self.reply, self.events, self.stream)
-
 
 class Typedef():
     def __init__(self, name, flags, block):
@@ -155,28 +153,24 @@ class Typedef():
         global_type_add(name, self)
 
     def __repr__(self):
-        return "Typedef(name={!r}, flags={!r}, block={!r})".format(
-            self.name, self.flags, self.block)
+        return self.name + str(self.flags) + str(self.block)
 
 
 class Using():
     def __init__(self, name, alias):
         self.name = name
 
-        # save constructor values for repr()
-        self._alias = alias
-
         if isinstance(alias, Array):
-            a = {'type': alias.fieldtype,
-                 'length': alias.length}
+            a = { 'type': alias.fieldtype,  # noqa: E201
+                  'length': alias.length }  # noqa: E202
         else:
-            a = {'type': alias.fieldtype}
+            a = { 'type': alias.fieldtype }  # noqa: E201,E202
         self.alias = a
         self.crc = str(alias).encode()
         global_type_add(name, self)
 
     def __repr__(self):
-        return "Using(name={!r}, alias={!r})".format(self.name, self._alias)
+        return self.name + str(self.alias)
 
 
 class Union():
@@ -190,7 +184,7 @@ class Union():
         global_type_add(name, self)
 
     def __repr__(self):
-        return "Union(name={!r}, block={!r})".format(self.name, self.block)
+        return str(self.block)
 
 
 class Define():
@@ -221,8 +215,7 @@ class Define():
                 block.remove(b)
 
     def __repr__(self):
-        return "Define(name={!r}, flags={!r}, block={!r})".format(
-            self.name, self.flags, self.block)
+        return self.name + str(self.flags) + str(self.block)
 
 
 class Enum():
@@ -243,8 +236,7 @@ class Enum():
         global_type_add(name, self)
 
     def __repr__(self):
-        return "Enum(name={!r}, block={!r}, enumtype={!r})".format(
-            self.name, self.block, self.enumtype)
+        return self.name + str(self.block)
 
 
 class Import():
@@ -259,15 +251,12 @@ class Import():
             f = os.path.join(dir, filename)
             if os.path.exists(f):
                 break
-        if sys.version[0] == '2':
-            with open(f) as fd:
-                self.result = parser.parse_file(fd, None)
-        else:
-            with open(f, encoding='utf-8') as fd:
-                self.result = parser.parse_file(fd, None)
+
+        with open(f, encoding='utf-8') as fd:
+            self.result = parser.parse_file(fd, None)
 
     def __repr__(self):
-        return "Import(filename={!r})".format(self.filename)
+        return self.filename
 
 
 class Option():
@@ -276,7 +265,7 @@ class Option():
         self.crc = str(option).encode()
 
     def __repr__(self):
-        return "Option({!r})".format(self.option)
+        return str(self.option)
 
     def __getitem__(self, index):
         return self.option[index]
@@ -286,11 +275,6 @@ class Array():
     def __init__(self, fieldtype, name, length):
         self.type = 'Array'
         self.fieldtype = fieldtype
-
-        # save constructor values for repr()
-        self._name = name
-        self._length = length
-
         self.fieldname = name
         if type(length) is str:
             self.lengthfield = length
@@ -300,20 +284,22 @@ class Array():
             self.lengthfield = None
 
     def __repr__(self):
-        return "Array(fieldtype={!r}, name={!r}, length={!r})".format(
-            self.fieldtype, self._name, self._length)
+        return str([self.fieldtype, self.fieldname, self.length,
+                    self.lengthfield])
 
 
 class Field():
     def __init__(self, fieldtype, name, limit=None):
         self.type = 'Field'
         self.fieldtype = fieldtype
+        if name in keyword.kwlist:
+            raise ValueError("Fieldname {!r} is a python keyword and is not "
+                             "accessible via the python API. ".format(name))
         self.fieldname = name
         self.limit = limit
 
     def __repr__(self):
-        return "Field(fieldtype={!r}, name={!r}, limit={!r})".format(
-            self.fieldtype, self.fieldname, self.limit)
+        return str([self.fieldtype, self.fieldname])
 
 
 class Coord(object):
@@ -533,13 +519,13 @@ class VPPAPIParser(object):
         if len(p) == 2:
             p[0] = p[1]
         else:
-            p[0] = {**p[1], **p[2]}
+            p[0] = { **p[1], **p[2] }
 
     def p_field_option(self, p):
         '''field_option : ID '=' assignee ','
                         | ID '=' assignee
         '''
-        p[0] = {p[1]: p[3]}
+        p[0] = { p[1]: p[3] }
 
     def p_declaration(self, p):
         '''declaration : type_specifier ID ';'
@@ -807,23 +793,21 @@ def foldup_crcs(s):
 # Main
 #
 def main():
+    if sys.version_info < (3, 5,):
+        log.exception('vppapigen requires a supported version of python. '
+                      'Please use version 3.5 or greater. '
+                      'Using {}'.format(sys.version))
+        return 1
+
     cliparser = argparse.ArgumentParser(description='VPP API generator')
     cliparser.add_argument('--pluginpath', default=""),
     cliparser.add_argument('--includedir', action='append'),
-    if sys.version[0] == '2':
-        cliparser.add_argument('--input', type=argparse.FileType('r'),
-                               default=sys.stdin)
-        cliparser.add_argument('--output', nargs='?',
-                               type=argparse.FileType('w'),
-                               default=sys.stdout)
-
-    else:
-        cliparser.add_argument('--input',
-                               type=argparse.FileType('r', encoding='UTF-8'),
-                               default=sys.stdin)
-        cliparser.add_argument('--output', nargs='?',
-                               type=argparse.FileType('w', encoding='UTF-8'),
-                               default=sys.stdout)
+    cliparser.add_argument('--input',
+                           type=argparse.FileType('r', encoding='UTF-8'),
+                           default=sys.stdin)
+    cliparser.add_argument('--output', nargs='?',
+                           type=argparse.FileType('w', encoding='UTF-8'),
+                           default=sys.stdout)
 
     cliparser.add_argument('output_module', nargs='?', default='C')
     cliparser.add_argument('--debug', action='store_true')
@@ -846,7 +830,6 @@ def main():
         logging.basicConfig(stream=sys.stdout, level=logging.WARNING)
     else:
         logging.basicConfig()
-    log = logging.getLogger('vppapigen')
 
     parser = VPPAPI(debug=args.debug, filename=filename, logger=log)
     parsed_objects = parser.parse_file(args.input, log)
@@ -893,7 +876,8 @@ def main():
     else:
         pluginpath = args.pluginpath + '/'
     if pluginpath == '':
-        raise Exception('Output plugin not found')
+        log.exception('Output plugin not found')
+        return 1
     module_path = '{}vppapigen_{}.py'.format(pluginpath,
                                              args.output_module.lower())
 
@@ -901,16 +885,19 @@ def main():
         plugin = SourceFileLoader(args.output_module,
                                   module_path).load_module()
     except Exception as err:
-        raise Exception('Error importing output plugin: {}, {}'
-                        .format(module_path, err))
+        log.exception('Error importing output plugin: {}, {}'
+                      .format(module_path, err))
+        return 1
 
     result = plugin.run(filename, s)
     if result:
         print(result, file=args.output)
     else:
-        raise Exception('Running plugin failed: {} {}'
-                        .format(filename, result))
+        log.exception('Running plugin failed: {} {}'
+                      .format(filename, result))
+        return 1
+    return 0
 
 
 if __name__ == '__main__':
-    main()
+    sys.exit(main())