import logging
import collections
import struct
+import functools
import json
import threading
import fnmatch
import atexit
from . vpp_serializer import VPPType, VPPEnumType, VPPUnionType, BaseTypes
from . vpp_serializer import VPPMessage, vpp_get_type, VPPTypeAlias
+from . macaddress import MACAddress, mac_pton, mac_ntop
logger = logging.getLogger(__name__)
import queue as queue
+def metaclass(metaclass):
+ @functools.wraps(metaclass)
+ def wrapper(cls):
+ return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy())
+
+ return wrapper
+
+
class VppEnumType(type):
def __getattr__(cls, name):
t = vpp_get_type(name)
return t.enum
-# Python3
-# class VppEnum(metaclass=VppEnumType):
-# pass
+@metaclass(VppEnumType)
class VppEnum(object):
- __metaclass__ = VppEnumType
+ pass
def vpp_atexit(vpp_weakref):
vpp_instance.logger.debug('Cleaning up VPP on exit')
vpp_instance.disconnect()
+
if sys.version[0] == '2':
def vpp_iterator(d):
return d.iteritems()
def __init__(self, func):
self._func = func
self.__name__ = func.__name__
+ self.__doc__ = func.__doc__
def __call__(self, **kwargs):
return self._func(**kwargs)
pass
-class VPP(object):
+class VPPApiClient(object):
"""VPP interface.
This class provides the APIs to VPP. The APIs are loaded
provides a means to register a callback function to receive
these messages in a background thread.
"""
+ apidir = None
VPPApiError = VPPApiError
VPPRuntimeError = VPPRuntimeError
VPPValueError = VPPValueError
:returns: A single directory name, or None if no such directory
could be found.
"""
- dirs = []
-
- if 'VPP_API_DIR' in os.environ:
- dirs.append(os.environ['VPP_API_DIR'])
+ dirs = [cls.apidir] if cls.apidir else []
# perhaps we're in the 'src/scripts' or 'src/vpp-api/python' dir;
# in which case, plot a course to likely places in the src tree
# finally, try the location system packages typically install into
dirs.append(os.path.sep.join(('', 'usr', 'share', 'vpp', 'api')))
- # check the directories for existance; first one wins
+ # check the directories for existence; first one wins
for dir in dirs:
if os.path.isdir(dir):
return dir
f.__doc__ = ", ".join(["%s %s" %
(msg.fieldtypes[j], k)
for j, k in enumerate(msg.fields)])
+ f.msg = msg
+
return f
def _register_functions(self, do_async=False):
self._api = VppApiDynamicMethodHolder()
for name, msg in vpp_iterator(self.messages):
n = name + '_' + msg.crc[2:]
- i = self.transport.get_msg_index(n.encode())
+ i = self.transport.get_msg_index(n.encode('utf-8'))
if i > 0:
self.id_msgdef[i] = msg
self.id_names[i] = name
def connect_internal(self, name, msg_handler, chroot_prefix, rx_qlen,
do_async):
- pfx = chroot_prefix.encode() if chroot_prefix else None
+ pfx = chroot_prefix.encode('utf-8') if chroot_prefix else None
- rv = self.transport.connect(name.encode(), pfx, msg_handler, rx_qlen)
+ rv = self.transport.connect(name.encode('utf-8'), pfx,
+ msg_handler, rx_qlen)
if rv != 0:
raise VPPIOError(2, 'Connect failed')
self.vpp_dictionary_maxid = self.transport.msg_table_max_index()
# Initialise control ping
crc = self.messages['control_ping'].crc
self.control_ping_index = self.transport.get_msg_index(
- ('control_ping' + '_' + crc[2:]).encode())
+ ('control_ping' + '_' + crc[2:]).encode('utf-8'))
self.control_ping_msgdef = self.messages['control_ping']
if self.async_thread:
self.event_thread = threading.Thread(
if self.event_callback:
self.event_callback(msgname, r)
+# Provide the old name for backward compatibility.
+VPP = VPPApiClient
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4