+from __future__ import absolute_import
+import sys
+import os
+import logging
+import collections
+import struct
+import json
+import threading
+import fnmatch
+import weakref
+import atexit
+from . vpp_serializer import VPPType, VPPEnumType, VPPUnionType, BaseTypes
+from . vpp_serializer import VPPMessage, vpp_get_type, VPPTypeAlias
+from . vpp_format import VPPFormat
+
+if sys.version[0] == '2':
+ import Queue as queue
+else:
+ import queue as queue
+
+
+class VppEnumType(type):
+ def __getattr__(cls, name):
+ t = vpp_get_type(name)
+ return t.enum
+
+
+# Python3
+# class VppEnum(metaclass=VppEnumType):
+# pass
+class VppEnum(object):
+ __metaclass__ = VppEnumType
+
+
+def vpp_atexit(vpp_weakref):
+ """Clean up VPP connection on shutdown."""
+ vpp_instance = vpp_weakref()
+ if vpp_instance and vpp_instance.transport.connected:
+ vpp_instance.logger.debug('Cleaning up VPP on exit')
+ vpp_instance.disconnect()
+
+
+def vpp_iterator(d):
+ if sys.version[0] == '2':
+ return d.iteritems()
+ else:
+ return d.items()
+
+
+class VppApiDynamicMethodHolder(object):
+ pass
+
+
+class FuncWrapper(object):
+ def __init__(self, func):
+ self._func = func
+ self.__name__ = func.__name__
+
+ def __call__(self, **kwargs):
+ return self._func(**kwargs)
+
+
+class VPP(object):
+ """VPP interface.
+
+ This class provides the APIs to VPP. The APIs are loaded
+ from provided .api.json files and makes functions accordingly.
+ These functions are documented in the VPP .api files, as they
+ are dynamically created.
+
+ Additionally, VPP can send callback messages; this class
+ provides a means to register a callback function to receive
+ these messages in a background thread.
+ """
+
+ def process_json_file(self, apidef_file):
+ api = json.load(apidef_file)
+ types = {}
+ for t in api['enums']:
+ t[0] = 'vl_api_' + t[0] + '_t'
+ types[t[0]] = {'type': 'enum', 'data': t}
+ for t in api['unions']:
+ t[0] = 'vl_api_' + t[0] + '_t'
+ types[t[0]] = {'type': 'union', 'data': t}
+ for t in api['types']:
+ t[0] = 'vl_api_' + t[0] + '_t'
+ types[t[0]] = {'type': 'type', 'data': t}
+ for t, v in api['aliases'].items():
+ types['vl_api_' + t + '_t'] = {'type': 'alias', 'data': v}
+
+ i = 0
+ while True:
+ unresolved = {}
+ for k, v in types.items():
+ t = v['data']
+ if not vpp_get_type(k):
+ if v['type'] == 'enum':
+ try:
+ VPPEnumType(t[0], t[1:])
+ except ValueError:
+ unresolved[k] = v
+ elif v['type'] == 'union':
+ try:
+ VPPUnionType(t[0], t[1:])
+ except ValueError:
+ unresolved[k] = v
+ elif v['type'] == 'type':
+ try:
+ VPPType(t[0], t[1:])
+ except ValueError:
+ unresolved[k] = v
+ elif v['type'] == 'alias':
+ try:
+ VPPTypeAlias(k, t)
+ except ValueError:
+ unresolved[k] = v
+ if len(unresolved) == 0:
+ break
+ if i > 3:
+ raise ValueError('Unresolved type definitions {}'
+ .format(unresolved))
+ types = unresolved
+ i += 1
+
+ for m in api['messages']:
+ try:
+ self.messages[m[0]] = VPPMessage(m[0], m[1:])
+ except NotImplementedError:
+ self.logger.error('Not implemented error for {}'.format(m[0]))
+
+ def __init__(self, apifiles=None, testmode=False, async_thread=True,
+ logger=None, loglevel=None,
+ read_timeout=5, use_socket=False,
+ server_address='/run/vpp-api.sock'):
+ """Create a VPP API object.
+
+ apifiles is a list of files containing API
+ descriptions that will be loaded - methods will be
+ dynamically created reflecting these APIs. If not
+ provided this will load the API files from VPP's
+ default install location.
+
+ logger, if supplied, is the logging logger object to log to.
+ loglevel, if supplied, is the log level this logger is set
+ to report at (from the loglevels in the logging module).
+ """
+ if logger is None:
+ logger = logging.getLogger(__name__)
+ if loglevel is not None:
+ logger.setLevel(loglevel)
+ self.logger = logger