misc: papi - add __repr__ to FuncWrapper
[vpp.git] / src / vpp-api / python / vpp_papi / vpp_papi.py
index f29c250..5207bbf 100644 (file)
 
 from __future__ import print_function
 from __future__ import absolute_import
+import ctypes
 import sys
+import multiprocessing as mp
 import os
 import logging
-import collections
-import struct
 import functools
 import json
 import threading
 import fnmatch
 import weakref
 import atexit
-from . vpp_serializer import VPPType, VPPEnumType, VPPUnionType, BaseTypes
+from . vpp_serializer import VPPType, VPPEnumType, VPPUnionType
 from . vpp_serializer import VPPMessage, vpp_get_type, VPPTypeAlias
-from . macaddress import MACAddress, mac_pton, mac_ntop
 
 logger = logging.getLogger(__name__)
 
@@ -38,6 +37,11 @@ if sys.version[0] == '2':
 else:
     import queue as queue
 
+__all__ = ('FuncWrapper', 'VPP', 'VppApiDynamicMethodHolder',
+           'VppEnum', 'VppEnumType',
+           'VPPIOError', 'VPPRuntimeError', 'VPPValueError',
+           'VPPApiClient', )
+
 
 def metaclass(metaclass):
     @functools.wraps(metaclass)
@@ -100,6 +104,9 @@ class FuncWrapper(object):
     def __call__(self, **kwargs):
         return self._func(**kwargs)
 
+    def __repr__(self):
+        return '<FuncWrapper(func=<%s(%s)>)>' % (self.__name__, self.__doc__)
+
 
 class VPPApiError(Exception):
     pass
@@ -229,6 +236,11 @@ class VPPApiClient(object):
         self.message_queue = queue.Queue()
         self.read_timeout = read_timeout
         self.async_thread = async_thread
+        self.event_thread = None
+        self.testmode = testmode
+        self.use_socket = use_socket
+        self.server_address = server_address
+        self._apifiles = apifiles
 
         if use_socket:
             from . vpp_transport_socket import VppTransport
@@ -262,16 +274,16 @@ class VPPApiClient(object):
         atexit.register(vpp_atexit, weakref.ref(self))
 
     class ContextId(object):
-        """Thread-safe provider of unique context IDs."""
+        """Multiprocessing-safe provider of unique context IDs."""
         def __init__(self):
-            self.context = 0
-            self.lock = threading.Lock()
+            self.context = mp.Value(ctypes.c_uint, 0)
+            self.lock = mp.Lock()
 
         def __call__(self):
             """Get a new unique (or, at least, not recently used) context."""
             with self.lock:
-                self.context += 1
-                return self.context
+                self.context.value += 1
+                return self.context.value
     get_context = ContextId()
 
     def get_type(self, name):
@@ -465,6 +477,8 @@ class VPPApiClient(object):
                 target=self.thread_msg_handler)
             self.event_thread.daemon = True
             self.event_thread.start()
+        else:
+            self.event_thread = None
         return rv
 
     def connect(self, name, chroot_prefix=None, do_async=False, rx_qlen=32):
@@ -495,7 +509,8 @@ class VPPApiClient(object):
     def disconnect(self):
         """Detach from VPP."""
         rv = self.transport.disconnect()
-        self.message_queue.put("terminate event thread")
+        if self.event_thread is not None:
+            self.message_queue.put("terminate event thread")
         return rv
 
     def msg_handler_sync(self, msg):
@@ -711,6 +726,15 @@ class VPPApiClient(object):
             if self.event_callback:
                 self.event_callback(msgname, r)
 
+    def __repr__(self):
+        return "<VPPApiClient apifiles=%s, testmode=%s, async_thread=%s, " \
+               "logger=%s, read_timeout=%s, use_socket=%s, " \
+               "server_address='%s'>" % (
+                   self._apifiles, self.testmode, self.async_thread,
+                   self.logger, self.read_timeout, self.use_socket,
+                   self.server_address)
+
+
 # Provide the old name for backward compatibility.
 VPP = VPPApiClient