ctypes allows to write extensions in pure Python. It is also part of the
Python's standard library and more portable across different
implementations and versions. This is also a first step to support
Python3.
A compatibility layer to the old vdeplug_python is also supplied as like
to the VdePlug module.
---
vde-2/configure.ac | 15 ---
vde-2/src/lib/python/Makefile.am | 15 +--
vde-2/src/lib/python/VdePlug.py | 96 ++-------------
vde-2/src/lib/python/vdeplug.py | 219 +++++++++++++++++++++++++++++++++
vde-2/src/lib/python/vdeplug_python.c | 102 ---------------
vde-2/src/lib/python/vdeplug_python.py | 15 +++
6 files changed, 248 insertions(+), 214 deletions(-)
create mode 100644 vde-2/src/lib/python/vdeplug.py
delete mode 100644 vde-2/src/lib/python/vdeplug_python.c
create mode 100644 vde-2/src/lib/python/vdeplug_python.py
diff --git a/vde-2/configure.ac b/vde-2/configure.ac
index c8f6d32..947aae6 100644
--- a/vde-2/configure.ac
+++ b/vde-2/configure.ac
@@ -223,21 +223,6 @@ AC_ARG_ENABLE([python],
if test x"$enable_python" = x"yes"; then
# check python
AM_PATH_PYTHON([2.5])
- AC_PATH_PROG(PYTHON_CONFIG, python$PYTHON_VERSION-config)
- if test x"$PYTHON_CONFIG" = x""; then
- AC_PATH_PROG(PYTHON_CONFIG, python-config)
- fi
- if test x"$PYTHON_CONFIG" = x""; then
- # not found, give up
- enable_python=no
- else
- PYTHON_CFLAGS=`$PYTHON_CONFIG --includes`
- PYTHON_LIBS=`$PYTHON_CONFIG --libs`
- PYTHON_INCLUDES="$PYTHON_CFLAGS"
- fi
- AC_SUBST(PYTHON_CFLAGS)
- AC_SUBST(PYTHON_INCLUDES)
- AC_SUBST(PYTHON_LIBS)
fi
diff --git a/vde-2/src/lib/python/Makefile.am b/vde-2/src/lib/python/Makefile.am
index b4d6e2b..4bfe5ef 100644
--- a/vde-2/src/lib/python/Makefile.am
+++ b/vde-2/src/lib/python/Makefile.am
@@ -1,12 +1,3 @@
-moddir = $(pythondir)
-
-AM_LIBTOOLFLAGS = --tag=disable-static
-
-LIBADD = $(top_builddir)/src/lib/libvdeplug.so
-
-mod_LTLIBRARIES = vdeplug_python.la
-dist_python_SCRIPTS = VdePlug.py
-
-vdeplug_python_la_CFLAGS = -I$(top_srcdir)/include $(PYTHON_CFLAGS)
$(PYTHON_INCLUDES)
-vdeplug_python_la_LIBADD = $(PYTHON_LIBS) $(top_builddir)/src/lib/libvdeplug.la
-vdeplug_python_la_LDFLAGS = -module -avoid-version
+python_PYTHON = VdePlug.py \
+ vdeplug.py \
+ vdeplug_python.py
diff --git a/vde-2/src/lib/python/VdePlug.py b/vde-2/src/lib/python/VdePlug.py
index 241c832..8035855 100755
--- a/vde-2/src/lib/python/VdePlug.py
+++ b/vde-2/src/lib/python/VdePlug.py
@@ -1,89 +1,15 @@
-#!/usr/bin/python
+from vdeplug import VdeStream, VdePlug
+import warnings
-'''
- LibVdePlug/python wrapper
- Copyright 2010 Daniele Lacamera
+__all__ = ["VdeStream", "VdePlug"]
- Released under the terms of GNU LGPL v. 2.1
- (see COPYING.libvdeplug in the main project directory)
-
-'''
-
-import vdeplug_python, os, sys, struct
-from array import array
-
-
-class VdeStream:
- def __init__(self, parent, outf, frecv = None, ferr = None):
- self.conn = parent
- self.outf = outf
- self.frecv = frecv
- self.ferr = ferr
- self.conn._streams.append(self)
- if (self.frecv == None):
- self.frecv=self.conn.send
-
- def recv(self, buf):
- (toth, totl) = struct.unpack("BB", buf[0:2])
- tot = (toth << 8) + totl
- buffer = buf[2:]
- if (len(buffer) < tot):
- sys.stderr.write("stream recv: wrong size %d, pkt is
%d\n" % (tot, len(buffer)))
- return -1
- elif (len(buffer) > tot):
- self.frecv(buffer[0:tot])
- return self.recv(buffer[tot:]) # Recursion for
remaining data
- elif (self.frecv(buffer) < 0):
- return -1
-
- def send(self, buf):
- if self.outf is None:
- return -1
- lh = (len(buf)>>8) & 0xFF
- ll = len(buf) & 0xFF
- a = struct.pack("BB", lh, ll)
- self.outf.write(a)
- self.outf.write(buf)
- self.outf.flush()
-
-
-
-
-
-class VdePlug:
-
- def __init__(self, sock=None, descr="Python", port=0, group=None,
mode=0):
- self._magic = vdeplug_python.open(sock, descr)
- self._ctl = os.fdopen(vdeplug_python.ctlfd(self._magic))
- self._data = os.fdopen(vdeplug_python.datafd(self._magic),
'wb+', os.O_NONBLOCK)
- self._streams = []
-
- def ctlfd(self):
- return self._ctl
-
- def datafd(self):
- return self._data
-
- def send(self, buffer):
- a = array('B', buffer)
- r = self._data.write(a)
- self._data.flush()
- return r
-
- def recv(self, size):
- return os.read(self._data.fileno(), size)
-
- def recvfrom_streams(self, buf):
- for s in self._streams:
- s.recv(buf)
-
- def sendto_streams(self, buf):
- for s in self._streams:
- s.send(buf)
-
- def close(self):
- vdeplug_python.close(self._magic)
- self._magic = None
-
+msg = """The module VdePlug is deprecated. Please use the module \
+vdeplug. Change your code as following:
+ try:
+ from vdeplug import VdePlug, VdeStream
+ except ImportError:
+ from VdePlug import VdePlug, VdeStream
+"""
+warnings.warn(msg, DeprecationWarning)
diff --git a/vde-2/src/lib/python/vdeplug.py b/vde-2/src/lib/python/vdeplug.py
new file mode 100644
index 0000000..6a63f08
--- /dev/null
+++ b/vde-2/src/lib/python/vdeplug.py
@@ -0,0 +1,219 @@
+# libvdeplug wrapper
+# Copyright (C) 2015 Marco Giusti
+#
+# Released under the terms of GNU LGPL v. 2.1
+# (see COPYING.libvdeplug in the main project directory)
+
+import os
+import ctypes
+import ctypes.util
+
+
+__all__ = ["LIBVDEPLUG_INTERFACE_VERSION", "VdeError", "open", "close",
+ "ctlfd", "datafd", "libvdeplug"]
+__version__ = "0.1"
+
+
+LIBVDEPLUG_INTERFACE_VERSION = 1
+
+
+# VdeError derives from RuntimeError only because of compatibility reasons
+
+class VdeError(EnvironmentError, RuntimeError):
+
+ def __init__(self, *args):
+ if not args:
+ errno = ctypes.get_errno()
+ args = errno, os.strerror(errno)
+ super(VdeError, self).__init__(*args)
+
+
+def open(sock, desc, port=0, group=None, mode=0o777):
+ """Open a VDE connection.
+
+ @param sock: switch id (path)
+ @type sock: str
+ @param desc: description that appear in the port description on the
+ switch
+ @type desc: str
+ @param port: connect to a specific port of the switch [default=0]
+ @type port: int
+ @param group: change the ownership of the communication port to a specific
+ group (None=no change) [default=None]
+ @type group: str
+ @param mode: set communication port mode (if 0 standard socket mode
+ applies) [default=0]
+ @type mode: int
+ """
+
+ args = _VdeOpenArgs(int(port), str(group), int(mode))
+ fd = libvdeplug.vde_open_real(sock, desc, LIBVDEPLUG_INTERFACE_VERSION,
+ ctypes.byref(args))
+ if not fd:
+ raise VdeError()
+ return fd
+
+
+def _invoke(func, conn):
+ i = func(conn)
+ if i < 0:
+ raise VdeError()
+ return i
+
+
+def ctlfd(conn):
+ """
+ for select/poll. the ctl socket is silent after the initial handshake.
+ when EOF the switch has closed the connection.
+ """
+
+ return _invoke(libvdeplug.vde_ctlfd, conn)
+
+
+def datafd(conn):
+ """
+ for select/poll when this fd receive data, there are packets to recv (call
+ vde_recv)
+ """
+
+ return _invoke(libvdeplug.vde_datafd, conn)
+
+
+def close(conn):
+ """Close a connection."""
+
+ return _invoke(libvdeplug.vde_close, conn)
+
+
+class Plug(object):
+
+ def __init__(self, sock, desc, port=0, group=None, mode=0o777):
+ self._conn = open(sock, desc, port, group, mode)
+ try:
+ self._ctlfd = os.fdopen(ctlfd(self._conn))
+ self._datafd = os.fdopen(datafd(self._conn), "wb+")
+ except:
+ self.close()
+ raise
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.close()
+
+ def ctlfd(self):
+ return self._ctlfd
+
+ def datafd(self):
+ return self._datafd
+
+ def close(self):
+ close(self._conn)
+
+
+class _VdeOpenArgs(ctypes.Structure):
+
+ _fields_ = [("port", ctypes.c_int),
+ ("group", ctypes.c_char_p),
+ ("mode", ctypes.c_int)]
+
+
+def _initializeModule(libvdeplug):
+ libvdeplug.vde_open_real.argtypes = [ctypes.c_char_p, ctypes.c_char_p,
+ ctypes.c_int,
+ ctypes.POINTER(_VdeOpenArgs)]
+ libvdeplug.vde_open_real.restype = ctypes.c_void_p
+ libvdeplug.vde_recv.argtypes = [ctypes.c_void_p, ctypes.c_void_p,
+ ctypes.c_size_t, ctypes.c_int]
+ libvdeplug.vde_recv.restype = ctypes.c_ssize_t
+ libvdeplug.vde_send.argtypes = [ctypes.c_void_p, ctypes.c_void_p,
+ ctypes.c_size_t, ctypes.c_int]
+ libvdeplug.vde_send.restype = ctypes.c_ssize_t
+ libvdeplug.vde_datafd.argtypes = [ctypes.c_void_p]
+ libvdeplug.vde_datafd.restype = ctypes.c_int
+ libvdeplug.vde_ctlfd.argtypes = [ctypes.c_void_p]
+ libvdeplug.vde_ctlfd.restype = ctypes.c_int
+ libvdeplug.vde_close.argtypes = [ctypes.c_void_p]
+ libvdeplug.vde_close.restype = ctypes.c_int
+
+
+name = ctypes.util.find_library("vdeplug")
+if not name:
+ raise ImportError("Can't find vdeplug library.")
+libvdeplug = ctypes.CDLL(name, use_errno=True)
+del name
+_initializeModule(libvdeplug)
+
+
+# old VdePlug compatibility
+
+# LibVdePlug/python wrapper
+# Copyright 2010 Daniele Lacamera
+#
+# Released under the terms of GNU LGPL v. 2.1
+# (see COPYING.libvdeplug in the main project directory)
+
+import sys
+import struct
+from array import array
+
+
+class VdePlug(Plug):
+
+ def __init__(self, sock=None, descr="Python", port=0, group=None, mode=0):
+ super(VdePlug, self).__init__(sock, descr, port, group, mode)
+ self._streams = []
+
+ def send(self, buffer):
+ a = array("B", buffer)
+ r = self._datafd.write(a)
+ self._datafd.flush()
+ return r
+
+ def recv(self, size):
+ return self._datafd.read(size)
+
+ def recvfrom_streams(self, buf):
+ for s in self._streams:
+ s.recv(buf)
+
+ def sendto_streams(self, buf):
+ for s in self._streams:
+ s.send(buf)
+
+
+class VdeStream:
+
+ def __init__(self, parent, outf, frecv=None, ferr=None):
+ self.conn = parent
+ self.outf = outf
+ self.frecv = frecv
+ self.ferr = ferr
+ self.conn._streams.append(self)
+ if self.frecv is None:
+ self.frecv = self.conn.send
+
+ def recv(self, buf):
+ toth, totl = struct.unpack("BB", buf[0:2])
+ tot = (toth << 8) + totl
+ buffer = buf[2:]
+ if len(buffer) < tot:
+ sys.stderr.write("stream recv: wrong size %d, pkt is %d\n" %
+ (tot, len(buffer)))
+ return -1
+ elif len(buffer) > tot:
+ self.frecv(buffer[0:tot])
+ return self.recv(buffer[tot:]) # Recursion for remaining data
+ elif self.frecv(buffer) < 0:
+ return -1
+
+ def send(self, buf):
+ if self.outf is None:
+ return -1
+ lh = (len(buf) >> 8) & 0xFF
+ ll = len(buf) & 0xFF
+ a = struct.pack("BB", lh, ll)
+ self.outf.write(a)
+ self.outf.write(buf)
+ self.outf.flush()
diff --git a/vde-2/src/lib/python/vdeplug_python.c
b/vde-2/src/lib/python/vdeplug_python.c
deleted file mode 100644
index 9d70e72..0000000
--- a/vde-2/src/lib/python/vdeplug_python.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * LibVdePlug/python wrapper
- * Copyright © 2010 Daniele Lacamera
- *
- * Released under the terms of GNU LGPL v. 2.1
- * (see COPYING.libvdeplug in the main project directory)
- *
- */
-#include "Python.h"
-#include <stdio.h>
-#include "libvdeplug.h"
-
-
-static PyObject *vdeplug_open(PyObject *self, PyObject *args)
-{
- struct vde_open_args vde_args = {0,NULL,0777};
- char *vde_sock = NULL, *vde_descr = NULL;
- VDECONN *ret;
-
- if (!PyArg_ParseTuple(args, "ss|isi", &vde_sock, &vde_descr,
&vde_args.port, &vde_args.group, &vde_args.mode))
- goto failure;
-
- ret = vde_open_real(vde_sock, vde_descr, 1, &vde_args);
- if (!ret)
- goto failure;
- else
- return PyLong_FromUnsignedLong((unsigned long) ret);
-
-
-failure:
- return PyErr_SetFromErrno(PyExc_RuntimeError);
-}
-
-static PyObject *vdeplug_ctlfd(PyObject *self, PyObject *args)
-{
- VDECONN *conn;
- unsigned long vde_magic = 0;
-
- if (!PyArg_ParseTuple(args, "k", &vde_magic))
- goto failure;
- conn = (VDECONN *) vde_magic;
-
- if (!conn)
- goto failure;
-
- return Py_BuildValue("i", vde_ctlfd(conn));
-
-failure:
- return PyErr_SetFromErrno(PyExc_RuntimeError);
-}
-
-static PyObject *vdeplug_datafd(PyObject *self, PyObject *args)
-{
- VDECONN *conn;
- unsigned long vde_magic = 0;
-
- if (!PyArg_ParseTuple(args, "k", &vde_magic))
- goto failure;
- conn = (VDECONN *) vde_magic;
-
- if (!conn)
- goto failure;
-
- return Py_BuildValue("i", vde_datafd(conn));
-
-failure:
- return PyErr_SetFromErrno(PyExc_RuntimeError);
-}
-
-static PyObject *vdeplug_close(PyObject *self, PyObject *args)
-{
- VDECONN *conn;
- unsigned long vde_magic = 0;
-
- if (!PyArg_ParseTuple(args, "k", &vde_magic))
- goto failure;
- conn = (VDECONN *) vde_magic;
-
- if (!conn)
- goto failure;
-
- return Py_BuildValue("i", vde_close(conn));
-
-failure:
- return PyErr_SetFromErrno(PyExc_RuntimeError);
-}
-
-
-
-static PyMethodDef vdeplug_methods[] = {
- {"open", vdeplug_open, METH_VARARGS},
- {"ctlfd", vdeplug_ctlfd, METH_VARARGS},
- {"datafd", vdeplug_datafd, METH_VARARGS},
- {"close", vdeplug_close, METH_VARARGS},
- {NULL, NULL} /* Sentinel */
-};
-
-void initvdeplug_python(void)
-{
- (void) Py_InitModule("vdeplug_python", vdeplug_methods);
-// PyErr_SetString(PyExc_RuntimeError,"vdeplug error");
-}
diff --git a/vde-2/src/lib/python/vdeplug_python.py
b/vde-2/src/lib/python/vdeplug_python.py
new file mode 100644
index 0000000..96738f3
--- /dev/null
+++ b/vde-2/src/lib/python/vdeplug_python.py
@@ -0,0 +1,15 @@
+from vdeplug import open, ctlfd, datafd, close
+import warnings
+
+
+__all__ = ["open", "ctlfd", "datafd", "close"]
+
+msg = """The module vdeplug_python is deprecated. Please use the module \
+vdeplug. Change your code as following:
+
+ try:
+ import vdeplug as vp
+ except ImportError:
+ import vdeplug_python as vp
+"""
+warnings.warn(msg, DeprecationWarning)
--
2.1.4
------------------------------------------------------------------------------
_______________________________________________
vde-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/vde-users