Merge branch 'collectd-5.4' into collectd-5.5
authorMarc Fournier <marc.fournier@camptocamp.com>
Wed, 14 Oct 2015 07:10:38 +0000 (09:10 +0200)
committerMarc Fournier <marc.fournier@camptocamp.com>
Wed, 14 Oct 2015 07:10:38 +0000 (09:10 +0200)
1  2 
src/python.c

diff --combined src/python.c
@@@ -46,19 -46,6 +46,19 @@@ typedef struct cpy_callback_s 
  
  static char log_doc[] = "This function sends a string to all logging plugins.";
  
 +static char get_ds_doc[] = "get_dataset(name) -> definition\n"
 +              "\n"
 +              "Returns the definition of a dataset specified by name.\n"
 +              "\n"
 +              "'name' is a string specifying the dataset to query.\n"
 +              "'definition' is a list of 4-tuples. Every tuple represents a \n"
 +              "    data source within the data set and its 4 values are the \n"
 +              "    name, type, min and max value.\n"
 +              "    'name' is a string.\n"
 +              "    'type' is a string that is equal to either DS_TYPE_COUNTER,\n"
 +              "        DS_TYPE_GAUGE, DS_TYPE_DERIVE or DS_TYPE_ABSOLUTE.\n"
 +              "    'min' and 'max' are either a float or None.";
 +
  static char flush_doc[] = "flush([plugin][, timeout][, identifier]) -> None\n"
                "\n"
                "Flushes the cache of another plugin.";
@@@ -302,7 -289,7 +302,7 @@@ void cpy_log_exception(const char *cont
                Py_XDECREF(traceback);
                return;
        }
-       list = PyObject_CallFunction(cpy_format_exception, "NNN", type, value, traceback); /* New reference. */
+       list = PyObject_CallFunction(cpy_format_exception, "NNN", type, value, traceback); /* New reference. Steals references from "type", "value" and "traceback". */
        if (list)
                l = PyObject_Length(list);
        for (i = 0; i < l; ++i) {
        }
        Py_XDECREF(list);
        PyErr_Clear();
-       Py_DECREF(type);
-       Py_XDECREF(value);
-       Py_XDECREF(traceback);
  }
  
  static int cpy_read_callback(user_data_t *data) {
@@@ -561,39 -545,7 +558,39 @@@ static PyObject *cpy_register_generic(c
        return cpy_string_to_unicode_or_bytes(buf);
  }
  
 -static PyObject *cpy_flush(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) {
 +static PyObject *float_or_none(float number) {
 +      if (isnan(number)) {
 +              Py_RETURN_NONE;
 +      }
 +      return PyFloat_FromDouble(number);
 +}
 +
 +static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) {
 +      int i;
 +      char *name;
 +      const data_set_t *ds;
 +      PyObject *list, *tuple;
 +
 +      if (PyArg_ParseTuple(args, "et", NULL, &name) == 0) return NULL;
 +      ds = plugin_get_ds(name);
 +      PyMem_Free(name);
 +      if (ds == NULL) {
 +              PyErr_Format(PyExc_TypeError, "Dataset %s not found", name);
 +              return NULL;
 +      }
 +      list = PyList_New(ds->ds_num); /* New reference. */
 +      for (i = 0; i < ds->ds_num; ++i) {
 +              tuple = PyTuple_New(4);
 +              PyTuple_SET_ITEM(tuple, 0, cpy_string_to_unicode_or_bytes(ds->ds[i].name));
 +              PyTuple_SET_ITEM(tuple, 1, cpy_string_to_unicode_or_bytes(DS_TYPE_TO_STRING(ds->ds[i].type)));
 +              PyTuple_SET_ITEM(tuple, 2, float_or_none(ds->ds[i].min));
 +              PyTuple_SET_ITEM(tuple, 3, float_or_none(ds->ds[i].max));
 +              PyList_SET_ITEM(list, i, tuple);
 +      }
 +      return list;
 +}
 +
 +static PyObject *cpy_flush(PyObject *self, PyObject *args, PyObject *kwds) {
        int timeout = -1;
        char *plugin = NULL, *identifier = NULL;
        static char *kwlist[] = {"plugin", "timeout", "identifier", NULL};
@@@ -862,7 -814,6 +859,7 @@@ static PyMethodDef cpy_methods[] = 
        {"notice", cpy_notice, METH_VARARGS, log_doc},
        {"warning", cpy_warning, METH_VARARGS, log_doc},
        {"error", cpy_error, METH_VARARGS, log_doc},
 +      {"get_dataset", (PyCFunction) cpy_get_dataset, METH_VARARGS, get_ds_doc},
        {"flush", (PyCFunction) cpy_flush, METH_VARARGS | METH_KEYWORDS, flush_doc},
        {"register_log", (PyCFunction) cpy_register_log, METH_VARARGS | METH_KEYWORDS, reg_log_doc},
        {"register_init", (PyCFunction) cpy_register_init, METH_VARARGS | METH_KEYWORDS, reg_init_doc},
@@@ -1034,15 -985,13 +1031,15 @@@ PyMODINIT_FUNC PyInit_collectd(void) 
  #endif
  
  static int cpy_init_python() {
 -      char *argv = "";
        PyObject *sys;
        PyObject *module;
  
  #ifdef IS_PY3K
 +      wchar_t *argv = L"";
        /* Add a builtin module, before Py_Initialize */
        PyImport_AppendInittab("collectd", PyInit_collectd);
 +#else
 +      char *argv = "";
  #endif
        
        Py_Initialize();
        PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
        PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
        PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
 +      PyModule_AddStringConstant(module, "DS_TYPE_COUNTER", DS_TYPE_TO_STRING(DS_TYPE_COUNTER));
 +      PyModule_AddStringConstant(module, "DS_TYPE_GAUGE", DS_TYPE_TO_STRING(DS_TYPE_GAUGE));
 +      PyModule_AddStringConstant(module, "DS_TYPE_DERIVE", DS_TYPE_TO_STRING(DS_TYPE_DERIVE));
 +      PyModule_AddStringConstant(module, "DS_TYPE_ABSOLUTE", DS_TYPE_TO_STRING(DS_TYPE_ABSOLUTE));
        return 0;
  }
  
@@@ -1119,13 -1064,9 +1116,13 @@@ static int cpy_config(oconfig_item_t *c
                } else if (strcasecmp(item->key, "Encoding") == 0) {
                        if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_STRING)
                                continue;
 +#ifdef IS_PY3K
 +                      NOTICE("python: \"Encoding\" was used in the config file but Python3 was used, which does not support changing encodings. Ignoring this.");
 +#else
                        /* Why is this even necessary? And undocumented? */
                        if (PyUnicode_SetDefaultEncoding(item->values[0].value.string))
                                cpy_log_exception("setting default encoding");
 +#endif
                } else if (strcasecmp(item->key, "LogTraces") == 0) {
                        if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
                                continue;
                                cpy_log_exception("python initialization");
                                continue;
                        }
 -                      if (PyList_Append(sys_path, dir_object) != 0) {
 -                              ERROR("python plugin: Unable to append \"%s\" to "
 +                      if (PyList_Insert(sys_path, 0, dir_object) != 0) {
 +                              ERROR("python plugin: Unable to prepend \"%s\" to "
                                      "python module path.", dir);
                                cpy_log_exception("python initialization");
                        }