Hey,

On 23. 07. 2019. 15:47, Aleksandar Lazic wrote:
> Hi.
> 
> Am 23.07.2019 um 15:34 schrieb Vedran Furac:
>> Hello,
>>
>> Attached is a simple port of SPOA with embedded Python 2 interpreter to 
>> Python 3
>> following the official Python porting documentation. I tried to keep the 
>> changes
>> at minimum. Tested on my local Debian with Python v3.7 using the provided
>> example script.
> 
> Please can you also adopt the README to reflect this change.

Thanks, updated the README, amended the commit and attached new patch.

Thanks,
Vedran
>From 360387fce1c97d36d7a6c9a7cb38c82f4ab51592 Mon Sep 17 00:00:00 2001
From: Vedran Furac <vedr...@haproxy.com>
Date: Fri, 19 Jul 2019 15:18:56 +0200
Subject: [PATCH] MINOR: contrib/spoa_server: Port SPOA server to Python 3

Python 2 will be EOL in 2020. This patch ports SPOA server with
embedded interpreter to Python 3
---
 contrib/spoa_server/Makefile    |   6 +-
 contrib/spoa_server/README      |   2 +-
 contrib/spoa_server/ps_python.c | 123 ++++++++++++++++++--------------
 3 files changed, 74 insertions(+), 57 deletions(-)

diff --git a/contrib/spoa_server/Makefile b/contrib/spoa_server/Makefile
index f0752829..70ccf988 100644
--- a/contrib/spoa_server/Makefile
+++ b/contrib/spoa_server/Makefile
@@ -23,12 +23,12 @@ endif
 
 ifneq ($(USE_PYTHON),)
 OBJS += ps_python.o
-CFLAGS += -I/usr/include/python2.7
-LDLIBS += -lpython2.7
+CFLAGS  += $(shell python3-config --cflags) -Wno-sign-compare -fPIC
+LDFLAGS += $(shell python3-config --ldflags)
 endif
 
 spoa: $(OBJS)
-	$(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+	$(LD) $(LDFLAGS) -o $@ $^
 
 install: spoa
 	install spoa $(DESTDIR)$(BINDIR)
diff --git a/contrib/spoa_server/README b/contrib/spoa_server/README
index fa039c1a..f8ada376 100644
--- a/contrib/spoa_server/README
+++ b/contrib/spoa_server/README
@@ -16,7 +16,7 @@ distribution repositories or from the source.
 
 CentOS/RHEL: yum install python-devel
 
-The current python version in use is 2.7.
+The current python version in use is 3.x.
 
 
   Compilation
diff --git a/contrib/spoa_server/ps_python.c b/contrib/spoa_server/ps_python.c
index 0a9fbffc..654bebdf 100644
--- a/contrib/spoa_server/ps_python.c
+++ b/contrib/spoa_server/ps_python.c
@@ -36,6 +36,10 @@ static int ps_python_start_worker(struct worker *w);
 static int ps_python_load_file(struct worker *w, const char *file);
 static int ps_python_exec_message(struct worker *w, void *ref, int nargs, struct spoe_kv *args);
 
+struct module_state {
+    PyObject *error;
+};
+
 static struct ps ps_python_bindings = {
 	.init_worker = ps_python_start_worker,
 	.load_file = ps_python_load_file,
@@ -171,11 +175,11 @@ static PyObject *ps_python_set_var_ipv4(PyObject *self, PyObject *args)
 	value = PyObject_GetAttrString(ipv4, "packed");
 	if (value == NULL)
 		return NULL;
-	if (PyString_GET_SIZE(value) != sizeof(ip)) {
-		PyErr_Format(spoa_error, "UPv6 manipulation internal error");
+	if (PyBytes_Size(value) != sizeof(ip)) {
+		PyErr_Format(spoa_error, "IPv4 manipulation internal error");
 		return NULL;
 	}
-	memcpy(&ip, PyString_AS_STRING(value), PyString_GET_SIZE(value));
+	memcpy(&ip, PyBytes_AsString(value), PyBytes_Size(value));
 	if (!set_var_ipv4(worker, name, name_len, scope, &ip)) {
 		PyErr_SetString(spoa_error, "No space left available");
 		return NULL;
@@ -202,11 +206,11 @@ static PyObject *ps_python_set_var_ipv6(PyObject *self, PyObject *args)
 	value = PyObject_GetAttrString(ipv6, "packed");
 	if (value == NULL)
 		return NULL;
-	if (PyString_GET_SIZE(value) != sizeof(ip)) {
-		PyErr_Format(spoa_error, "UPv6 manipulation internal error");
+	if (PyBytes_Size(value) != sizeof(ip)) {
+		PyErr_Format(spoa_error, "IPv6 manipulation internal error");
 		return NULL;
 	}
-	memcpy(&ip, PyString_AS_STRING(value), PyString_GET_SIZE(value));
+	memcpy(&ip, PyBytes_AsString(value), PyBytes_Size(value));
 	if (!set_var_ipv6(worker, name, name_len, scope, &ip)) {
 		PyErr_SetString(spoa_error, "No space left available");
 		return NULL;
@@ -272,55 +276,31 @@ static PyMethodDef spoa_methods[] = {
 	 "Set SPOA str variable"},
 	{"set_var_bin", ps_python_set_var_bin, METH_VARARGS,
 	 "Set SPOA bin variable"},
-	{ /* end */ }
+	{NULL, NULL}
 };
 
-static int ps_python_start_worker(struct worker *w)
+static struct PyModuleDef spoa_module = {
+        PyModuleDef_HEAD_INIT,
+        "spoa",
+        NULL,
+        sizeof(struct module_state),
+        spoa_methods,
+        NULL,
+        NULL,
+        NULL,
+        NULL
+};
+
+static PyObject *PyInit_spoa(void)
 {
-	PyObject *m;
-	PyObject *module_name;
-	PyObject *value;
 	int ret;
-
-	Py_SetProgramName("spoa-server");
-	Py_Initialize();
-
-	module_name = PyString_FromString("ipaddress");
-	if (module_name == NULL) {
-		PyErr_Print();
-		return 0;
-	}
-
-	module_ipaddress = PyImport_Import(module_name);
-	Py_DECREF(module_name);
-	if (module_ipaddress == NULL) {
-		PyErr_Print();
-		return 0;
-	}
-
-	ipv4_address = PyObject_GetAttrString(module_ipaddress, "IPv4Address");
-	if (ipv4_address == NULL) {
-		PyErr_Print();
-		return 0;
-	}
-
-	ipv6_address = PyObject_GetAttrString(module_ipaddress, "IPv6Address");
-	if (ipv4_address == NULL) {
-		PyErr_Print();
-		return 0;
-	}
-
-	m = Py_InitModule("spoa", spoa_methods);
-	if (m == NULL) {
-		PyErr_Print();
-		return 0;
-	}
+	PyObject *value;
+	PyObject *m = PyModule_Create(&spoa_module);
 
 	spoa_error = PyErr_NewException("spoa.error", NULL, NULL);
 	Py_INCREF(spoa_error);
 	PyModule_AddObject(m, "error", spoa_error);
 
-
 	value = PyLong_FromLong(SPOE_SCOPE_PROC);
 	if (value == NULL) {
 		PyErr_Print();
@@ -387,6 +367,43 @@ static int ps_python_start_worker(struct worker *w)
 		return 0;
 	}
 
+    return m;
+}
+
+static int ps_python_start_worker(struct worker *w)
+{
+	PyObject *module_name;
+
+	Py_SetProgramName(Py_DecodeLocale("spoa-server", NULL));
+
+	PyImport_AppendInittab("spoa", &PyInit_spoa);
+	Py_Initialize();
+
+	module_name = PyUnicode_FromString("ipaddress");
+	if (module_name == NULL) {
+		PyErr_Print();
+		return 0;
+	}
+
+	module_ipaddress = PyImport_Import(module_name);
+	Py_DECREF(module_name);
+	if (module_ipaddress == NULL) {
+		PyErr_Print();
+		return 0;
+	}
+
+	ipv4_address = PyObject_GetAttrString(module_ipaddress, "IPv4Address");
+	if (ipv4_address == NULL) {
+		PyErr_Print();
+		return 0;
+	}
+
+	ipv6_address = PyObject_GetAttrString(module_ipaddress, "IPv6Address");
+	if (ipv4_address == NULL) {
+		PyErr_Print();
+		return 0;
+	}
+
 	worker = w;
 	return 1;
 }
@@ -452,14 +469,14 @@ static int ps_python_exec_message(struct worker *w, void *ref, int nargs, struct
 
 		/* Create the name entry */
 
-		key = PyString_FromString("name");
+		key = PyUnicode_FromString("name");
 		if (key == NULL) {
 			Py_DECREF(kw_args);
 			PyErr_Print();
 			return 0;
 		}
 
-		value = PyString_FromStringAndSize(args[i].name.str, args[i].name.len);
+		value = PyUnicode_FromStringAndSize(args[i].name.str, args[i].name.len);
 		if (value == NULL) {
 			Py_DECREF(kw_args);
 			Py_DECREF(ent);
@@ -480,7 +497,7 @@ static int ps_python_exec_message(struct worker *w, void *ref, int nargs, struct
 
 		/* Create th value entry */
 
-		key = PyString_FromString("value");
+		key = PyUnicode_FromString("value");
 		if (key == NULL) {
 			Py_DECREF(kw_args);
 			Py_DECREF(ent);
@@ -531,7 +548,7 @@ static int ps_python_exec_message(struct worker *w, void *ref, int nargs, struct
 				PyErr_Print();
 				return 0;
 			}
-			ip_name = PyString_FromString("address");
+			ip_name = PyUnicode_FromString("address");
 			if (ip_name == NULL) {
 				Py_DECREF(kw_args);
 				Py_DECREF(ent);
@@ -564,10 +581,10 @@ static int ps_python_exec_message(struct worker *w, void *ref, int nargs, struct
 			break;
 
 		case SPOE_DATA_T_STR:
-			value = PyString_FromStringAndSize(args[i].value.u.buffer.str, args[i].value.u.buffer.len);
+			value = PyUnicode_FromStringAndSize(args[i].value.u.buffer.str, args[i].value.u.buffer.len);
 			break;
 		case SPOE_DATA_T_BIN:
-			value = PyString_FromStringAndSize(args[i].value.u.buffer.str, args[i].value.u.buffer.len);
+			value = PyUnicode_FromStringAndSize(args[i].value.u.buffer.str, args[i].value.u.buffer.len);
 			break;
 		default:
 			value = Py_None;
@@ -611,7 +628,7 @@ static int ps_python_exec_message(struct worker *w, void *ref, int nargs, struct
 		return 0;
 	}
 
-	key = PyString_FromString("args");
+	key = PyUnicode_FromString("args");
 	if (key == NULL) {
 		Py_DECREF(kw_args);
 		Py_DECREF(fkw);
-- 
2.20.1

Reply via email to