From ace2715cf72e504c94794d096966d864810f6e23 Mon Sep 17 00:00:00 2001 From: James Booth Date: Thu, 14 Jul 2016 00:00:46 +0100 Subject: [PATCH 01/13] Added PYTHON3 define --- configure-debug | 2 +- configure.ac | 1 + src/plugins/python_api.c | 49 ++++++++++++++- src/plugins/python_plugins.c | 119 +++++++++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 3 deletions(-) diff --git a/configure-debug b/configure-debug index 48b5fb5c..a787e746 100755 --- a/configure-debug +++ b/configure-debug @@ -1,3 +1,3 @@ #!/bin/sh -./configure CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ +./configure PYTHON_VERSION=3 CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ diff --git a/configure.ac b/configure.ac index 8d06ecfe..e6ee131e 100644 --- a/configure.ac +++ b/configure.ac @@ -96,6 +96,7 @@ elif test "x$enable_python_plugins" = xyes; then fi fi AS_IF([test "x$PLATFORM" = xosx], [rm -f Python.framework]) + AS_IF([test "x$PYTHON_VERSION" = x3], [AC_DEFINE([PYTHON3], [1], [Python 3 build])]) else AM_CONDITIONAL([BUILD_PYTHON_API], [false]) fi diff --git a/src/plugins/python_api.c b/src/plugins/python_api.c index 6f478893..70e67820 100644 --- a/src/plugins/python_api.c +++ b/src/plugins/python_api.c @@ -32,6 +32,8 @@ * */ +#include "config.h" + #include #include @@ -128,7 +130,11 @@ python_api_register_command(PyObject *self, PyObject *args) Py_ssize_t i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(synopsis, i); +#ifdef PYTHON3 + char *c_item = PyBytes_AS_STRING(PyUnicode_AsUTF8String(item)); +#else char *c_item = PyString_AsString(item); +#endif c_synopsis[i] = c_item; } c_synopsis[len] = NULL; @@ -143,10 +149,18 @@ python_api_register_command(PyObject *self, PyObject *args) return Py_BuildValue(""); } PyObject *arg = PyList_GetItem(item, 0); +#ifdef PYTHON3 + char *c_arg = PyBytes_AS_STRING(PyUnicode_AsUTF8String(arg)); +#else char *c_arg = PyString_AsString(arg); +#endif PyObject *desc = PyList_GetItem(item, 1); - char *c_desc = PyString_AsString(desc); +#ifdef PYTHON3 + char *c_desc = PyBytes_AS_STRING(PyUnicode_AsUTF8String(desc)); +#else + char *c_desc = PyString_AsString(desc); +#endif c_arguments[i][0] = c_arg; c_arguments[i][1] = c_desc; } @@ -159,7 +173,11 @@ python_api_register_command(PyObject *self, PyObject *args) i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(examples, i); +#ifdef PYTHON3 + char *c_item = PyBytes_AS_STRING(PyUnicode_AsUTF8String(item)); +#else char *c_item = PyString_AsString(item); +#endif c_examples[i] = c_item; } c_examples[len] = NULL; @@ -218,7 +236,11 @@ python_api_completer_add(PyObject *self, PyObject *args) Py_ssize_t i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(items, i); +#ifdef PYTHON3 + char *c_item = PyBytes_AS_STRING(PyUnicode_AsUTF8String(item)); +#else char *c_item = PyString_AsString(item); +#endif c_items[i] = c_item; } c_items[len] = NULL; @@ -251,7 +273,11 @@ python_api_completer_remove(PyObject *self, PyObject *args) Py_ssize_t i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(items, i); +#ifdef PYTHON3 + char *c_item = PyBytes_AS_STRING(PyUnicode_AsUTF8String(item)); +#else char *c_item = PyString_AsString(item); +#endif c_items[i] = c_item; } c_items[len] = NULL; @@ -783,7 +809,7 @@ python_window_callback(PluginWindowCallback *window_callback, char *tag, char *l static PyMethodDef apiMethods[] = { { "cons_alert", python_api_cons_alert, METH_NOARGS, "Highlight the console window in the status bar." }, - { "cons_show", python_api_cons_show, METH_VARARGS, "Print a line to the console." }, + { "cons_show", (PyCFunction)python_api_cons_show, METH_VARARGS, "Print a line to the console." }, { "cons_show_themed", python_api_cons_show_themed, METH_VARARGS, "Print a themed line to the console" }, { "cons_bad_cmd_usage", python_api_cons_bad_cmd_usage, METH_VARARGS, "Show invalid command message in console" }, { "register_command", python_api_register_command, METH_VARARGS, "Register a command." }, @@ -819,10 +845,25 @@ static PyMethodDef apiMethods[] = { { NULL, NULL, 0, NULL } }; +#ifdef PYTHON3 +static struct PyModuleDef profModule = +{ + PyModuleDef_HEAD_INIT, + "prof", /* name of module */ + "", /* module documentation, may be NULL */ + -1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */ + apiMethods +}; +#endif + void python_api_init(void) { +#ifdef PYTHON3 + PyModule_Create(&profModule); +#else Py_InitModule("prof", apiMethods); +#endif } static char* @@ -830,7 +871,11 @@ _python_plugin_name(void) { PyThreadState *ts = PyThreadState_Get(); PyFrameObject *frame = ts->frame; +#ifdef PYTHON3 + char const *filename = PyBytes_AS_STRING(PyUnicode_AsUTF8String(frame->f_code->co_filename)); +#else char const* filename = PyString_AsString(frame->f_code->co_filename); +#endif gchar **split = g_strsplit(filename, "/", 0); char *plugin_name = strdup(split[g_strv_length(split)-1]); g_strfreev(split); diff --git a/src/plugins/python_plugins.c b/src/plugins/python_plugins.c index 61a4c479..ab50c10e 100644 --- a/src/plugins/python_plugins.c +++ b/src/plugins/python_plugins.c @@ -34,6 +34,8 @@ #include +#include "config.h" + #include "config/preferences.h" #include "plugins/api.h" #include "plugins/callbacks.h" @@ -277,6 +279,18 @@ python_pre_chat_message_display_hook(ProfPlugin *plugin, const char *const jid, PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + +#ifdef PYTHON3 + if (result != Py_None) { + char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); + Py_XDECREF(result); + allow_python_threads(); + return result_str; + } else { + allow_python_threads(); + return NULL; + } +#else if (PyUnicode_Check(result)) { char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -291,6 +305,7 @@ python_pre_chat_message_display_hook(ProfPlugin *plugin, const char *const jid, allow_python_threads(); return NULL; } +#endif } } @@ -334,6 +349,18 @@ python_pre_chat_message_send_hook(ProfPlugin *plugin, const char * const jid, co PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + +#ifdef PYTHON3 + if (result != Py_None) { + char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); + Py_XDECREF(result); + allow_python_threads(); + return result_str; + } else { + allow_python_threads(); + return NULL; + } +#else if (PyUnicode_Check(result)) { char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -348,6 +375,7 @@ python_pre_chat_message_send_hook(ProfPlugin *plugin, const char * const jid, co allow_python_threads(); return NULL; } +#endif } } @@ -391,6 +419,18 @@ python_pre_room_message_display_hook(ProfPlugin *plugin, const char * const room PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + +#ifdef PYTHON3 + if (result != Py_None) { + char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); + Py_XDECREF(result); + allow_python_threads(); + return result_str; + } else { + allow_python_threads(); + return NULL; + } +#else if (PyUnicode_Check(result)) { char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -405,6 +445,7 @@ python_pre_room_message_display_hook(ProfPlugin *plugin, const char * const room allow_python_threads(); return NULL; } +#endif } } @@ -449,6 +490,18 @@ python_pre_room_message_send_hook(ProfPlugin *plugin, const char *const room, co PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + +#ifdef PYTHON3 + if (result != Py_None) { + char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); + Py_XDECREF(result); + allow_python_threads(); + return result_str; + } else { + allow_python_threads(); + return NULL; + } +#else if (PyUnicode_Check(result)) { char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -463,6 +516,7 @@ python_pre_room_message_send_hook(ProfPlugin *plugin, const char *const room, co allow_python_threads(); return NULL; } +#endif } } @@ -529,6 +583,18 @@ python_pre_priv_message_display_hook(ProfPlugin *plugin, const char *const room, PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + +#ifdef PYTHON3 + if (result != Py_None) { + char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); + Py_XDECREF(result); + allow_python_threads(); + return result_str; + } else { + allow_python_threads(); + return NULL; + } +#else if (PyUnicode_Check(result)) { char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -543,6 +609,7 @@ python_pre_priv_message_display_hook(ProfPlugin *plugin, const char *const room, allow_python_threads(); return NULL; } +#endif } } @@ -588,6 +655,18 @@ python_pre_priv_message_send_hook(ProfPlugin *plugin, const char *const room, co PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + +#ifdef PYTHON3 + if (result != Py_None) { + char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); + Py_XDECREF(result); + allow_python_threads(); + return result_str; + } else { + allow_python_threads(); + return NULL; + } +#else if (PyUnicode_Check(result)) { char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -602,6 +681,7 @@ python_pre_priv_message_send_hook(ProfPlugin *plugin, const char *const room, co allow_python_threads(); return NULL; } +#endif } } @@ -646,6 +726,18 @@ python_on_message_stanza_send_hook(ProfPlugin *plugin, const char *const text) PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + +#ifdef PYTHON3 + if (result != Py_None) { + char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); + Py_XDECREF(result); + allow_python_threads(); + return result_str; + } else { + allow_python_threads(); + return NULL; + } +#else if (PyUnicode_Check(result)) { char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -660,6 +752,7 @@ python_on_message_stanza_send_hook(ProfPlugin *plugin, const char *const text) allow_python_threads(); return NULL; } +#endif } } @@ -711,6 +804,18 @@ python_on_presence_stanza_send_hook(ProfPlugin *plugin, const char *const text) PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + +#ifdef PYTHON3 + if (result != Py_None) { + char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); + Py_XDECREF(result); + allow_python_threads(); + return result_str; + } else { + allow_python_threads(); + return NULL; + } +#else if (PyUnicode_Check(result)) { char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -725,6 +830,7 @@ python_on_presence_stanza_send_hook(ProfPlugin *plugin, const char *const text) allow_python_threads(); return NULL; } +#endif } } @@ -776,6 +882,18 @@ python_on_iq_stanza_send_hook(ProfPlugin *plugin, const char *const text) PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + +#ifdef PYTHON3 + if (result != Py_None) { + char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); + Py_XDECREF(result); + allow_python_threads(); + return result_str; + } else { + allow_python_threads(); + return NULL; + } +#else if (PyUnicode_Check(result)) { char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -790,6 +908,7 @@ python_on_iq_stanza_send_hook(ProfPlugin *plugin, const char *const text) allow_python_threads(); return NULL; } +#endif } } From 7d742f704fd495fc6b4cda85e0ee0f517bb77797 Mon Sep 17 00:00:00 2001 From: James Booth Date: Mon, 18 Jul 2016 01:27:23 +0100 Subject: [PATCH 02/13] Fix prof module init for python3 --- configure-debug | 1 + configure.ac | 1 - src/plugins/python_api.c | 36 +++++++++++++++++++-------------- src/plugins/python_api.h | 4 +++- src/plugins/python_plugins.c | 39 +++++++++++++++++++++++++----------- 5 files changed, 52 insertions(+), 29 deletions(-) diff --git a/configure-debug b/configure-debug index a787e746..82734474 100755 --- a/configure-debug +++ b/configure-debug @@ -1,3 +1,4 @@ #!/bin/sh ./configure PYTHON_VERSION=3 CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ +#./configure CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ diff --git a/configure.ac b/configure.ac index e6ee131e..8d06ecfe 100644 --- a/configure.ac +++ b/configure.ac @@ -96,7 +96,6 @@ elif test "x$enable_python_plugins" = xyes; then fi fi AS_IF([test "x$PLATFORM" = xosx], [rm -f Python.framework]) - AS_IF([test "x$PYTHON_VERSION" = x3], [AC_DEFINE([PYTHON3], [1], [Python 3 build])]) else AM_CONDITIONAL([BUILD_PYTHON_API], [false]) fi diff --git a/src/plugins/python_api.c b/src/plugins/python_api.c index 70e67820..e0d54c1c 100644 --- a/src/plugins/python_api.c +++ b/src/plugins/python_api.c @@ -130,7 +130,7 @@ python_api_register_command(PyObject *self, PyObject *args) Py_ssize_t i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(synopsis, i); -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 char *c_item = PyBytes_AS_STRING(PyUnicode_AsUTF8String(item)); #else char *c_item = PyString_AsString(item); @@ -149,14 +149,14 @@ python_api_register_command(PyObject *self, PyObject *args) return Py_BuildValue(""); } PyObject *arg = PyList_GetItem(item, 0); -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 char *c_arg = PyBytes_AS_STRING(PyUnicode_AsUTF8String(arg)); #else char *c_arg = PyString_AsString(arg); #endif PyObject *desc = PyList_GetItem(item, 1); -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 char *c_desc = PyBytes_AS_STRING(PyUnicode_AsUTF8String(desc)); #else char *c_desc = PyString_AsString(desc); @@ -173,7 +173,7 @@ python_api_register_command(PyObject *self, PyObject *args) i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(examples, i); -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 char *c_item = PyBytes_AS_STRING(PyUnicode_AsUTF8String(item)); #else char *c_item = PyString_AsString(item); @@ -236,7 +236,7 @@ python_api_completer_add(PyObject *self, PyObject *args) Py_ssize_t i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(items, i); -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 char *c_item = PyBytes_AS_STRING(PyUnicode_AsUTF8String(item)); #else char *c_item = PyString_AsString(item); @@ -273,7 +273,7 @@ python_api_completer_remove(PyObject *self, PyObject *args) Py_ssize_t i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(items, i); -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 char *c_item = PyBytes_AS_STRING(PyUnicode_AsUTF8String(item)); #else char *c_item = PyString_AsString(item); @@ -809,7 +809,7 @@ python_window_callback(PluginWindowCallback *window_callback, char *tag, char *l static PyMethodDef apiMethods[] = { { "cons_alert", python_api_cons_alert, METH_NOARGS, "Highlight the console window in the status bar." }, - { "cons_show", (PyCFunction)python_api_cons_show, METH_VARARGS, "Print a line to the console." }, + { "cons_show", python_api_cons_show, METH_VARARGS, "Print a line to the console." }, { "cons_show_themed", python_api_cons_show_themed, METH_VARARGS, "Print a themed line to the console" }, { "cons_bad_cmd_usage", python_api_cons_bad_cmd_usage, METH_VARARGS, "Show invalid command message in console" }, { "register_command", python_api_register_command, METH_VARARGS, "Register a command." }, @@ -845,22 +845,28 @@ static PyMethodDef apiMethods[] = { { NULL, NULL, 0, NULL } }; -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 static struct PyModuleDef profModule = { PyModuleDef_HEAD_INIT, - "prof", /* name of module */ - "", /* module documentation, may be NULL */ - -1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */ + "prof", + "", + -1, apiMethods }; #endif -void +PyMODINIT_FUNC python_api_init(void) { -#ifdef PYTHON3 - PyModule_Create(&profModule); +#if PY_MAJOR_VERSION >= 3 + PyObject *result = PyModule_Create(&profModule); + if (!result) { + log_debug("Failed to initialise prof module"); + } else { + log_debug("Initialised prof module"); + } + return result; #else Py_InitModule("prof", apiMethods); #endif @@ -871,7 +877,7 @@ _python_plugin_name(void) { PyThreadState *ts = PyThreadState_Get(); PyFrameObject *frame = ts->frame; -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 char const *filename = PyBytes_AS_STRING(PyUnicode_AsUTF8String(frame->f_code->co_filename)); #else char const* filename = PyString_AsString(frame->f_code->co_filename); diff --git a/src/plugins/python_api.h b/src/plugins/python_api.h index f936a9cb..339ac06b 100644 --- a/src/plugins/python_api.h +++ b/src/plugins/python_api.h @@ -35,8 +35,10 @@ #ifndef PYTHON_API_H #define PYTHON_API_H +#include + void python_env_init(void); -void python_api_init(void); +PyMODINIT_FUNC python_api_init(void); void python_shutdown(void); void python_command_callback(PluginCommand *command, gchar **args); diff --git a/src/plugins/python_plugins.c b/src/plugins/python_plugins.c index ab50c10e..670dd46f 100644 --- a/src/plugins/python_plugins.c +++ b/src/plugins/python_plugins.c @@ -68,22 +68,34 @@ _unref_module(PyObject *module) void python_env_init(void) { + loaded_modules = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_unref_module); +#if PY_MAJOR_VERSION >= 3 + PyImport_AppendInittab("prof", python_api_init); + Py_Initialize(); + PyEval_InitThreads(); +#else Py_Initialize(); PyEval_InitThreads(); python_api_init(); +#endif + const char *ver = Py_GetVersion(); + cons_show("PYTHON: %s", ver); + + gchar *plugins_dir = plugins_get_dir(); GString *path = g_string_new("import sys\n"); g_string_append(path, "sys.path.append(\""); - gchar *plugins_dir = plugins_get_dir(); g_string_append(path, plugins_dir); - g_free(plugins_dir); g_string_append(path, "/\")\n"); PyRun_SimpleString(path->str); + python_check_error(); g_string_free(path, TRUE); + g_free(plugins_dir); + allow_python_threads(); } @@ -98,7 +110,9 @@ python_plugin_create(const char *const filename) } else { gchar *module_name = g_strndup(filename, strlen(filename) - 3); p_module = PyImport_ImportModule(module_name); - g_hash_table_insert(loaded_modules, strdup(filename), p_module); + if (p_module) { + g_hash_table_insert(loaded_modules, strdup(filename), p_module); + } g_free(module_name); } @@ -280,7 +294,7 @@ python_pre_chat_message_display_hook(ProfPlugin *plugin, const char *const jid, python_check_error(); Py_XDECREF(p_function); -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 if (result != Py_None) { char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -350,7 +364,7 @@ python_pre_chat_message_send_hook(ProfPlugin *plugin, const char * const jid, co python_check_error(); Py_XDECREF(p_function); -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 if (result != Py_None) { char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -420,7 +434,7 @@ python_pre_room_message_display_hook(ProfPlugin *plugin, const char * const room python_check_error(); Py_XDECREF(p_function); -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 if (result != Py_None) { char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -491,7 +505,7 @@ python_pre_room_message_send_hook(ProfPlugin *plugin, const char *const room, co python_check_error(); Py_XDECREF(p_function); -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 if (result != Py_None) { char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -584,7 +598,7 @@ python_pre_priv_message_display_hook(ProfPlugin *plugin, const char *const room, python_check_error(); Py_XDECREF(p_function); -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 if (result != Py_None) { char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -656,7 +670,7 @@ python_pre_priv_message_send_hook(ProfPlugin *plugin, const char *const room, co python_check_error(); Py_XDECREF(p_function); -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 if (result != Py_None) { char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -727,7 +741,7 @@ python_on_message_stanza_send_hook(ProfPlugin *plugin, const char *const text) python_check_error(); Py_XDECREF(p_function); -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 if (result != Py_None) { char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -805,7 +819,7 @@ python_on_presence_stanza_send_hook(ProfPlugin *plugin, const char *const text) python_check_error(); Py_XDECREF(p_function); -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 if (result != Py_None) { char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -883,7 +897,7 @@ python_on_iq_stanza_send_hook(ProfPlugin *plugin, const char *const text) python_check_error(); Py_XDECREF(p_function); -#ifdef PYTHON3 +#if PY_MAJOR_VERSION >= 3 if (result != Py_None) { char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); Py_XDECREF(result); @@ -1036,6 +1050,7 @@ python_check_error(void) { if (PyErr_Occurred()) { PyErr_Print(); + PyRun_SimpleString("import sys\nsys.stdout.flush()"); PyErr_Clear(); } } From 71ccfcc09fed24bb3b9115efe3a827b862d366de Mon Sep 17 00:00:00 2001 From: James Booth Date: Mon, 18 Jul 2016 23:24:26 +0100 Subject: [PATCH 03/13] Add python_init_prof() --- src/plugins/python_api.c | 14 ++++++++++++++ src/plugins/python_api.h | 4 +--- src/plugins/python_plugins.c | 11 +---------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/plugins/python_api.c b/src/plugins/python_api.c index e0d54c1c..01f7f8bd 100644 --- a/src/plugins/python_api.c +++ b/src/plugins/python_api.c @@ -872,6 +872,20 @@ python_api_init(void) #endif } +void +python_init_prof(void) +{ +#if PY_MAJOR_VERSION >= 3 + PyImport_AppendInittab("prof", python_api_init); + Py_Initialize(); + PyEval_InitThreads(); +#else + Py_Initialize(); + PyEval_InitThreads(); + python_api_init(); +#endif +} + static char* _python_plugin_name(void) { diff --git a/src/plugins/python_api.h b/src/plugins/python_api.h index 339ac06b..79280cc6 100644 --- a/src/plugins/python_api.h +++ b/src/plugins/python_api.h @@ -35,10 +35,8 @@ #ifndef PYTHON_API_H #define PYTHON_API_H -#include - void python_env_init(void); -PyMODINIT_FUNC python_api_init(void); +void python_init_prof(void); void python_shutdown(void); void python_command_callback(PluginCommand *command, gchar **args); diff --git a/src/plugins/python_plugins.c b/src/plugins/python_plugins.c index 670dd46f..15e244e1 100644 --- a/src/plugins/python_plugins.c +++ b/src/plugins/python_plugins.c @@ -68,18 +68,9 @@ _unref_module(PyObject *module) void python_env_init(void) { - loaded_modules = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_unref_module); -#if PY_MAJOR_VERSION >= 3 - PyImport_AppendInittab("prof", python_api_init); - Py_Initialize(); - PyEval_InitThreads(); -#else - Py_Initialize(); - PyEval_InitThreads(); - python_api_init(); -#endif + python_init_prof(); const char *ver = Py_GetVersion(); cons_show("PYTHON: %s", ver); From 376811a960a7c91ca33d4665bbf08e9ab9cee665 Mon Sep 17 00:00:00 2001 From: James Booth Date: Tue, 19 Jul 2016 01:02:33 +0100 Subject: [PATCH 04/13] Tidy python3 conditional code --- configure-debug | 4 +- src/plugins/python_api.c | 57 +++---- src/plugins/python_api.h | 2 + src/plugins/python_plugins.c | 289 +++++++---------------------------- 4 files changed, 78 insertions(+), 274 deletions(-) diff --git a/configure-debug b/configure-debug index 82734474..92ddceb4 100755 --- a/configure-debug +++ b/configure-debug @@ -1,4 +1,4 @@ #!/bin/sh -./configure PYTHON_VERSION=3 CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ -#./configure CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ +#./configure PYTHON_VERSION=3 CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ +./configure CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ diff --git a/src/plugins/python_api.c b/src/plugins/python_api.c index 01f7f8bd..08060f3f 100644 --- a/src/plugins/python_api.c +++ b/src/plugins/python_api.c @@ -56,7 +56,6 @@ python_api_cons_alert(PyObject *self, PyObject *args) disable_python_threads(); return Py_BuildValue(""); - } static PyObject* @@ -130,11 +129,7 @@ python_api_register_command(PyObject *self, PyObject *args) Py_ssize_t i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(synopsis, i); -#if PY_MAJOR_VERSION >= 3 - char *c_item = PyBytes_AS_STRING(PyUnicode_AsUTF8String(item)); -#else - char *c_item = PyString_AsString(item); -#endif + char *c_item = python_object_to_string(item); c_synopsis[i] = c_item; } c_synopsis[len] = NULL; @@ -149,19 +144,11 @@ python_api_register_command(PyObject *self, PyObject *args) return Py_BuildValue(""); } PyObject *arg = PyList_GetItem(item, 0); -#if PY_MAJOR_VERSION >= 3 - char *c_arg = PyBytes_AS_STRING(PyUnicode_AsUTF8String(arg)); -#else - char *c_arg = PyString_AsString(arg); -#endif - PyObject *desc = PyList_GetItem(item, 1); - -#if PY_MAJOR_VERSION >= 3 - char *c_desc = PyBytes_AS_STRING(PyUnicode_AsUTF8String(desc)); -#else - char *c_desc = PyString_AsString(desc); -#endif + char *c_arg = python_object_to_string(arg); c_arguments[i][0] = c_arg; + + PyObject *desc = PyList_GetItem(item, 1); + char *c_desc = python_object_to_string(desc); c_arguments[i][1] = c_desc; } @@ -173,11 +160,7 @@ python_api_register_command(PyObject *self, PyObject *args) i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(examples, i); -#if PY_MAJOR_VERSION >= 3 - char *c_item = PyBytes_AS_STRING(PyUnicode_AsUTF8String(item)); -#else - char *c_item = PyString_AsString(item); -#endif + char *c_item = python_object_to_string(item); c_examples[i] = c_item; } c_examples[len] = NULL; @@ -236,11 +219,7 @@ python_api_completer_add(PyObject *self, PyObject *args) Py_ssize_t i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(items, i); -#if PY_MAJOR_VERSION >= 3 - char *c_item = PyBytes_AS_STRING(PyUnicode_AsUTF8String(item)); -#else - char *c_item = PyString_AsString(item); -#endif + char *c_item = python_object_to_string(item); c_items[i] = c_item; } c_items[len] = NULL; @@ -273,11 +252,7 @@ python_api_completer_remove(PyObject *self, PyObject *args) Py_ssize_t i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(items, i); -#if PY_MAJOR_VERSION >= 3 - char *c_item = PyBytes_AS_STRING(PyUnicode_AsUTF8String(item)); -#else - char *c_item = PyString_AsString(item); -#endif + char *c_item = python_object_to_string(item); c_items[i] = c_item; } c_items[len] = NULL; @@ -891,14 +866,20 @@ _python_plugin_name(void) { PyThreadState *ts = PyThreadState_Get(); PyFrameObject *frame = ts->frame; -#if PY_MAJOR_VERSION >= 3 - char const *filename = PyBytes_AS_STRING(PyUnicode_AsUTF8String(frame->f_code->co_filename)); -#else - char const* filename = PyString_AsString(frame->f_code->co_filename); -#endif + char const* filename = python_object_to_string(frame->f_code->co_filename); gchar **split = g_strsplit(filename, "/", 0); char *plugin_name = strdup(split[g_strv_length(split)-1]); g_strfreev(split); return plugin_name; } + +char* +python_object_to_string(void *obj) +{ +#if PY_MAJOR_VERSION >= 3 + return PyBytes_AS_STRING(PyUnicode_AsUTF8String(obj)); +#else + return PyString_AsString(obj); +#endif +} diff --git a/src/plugins/python_api.h b/src/plugins/python_api.h index 79280cc6..dbc2b979 100644 --- a/src/plugins/python_api.h +++ b/src/plugins/python_api.h @@ -43,4 +43,6 @@ void python_command_callback(PluginCommand *command, gchar **args); void python_timed_callback(PluginTimedFunction *timed_function); void python_window_callback(PluginWindowCallback *window_callback, char *tag, char *line); +char* python_object_to_string(void *obj); + #endif diff --git a/src/plugins/python_plugins.c b/src/plugins/python_plugins.c index 15e244e1..c7f59956 100644 --- a/src/plugins/python_plugins.c +++ b/src/plugins/python_plugins.c @@ -47,6 +47,8 @@ static PyThreadState *thread_state; static GHashTable *loaded_modules; +static char* _python_parse_string_result(PyObject *result); + void allow_python_threads() { @@ -284,33 +286,10 @@ python_pre_chat_message_display_hook(ProfPlugin *plugin, const char *const jid, PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + char *result_str = _python_parse_string_result(result); + allow_python_threads(); -#if PY_MAJOR_VERSION >= 3 - if (result != Py_None) { - char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#else - if (PyUnicode_Check(result)) { - char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else if (result != Py_None) { - char *result_str = strdup(PyString_AsString(result)); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#endif + return result_str; } } @@ -354,33 +333,10 @@ python_pre_chat_message_send_hook(ProfPlugin *plugin, const char * const jid, co PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + char *result_str = _python_parse_string_result(result); + allow_python_threads(); -#if PY_MAJOR_VERSION >= 3 - if (result != Py_None) { - char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#else - if (PyUnicode_Check(result)) { - char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else if (result != Py_None) { - char *result_str = strdup(PyString_AsString(result)); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#endif + return result_str; } } @@ -424,33 +380,10 @@ python_pre_room_message_display_hook(ProfPlugin *plugin, const char * const room PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + char *result_str = _python_parse_string_result(result); + allow_python_threads(); -#if PY_MAJOR_VERSION >= 3 - if (result != Py_None) { - char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#else - if (PyUnicode_Check(result)) { - char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else if (result != Py_None) { - char *result_str = strdup(PyString_AsString(result)); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#endif + return result_str; } } @@ -495,33 +428,10 @@ python_pre_room_message_send_hook(ProfPlugin *plugin, const char *const room, co PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + char *result_str = _python_parse_string_result(result); + allow_python_threads(); -#if PY_MAJOR_VERSION >= 3 - if (result != Py_None) { - char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#else - if (PyUnicode_Check(result)) { - char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else if (result != Py_None) { - char *result_str = strdup(PyString_AsString(result)); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#endif + return result_str; } } @@ -588,33 +498,10 @@ python_pre_priv_message_display_hook(ProfPlugin *plugin, const char *const room, PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + char *result_str = _python_parse_string_result(result); + allow_python_threads(); -#if PY_MAJOR_VERSION >= 3 - if (result != Py_None) { - char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#else - if (PyUnicode_Check(result)) { - char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else if (result != Py_None) { - char *result_str = strdup(PyString_AsString(result)); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#endif + return result_str; } } @@ -660,33 +547,10 @@ python_pre_priv_message_send_hook(ProfPlugin *plugin, const char *const room, co PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + char *result_str = _python_parse_string_result(result); + allow_python_threads(); -#if PY_MAJOR_VERSION >= 3 - if (result != Py_None) { - char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#else - if (PyUnicode_Check(result)) { - char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else if (result != Py_None) { - char *result_str = strdup(PyString_AsString(result)); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#endif + return result_str; } } @@ -731,33 +595,10 @@ python_on_message_stanza_send_hook(ProfPlugin *plugin, const char *const text) PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + char *result_str = _python_parse_string_result(result); + allow_python_threads(); -#if PY_MAJOR_VERSION >= 3 - if (result != Py_None) { - char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#else - if (PyUnicode_Check(result)) { - char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else if (result != Py_None) { - char *result_str = strdup(PyString_AsString(result)); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#endif + return result_str; } } @@ -809,33 +650,10 @@ python_on_presence_stanza_send_hook(ProfPlugin *plugin, const char *const text) PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + char *result_str = _python_parse_string_result(result); + allow_python_threads(); -#if PY_MAJOR_VERSION >= 3 - if (result != Py_None) { - char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#else - if (PyUnicode_Check(result)) { - char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else if (result != Py_None) { - char *result_str = strdup(PyString_AsString(result)); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#endif + return result_str; } } @@ -887,33 +705,10 @@ python_on_iq_stanza_send_hook(ProfPlugin *plugin, const char *const text) PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); + char *result_str = _python_parse_string_result(result); + allow_python_threads(); -#if PY_MAJOR_VERSION >= 3 - if (result != Py_None) { - char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#else - if (PyUnicode_Check(result)) { - char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else if (result != Py_None) { - char *result_str = strdup(PyString_AsString(result)); - Py_XDECREF(result); - allow_python_threads(); - return result_str; - } else { - allow_python_threads(); - return NULL; - } -#endif + return result_str; } } @@ -1063,3 +858,29 @@ python_shutdown(void) g_hash_table_destroy(loaded_modules); Py_Finalize(); } + +static char* +_python_parse_string_result(PyObject *result) +{ +#if PY_MAJOR_VERSION >= 3 + if (result != Py_None) { + char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); + Py_XDECREF(result); + return result_str; + } else { + return NULL; + } +#else + if (PyUnicode_Check(result)) { + char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); + Py_XDECREF(result); + return result_str; + } else if (result != Py_None) { + char *result_str = strdup(PyString_AsString(result)); + Py_XDECREF(result); + return result_str; + } else { + return NULL; + } +#endif +} From f1dea893aa00335176610ff40cc54ca36e9e1dba Mon Sep 17 00:00:00 2001 From: James Booth Date: Tue, 19 Jul 2016 01:05:17 +0100 Subject: [PATCH 05/13] Use python3 in configure-debug --- configure-debug | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure-debug b/configure-debug index 92ddceb4..82734474 100755 --- a/configure-debug +++ b/configure-debug @@ -1,4 +1,4 @@ #!/bin/sh -#./configure PYTHON_VERSION=3 CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ -./configure CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ +./configure PYTHON_VERSION=3 CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ +#./configure CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ From 066526db418b1a21078ae8782f2cc8bd82ed9497 Mon Sep 17 00:00:00 2001 From: James Booth Date: Tue, 19 Jul 2016 23:43:43 +0100 Subject: [PATCH 06/13] Comment python version arg in configure-debug --- configure-debug | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure-debug b/configure-debug index 82734474..92ddceb4 100755 --- a/configure-debug +++ b/configure-debug @@ -1,4 +1,4 @@ #!/bin/sh -./configure PYTHON_VERSION=3 CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ -#./configure CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ +#./configure PYTHON_VERSION=3 CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ +./configure CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ From b68d2ce106fa0ef9365dc2902201f4dce72fd978 Mon Sep 17 00:00:00 2001 From: James Booth Date: Tue, 19 Jul 2016 23:44:38 +0100 Subject: [PATCH 07/13] Update gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 5a6c56c4..e88e93c3 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,7 @@ valgrind.out .DS_Store apidocs/c/html/ + +*.swp +python2/ +python3/ From d2e237203ca55a0d947abab8aa312f7fbbd5a49c Mon Sep 17 00:00:00 2001 From: James Booth Date: Thu, 21 Jul 2016 22:23:28 +0100 Subject: [PATCH 08/13] Check for win callback hash before removing --- src/plugins/callbacks.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/plugins/callbacks.c b/src/plugins/callbacks.c index 1ac4c5b9..c7ea471b 100644 --- a/src/plugins/callbacks.c +++ b/src/plugins/callbacks.c @@ -159,13 +159,15 @@ callbacks_remove(const char *const plugin_name) g_hash_table_remove(p_timed_functions, plugin_name); GHashTable *tag_to_win_cb_hash = g_hash_table_lookup(p_window_callbacks, plugin_name); - GList *tags = g_hash_table_get_keys(tag_to_win_cb_hash); - GList *curr = tags; - while (curr) { - wins_close_plugin(curr->data); - curr = g_list_next(curr); + if (tag_to_win_cb_hash) { + GList *tags = g_hash_table_get_keys(tag_to_win_cb_hash); + GList *curr = tags; + while (curr) { + wins_close_plugin(curr->data); + curr = g_list_next(curr); + } + g_list_free(tags); } - g_list_free(tags); g_hash_table_remove(p_window_callbacks, plugin_name); } From d44472049b6c4bf4ff96315182ad214db693057f Mon Sep 17 00:00:00 2001 From: James Booth Date: Sun, 24 Jul 2016 01:09:18 +0100 Subject: [PATCH 09/13] Allow str and unicode in python api --- src/plugins/python_api.c | 329 ++++++++++++++++++++++------------- src/plugins/python_api.h | 2 +- src/plugins/python_plugins.c | 46 +---- 3 files changed, 222 insertions(+), 155 deletions(-) diff --git a/src/plugins/python_api.c b/src/plugins/python_api.c index 08060f3f..d65b35e0 100644 --- a/src/plugins/python_api.c +++ b/src/plugins/python_api.c @@ -61,12 +61,15 @@ python_api_cons_alert(PyObject *self, PyObject *args) static PyObject* python_api_cons_show(PyObject *self, PyObject *args) { - const char *message = NULL; - if (!PyArg_ParseTuple(args, "s", &message)) { + PyObject* message = NULL; + if (!PyArg_ParseTuple(args, "O", &message)) { return Py_BuildValue(""); } + + char *message_str = python_str_or_unicode_to_string(message); + allow_python_threads(); - api_cons_show(message); + api_cons_show(message_str); disable_python_threads(); return Py_BuildValue(""); @@ -75,15 +78,21 @@ python_api_cons_show(PyObject *self, PyObject *args) static PyObject* python_api_cons_show_themed(PyObject *self, PyObject *args) { - const char *group = NULL; - const char *key = NULL; - const char *def = NULL; - const char *message = NULL; - if (!PyArg_ParseTuple(args, "zzzs", &group, &key, &def, &message)) { + PyObject *group = NULL; + PyObject *key = NULL; + PyObject *def = NULL; + PyObject *message = NULL; + if (!PyArg_ParseTuple(args, "OOOO", &group, &key, &def, &message)) { return Py_BuildValue(""); } + + char *group_str = python_str_or_unicode_to_string(group); + char *key_str = python_str_or_unicode_to_string(key); + char *def_str = python_str_or_unicode_to_string(def); + char *message_str = python_str_or_unicode_to_string(message); + allow_python_threads(); - api_cons_show_themed(group, key, def, message); + api_cons_show_themed(group_str, key_str, def_str, message_str); disable_python_threads(); return Py_BuildValue(""); @@ -92,12 +101,15 @@ python_api_cons_show_themed(PyObject *self, PyObject *args) static PyObject* python_api_cons_bad_cmd_usage(PyObject *self, PyObject *args) { - const char *cmd = NULL; - if (!PyArg_ParseTuple(args, "s", &cmd)) { + PyObject *cmd = NULL; + if (!PyArg_ParseTuple(args, "O", &cmd)) { return Py_BuildValue(""); } + + char *cmd_str = python_str_or_unicode_to_string(cmd); + allow_python_threads(); - api_cons_bad_cmd_usage(cmd); + api_cons_bad_cmd_usage(cmd_str); disable_python_threads(); return Py_BuildValue(""); @@ -106,22 +118,25 @@ python_api_cons_bad_cmd_usage(PyObject *self, PyObject *args) static PyObject* python_api_register_command(PyObject *self, PyObject *args) { - const char *command_name = NULL; + PyObject *command_name = NULL; int min_args = 0; int max_args = 0; PyObject *synopsis = NULL; - const char *description = NULL; + PyObject *description = NULL; PyObject *arguments = NULL; PyObject *examples = NULL; PyObject *p_callback = NULL; - if (!PyArg_ParseTuple(args, "siiOsOOO", &command_name, &min_args, &max_args, + if (!PyArg_ParseTuple(args, "OiiOOOOO", &command_name, &min_args, &max_args, &synopsis, &description, &arguments, &examples, &p_callback)) { return Py_BuildValue(""); } + char *command_name_str = python_str_or_unicode_to_string(command_name); + char *description_str = python_str_or_unicode_to_string(description); + char *plugin_name = _python_plugin_name(); - log_debug("Register command %s for %s", command_name, plugin_name); + log_debug("Register command %s for %s", command_name_str, plugin_name); if (p_callback && PyCallable_Check(p_callback)) { Py_ssize_t len = PyList_Size(synopsis); @@ -129,7 +144,7 @@ python_api_register_command(PyObject *self, PyObject *args) Py_ssize_t i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(synopsis, i); - char *c_item = python_object_to_string(item); + char *c_item = python_str_or_unicode_to_string(item); c_synopsis[i] = c_item; } c_synopsis[len] = NULL; @@ -144,11 +159,11 @@ python_api_register_command(PyObject *self, PyObject *args) return Py_BuildValue(""); } PyObject *arg = PyList_GetItem(item, 0); - char *c_arg = python_object_to_string(arg); + char *c_arg = python_str_or_unicode_to_string(arg); c_arguments[i][0] = c_arg; PyObject *desc = PyList_GetItem(item, 1); - char *c_desc = python_object_to_string(desc); + char *c_desc = python_str_or_unicode_to_string(desc); c_arguments[i][1] = c_desc; } @@ -160,14 +175,14 @@ python_api_register_command(PyObject *self, PyObject *args) i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(examples, i); - char *c_item = python_object_to_string(item); + char *c_item = python_str_or_unicode_to_string(item); c_examples[i] = c_item; } c_examples[len] = NULL; allow_python_threads(); - api_register_command(plugin_name, command_name, min_args, max_args, c_synopsis, - description, c_arguments, c_examples, p_callback, python_command_callback, NULL); + api_register_command(plugin_name, command_name_str, min_args, max_args, c_synopsis, + description_str, c_arguments, c_examples, p_callback, python_command_callback, NULL); disable_python_threads(); } @@ -203,15 +218,17 @@ python_api_register_timed(PyObject *self, PyObject *args) static PyObject * python_api_completer_add(PyObject *self, PyObject *args) { - const char *key = NULL; + PyObject *key = NULL; PyObject *items = NULL; - if (!PyArg_ParseTuple(args, "sO", &key, &items)) { + if (!PyArg_ParseTuple(args, "OO", &key, &items)) { return Py_BuildValue(""); } + char *key_str = python_str_or_unicode_to_string(key); + char *plugin_name = _python_plugin_name(); - log_debug("Autocomplete add %s for %s", key, plugin_name); + log_debug("Autocomplete add %s for %s", key_str, plugin_name); Py_ssize_t len = PyList_Size(items); char *c_items[len]; @@ -219,13 +236,13 @@ python_api_completer_add(PyObject *self, PyObject *args) Py_ssize_t i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(items, i); - char *c_item = python_object_to_string(item); + char *c_item = python_str_or_unicode_to_string(item); c_items[i] = c_item; } c_items[len] = NULL; allow_python_threads(); - api_completer_add(plugin_name, key, c_items); + api_completer_add(plugin_name, key_str, c_items); disable_python_threads(); free(plugin_name); @@ -236,15 +253,17 @@ python_api_completer_add(PyObject *self, PyObject *args) static PyObject * python_api_completer_remove(PyObject *self, PyObject *args) { - const char *key = NULL; + PyObject *key = NULL; PyObject *items = NULL; - if (!PyArg_ParseTuple(args, "sO", &key, &items)) { + if (!PyArg_ParseTuple(args, "OO", &key, &items)) { return Py_BuildValue(""); } + char *key_str = python_str_or_unicode_to_string(key); + char *plugin_name = _python_plugin_name(); - log_debug("Autocomplete remove %s for %s", key, plugin_name); + log_debug("Autocomplete remove %s for %s", key_str, plugin_name); Py_ssize_t len = PyList_Size(items); char *c_items[len]; @@ -252,13 +271,13 @@ python_api_completer_remove(PyObject *self, PyObject *args) Py_ssize_t i = 0; for (i = 0; i < len; i++) { PyObject *item = PyList_GetItem(items, i); - char *c_item = python_object_to_string(item); + char *c_item = python_str_or_unicode_to_string(item); c_items[i] = c_item; } c_items[len] = NULL; allow_python_threads(); - api_completer_remove(plugin_name, key, c_items); + api_completer_remove(plugin_name, key_str, c_items); disable_python_threads(); free(plugin_name); @@ -269,17 +288,19 @@ python_api_completer_remove(PyObject *self, PyObject *args) static PyObject * python_api_completer_clear(PyObject *self, PyObject *args) { - const char *key = NULL; + PyObject *key = NULL; - if (!PyArg_ParseTuple(args, "s", &key)) { + if (!PyArg_ParseTuple(args, "O", &key)) { return Py_BuildValue(""); } + char *key_str = python_str_or_unicode_to_string(key); + char *plugin_name = _python_plugin_name(); - log_debug("Autocomplete clear %s for %s", key, plugin_name); + log_debug("Autocomplete clear %s for %s", key_str, plugin_name); allow_python_threads(); - api_completer_clear(plugin_name, key); + api_completer_clear(plugin_name, key_str); disable_python_threads(); free(plugin_name); @@ -290,16 +311,19 @@ python_api_completer_clear(PyObject *self, PyObject *args) static PyObject* python_api_notify(PyObject *self, PyObject *args) { - const char *message = NULL; - const char *category = NULL; + PyObject *message = NULL; + PyObject *category = NULL; int timeout_ms = 5000; - if (!PyArg_ParseTuple(args, "sis", &message, &timeout_ms, &category)) { + if (!PyArg_ParseTuple(args, "OiO", &message, &timeout_ms, &category)) { return Py_BuildValue(""); } + char *message_str = python_str_or_unicode_to_string(message); + char *category_str = python_str_or_unicode_to_string(category); + allow_python_threads(); - api_notify(message, category, timeout_ms); + api_notify(message_str, category_str, timeout_ms); disable_python_threads(); return Py_BuildValue(""); @@ -308,13 +332,15 @@ python_api_notify(PyObject *self, PyObject *args) static PyObject* python_api_send_line(PyObject *self, PyObject *args) { - char *line = NULL; - if (!PyArg_ParseTuple(args, "s", &line)) { + PyObject *line = NULL; + if (!PyArg_ParseTuple(args, "O", &line)) { return Py_BuildValue(""); } + char *line_str = python_str_or_unicode_to_string(line); + allow_python_threads(); - api_send_line(line); + api_send_line(line_str); disable_python_threads(); return Py_BuildValue(""); @@ -394,12 +420,15 @@ python_api_current_win_is_console(PyObject *self, PyObject *args) static PyObject * python_api_log_debug(PyObject *self, PyObject *args) { - const char *message = NULL; - if (!PyArg_ParseTuple(args, "s", &message)) { + PyObject *message = NULL; + if (!PyArg_ParseTuple(args, "O", &message)) { return Py_BuildValue(""); } + + char *message_str = python_str_or_unicode_to_string(message); + allow_python_threads(); - api_log_debug(message); + api_log_debug(message_str); disable_python_threads(); return Py_BuildValue(""); @@ -408,13 +437,15 @@ python_api_log_debug(PyObject *self, PyObject *args) static PyObject * python_api_log_info(PyObject *self, PyObject *args) { - const char *message = NULL; - if (!PyArg_ParseTuple(args, "s", &message)) { + PyObject *message = NULL; + if (!PyArg_ParseTuple(args, "O", &message)) { return Py_BuildValue(""); } + char *message_str = python_str_or_unicode_to_string(message); + allow_python_threads(); - api_log_info(message); + api_log_info(message_str); disable_python_threads(); return Py_BuildValue(""); @@ -423,26 +454,32 @@ python_api_log_info(PyObject *self, PyObject *args) static PyObject * python_api_log_warning(PyObject *self, PyObject *args) { - const char *message = NULL; - if (!PyArg_ParseTuple(args, "s", &message)) { + PyObject *message = NULL; + if (!PyArg_ParseTuple(args, "O", &message)) { return Py_BuildValue(""); } + char *message_str = python_str_or_unicode_to_string(message); + allow_python_threads(); - api_log_warning(message); + api_log_warning(message_str); disable_python_threads(); + return Py_BuildValue(""); } static PyObject * python_api_log_error(PyObject *self, PyObject *args) { - const char *message = NULL; - if (!PyArg_ParseTuple(args, "s", &message)) { + PyObject *message = NULL; + if (!PyArg_ParseTuple(args, "O", &message)) { return Py_BuildValue(""); } + + char *message_str = python_str_or_unicode_to_string(message); + allow_python_threads(); - api_log_error(message); + api_log_error(message_str); disable_python_threads(); return Py_BuildValue(""); @@ -451,13 +488,15 @@ python_api_log_error(PyObject *self, PyObject *args) static PyObject * python_api_win_exists(PyObject *self, PyObject *args) { - char *tag = NULL; - if (!PyArg_ParseTuple(args, "s", &tag)) { + PyObject *tag = NULL; + if (!PyArg_ParseTuple(args, "O", &tag)) { return Py_BuildValue(""); } + char *tag_str = python_str_or_unicode_to_string(tag); + allow_python_threads(); - gboolean exists = api_win_exists(tag); + gboolean exists = api_win_exists(tag_str); disable_python_threads(); if (exists) { @@ -470,19 +509,21 @@ python_api_win_exists(PyObject *self, PyObject *args) static PyObject * python_api_win_create(PyObject *self, PyObject *args) { - char *tag = NULL; + PyObject *tag = NULL; PyObject *p_callback = NULL; - if (!PyArg_ParseTuple(args, "sO", &tag, &p_callback)) { + if (!PyArg_ParseTuple(args, "OO", &tag, &p_callback)) { return Py_BuildValue(""); } + char *tag_str = python_str_or_unicode_to_string(tag); + char *plugin_name = _python_plugin_name(); - log_debug("Win create %s for %s", tag, plugin_name); + log_debug("Win create %s for %s", tag_str, plugin_name); if (p_callback && PyCallable_Check(p_callback)) { allow_python_threads(); - api_win_create(plugin_name, tag, p_callback, python_window_callback, NULL); + api_win_create(plugin_name, tag_str, p_callback, python_window_callback, NULL); disable_python_threads(); } @@ -494,14 +535,16 @@ python_api_win_create(PyObject *self, PyObject *args) static PyObject * python_api_win_focus(PyObject *self, PyObject *args) { - char *tag = NULL; + PyObject *tag = NULL; - if (!PyArg_ParseTuple(args, "s", &tag)) { + if (!PyArg_ParseTuple(args, "O", &tag)) { return Py_BuildValue(""); } + char *tag_str = python_str_or_unicode_to_string(tag); + allow_python_threads(); - api_win_focus(tag); + api_win_focus(tag_str); disable_python_threads(); return Py_BuildValue(""); @@ -510,15 +553,18 @@ python_api_win_focus(PyObject *self, PyObject *args) static PyObject * python_api_win_show(PyObject *self, PyObject *args) { - char *tag = NULL; - char *line = NULL; + PyObject *tag = NULL; + PyObject *line = NULL; - if (!PyArg_ParseTuple(args, "ss", &tag, &line)) { + if (!PyArg_ParseTuple(args, "OO", &tag, &line)) { return Py_BuildValue(""); } + char *tag_str = python_str_or_unicode_to_string(tag); + char *line_str = python_str_or_unicode_to_string(line); + allow_python_threads(); - api_win_show(tag, line); + api_win_show(tag_str, line_str); disable_python_threads(); return Py_BuildValue(""); @@ -527,18 +573,25 @@ python_api_win_show(PyObject *self, PyObject *args) static PyObject * python_api_win_show_themed(PyObject *self, PyObject *args) { - char *tag = NULL; - char *group = NULL; - char *key = NULL; - char *def = NULL; - char *line = NULL; + PyObject *tag = NULL; + PyObject *group = NULL; + PyObject *key = NULL; + PyObject *def = NULL; + PyObject *line = NULL; - if (!PyArg_ParseTuple(args, "szzzs", &tag, &group, &key, &def, &line)) { + if (!PyArg_ParseTuple(args, "OOOOO", &tag, &group, &key, &def, &line)) { + python_check_error(); return Py_BuildValue(""); } + char *tag_str = python_str_or_unicode_to_string(tag); + char *group_str = python_str_or_unicode_to_string(group); + char *key_str = python_str_or_unicode_to_string(key); + char *def_str = python_str_or_unicode_to_string(def); + char *line_str = python_str_or_unicode_to_string(line); + allow_python_threads(); - api_win_show_themed(tag, group, key, def, line); + api_win_show_themed(tag_str, group_str, key_str, def_str, line_str); disable_python_threads(); return Py_BuildValue(""); @@ -547,13 +600,15 @@ python_api_win_show_themed(PyObject *self, PyObject *args) static PyObject* python_api_send_stanza(PyObject *self, PyObject *args) { - const char *stanza = NULL; - if (!PyArg_ParseTuple(args, "s", &stanza)) { + PyObject *stanza = NULL; + if (!PyArg_ParseTuple(args, "O", &stanza)) { return Py_BuildValue("O", Py_False); } + char *stanza_str = python_str_or_unicode_to_string(stanza); + allow_python_threads(); - int res = api_send_stanza(stanza); + int res = api_send_stanza(stanza_str); disable_python_threads(); if (res) { return Py_BuildValue("O", Py_True); @@ -565,18 +620,20 @@ python_api_send_stanza(PyObject *self, PyObject *args) static PyObject* python_api_settings_get_boolean(PyObject *self, PyObject *args) { - char *group = NULL; - char *key = NULL; + PyObject *group = NULL; + PyObject *key = NULL; PyObject *defobj = NULL; - if (!PyArg_ParseTuple(args, "ssO!", &group, &key, &PyBool_Type, &defobj)) { + if (!PyArg_ParseTuple(args, "OOO!", &group, &key, &PyBool_Type, &defobj)) { return Py_BuildValue(""); } + char *group_str = python_str_or_unicode_to_string(group); + char *key_str = python_str_or_unicode_to_string(key); int def = PyObject_IsTrue(defobj); allow_python_threads(); - int res = api_settings_get_boolean(group, key, def); + int res = api_settings_get_boolean(group_str, key_str, def); disable_python_threads(); if (res) { @@ -589,18 +646,20 @@ python_api_settings_get_boolean(PyObject *self, PyObject *args) static PyObject* python_api_settings_set_boolean(PyObject *self, PyObject *args) { - char *group = NULL; - char *key = NULL; + PyObject *group = NULL; + PyObject *key = NULL; PyObject *valobj = NULL; - if (!PyArg_ParseTuple(args, "ssO!", &group, &key, &PyBool_Type, &valobj)) { + if (!PyArg_ParseTuple(args, "OOO!", &group, &key, &PyBool_Type, &valobj)) { return Py_BuildValue(""); } + char *group_str = python_str_or_unicode_to_string(group); + char *key_str = python_str_or_unicode_to_string(key); int val = PyObject_IsTrue(valobj); allow_python_threads(); - api_settings_set_boolean(group, key, val); + api_settings_set_boolean(group_str, key_str, val); disable_python_threads(); return Py_BuildValue(""); @@ -609,16 +668,20 @@ python_api_settings_set_boolean(PyObject *self, PyObject *args) static PyObject* python_api_settings_get_string(PyObject *self, PyObject *args) { - char *group = NULL; - char *key = NULL; - char *def = NULL; + PyObject *group = NULL; + PyObject *key = NULL; + PyObject *def = NULL; - if (!PyArg_ParseTuple(args, "ssz", &group, &key, &def)) { + if (!PyArg_ParseTuple(args, "OOO", &group, &key, &def)) { return Py_BuildValue(""); } + char *group_str = python_str_or_unicode_to_string(group); + char *key_str = python_str_or_unicode_to_string(key); + char *def_str = python_str_or_unicode_to_string(def); + allow_python_threads(); - char *res = api_settings_get_string(group, key, def); + char *res = api_settings_get_string(group_str, key_str, def_str); disable_python_threads(); if (res) { @@ -631,16 +694,20 @@ python_api_settings_get_string(PyObject *self, PyObject *args) static PyObject* python_api_settings_set_string(PyObject *self, PyObject *args) { - char *group = NULL; - char *key = NULL; - char *val = NULL; + PyObject *group = NULL; + PyObject *key = NULL; + PyObject *val = NULL; - if (!PyArg_ParseTuple(args, "sss", &group, &key, &val)) { + if (!PyArg_ParseTuple(args, "OOO", &group, &key, &val)) { return Py_BuildValue(""); } + char *group_str = python_str_or_unicode_to_string(group); + char *key_str = python_str_or_unicode_to_string(key); + char *val_str = python_str_or_unicode_to_string(val); + allow_python_threads(); - api_settings_set_string(group, key, val); + api_settings_set_string(group_str, key_str, val_str); disable_python_threads(); return Py_BuildValue(""); @@ -649,16 +716,19 @@ python_api_settings_set_string(PyObject *self, PyObject *args) static PyObject* python_api_settings_get_int(PyObject *self, PyObject *args) { - char *group = NULL; - char *key = NULL; + PyObject *group = NULL; + PyObject *key = NULL; int def = 0; - if (!PyArg_ParseTuple(args, "ssi", &group, &key, &def)) { + if (!PyArg_ParseTuple(args, "OOi", &group, &key, &def)) { return Py_BuildValue(""); } + char *group_str = python_str_or_unicode_to_string(group); + char *key_str = python_str_or_unicode_to_string(key); + allow_python_threads(); - int res = api_settings_get_int(group, key, def); + int res = api_settings_get_int(group_str, key_str, def); disable_python_threads(); return Py_BuildValue("i", res); @@ -667,16 +737,19 @@ python_api_settings_get_int(PyObject *self, PyObject *args) static PyObject* python_api_settings_set_int(PyObject *self, PyObject *args) { - char *group = NULL; - char *key = NULL; + PyObject *group = NULL; + PyObject *key = NULL; int val = 0; - if (!PyArg_ParseTuple(args, "ssi", &group, &key, &val)) { + if (!PyArg_ParseTuple(args, "OOi", &group, &key, &val)) { return Py_BuildValue(""); } + char *group_str = python_str_or_unicode_to_string(group); + char *key_str = python_str_or_unicode_to_string(key); + allow_python_threads(); - api_settings_set_int(group, key, val); + api_settings_set_int(group_str, key_str, val); disable_python_threads(); return Py_BuildValue(""); @@ -685,16 +758,20 @@ python_api_settings_set_int(PyObject *self, PyObject *args) static PyObject* python_api_incoming_message(PyObject *self, PyObject *args) { - char *barejid = NULL; - char *resource = NULL; - char *message = NULL; + PyObject *barejid = NULL; + PyObject *resource = NULL; + PyObject *message = NULL; - if (!PyArg_ParseTuple(args, "sss", &barejid, &resource, &message)) { + if (!PyArg_ParseTuple(args, "OOO", &barejid, &resource, &message)) { return Py_BuildValue(""); } + char *barejid_str = python_str_or_unicode_to_string(barejid); + char *resource_str = python_str_or_unicode_to_string(resource); + char *message_str = python_str_or_unicode_to_string(message); + allow_python_threads(); - api_incoming_message(barejid, resource, message); + api_incoming_message(barejid_str, resource_str, message_str); disable_python_threads(); return Py_BuildValue(""); @@ -703,13 +780,15 @@ python_api_incoming_message(PyObject *self, PyObject *args) static PyObject* python_api_disco_add_feature(PyObject *self, PyObject *args) { - char *feature = NULL; - if (!PyArg_ParseTuple(args, "s", &feature)) { + PyObject *feature = NULL; + if (!PyArg_ParseTuple(args, "O", &feature)) { return Py_BuildValue(""); } + char *feature_str = python_str_or_unicode_to_string(feature); + allow_python_threads(); - api_disco_add_feature(feature); + api_disco_add_feature(feature_str); disable_python_threads(); return Py_BuildValue(""); @@ -866,7 +945,7 @@ _python_plugin_name(void) { PyThreadState *ts = PyThreadState_Get(); PyFrameObject *frame = ts->frame; - char const* filename = python_object_to_string(frame->f_code->co_filename); + char const* filename = python_str_or_unicode_to_string(frame->f_code->co_filename); gchar **split = g_strsplit(filename, "/", 0); char *plugin_name = strdup(split[g_strv_length(split)-1]); g_strfreev(split); @@ -875,11 +954,27 @@ _python_plugin_name(void) } char* -python_object_to_string(void *obj) +python_str_or_unicode_to_string(void *obj) { + if (!obj) { + return NULL; + } + PyObject *pyobj = (PyObject*)obj; + if (pyobj == Py_None) { + return NULL; + } + #if PY_MAJOR_VERSION >= 3 - return PyBytes_AS_STRING(PyUnicode_AsUTF8String(obj)); + if (PyUnicode_Check(pyobj)) { + return strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(pyobj))); + } else { + return strdup(PyBytes_AS_STRING(pyobj)); + } #else - return PyString_AsString(obj); + if (PyUnicode_Check(pyobj)) { + return strdup(PyString_AsString(PyUnicode_AsUTF8String(pyobj))); + } else { + return strdup(PyString_AsString(pyobj)); + } #endif } diff --git a/src/plugins/python_api.h b/src/plugins/python_api.h index dbc2b979..09c52037 100644 --- a/src/plugins/python_api.h +++ b/src/plugins/python_api.h @@ -43,6 +43,6 @@ void python_command_callback(PluginCommand *command, gchar **args); void python_timed_callback(PluginTimedFunction *timed_function); void python_window_callback(PluginWindowCallback *window_callback, char *tag, char *line); -char* python_object_to_string(void *obj); +char* python_str_or_unicode_to_string(void *obj); #endif diff --git a/src/plugins/python_plugins.c b/src/plugins/python_plugins.c index c7f59956..73e2a1ed 100644 --- a/src/plugins/python_plugins.c +++ b/src/plugins/python_plugins.c @@ -47,8 +47,6 @@ static PyThreadState *thread_state; static GHashTable *loaded_modules; -static char* _python_parse_string_result(PyObject *result); - void allow_python_threads() { @@ -286,7 +284,7 @@ python_pre_chat_message_display_hook(ProfPlugin *plugin, const char *const jid, PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); - char *result_str = _python_parse_string_result(result); + char *result_str = python_str_or_unicode_to_string(result); allow_python_threads(); return result_str; @@ -333,7 +331,7 @@ python_pre_chat_message_send_hook(ProfPlugin *plugin, const char * const jid, co PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); - char *result_str = _python_parse_string_result(result); + char *result_str = python_str_or_unicode_to_string(result); allow_python_threads(); return result_str; @@ -380,7 +378,7 @@ python_pre_room_message_display_hook(ProfPlugin *plugin, const char * const room PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); - char *result_str = _python_parse_string_result(result); + char *result_str = python_str_or_unicode_to_string(result); allow_python_threads(); return result_str; @@ -428,7 +426,7 @@ python_pre_room_message_send_hook(ProfPlugin *plugin, const char *const room, co PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); - char *result_str = _python_parse_string_result(result); + char *result_str = python_str_or_unicode_to_string(result); allow_python_threads(); return result_str; @@ -498,7 +496,7 @@ python_pre_priv_message_display_hook(ProfPlugin *plugin, const char *const room, PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); - char *result_str = _python_parse_string_result(result); + char *result_str = python_str_or_unicode_to_string(result); allow_python_threads(); return result_str; @@ -547,7 +545,7 @@ python_pre_priv_message_send_hook(ProfPlugin *plugin, const char *const room, co PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); - char *result_str = _python_parse_string_result(result); + char *result_str = python_str_or_unicode_to_string(result); allow_python_threads(); return result_str; @@ -595,7 +593,7 @@ python_on_message_stanza_send_hook(ProfPlugin *plugin, const char *const text) PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); - char *result_str = _python_parse_string_result(result); + char *result_str = python_str_or_unicode_to_string(result); allow_python_threads(); return result_str; @@ -650,7 +648,7 @@ python_on_presence_stanza_send_hook(ProfPlugin *plugin, const char *const text) PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); - char *result_str = _python_parse_string_result(result); + char *result_str = python_str_or_unicode_to_string(result); allow_python_threads(); return result_str; @@ -705,7 +703,7 @@ python_on_iq_stanza_send_hook(ProfPlugin *plugin, const char *const text) PyObject *result = PyObject_CallObject(p_function, p_args); python_check_error(); Py_XDECREF(p_function); - char *result_str = _python_parse_string_result(result); + char *result_str = python_str_or_unicode_to_string(result); allow_python_threads(); return result_str; @@ -858,29 +856,3 @@ python_shutdown(void) g_hash_table_destroy(loaded_modules); Py_Finalize(); } - -static char* -_python_parse_string_result(PyObject *result) -{ -#if PY_MAJOR_VERSION >= 3 - if (result != Py_None) { - char *result_str = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - return result_str; - } else { - return NULL; - } -#else - if (PyUnicode_Check(result)) { - char *result_str = strdup(PyString_AsString(PyUnicode_AsUTF8String(result))); - Py_XDECREF(result); - return result_str; - } else if (result != Py_None) { - char *result_str = strdup(PyString_AsString(result)); - Py_XDECREF(result); - return result_str; - } else { - return NULL; - } -#endif -} From 27a842d1cf2b37c197b1a2a927a2ee611348847c Mon Sep 17 00:00:00 2001 From: James Booth Date: Sun, 24 Jul 2016 01:34:02 +0100 Subject: [PATCH 10/13] Include python plugins by default in build --- configure-debug | 4 ++-- configure.ac | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/configure-debug b/configure-debug index 92ddceb4..63679c98 100755 --- a/configure-debug +++ b/configure-debug @@ -1,4 +1,4 @@ #!/bin/sh -#./configure PYTHON_VERSION=3 CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ -./configure CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' --enable-python-plugins $@ +#./configure PYTHON_VERSION=3 CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' $@ +./configure CFLAGS='-g3 -O0' CXXFLAGS='-g3 -O0' $@ diff --git a/configure.ac b/configure.ac index 8d06ecfe..71039dcb 100644 --- a/configure.ac +++ b/configure.ac @@ -71,12 +71,7 @@ AC_ARG_ENABLE([icons], # python if test "x$enable_plugins" = xno; then AM_CONDITIONAL([BUILD_PYTHON_API], [false]) -# -# Python plugins are temporary disabled by default, because Profanity doesn't -# build with all python versions. Change `= xyes` to `!= xno` to enable it by -# default. -# -elif test "x$enable_python_plugins" = xyes; then +elif test "x$enable_python_plugins" != xno; then AS_IF([test "x$PLATFORM" = xosx], [ AS_IF([test "x$PYTHON_FRAMEWORK" = x], [ PYTHON_FRAMEWORK="/Library/Frameworks/Python.framework" ]) AC_MSG_NOTICE([Symlinking Python.framework to $PYTHON_FRAMEWORK]) From b48a3d2f6a50a8dea92c87d640573e0c827eb0cd Mon Sep 17 00:00:00 2001 From: James Booth Date: Sun, 24 Jul 2016 01:53:13 +0100 Subject: [PATCH 11/13] Python plugins: Free string values --- src/plugins/python_api.c | 59 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/src/plugins/python_api.c b/src/plugins/python_api.c index 0a350335..53b1e63e 100644 --- a/src/plugins/python_api.c +++ b/src/plugins/python_api.c @@ -34,6 +34,8 @@ #include "config.h" +#include + #include #include @@ -70,6 +72,7 @@ python_api_cons_show(PyObject *self, PyObject *args) allow_python_threads(); api_cons_show(message_str); + free(message_str); disable_python_threads(); return Py_BuildValue(""); @@ -93,6 +96,10 @@ python_api_cons_show_themed(PyObject *self, PyObject *args) allow_python_threads(); api_cons_show_themed(group_str, key_str, def_str, message_str); + free(group_str); + free(key_str); + free(def_str); + free(message_str); disable_python_threads(); return Py_BuildValue(""); @@ -110,6 +117,7 @@ python_api_cons_bad_cmd_usage(PyObject *self, PyObject *args) allow_python_threads(); api_cons_bad_cmd_usage(cmd_str); + free(cmd_str); disable_python_threads(); return Py_BuildValue(""); @@ -183,6 +191,8 @@ python_api_register_command(PyObject *self, PyObject *args) allow_python_threads(); api_register_command(plugin_name, command_name_str, min_args, max_args, c_synopsis, description_str, c_arguments, c_examples, p_callback, python_command_callback, NULL); + free(command_name_str); + free(description_str); disable_python_threads(); } @@ -243,6 +253,7 @@ python_api_completer_add(PyObject *self, PyObject *args) allow_python_threads(); api_completer_add(plugin_name, key_str, c_items); + free(key_str); disable_python_threads(); free(plugin_name); @@ -278,6 +289,7 @@ python_api_completer_remove(PyObject *self, PyObject *args) allow_python_threads(); api_completer_remove(plugin_name, key_str, c_items); + free(key_str); disable_python_threads(); free(plugin_name); @@ -301,6 +313,7 @@ python_api_completer_clear(PyObject *self, PyObject *args) allow_python_threads(); api_completer_clear(plugin_name, key_str); + free(key_str); disable_python_threads(); free(plugin_name); @@ -324,6 +337,8 @@ python_api_notify(PyObject *self, PyObject *args) allow_python_threads(); api_notify(message_str, category_str, timeout_ms); + free(message_str); + free(category_str); disable_python_threads(); return Py_BuildValue(""); @@ -341,6 +356,7 @@ python_api_send_line(PyObject *self, PyObject *args) allow_python_threads(); api_send_line(line_str); + free(line_str); disable_python_threads(); return Py_BuildValue(""); @@ -429,6 +445,7 @@ python_api_log_debug(PyObject *self, PyObject *args) allow_python_threads(); api_log_debug(message_str); + free(message_str); disable_python_threads(); return Py_BuildValue(""); @@ -446,6 +463,7 @@ python_api_log_info(PyObject *self, PyObject *args) allow_python_threads(); api_log_info(message_str); + free(message_str); disable_python_threads(); return Py_BuildValue(""); @@ -463,6 +481,7 @@ python_api_log_warning(PyObject *self, PyObject *args) allow_python_threads(); api_log_warning(message_str); + free(message_str); disable_python_threads(); return Py_BuildValue(""); @@ -480,6 +499,7 @@ python_api_log_error(PyObject *self, PyObject *args) allow_python_threads(); api_log_error(message_str); + free(message_str); disable_python_threads(); return Py_BuildValue(""); @@ -497,6 +517,7 @@ python_api_win_exists(PyObject *self, PyObject *args) allow_python_threads(); gboolean exists = api_win_exists(tag_str); + free(tag_str); disable_python_threads(); if (exists) { @@ -524,6 +545,7 @@ python_api_win_create(PyObject *self, PyObject *args) if (p_callback && PyCallable_Check(p_callback)) { allow_python_threads(); api_win_create(plugin_name, tag_str, p_callback, python_window_callback, NULL); + free(tag_str); disable_python_threads(); } @@ -545,6 +567,7 @@ python_api_win_focus(PyObject *self, PyObject *args) allow_python_threads(); api_win_focus(tag_str); + free(tag_str); disable_python_threads(); return Py_BuildValue(""); @@ -565,6 +588,8 @@ python_api_win_show(PyObject *self, PyObject *args) allow_python_threads(); api_win_show(tag_str, line_str); + free(tag_str); + free(line_str); disable_python_threads(); return Py_BuildValue(""); @@ -592,6 +617,11 @@ python_api_win_show_themed(PyObject *self, PyObject *args) allow_python_threads(); api_win_show_themed(tag_str, group_str, key_str, def_str, line_str); + free(tag_str); + free(group_str); + free(key_str); + free(def_str); + free(line_str); disable_python_threads(); return Py_BuildValue(""); @@ -609,6 +639,7 @@ python_api_send_stanza(PyObject *self, PyObject *args) allow_python_threads(); int res = api_send_stanza(stanza_str); + free(stanza_str); disable_python_threads(); if (res) { return Py_BuildValue("O", Py_True); @@ -634,6 +665,8 @@ python_api_settings_get_boolean(PyObject *self, PyObject *args) allow_python_threads(); int res = api_settings_get_boolean(group_str, key_str, def); + free(group_str); + free(key_str); disable_python_threads(); if (res) { @@ -660,6 +693,8 @@ python_api_settings_set_boolean(PyObject *self, PyObject *args) allow_python_threads(); api_settings_set_boolean(group_str, key_str, val); + free(group_str); + free(key_str); disable_python_threads(); return Py_BuildValue(""); @@ -682,6 +717,9 @@ python_api_settings_get_string(PyObject *self, PyObject *args) allow_python_threads(); char *res = api_settings_get_string(group_str, key_str, def_str); + free(group_str); + free(key_str); + free(def_str); disable_python_threads(); if (res) { @@ -708,6 +746,9 @@ python_api_settings_set_string(PyObject *self, PyObject *args) allow_python_threads(); api_settings_set_string(group_str, key_str, val_str); + free(group_str); + free(key_str); + free(val_str); disable_python_threads(); return Py_BuildValue(""); @@ -729,6 +770,8 @@ python_api_settings_get_int(PyObject *self, PyObject *args) allow_python_threads(); int res = api_settings_get_int(group_str, key_str, def); + free(group_str); + free(key_str); disable_python_threads(); return Py_BuildValue("i", res); @@ -750,6 +793,8 @@ python_api_settings_set_int(PyObject *self, PyObject *args) allow_python_threads(); api_settings_set_int(group_str, key_str, val); + free(group_str); + free(key_str); disable_python_threads(); return Py_BuildValue(""); @@ -772,6 +817,9 @@ python_api_incoming_message(PyObject *self, PyObject *args) allow_python_threads(); api_incoming_message(barejid_str, resource_str, message_str); + free(barejid_str); + free(resource_str); + free(message_str); disable_python_threads(); return Py_BuildValue(""); @@ -789,6 +837,7 @@ python_api_disco_add_feature(PyObject *self, PyObject *args) allow_python_threads(); api_disco_add_feature(feature_str); + free(feature_str); disable_python_threads(); return Py_BuildValue(""); @@ -966,13 +1015,19 @@ python_str_or_unicode_to_string(void *obj) #if PY_MAJOR_VERSION >= 3 if (PyUnicode_Check(pyobj)) { - return strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(pyobj))); + PyObject *utf8_str = PyUnicode_AsUTF8String(pyobj); + char *result = strdup(PyBytes_AS_STRING(utf8_str)); + Py_XDECREF(utf8_str); + return result; } else { return strdup(PyBytes_AS_STRING(pyobj)); } #else if (PyUnicode_Check(pyobj)) { - return strdup(PyString_AsString(PyUnicode_AsUTF8String(pyobj))); + PyObject *utf8_str = PyUnicode_AsUTF8String(pyobj); + char *result = strdup(PyString_AsString(utf8_str)); + Py_XDECREF(utf8_str); + return result; } else { return strdup(PyString_AsString(pyobj)); } From 4209b1cf45b9b52e852b58aa6dcfe513c16c8dcd Mon Sep 17 00:00:00 2001 From: James Booth Date: Sun, 24 Jul 2016 02:12:56 +0100 Subject: [PATCH 12/13] Add /plugins python_version command --- src/command/cmd_ac.c | 1 + src/command/cmd_defs.c | 6 ++++-- src/command/cmd_funcs.c | 13 +++++++++++++ src/plugins/python_plugins.c | 9 ++++++--- src/plugins/python_plugins.h | 2 ++ 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 0d30df88..69e350bc 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -711,6 +711,7 @@ cmd_ac_init(void) autocomplete_add(plugins_ac, "load"); autocomplete_add(plugins_ac, "unload"); autocomplete_add(plugins_ac, "reload"); + autocomplete_add(plugins_ac, "python_version"); filepath_ac = autocomplete_new(); diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 900e8e96..34f840ed 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -1982,14 +1982,16 @@ static struct cmd_t command_defs[] = "/plugins install ", "/plugins unload ", "/plugins load ", - "/plugins reload []") + "/plugins reload []", + "/plugins python_version") CMD_DESC( "Manage plugins. Passing no arguments lists currently loaded plugins.") CMD_ARGS( { "install ", "Install file to plugins directory, and load or reload the plugin." }, { "load ", "Load a plugin that already exists in the plugin directory." }, { "unload ", "Unload a loaded plugin." }, - { "reload []", "Reload a plugin, passing no argument will reload all plugins" }) + { "reload []", "Reload a plugin, passing no argument will reload all plugins." }, + { "python_version", "Show the Python interpreter version." }) CMD_EXAMPLES( "/plugin install /home/steveharris/Downloads/metal.py", "/plugin load browser.py", diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index c9094f18..65982541 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -84,6 +84,9 @@ #include "tray.h" #endif #include "tools/http_upload.h" +#ifdef HAVE_PYTHON +#include "plugins/python_plugins.h" +#endif static void _update_presence(const resource_presence_t presence, const char *const show, gchar **args); @@ -6109,6 +6112,16 @@ cmd_plugins(ProfWin *window, const char *const command, gchar **args) } return TRUE; + } else if (g_strcmp0(args[0], "python_version") == 0) { +#ifdef HAVE_PYTHON + const char *version = python_get_version(); + cons_show("Python version:"); + cons_show("%s", version); +#else + cons_show("This build does not support pytyon plugins."); +#endif + return TRUE; + } else { GList *plugins = plugins_loaded_list(); if (plugins == NULL) { diff --git a/src/plugins/python_plugins.c b/src/plugins/python_plugins.c index 61c7573f..40046200 100644 --- a/src/plugins/python_plugins.c +++ b/src/plugins/python_plugins.c @@ -65,6 +65,12 @@ _unref_module(PyObject *module) Py_XDECREF(module); } +const char* +python_get_version(void) +{ + return Py_GetVersion(); +} + void python_env_init(void) { @@ -72,9 +78,6 @@ python_env_init(void) python_init_prof(); - const char *ver = Py_GetVersion(); - cons_show("PYTHON: %s", ver); - gchar *plugins_dir = plugins_get_dir(); GString *path = g_string_new("import sys\n"); g_string_append(path, "sys.path.append(\""); diff --git a/src/plugins/python_plugins.h b/src/plugins/python_plugins.h index f3ab7bce..dda73405 100644 --- a/src/plugins/python_plugins.h +++ b/src/plugins/python_plugins.h @@ -43,6 +43,8 @@ void python_check_error(void); void allow_python_threads(); void disable_python_threads(); +const char* python_get_version(void); + void python_init_hook(ProfPlugin *plugin, const char *const version, const char *const status, const char *const account_name, const char *const fulljid); void python_on_start_hook(ProfPlugin *plugin); From 7c593c278014760c065a87edf293546794911f58 Mon Sep 17 00:00:00 2001 From: James Booth Date: Sun, 24 Jul 2016 02:16:57 +0100 Subject: [PATCH 13/13] Reorder headers --- src/plugins/python_api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/python_api.c b/src/plugins/python_api.c index 53b1e63e..ef6b9ccd 100644 --- a/src/plugins/python_api.c +++ b/src/plugins/python_api.c @@ -34,11 +34,11 @@ #include "config.h" -#include - #include #include +#include + #include #include "plugins/api.h"