From 22ea088ea6adc9a41c3f486cf8555a4521566120 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Sat, 24 Apr 2021 10:28:43 +0300 Subject: Remove support for Python 2.x --- NEWS | 5 +- README | 2 +- dicoweb/INSTALL | 13 +- dicoweb/requirements.txt | 3 +- dicoweb/views.py | 21 +- modules/python/Makefile.am | 6 +- modules/python/module.ac | 69 ++- modules/python/python2.c | 1033 -------------------------------------------- 8 files changed, 71 insertions(+), 1081 deletions(-) delete mode 100644 modules/python/python2.c diff --git a/NEWS b/NEWS index dbc8eee..3121615 100644 --- a/NEWS +++ b/NEWS @@ -1,9 +1,12 @@ -GNU Dico NEWS -- history of user-visible changes. 2021-01-08 +GNU Dico NEWS -- history of user-visible changes. 2021-04-24 See the end of file for copying conditions. Please send Dico bug reports to Version 2.10.90 (git) + +* Support for Python 2 has been withdrawn + Version 2.10, 2020-09-04 diff --git a/README b/README index dad0e04..7ba0406 100644 --- a/README +++ b/README @@ -72,7 +72,7 @@ The package comes with the following modules: - python An abstract layer for interfacing with database modules written in - Python. + Python (version 3.6 or newer). - substr Defines the "substr" lookup strategy, which matches a supplied diff --git a/dicoweb/INSTALL b/dicoweb/INSTALL index 3a59d38..2f13ca2 100644 --- a/dicoweb/INSTALL +++ b/dicoweb/INSTALL @@ -53,16 +53,15 @@ follows: ServerName dict.example.org DocumentRoot /var/www/dicoweb - # Ensure proper encoding (for Python 3) - SetEnv LC_ALL en_US.utf8 - # Configure virtual environment. # (If not using virtual environment, omit the WSGIDaemonProcess and # WSGIProcessGroup statements). - # Make sure to edit the statement below to match to the actual - # path to the site-packages directory. - WSGIDaemonProcess dicoweb python-path=/var/www/dicoweb/venv/lib/python3.5/site-packages + # Edit the statement below to match to the actual virtual + # environment location. + # Notice the 'locale=' setting. It is necessary to force the + # UTF-8 locale. + WSGIDaemonProcess dicoweb python-home=/var/www/dicoweb/venv locale=en_US.UTF-8 WSGIProcessGroup dicoweb # Start up the module. @@ -89,7 +88,7 @@ the following output: Validating models... 0 errors found. - Django version 1.11.5, using settings 'dicoweb.settings' + Django version 3.2.0, using settings 'dicoweb.settings' Development server is running at http://127.0.0.1:8000/ Quit the server with CONTROL-C. diff --git a/dicoweb/requirements.txt b/dicoweb/requirements.txt index 2bc4fe9..2f92016 100644 --- a/dicoweb/requirements.txt +++ b/dicoweb/requirements.txt @@ -1,4 +1,3 @@ -Django>=2.0;python_version>="3.0" -Django==1.11.5;python_version<="2.7" +Django>=2.0 wikitrans>=1.2 python-memcached>=1.59 diff --git a/dicoweb/views.py b/dicoweb/views.py index 207917a..6784af3 100644 --- a/dicoweb/views.py +++ b/dicoweb/views.py @@ -23,7 +23,7 @@ try: except ImportError: from django.urls import reverse from django.core.cache import cache -from django.shortcuts import render_to_response +from django.shortcuts import render from django.utils.encoding import force_bytes from django.utils.translation import ugettext as _ @@ -103,7 +103,7 @@ def index(request): strategies = dc.show_strategies()['strategies'] dc.close() except (socket.timeout, socket.error, dicoclient.DicoNotConnectedError): - return render_to_response('index.html', {'selects': selects}) + return render(request, 'index.html', {'selects': selects}) cache.set(key_databases, databases, timeout=86400) cache.set(key_strategies, strategies, timeout=86400) @@ -157,8 +157,7 @@ def index(request): except (socket.timeout, socket.error, dicoclient.DicoNotConnectedError): - return render_to_response('index.html', - {'selects': selects}) + return render(request, 'index.html', {'selects': selects}) # get last match results if sid and type == 'search': @@ -236,18 +235,18 @@ Additionally, ONERROR['UNSUPPORTED_CONTENT_TYPE'] has unsupported value (%s). if result['count'] == 0: result = { 'error': 552, 'msg': 'No match' } - return render_to_response('index.html', {'page': page, - 'q': q, - 'mtc': mtc, - 'result': result, - 'selects': selects, }) + return render(request, 'index.html', {'page': page, + 'q': q, + 'mtc': mtc, + 'result': result, + 'selects': selects, }) def opensearch(request): url_query = request.build_absolute_uri(reverse('index')) url_media = request.build_absolute_uri(settings.MEDIA_URL) - return render_to_response('opensearch.xml', {'url_query': url_query, - 'url_media': url_media}, + return render(request, 'opensearch.xml', {'url_query': url_query, + 'url_media': url_media}, content_type='application/xml') diff --git a/modules/python/Makefile.am b/modules/python/Makefile.am index 7975752..c774e3c 100644 --- a/modules/python/Makefile.am +++ b/modules/python/Makefile.am @@ -20,11 +20,7 @@ moddir=@DICO_MODDIR@ mod_LTLIBRARIES=python.la -if PYTHON3_COND - python_la_SOURCES = python.c -else - python_la_SOURCES = python2.c -endif +python_la_SOURCES = python.c python_la_LIBADD = ../../lib/libdico.la @PYTHON_LIBS@ AM_LDFLAGS = -module -avoid-version -no-undefined -rpath $(moddir) diff --git a/modules/python/module.ac b/modules/python/module.ac index 535b95b..7ecd177 100644 --- a/modules/python/module.ac +++ b/modules/python/module.ac @@ -17,33 +17,60 @@ AC_ARG_WITH([python], AC_HELP_STRING([--without-python], [do not build Python interface]), - [ + [ case "${withval}" in yes) status_python=yes ;; no) status_python=no ;; - *) AC_MSG_ERROR(bad value ${withval} for --without-python) ;; + *) AC_MSG_ERROR(bad value ${withval} for --with-python) ;; esac],[status_python=yes]) -PYTHON3_COND=0 +AC_SUBST(PYTHON_LIBS) +AC_SUBST(PYTHON_INCLUDES) + if test "$status_python" = yes; then - AC_ARG_VAR([PYTHON], [The name of python binary]) - AC_PATH_PROG([PYTHON], python) - - AC_ARG_VAR([PYTHON_CONFIG], [The name of python-config binary]) - AC_PATH_PROG([PYTHON_CONFIG], python-config) - if test -n "$PYTHON_CONFIG"; then - AC_SUBST(PYTHON_LIBS) - PYTHON_LIBS=`$PYTHON_CONFIG --libs --embed 2>/dev/null` || \ + AM_PATH_PYTHON(3.0,, [status_python=no]) + if test "$status_python" = yes; then + AC_ARG_VAR([PYTHON_CONFIG], [The name of python-config binary]) + if test -z "$PYTHON_CONFIG"; then + AC_PATH_PROGS([PYTHON_CONFIG], [python3-config python-config]) + fi + if test -n "$PYTHON_CONFIG"; then + save_CPPFLAGS=$CPPFLAGS + CPPFLAGS=$($PYTHON_CONFIG --includes) + AC_MSG_CHECKING([whether python-config ($PYTHON_CONFIG) is of same version as python]) + AC_EGREP_CPP([^\"$PYTHON_VERSION], + [#include +PY_VERSION], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + status_python=no]) + CPPFLAGS=$save_CPPFLAGS + else + status_python=no + fi + + if test "$status_python" = yes; then + # See https://docs.python.org/dev/whatsnew/3.8.html#debug-build-uses-the-same-abi-as-release-build + PYTHON_LIBS=`$PYTHON_CONFIG --libs --embed 2>/dev/null` || \ PYTHON_LIBS=`$PYTHON_CONFIG --libs` - AC_SUBST(PYTHON_INCLUDES,`$PYTHON_CONFIG --includes`) - $PYTHON <. */ - -#include -#include -#include -#include -#include -#include - -static char *init_script; -static char *load_path; -static char *root_class = "DicoModule"; - -static struct dico_option init_option[] = { - { DICO_OPTSTR(init-script), dico_opt_string, &init_script }, - { DICO_OPTSTR(load-path), dico_opt_string, &load_path }, - { DICO_OPTSTR(root-class), dico_opt_string, &root_class }, - { NULL } -}; - -struct _python_database { - const char *dbname; - int argc; - char **argv; - PyThreadState *py_ths; - PyObject *py_instance; -}; - - -typedef struct { - PyObject_HEAD; - struct dico_key *key; -} PySelectionKey; - -static void -_PySelectionKey_dealloc (PyObject *self) -{ -} - -static PyMethodDef selection_key_methods[] = { - /* None so far */ - { NULL, NULL, 0, NULL } -}; - -static PyObject * -_PySelectionKey_getattr (PyObject *self, char *name) -{ - PySelectionKey *py_key = (PySelectionKey *)self; - - if (strcmp (name, "word") == 0) - return PyString_FromString (py_key->key->word); - return Py_FindMethod (selection_key_methods, self, name); -} - -static PyObject * -_PySelectionKey_repr (PyObject *self) -{ - PySelectionKey *py_key = (PySelectionKey *)self; - char buf[80]; - snprintf (buf, sizeof buf, "", py_key->key->word); - return PyString_FromString (buf); -} - -static PyObject * -_PySelectionKey_str (PyObject *self) -{ - PySelectionKey *py_key = (PySelectionKey *)self; - return PyString_FromString (py_key->key->word); -} - -static PyTypeObject PySelectionKeyType = { - PyObject_HEAD_INIT(&PyType_Type) - 0, - "DicoSelectionKey", /* tp_name */ - sizeof (PySelectionKey), /* tp_basicsize */ - 0, /* tp_itemsize; */ - _PySelectionKey_dealloc, /* tp_dealloc; */ - NULL, /* tp_print; */ - _PySelectionKey_getattr, /* tp_getattr; __getattr__ */ - NULL, /* tp_setattr; __setattr__ */ - NULL, /* tp_compare; __cmp__ */ - _PySelectionKey_repr, /* tp_repr; __repr__ */ - NULL, /* tp_as_number */ - NULL, /* tp_as_sequence */ - NULL, /* tp_as_mapping */ - NULL, /* tp_hash; __hash__ */ - NULL, /* tp_call; __call__ */ - _PySelectionKey_str, /* tp_str; __str__ */ -}; - -typedef struct { - PyObject_HEAD; - dico_strategy_t strat; -} PyStrategy; - -static inline PyObject * -_ro (PyObject *obj) -{ - Py_INCREF (obj); - return obj; -} - -static PyObject * -strat_select_method (PyObject *self, PyObject *args) -{ - PyStrategy *py_strat = (PyStrategy *)self; - PySelectionKey *py_key; - char *word = NULL; - - if (!PyArg_ParseTuple (args, "sO!", &word, &PySelectionKeyType, &py_key)) - return _ro (Py_False); - - return _ro (py_strat->strat->sel (DICO_SELECT_RUN, py_key->key, word) - ? Py_True : Py_False); -} - -static PyMethodDef strategy_methods[] = { - { "select", strat_select_method, METH_VARARGS, - "Return True if KEY matches WORD as per this strategy." }, - { NULL, NULL, 0, NULL } -}; - -static void -_PyStrategy_dealloc (PyObject *self) -{ -} - -static PyObject * -_PyStrategy_getattr (PyObject *self, char *name) -{ - PyStrategy *py_strat = (PyStrategy *)self; - dico_strategy_t strat = py_strat->strat; - - if (strcmp (name, "name") == 0) { - /* Return the name of the strategy STRAT. */ - return PyString_FromString (strat->name); - } else if (strcmp (name, "descr") == 0) { - /* Return a textual description of the strategy STRAT. */ - return PyString_FromString (strat->descr); - } else if (strcmp (name, "has_selector") == 0) { - /* Return True if STRAT has a selector. */ - return _ro (strat->sel ? Py_True : Py_False); - } else if (strcmp (name, "is_default") == 0) { - /* Return True if STRAT is a default strategy. */ - return _ro (dico_strategy_is_default_p (strat) ? Py_True : Py_False); - } - return Py_FindMethod (strategy_methods, self, name); -} - -static PyObject * -_PyStrategy_repr (PyObject *self) -{ - PyStrategy *py_strat = (PyStrategy *)self; - char buf[80]; - snprintf (buf, sizeof buf, "", py_strat->strat->name); - return PyString_FromString (buf); -} - -static PyObject * -_PyStrategy_str (PyObject *self) -{ - PyStrategy *py_strat = (PyStrategy *)self; - return PyString_FromString (py_strat->strat->name); -} - -static PyTypeObject PyStrategyType = { - PyObject_HEAD_INIT(&PyType_Type) - 0, - "DicoStrategy", /* tp_name */ - sizeof (PyStrategy), /* tp_basicsize */ - 0, /* tp_itemsize; */ - _PyStrategy_dealloc, /* tp_dealloc; */ - NULL, /* tp_print; */ - _PyStrategy_getattr, /* tp_getattr; __getattr__ */ - NULL, /* tp_setattr; __setattr__ */ - NULL, /* tp_compare; __cmp__ */ - _PyStrategy_repr, /* tp_repr; __repr__ */ - NULL, /* tp_as_number */ - NULL, /* tp_as_sequence */ - NULL, /* tp_as_mapping */ - NULL, /* tp_hash; __hash__ */ - NULL, /* tp_call; __call__ */ - _PyStrategy_str, /* tp_str; __str__ */ -}; - - -static dico_stream_t dico_stream_output; -static dico_stream_t dico_stream_log_err; -static dico_stream_t dico_stream_log_info; - -static PyObject * -_capture_stdout_result (PyObject *self, PyObject *args) -{ - char *buf = ""; - if (!PyArg_ParseTuple (args, "s", &buf)) - return NULL; - if (dico_stream_output) - dico_stream_write (dico_stream_output, buf, strlen (buf)); - return _ro (Py_None); -} - -static PyObject * -_capture_stdout_info (PyObject *self, PyObject *args) -{ - char *buf = ""; - if (!PyArg_ParseTuple (args, "s", &buf)) - return NULL; - if (dico_stream_log_info) - dico_stream_write (dico_stream_log_info, buf, strlen (buf)); - return _ro (Py_None); -} - -static PyObject * -_capture_stderr (PyObject *self, PyObject *args) -{ - char *buf = ""; - if (!PyArg_ParseTuple (args, "s", &buf)) - return NULL; - if (dico_stream_log_err) - dico_stream_write (dico_stream_log_err, buf, strlen (buf)); - return _ro (Py_None); -} - -static PyMethodDef capture_stdout_result_method[] = -{ - { "write", _capture_stdout_result, 1 }, - { NULL, NULL, 0, NULL } -}; -static PyMethodDef capture_stdout_info_method[] = -{ - { "write", _capture_stdout_info, 1 }, - { NULL, NULL, 0, NULL } -}; -static PyMethodDef capture_stderr_method[] = -{ - { "write", _capture_stderr, 1 }, - { NULL, NULL, 0, NULL } -}; - -static int -_python_selector (int cmd, struct dico_key *key, const char *dict_word) -{ - PyObject *py_args, *py_res; - PySelectionKey *py_key; - void *closure = key->strat->closure; - - py_args = PyTuple_New (3); - PyTuple_SetItem (py_args, 0, PyInt_FromLong (cmd)); - py_key = PyObject_NEW (PySelectionKey, &PySelectionKeyType); - py_key->key = key; - PyTuple_SetItem (py_args, 1, (PyObject*)py_key); - PyTuple_SetItem (py_args, 2, PyString_FromString (dict_word)); - - if (closure && PyCallable_Check (closure)) { - py_res = PyObject_CallObject (closure, py_args); - if (py_res) { - if (PyBool_Check (py_res)) - return py_res == Py_True ? 1 : 0; - } else if (PyErr_Occurred ()) - PyErr_Print (); - } - return 0; -} - -static PyObject * -dico_register_strat (PyObject *self, PyObject *args) -{ - struct dico_strategy strat; - char *name = NULL; - char *descr = NULL; - char *fnc = NULL; - - if (!PyArg_ParseTuple (args, "ss|s", &name, &descr, &fnc)) - return NULL; - - strat.name = name; - strat.descr = descr; - if (!fnc) { - strat.sel = NULL; - strat.closure = NULL; - } else { - strat.sel = _python_selector; - strat.closure = fnc; - } - dico_strategy_add (&strat); - - return _ro (Py_None); -} - -static PyObject * -dico_register_markup (PyObject *self, PyObject *py_obj) -{ - int rc; - char *type; - - if (!PyString_Check (py_obj)) { - PyErr_SetString (PyExc_TypeError, _("This parameter must be a string")); - return NULL; - } - - type = strdup (PyString_AsString (py_obj)); - rc = dico_markup_register (type); - free (type); - if (rc) - return NULL; - - return _ro (Py_None); -} - -static PyObject * -dico_current_markup (PyObject *self) -{ - return _ro (PyString_FromString (dico_markup_type)); -} - -static PyMethodDef dico_methods[] = { - { "register_strat", dico_register_strat, METH_VARARGS, - "Register a new strategy." }, - { "register_markup", dico_register_markup, METH_O, - "Register a new markup type." }, - { "current_markup", (PyCFunction) dico_current_markup, METH_NOARGS, - "Return current dico markup type." }, - { NULL, NULL, 0, NULL } -}; - - -static PyObject * -_argv_to_tuple (int argc, char **argv) -{ - int i; - PyObject *py_args = PyTuple_New (argc); - for (i = 0; argc; argc--, argv++, i++) { - PyTuple_SetItem (py_args, i, PyString_FromString (*argv)); - } - return py_args; -} - -static int -mod_init (int argc, char **argv) -{ - if (dico_parseopt (init_option, argc, argv, 0, NULL)) - return 1; - - if (!Py_IsInitialized ()) - Py_Initialize (); - - dico_stream_log_err = dico_log_stream_create (L_ERR); - dico_stream_log_info = dico_log_stream_create (L_INFO); - return 0; -} - -static void -insert_load_path (const char *dir) -{ - PyObject *py_sys, *py_path, *py_dirstr; - const char *p; - - py_sys = PyImport_ImportModule ("sys"); - py_path = PyObject_GetAttrString (py_sys, "path"); - p = dir + strlen (dir); - do { - size_t len; - for (len = 0; p > dir && p[-1] != ':'; p--, len++) - ; - py_dirstr = PyString_FromStringAndSize (p, len); - if (PySequence_Index (py_path, py_dirstr) == -1) { - PyObject *py_list; - PyErr_Clear (); - py_list = Py_BuildValue ("[O]", py_dirstr); - PyList_SetSlice (py_path, 0, 0, py_list); - Py_DECREF (py_list); - } - Py_DECREF (py_dirstr); - } while (p-- > dir); - Py_DECREF (py_path); - Py_DECREF (py_sys); -} - -static struct { - char *name; - int value; -} constab[] = { - { "DICO_SELECT_BEGIN", DICO_SELECT_BEGIN }, - { "DICO_SELECT_RUN", DICO_SELECT_RUN }, - { "DICO_SELECT_END", DICO_SELECT_END }, - { NULL } -}; - -static void -declare_constants(PyObject *module) -{ - int i; - - for (i = 0; constab[i].name; i++) - PyModule_AddIntConstant (module, constab[i].name, constab[i].value); -} - -static dico_handle_t -mod_init_db (const char *dbname, int argc, char **argv) -{ - int pindex; - struct _python_database *db; - PyObject *py_err, *py_out, *py_name, *py_module, *py_class; - PyThreadState *py_ths; - - if (dico_parseopt (init_option, argc, argv, DICO_PARSEOPT_PERMUTE, - &pindex)) - return NULL; - - if (!init_script) - return NULL; - - argv += pindex; - argc -= pindex; - - db = malloc (sizeof (*db)); - if (!db) { - DICO_LOG_ERRNO(); - return NULL; - } - db->dbname = dbname; - db->argc = argc; - db->argv = argv; - - py_ths = Py_NewInterpreter (); - if (!py_ths) { - dico_log (L_ERR, 0, - _("mod_init_db: cannot create new interpreter: %s"), - init_script); - return NULL; - } - - PyThreadState_Swap (py_ths); - db->py_ths = py_ths; - - declare_constants (Py_InitModule ("dico", dico_methods)); - - PyRun_SimpleString ("import sys"); - if (load_path) - insert_load_path (load_path); - insert_load_path (""); - - py_err = Py_InitModule ("stderr", capture_stderr_method); - if (py_err) - PySys_SetObject ("stderr", py_err); - py_out = Py_InitModule ("stdout", capture_stdout_info_method); - if (py_out) - PySys_SetObject ("stdout", py_out); - - py_name = PyString_FromString (init_script); - py_module = PyImport_Import (py_name); - Py_DECREF (py_name); - - if (!py_module) { - dico_log (L_ERR, 0, _("mod_init_db: cannot load init script: %s"), - init_script); - if (PyErr_Occurred ()) - PyErr_Print (); - return NULL; - } - - py_class = PyObject_GetAttrString (py_module, root_class); - if (py_class && PyClass_Check (py_class)) { - PyObject *py_instance = PyInstance_New (py_class, - _argv_to_tuple (argc, argv), - NULL); - if (py_instance && PyInstance_Check (py_instance)) - db->py_instance = py_instance; - else if (PyErr_Occurred ()) { - PyErr_Print (); - return NULL; - } - } else { - dico_log (L_ERR, 0, _("mod_init_db: cannot create class instance: %s"), - root_class); - if (PyErr_Occurred ()) - PyErr_Print (); - return NULL; - } - return (dico_handle_t)db; -} - -static int -mod_free_db (dico_handle_t hp) -{ - struct _python_database *db = (struct _python_database *)hp; - - PyThreadState_Swap (NULL); - PyThreadState_Delete (db->py_ths); - - free (db); - return 0; -} - -static int -mod_open (dico_handle_t hp) -{ - PyObject *py_args, *py_value, *py_fnc, *py_res; - struct _python_database *db = (struct _python_database *)hp; - - PyThreadState_Swap (db->py_ths); - - py_value = PyString_FromString (db->dbname); - py_args = PyTuple_New (1); - PyTuple_SetItem (py_args, 0, py_value); - - py_fnc = PyObject_GetAttrString (db->py_instance, "open"); - if (py_fnc && PyCallable_Check (py_fnc)) { - py_res = PyObject_CallObject (py_fnc, py_args); - Py_DECREF (py_args); - Py_DECREF (py_fnc); - if (py_res && PyBool_Check (py_res) && py_res == Py_False) { - return 1; - } else if (PyErr_Occurred ()) { - PyErr_Print (); - return 1; - } - } - return 0; -} - -static int -mod_close (dico_handle_t hp) -{ - PyObject *py_fnc, *py_res; - struct _python_database *db = (struct _python_database *)hp; - - PyThreadState_Swap (db->py_ths); - - py_fnc = PyObject_GetAttrString (db->py_instance, "close"); - if (py_fnc && PyCallable_Check (py_fnc)) { - py_res = PyObject_CallObject (py_fnc, NULL); - Py_DECREF (py_fnc); - if (py_res && PyBool_Check (py_res) && py_res == Py_False) { - return 1; - } - else if (PyErr_Occurred ()) { - PyErr_Print (); - return 1; - } - } - return 0; -} - -static char * -_mod_get_text (PyObject *py_instance, const char *method) -{ - PyObject *py_fnc, *py_res; - - if (!py_instance) - return NULL; - else if (!PyObject_HasAttrString (py_instance, method)) - return NULL; - - py_fnc = PyObject_GetAttrString (py_instance, method); - if (py_fnc && PyCallable_Check (py_fnc)) { - py_res = PyObject_CallObject (py_fnc, NULL); - Py_DECREF (py_fnc); - if (py_res && PyString_Check (py_res)) { - char *text = strdup (PyString_AsString (py_res)); - Py_DECREF (py_res); - return text; - } else if (PyErr_Occurred ()) - PyErr_Print (); - } - return NULL; -} - -static char * -mod_info (dico_handle_t hp) -{ - struct _python_database *db = (struct _python_database *)hp; - - PyThreadState_Swap (db->py_ths); - return _mod_get_text (db->py_instance, "info"); -} - -static char * -mod_descr (dico_handle_t hp) -{ - struct _python_database *db = (struct _python_database *)hp; - - PyThreadState_Swap (db->py_ths); - return _mod_get_text (db->py_instance, "descr"); -} - -static dico_list_t -_tuple_to_langlist (PyObject *py_obj) -{ - dico_list_t list = NULL; - - if (!py_obj) - return NULL; - - if (PyString_Check (py_obj)) { - char *text = strdup (PyString_AsString (py_obj)); - list = dico_list_create (); - dico_list_append (list, text); - } else if (PyTuple_Check (py_obj) || PyList_Check (py_obj)) { - PyObject *py_item; - PyObject *py_iterator = PyObject_GetIter (py_obj); - - list = dico_list_create (); - - if (py_iterator) { - while ((py_item = PyIter_Next (py_iterator))) { - if (PyString_Check (py_item)) { - char *text = strdup (PyString_AsString (py_item)); - dico_list_append (list, text); - } - Py_DECREF (py_item); - } - Py_DECREF (py_iterator); - if (PyErr_Occurred ()) { - PyErr_Print (); - return NULL; - } - } - } - return list; -} - -static int -mod_lang (dico_handle_t hp, dico_list_t list[2]) -{ - PyObject *py_fnc, *py_res; - struct _python_database *db = (struct _python_database *)hp; - list[0] = list[1] = NULL; - - PyThreadState_Swap (db->py_ths); - if (!PyObject_HasAttrString (db->py_instance, "lang")) - return 1; - - py_fnc = PyObject_GetAttrString (db->py_instance, "lang"); - if (py_fnc && PyCallable_Check (py_fnc)) { - py_res = PyObject_CallObject (py_fnc, NULL); - Py_DECREF (py_fnc); - if (py_res) { - if (PyString_Check (py_res)) { - char *text = strdup (PyString_AsString (py_res)); - Py_DECREF (py_res); - list[0] = dico_list_create (); - dico_list_append (list[0], text); - } else if (PyTuple_Check (py_res)) { - switch (PyTuple_Size (py_res)) { - case 2: - list[0] = _tuple_to_langlist (PyTuple_GetItem (py_res, 0)); - list[1] = _tuple_to_langlist (PyTuple_GetItem (py_res, 1)); - break; - - case 1: - list[0] = _tuple_to_langlist (PyTuple_GetItem (py_res, 0)); - break; - - default: - dico_log (L_ERR, 0, - _("Method `lang' must return at most" - " 2 elements")); - return 1; - } - Py_DECREF (py_res); - } else if (PyList_Check (py_res)) { - switch (PyList_Size (py_res)) { - case 2: - list[0] = _tuple_to_langlist (PyList_GetItem (py_res, 0)); - list[1] = _tuple_to_langlist (PyList_GetItem (py_res, 1)); - break; - - case 1: - list[0] = _tuple_to_langlist (PyList_GetItem (py_res, 0)); - break; - - default: - dico_log (L_ERR, 0, - _("Method `lang' must return at most" - " 2 elements")); - return 1; - } - Py_DECREF (py_res); - } else { - dico_log (L_ERR, 0, _("Method `lang' must return a tuple or " - "a list")); - return 1; - } - } else if (PyErr_Occurred ()) { - PyErr_Print (); - return 1; - } - } - return 0; -} - -struct python_result { - struct _python_database *db; - PyObject *result; -}; - -static dico_result_t -_make_python_result (struct _python_database *db, PyObject *res) -{ - struct python_result *rp = malloc (sizeof (*rp)); - if (rp) { - rp->db = db; - rp->result = res; - } - return (dico_result_t)rp; -} - -dico_result_t -do_match(struct _python_database *db, const dico_strategy_t strat, - struct dico_key *key) -{ - PyStrategy *py_strat; - PySelectionKey *py_key; - PyObject *py_args, *py_fnc, *py_res; - - py_key = PyObject_NEW(PySelectionKey, &PySelectionKeyType); - if (!py_key) - return NULL; - py_key->key = key; - - py_strat = PyObject_NEW(PyStrategy, &PyStrategyType); - if (py_strat) { - py_strat->strat = strat; - - py_args = PyTuple_New(2); - PyTuple_SetItem(py_args, 0, (PyObject *)py_strat); - PyTuple_SetItem(py_args, 1, (PyObject *)py_key); - py_fnc = PyObject_GetAttrString(db->py_instance, "match_word"); - if (py_fnc && PyCallable_Check(py_fnc)) { - py_res = PyObject_CallObject(py_fnc, py_args); - Py_DECREF(py_args); - Py_DECREF(py_fnc); - if (py_res) { - if (PyBool_Check(py_res) && py_res == Py_False) - return NULL; - else - return _make_python_result(db, py_res); - } else if (PyErr_Occurred()) - PyErr_Print(); - } - } - return NULL; -} - -static dico_result_t -mod_match (dico_handle_t hp, const dico_strategy_t strat, const char *word) -{ - struct _python_database *db = (struct _python_database *)hp; - struct dico_key key; - dico_result_t res; - - PyThreadState_Swap(db->py_ths); - - if (dico_key_init(&key, strat, word)) { - dico_log(L_ERR, 0, _("mod_match: key initialization failed")); - return NULL; - } - res = do_match(db, strat, &key); - dico_key_deinit(&key); - return res; -} - -static dico_result_t -mod_define (dico_handle_t hp, const char *word) -{ - PyObject *py_args, *py_fnc, *py_res; - struct _python_database *db = (struct _python_database *)hp; - - PyThreadState_Swap (db->py_ths); - - py_args = PyTuple_New (1); - PyTuple_SetItem (py_args, 0, PyString_FromString (word)); - - py_fnc = PyObject_GetAttrString (db->py_instance, "define_word"); - if (py_fnc && PyCallable_Check (py_fnc)) { - py_res = PyObject_CallObject (py_fnc, py_args); - Py_DECREF (py_args); - Py_DECREF (py_fnc); - if (py_res) { - if (PyBool_Check (py_res) && py_res == Py_False) - return NULL; - else - return _make_python_result (db, py_res); - } else if (PyErr_Occurred ()) - PyErr_Print (); - } - return NULL; -} - -static int -mod_output_result (dico_result_t rp, size_t n, dico_stream_t str) -{ - PyObject *py_args, *py_fnc, *py_out; - struct python_result *gres = (struct python_result *)rp; - struct _python_database *db = (struct _python_database *)gres->db; - - PyThreadState_Swap (db->py_ths); - - dico_stream_output = str; - - py_out = Py_InitModule ("stdout", capture_stdout_result_method); - if (py_out) - PySys_SetObject ("stdout", py_out); - else { - dico_log (L_ERR, 0, _("mod_output_result: cannot capture stdout")); - return 1; - } - - py_args = PyTuple_New (2); - PyTuple_SetItem (py_args, 0, gres->result); - Py_INCREF (gres->result); - PyTuple_SetItem (py_args, 1, PyLong_FromLong (n)); - - py_fnc = PyObject_GetAttrString (db->py_instance, "output"); - if (py_fnc && PyCallable_Check (py_fnc)) { - /* FIXME: should we checj/propagate the retval? */ - PyObject_CallObject (py_fnc, py_args); - Py_DECREF (py_args); - Py_DECREF (py_fnc); - if (PyErr_Occurred ()) - PyErr_Print (); - } - - py_out = Py_InitModule ("stdout", capture_stdout_info_method); - if (py_out) - PySys_SetObject ("stdout", py_out); - - dico_stream_output = NULL; - return 0; -} - -static size_t -_mod_get_size_t (PyObject *py_instance, PyObject *py_args, const char *method) -{ - PyObject *py_fnc, *py_res; - - if (!py_instance) - return 0; - - py_fnc = PyObject_GetAttrString (py_instance, method); - if (py_fnc && PyCallable_Check (py_fnc)) { - py_res = PyObject_CallObject (py_fnc, py_args); - Py_DECREF (py_fnc); - if (py_res && PyInt_Check (py_res)) { - size_t s = (size_t)PyInt_AsSsize_t (py_res); - Py_DECREF (py_res); - return s; - } else if (PyErr_Occurred ()) - PyErr_Print (); - } - return 0; -} - -static size_t -mod_result_count (dico_result_t rp) -{ - PyObject *py_args; - struct python_result *gres = (struct python_result *)rp; - struct _python_database *db = (struct _python_database *)gres->db; - size_t ret; - - PyThreadState_Swap (db->py_ths); - - py_args = PyTuple_New (1); - PyTuple_SetItem (py_args, 0, gres->result); - Py_INCREF (gres->result); - ret = _mod_get_size_t (db->py_instance, py_args, "result_count"); - Py_DECREF (py_args); - return ret; -} - -static size_t -mod_compare_count (dico_result_t rp) -{ - PyObject *py_args; - struct python_result *gres = (struct python_result *)rp; - struct _python_database *db = (struct _python_database *)gres->db; - size_t ret; - - PyThreadState_Swap (db->py_ths); - if (!PyObject_HasAttrString (db->py_instance, "compare_count")) - return 0; - - py_args = PyTuple_New (1); - PyTuple_SetItem (py_args, 0, gres->result); - Py_INCREF (gres->result); - ret = _mod_get_size_t (db->py_instance, py_args, "compare_count"); - Py_DECREF (py_args); - return ret; -} - -static void -mod_free_result (dico_result_t rp) -{ - PyObject *py_args, *py_fnc; - struct python_result *gres = (struct python_result *)rp; - struct _python_database *db = (struct _python_database *)gres->db; - - PyThreadState_Swap (db->py_ths); - if (!PyObject_HasAttrString (db->py_instance, "free_result")) - return; - - py_args = PyTuple_New (1); - PyTuple_SetItem (py_args, 0, gres->result); - Py_INCREF (gres->result); - py_fnc = PyObject_GetAttrString (db->py_instance, "free_result"); - if (py_fnc && PyCallable_Check (py_fnc)) { - PyObject_CallObject (py_fnc, py_args); - Py_DECREF (py_args); - Py_DECREF (py_fnc); - if (PyErr_Occurred ()) - PyErr_Print (); - } - Py_DECREF (gres->result); - free (gres); -} - -static PyObject * -_assoc_to_dict (dico_assoc_list_t assoc) -{ - PyObject *py_dict; - dico_iterator_t itr; - struct dico_assoc *p; - - py_dict = PyDict_New (); - if (py_dict) { - itr = dico_assoc_iterator (assoc); - for (p = dico_iterator_first (itr); p; p = dico_iterator_next (itr)) { - PyDict_SetItemString (py_dict, p->key, - PyString_FromString (p->value)); - } - dico_iterator_destroy (&itr); - return _ro (py_dict); - } - return NULL; -} - -static void -_dict_to_assoc (dico_assoc_list_t assoc, PyObject *py_dict) -{ - PyObject *py_key, *py_value; - Py_ssize_t py_pos = 0; - - dico_assoc_clear (assoc); - - while (PyDict_Next (py_dict, &py_pos, &py_key, &py_value)) { - char *key, *val; - key = strdup (PyString_AsString (py_key)); - val = strdup (PyString_AsString (py_value)); - dico_assoc_append (assoc, key, val); - } -} - -static int -mod_result_headers (dico_result_t rp, dico_assoc_list_t hdr) -{ - PyObject *py_dict, *py_args, *py_fnc, *py_res; - struct python_result *gres = (struct python_result *)rp; - struct _python_database *db = (struct _python_database *)gres->db; - - PyThreadState_Swap (db->py_ths); - if (!PyObject_HasAttrString (db->py_instance, "result_headers")) - return 0; - - py_dict = _assoc_to_dict (hdr); - - py_args = PyTuple_New (2); - PyTuple_SetItem (py_args, 0, gres->result); - PyTuple_SetItem (py_args, 1, py_dict); - Py_INCREF (gres->result); - - py_fnc = PyObject_GetAttrString (db->py_instance, "result_headers"); - if (py_fnc && PyCallable_Check (py_fnc)) { - py_res = PyObject_CallObject (py_fnc, py_args); - Py_DECREF (py_args); - Py_DECREF (py_fnc); - if (py_res && PyDict_Check (py_res)) { - _dict_to_assoc (hdr, py_res); - Py_DECREF (py_res); - } else if (PyErr_Occurred ()) { - PyErr_Print (); - return 1; - } - } - Py_DECREF (py_dict); - return 0; -} - -static char * -mod_db_mime_header (dico_handle_t hp) -{ - struct _python_database *db = (struct _python_database *)hp; - - PyThreadState_Swap (db->py_ths); - return _mod_get_text (db->py_instance, "db_mime_header"); -} - -struct dico_database_module DICO_EXPORT(python, module) = { - .dico_version = DICO_MODULE_VERSION, - .dico_capabilities = DICO_CAPA_NONE, - .dico_init = mod_init, - .dico_init_db = mod_init_db, - .dico_free_db = mod_free_db, - .dico_open = mod_open, - .dico_close = mod_close, - .dico_db_info = mod_info, - .dico_db_descr = mod_descr, - .dico_db_lang = mod_lang, - .dico_match = mod_match, - .dico_define = mod_define, - .dico_output_result = mod_output_result, - .dico_result_count = mod_result_count, - .dico_compare_count = mod_compare_count, - .dico_free_result = mod_free_result, - .dico_result_headers = mod_result_headers, - .dico_db_mime_header = mod_db_mime_header -}; -- cgit v1.2.1