[libvirt] [libvirt-python PATCH 05/23] Move utils and shared code into libvirt-utils

Pavel Hrdina phrdina at redhat.com
Thu Sep 24 14:01:42 UTC 2015


Signed-off-by: Pavel Hrdina <phrdina at redhat.com>
---
 libvirt-lxc-override.c  |   7 -
 libvirt-override.c      | 413 ------------------------------------------------
 libvirt-qemu-override.c |   7 -
 libvirt-utils.c         | 406 +++++++++++++++++++++++++++++++++++++++++++++++
 libvirt-utils.h         |  51 ++++++
 5 files changed, 457 insertions(+), 427 deletions(-)

diff --git a/libvirt-lxc-override.c b/libvirt-lxc-override.c
index d0d9ffd..e0d3e60 100644
--- a/libvirt-lxc-override.c
+++ b/libvirt-lxc-override.c
@@ -47,13 +47,6 @@ extern void initcygvirtmod_lxc(void);
    do {} while (0)
 #endif
 
-/* The two-statement sequence "Py_INCREF(Py_None); return Py_None;"
-   is so common that we encapsulate it here.  Now, each use is simply
-   return VIR_PY_NONE;  */
-#define VIR_PY_NONE (Py_INCREF (Py_None), Py_None)
-#define VIR_PY_INT_FAIL (libvirt_intWrap(-1))
-#define VIR_PY_INT_SUCCESS (libvirt_intWrap(0))
-
 /************************************************************************
  *									*
  *		Statistics						*
diff --git a/libvirt-override.c b/libvirt-override.c
index b18196f..ff6f338 100644
--- a/libvirt-override.c
+++ b/libvirt-override.c
@@ -51,419 +51,6 @@ extern void initcygvirtmod(void);
    do {} while (0)
 #endif
 
-/* The two-statement sequence "Py_INCREF(Py_None); return Py_None;"
-   is so common that we encapsulate it here.  Now, each use is simply
-   return VIR_PY_NONE;  */
-#define VIR_PY_NONE (Py_INCREF (Py_None), Py_None)
-#define VIR_PY_INT_FAIL (libvirt_intWrap(-1))
-#define VIR_PY_INT_SUCCESS (libvirt_intWrap(0))
-
-static char *py_str(PyObject *obj)
-{
-    PyObject *str = PyObject_Str(obj);
-    char *ret;
-    if (!str) {
-        PyErr_Print();
-        PyErr_Clear();
-        return NULL;
-    };
-    libvirt_charPtrUnwrap(str, &ret);
-    return ret;
-}
-
-/* Helper function to convert a virTypedParameter output array into a
- * Python dictionary for return to the user.  Return NULL on failure,
- * after raising a python exception.  */
-static PyObject *
-getPyVirTypedParameter(const virTypedParameter *params, int nparams)
-{
-    PyObject *key, *val, *info;
-    size_t i;
-
-    if ((info = PyDict_New()) == NULL)
-        return NULL;
-
-    for (i = 0; i < nparams; i++) {
-        switch (params[i].type) {
-        case VIR_TYPED_PARAM_INT:
-            val = libvirt_intWrap(params[i].value.i);
-            break;
-
-        case VIR_TYPED_PARAM_UINT:
-            val = libvirt_intWrap(params[i].value.ui);
-            break;
-
-        case VIR_TYPED_PARAM_LLONG:
-            val = libvirt_longlongWrap(params[i].value.l);
-            break;
-
-        case VIR_TYPED_PARAM_ULLONG:
-            val = libvirt_ulonglongWrap(params[i].value.ul);
-            break;
-
-        case VIR_TYPED_PARAM_DOUBLE:
-            val = PyFloat_FromDouble(params[i].value.d);
-            break;
-
-        case VIR_TYPED_PARAM_BOOLEAN:
-            val = PyBool_FromLong(params[i].value.b);
-            break;
-
-        case VIR_TYPED_PARAM_STRING:
-            val = libvirt_constcharPtrWrap(params[i].value.s);
-            break;
-
-        default:
-            /* Possible if a newer server has a bug and sent stuff we
-             * don't recognize.  */
-            PyErr_Format(PyExc_LookupError,
-                         "Type value \"%d\" not recognized",
-                         params[i].type);
-            val = NULL;
-            break;
-        }
-
-        key = libvirt_constcharPtrWrap(params[i].field);
-        if (!key || !val)
-            goto cleanup;
-
-        if (PyDict_SetItem(info, key, val) < 0) {
-            Py_DECREF(info);
-            goto cleanup;
-        }
-
-        Py_DECREF(key);
-        Py_DECREF(val);
-    }
-    return info;
-
-cleanup:
-    Py_XDECREF(key);
-    Py_XDECREF(val);
-    return NULL;
-}
-
-/* Allocate a new typed parameter array with the same contents and
- * length as info, and using the array params of length nparams as
- * hints on what types to use when creating the new array. The caller
- * must clear the array before freeing it. Return NULL on failure,
- * after raising a python exception.  */
-static virTypedParameterPtr ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
-setPyVirTypedParameter(PyObject *info,
-                       const virTypedParameter *params, int nparams)
-{
-    PyObject *key, *value;
-#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 4
-    int pos = 0;
-#else
-    Py_ssize_t pos = 0;
-#endif
-    virTypedParameterPtr temp = NULL, ret = NULL;
-    Py_ssize_t size;
-    size_t i;
-
-    if ((size = PyDict_Size(info)) < 0)
-        return NULL;
-
-    /* Libvirt APIs use NULL array and 0 size as a special case;
-     * setting should have at least one parameter.  */
-    if (size == 0) {
-        PyErr_Format(PyExc_LookupError, "Dictionary must not be empty");
-        return NULL;
-    }
-
-    if (VIR_ALLOC_N(ret, size) < 0) {
-        PyErr_NoMemory();
-        return NULL;
-    }
-
-    temp = &ret[0];
-    while (PyDict_Next(info, &pos, &key, &value)) {
-        char *keystr = NULL;
-
-        if (libvirt_charPtrUnwrap(key, &keystr) < 0 ||
-            keystr == NULL)
-            goto cleanup;
-
-        for (i = 0; i < nparams; i++) {
-            if (STREQ(params[i].field, keystr))
-                break;
-        }
-        if (i == nparams) {
-            PyErr_Format(PyExc_LookupError,
-                         "Attribute name \"%s\" could not be recognized",
-                         keystr);
-            VIR_FREE(keystr);
-            goto cleanup;
-        }
-
-        strncpy(temp->field, keystr, VIR_TYPED_PARAM_FIELD_LENGTH - 1);
-        temp->type = params[i].type;
-        VIR_FREE(keystr);
-
-        switch (params[i].type) {
-        case VIR_TYPED_PARAM_INT:
-            if (libvirt_intUnwrap(value, &temp->value.i) < 0)
-                goto cleanup;
-            break;
-
-        case VIR_TYPED_PARAM_UINT:
-            if (libvirt_uintUnwrap(value, &temp->value.ui) < 0)
-                goto cleanup;
-            break;
-
-        case VIR_TYPED_PARAM_LLONG:
-            if (libvirt_longlongUnwrap(value, &temp->value.l) < 0)
-                goto cleanup;
-            break;
-
-        case VIR_TYPED_PARAM_ULLONG:
-            if (libvirt_ulonglongUnwrap(value, &temp->value.ul) < 0)
-                goto cleanup;
-            break;
-
-        case VIR_TYPED_PARAM_DOUBLE:
-            if (libvirt_doubleUnwrap(value, &temp->value.d) < 0)
-                goto cleanup;
-            break;
-
-        case VIR_TYPED_PARAM_BOOLEAN:
-        {
-            bool b;
-            if (libvirt_boolUnwrap(value, &b) < 0)
-                goto cleanup;
-            temp->value.b = b;
-            break;
-        }
-        case VIR_TYPED_PARAM_STRING:
-        {
-            char *string_val;
-            if (libvirt_charPtrUnwrap(value, &string_val) < 0 ||
-                !string_val)
-                goto cleanup;
-            temp->value.s = string_val;
-            break;
-        }
-
-        default:
-            /* Possible if a newer server has a bug and sent stuff we
-             * don't recognize.  */
-            PyErr_Format(PyExc_LookupError,
-                         "Type value \"%d\" not recognized",
-                         params[i].type);
-            goto cleanup;
-        }
-
-        temp++;
-    }
-    return ret;
-
-cleanup:
-    virTypedParamsFree(ret, size);
-    return NULL;
-}
-
-/* While these appeared in libvirt in 1.0.2, we only
- * need them in the python from 1.1.0 onwards */
-#if LIBVIR_CHECK_VERSION(1, 1, 0)
-typedef struct {
-    const char *name;
-    int type;
-} virPyTypedParamsHint;
-typedef virPyTypedParamsHint *virPyTypedParamsHintPtr;
-
-# if PY_MAJOR_VERSION > 2
-#  define libvirt_PyString_Check PyUnicode_Check
-# else
-#  define libvirt_PyString_Check PyString_Check
-# endif
-
-static int
-virPyDictToTypedParamOne(virTypedParameterPtr *params,
-                         int *n,
-                         int *max,
-                         virPyTypedParamsHintPtr hints,
-                         int nhints,
-                         const char *keystr,
-                         PyObject *value)
-{
-    int rv = -1, type = -1;
-    size_t i;
-
-    for (i = 0; i < nhints; i++) {
-        if (STREQ(hints[i].name, keystr)) {
-            type = hints[i].type;
-            break;
-        }
-    }
-
-    if (type == -1) {
-        if (libvirt_PyString_Check(value)) {
-            type = VIR_TYPED_PARAM_STRING;
-        } else if (PyBool_Check(value)) {
-            type = VIR_TYPED_PARAM_BOOLEAN;
-        } else if (PyLong_Check(value)) {
-            unsigned long long ull = PyLong_AsUnsignedLongLong(value);
-            if (ull == (unsigned long long) -1 && PyErr_Occurred())
-                type = VIR_TYPED_PARAM_LLONG;
-            else
-                type = VIR_TYPED_PARAM_ULLONG;
-#if PY_MAJOR_VERSION < 3
-        } else if (PyInt_Check(value)) {
-            if (PyInt_AS_LONG(value) < 0)
-                type = VIR_TYPED_PARAM_LLONG;
-            else
-                type = VIR_TYPED_PARAM_ULLONG;
-#endif
-        } else if (PyFloat_Check(value)) {
-            type = VIR_TYPED_PARAM_DOUBLE;
-        }
-    }
-
-    if (type == -1) {
-        PyErr_Format(PyExc_TypeError,
-                     "Unknown type of \"%s\" field", keystr);
-        goto cleanup;
-    }
-
-    switch ((virTypedParameterType) type) {
-    case VIR_TYPED_PARAM_INT:
-    {
-        int val;
-        if (libvirt_intUnwrap(value, &val) < 0 ||
-            virTypedParamsAddInt(params, n, max, keystr, val) < 0)
-            goto cleanup;
-        break;
-    }
-    case VIR_TYPED_PARAM_UINT:
-    {
-        unsigned int val;
-        if (libvirt_uintUnwrap(value, &val) < 0 ||
-            virTypedParamsAddUInt(params, n, max, keystr, val) < 0)
-            goto cleanup;
-        break;
-    }
-    case VIR_TYPED_PARAM_LLONG:
-    {
-        long long val;
-        if (libvirt_longlongUnwrap(value, &val) < 0 ||
-            virTypedParamsAddLLong(params, n, max, keystr, val) < 0)
-            goto cleanup;
-        break;
-    }
-    case VIR_TYPED_PARAM_ULLONG:
-    {
-        unsigned long long val;
-        if (libvirt_ulonglongUnwrap(value, &val) < 0 ||
-            virTypedParamsAddULLong(params, n, max, keystr, val) < 0)
-            goto cleanup;
-        break;
-    }
-    case VIR_TYPED_PARAM_DOUBLE:
-    {
-        double val;
-        if (libvirt_doubleUnwrap(value, &val) < 0 ||
-            virTypedParamsAddDouble(params, n, max, keystr, val) < 0)
-            goto cleanup;
-        break;
-    }
-    case VIR_TYPED_PARAM_BOOLEAN:
-    {
-        bool val;
-        if (libvirt_boolUnwrap(value, &val) < 0 ||
-            virTypedParamsAddBoolean(params, n, max, keystr, val) < 0)
-            goto cleanup;
-        break;
-    }
-    case VIR_TYPED_PARAM_STRING:
-    {
-        char *val;;
-        if (libvirt_charPtrUnwrap(value, &val) < 0 ||
-            !val ||
-            virTypedParamsAddString(params, n, max, keystr, val) < 0) {
-            VIR_FREE(val);
-            goto cleanup;
-        }
-        VIR_FREE(val);
-        break;
-    }
-    case VIR_TYPED_PARAM_LAST:
-        break; /* unreachable */
-    }
-
-    rv = 0;
-
- cleanup:
-    return rv;
-}
-
-
-/* Automatically convert dict into type parameters based on types reported
- * by python. All integer types are converted into LLONG (in case of a negative
- * value) or ULLONG (in case of a positive value). If you need different
- * handling, use @hints to explicitly specify what types should be used for
- * specific parameters.
- */
-static int
-ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
-virPyDictToTypedParams(PyObject *dict,
-                       virTypedParameterPtr *ret_params,
-                       int *ret_nparams,
-                       virPyTypedParamsHintPtr hints,
-                       int nhints)
-{
-    PyObject *key;
-    PyObject *value;
-#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 4
-    int pos = 0;
-#else
-    Py_ssize_t pos = 0;
-#endif
-    virTypedParameterPtr params = NULL;
-    int n = 0;
-    int max = 0;
-    int ret = -1;
-    char *keystr = NULL;
-
-    *ret_params = NULL;
-    *ret_nparams = 0;
-
-    if (PyDict_Size(dict) < 0)
-        return -1;
-
-    while (PyDict_Next(dict, &pos, &key, &value)) {
-        if (libvirt_charPtrUnwrap(key, &keystr) < 0 ||
-            !keystr)
-            goto cleanup;
-
-        if (PyList_Check(value) || PyTuple_Check(value)) {
-            Py_ssize_t i, size = PySequence_Size(value);
-
-            for (i = 0; i < size; i++) {
-                PyObject *v = PySequence_ITEM(value, i);
-                if (virPyDictToTypedParamOne(&params, &n, &max,
-                                             hints, nhints, keystr, v) < 0)
-                    goto cleanup;
-            }
-        } else if (virPyDictToTypedParamOne(&params, &n, &max,
-                                            hints, nhints, keystr, value) < 0)
-            goto cleanup;
-
-        VIR_FREE(keystr);
-    }
-
-    *ret_params = params;
-    *ret_nparams = n;
-    params = NULL;
-    ret = 0;
-
-cleanup:
-    VIR_FREE(keystr);
-    virTypedParamsFree(params, n);
-    return ret;
-}
-#endif /* LIBVIR_CHECK_VERSION(1, 1, 0) */
-
 
 /*
  * Utility function to retrieve the number of node CPUs present.
diff --git a/libvirt-qemu-override.c b/libvirt-qemu-override.c
index ce6f4fd..c082324 100644
--- a/libvirt-qemu-override.c
+++ b/libvirt-qemu-override.c
@@ -47,13 +47,6 @@ extern void initcygvirtmod_qemu(void);
    do {} while (0)
 #endif
 
-/* The two-statement sequence "Py_INCREF(Py_None); return Py_None;"
-   is so common that we encapsulate it here.  Now, each use is simply
-   return VIR_PY_NONE;  */
-#define VIR_PY_NONE (Py_INCREF (Py_None), Py_None)
-#define VIR_PY_INT_FAIL (libvirt_intWrap(-1))
-#define VIR_PY_INT_SUCCESS (libvirt_intWrap(0))
-
 /*******************************************
  * Helper functions to avoid importing modules
  * for every callback
diff --git a/libvirt-utils.c b/libvirt-utils.c
index d1f6e70..651d74f 100644
--- a/libvirt-utils.c
+++ b/libvirt-utils.c
@@ -19,12 +19,21 @@
  *
  */
 
+#include <Python.h>
+
+/* Ugly python defines that, which is also defined in errno.h */
+#undef _POSIC_C_SOURCE
+
+/* We want to see *_LAST enums.  */
+#define VIR_ENUM_SENTINELS
+
 #include <errno.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <libvirt/libvirt.h>
 #include "libvirt-utils.h"
+#include "typewrappers.h"
 
 /**
  * virAlloc:
@@ -184,3 +193,400 @@ virTypedParamsFree(virTypedParameterPtr params,
     VIR_FREE(params);
 }
 #endif /* ! LIBVIR_CHECK_VERSION(1, 0, 2) */
+
+char *
+py_str(PyObject *obj)
+{
+    PyObject *str = PyObject_Str(obj);
+    char *ret;
+    if (!str) {
+        PyErr_Print();
+        PyErr_Clear();
+        return NULL;
+    };
+    libvirt_charPtrUnwrap(str, &ret);
+    return ret;
+}
+
+/* Helper function to convert a virTypedParameter output array into a
+ * Python dictionary for return to the user.  Return NULL on failure,
+ * after raising a python exception.  */
+PyObject *
+getPyVirTypedParameter(const virTypedParameter *params,
+                       int nparams)
+{
+    PyObject *key, *val, *info;
+    size_t i;
+
+    if ((info = PyDict_New()) == NULL)
+        return NULL;
+
+    for (i = 0; i < nparams; i++) {
+        switch (params[i].type) {
+        case VIR_TYPED_PARAM_INT:
+            val = libvirt_intWrap(params[i].value.i);
+            break;
+
+        case VIR_TYPED_PARAM_UINT:
+            val = libvirt_intWrap(params[i].value.ui);
+            break;
+
+        case VIR_TYPED_PARAM_LLONG:
+            val = libvirt_longlongWrap(params[i].value.l);
+            break;
+
+        case VIR_TYPED_PARAM_ULLONG:
+            val = libvirt_ulonglongWrap(params[i].value.ul);
+            break;
+
+        case VIR_TYPED_PARAM_DOUBLE:
+            val = PyFloat_FromDouble(params[i].value.d);
+            break;
+
+        case VIR_TYPED_PARAM_BOOLEAN:
+            val = PyBool_FromLong(params[i].value.b);
+            break;
+
+        case VIR_TYPED_PARAM_STRING:
+            val = libvirt_constcharPtrWrap(params[i].value.s);
+            break;
+
+        default:
+            /* Possible if a newer server has a bug and sent stuff we
+             * don't recognize.  */
+            PyErr_Format(PyExc_LookupError,
+                         "Type value \"%d\" not recognized",
+                         params[i].type);
+            val = NULL;
+            break;
+        }
+
+        key = libvirt_constcharPtrWrap(params[i].field);
+        if (!key || !val)
+            goto cleanup;
+
+        if (PyDict_SetItem(info, key, val) < 0) {
+            Py_DECREF(info);
+            goto cleanup;
+        }
+
+        Py_DECREF(key);
+        Py_DECREF(val);
+    }
+    return info;
+
+ cleanup:
+    Py_XDECREF(key);
+    Py_XDECREF(val);
+    return NULL;
+}
+
+/* Allocate a new typed parameter array with the same contents and
+ * length as info, and using the array params of length nparams as
+ * hints on what types to use when creating the new array. The caller
+ * must clear the array before freeing it. Return NULL on failure,
+ * after raising a python exception.  */
+virTypedParameterPtr
+setPyVirTypedParameter(PyObject *info,
+                       const virTypedParameter *params,
+                       int nparams)
+{
+    PyObject *key, *value;
+#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 4
+    int pos = 0;
+#else
+    Py_ssize_t pos = 0;
+#endif
+    virTypedParameterPtr temp = NULL, ret = NULL;
+    Py_ssize_t size;
+    size_t i;
+
+    if ((size = PyDict_Size(info)) < 0)
+        return NULL;
+
+    /* Libvirt APIs use NULL array and 0 size as a special case;
+     * setting should have at least one parameter.  */
+    if (size == 0) {
+        PyErr_Format(PyExc_LookupError, "Dictionary must not be empty");
+        return NULL;
+    }
+
+    if (VIR_ALLOC_N(ret, size) < 0) {
+        PyErr_NoMemory();
+        return NULL;
+    }
+
+    temp = &ret[0];
+    while (PyDict_Next(info, &pos, &key, &value)) {
+        char *keystr = NULL;
+
+        if (libvirt_charPtrUnwrap(key, &keystr) < 0 ||
+            keystr == NULL)
+            goto cleanup;
+
+        for (i = 0; i < nparams; i++) {
+            if (STREQ(params[i].field, keystr))
+                break;
+        }
+        if (i == nparams) {
+            PyErr_Format(PyExc_LookupError,
+                         "Attribute name \"%s\" could not be recognized",
+                         keystr);
+            VIR_FREE(keystr);
+            goto cleanup;
+        }
+
+        strncpy(temp->field, keystr, VIR_TYPED_PARAM_FIELD_LENGTH - 1);
+        temp->type = params[i].type;
+        VIR_FREE(keystr);
+
+        switch (params[i].type) {
+        case VIR_TYPED_PARAM_INT:
+            if (libvirt_intUnwrap(value, &temp->value.i) < 0)
+                goto cleanup;
+            break;
+
+        case VIR_TYPED_PARAM_UINT:
+            if (libvirt_uintUnwrap(value, &temp->value.ui) < 0)
+                goto cleanup;
+            break;
+
+        case VIR_TYPED_PARAM_LLONG:
+            if (libvirt_longlongUnwrap(value, &temp->value.l) < 0)
+                goto cleanup;
+            break;
+
+        case VIR_TYPED_PARAM_ULLONG:
+            if (libvirt_ulonglongUnwrap(value, &temp->value.ul) < 0)
+                goto cleanup;
+            break;
+
+        case VIR_TYPED_PARAM_DOUBLE:
+            if (libvirt_doubleUnwrap(value, &temp->value.d) < 0)
+                goto cleanup;
+            break;
+
+        case VIR_TYPED_PARAM_BOOLEAN:
+        {
+            bool b;
+            if (libvirt_boolUnwrap(value, &b) < 0)
+                goto cleanup;
+            temp->value.b = b;
+            break;
+        }
+        case VIR_TYPED_PARAM_STRING:
+        {
+            char *string_val;
+            if (libvirt_charPtrUnwrap(value, &string_val) < 0 ||
+                !string_val)
+                goto cleanup;
+            temp->value.s = string_val;
+            break;
+        }
+
+        default:
+            /* Possible if a newer server has a bug and sent stuff we
+             * don't recognize.  */
+            PyErr_Format(PyExc_LookupError,
+                         "Type value \"%d\" not recognized",
+                         params[i].type);
+            goto cleanup;
+        }
+
+        temp++;
+    }
+    return ret;
+
+cleanup:
+    virTypedParamsFree(ret, size);
+    return NULL;
+}
+
+
+/* While these appeared in libvirt in 1.0.2, we only
+ * need them in the python from 1.1.0 onwards */
+#if LIBVIR_CHECK_VERSION(1, 1, 0)
+int
+virPyDictToTypedParamOne(virTypedParameterPtr *params,
+                         int *n,
+                         int *max,
+                         virPyTypedParamsHintPtr hints,
+                         int nhints,
+                         const char *keystr,
+                         PyObject *value)
+{
+    int rv = -1, type = -1;
+    size_t i;
+
+    for (i = 0; i < nhints; i++) {
+        if (STREQ(hints[i].name, keystr)) {
+            type = hints[i].type;
+            break;
+        }
+    }
+
+    if (type == -1) {
+        if (libvirt_PyString_Check(value)) {
+            type = VIR_TYPED_PARAM_STRING;
+        } else if (PyBool_Check(value)) {
+            type = VIR_TYPED_PARAM_BOOLEAN;
+        } else if (PyLong_Check(value)) {
+            unsigned long long ull = PyLong_AsUnsignedLongLong(value);
+            if (ull == (unsigned long long) -1 && PyErr_Occurred())
+                type = VIR_TYPED_PARAM_LLONG;
+            else
+                type = VIR_TYPED_PARAM_ULLONG;
+#if PY_MAJOR_VERSION < 3
+        } else if (PyInt_Check(value)) {
+            if (PyInt_AS_LONG(value) < 0)
+                type = VIR_TYPED_PARAM_LLONG;
+            else
+                type = VIR_TYPED_PARAM_ULLONG;
+#endif
+        } else if (PyFloat_Check(value)) {
+            type = VIR_TYPED_PARAM_DOUBLE;
+        }
+    }
+
+    if (type == -1) {
+        PyErr_Format(PyExc_TypeError,
+                     "Unknown type of \"%s\" field", keystr);
+        goto cleanup;
+    }
+
+    switch ((virTypedParameterType) type) {
+    case VIR_TYPED_PARAM_INT:
+    {
+        int val;
+        if (libvirt_intUnwrap(value, &val) < 0 ||
+            virTypedParamsAddInt(params, n, max, keystr, val) < 0)
+            goto cleanup;
+        break;
+    }
+    case VIR_TYPED_PARAM_UINT:
+    {
+        unsigned int val;
+        if (libvirt_uintUnwrap(value, &val) < 0 ||
+            virTypedParamsAddUInt(params, n, max, keystr, val) < 0)
+            goto cleanup;
+        break;
+    }
+    case VIR_TYPED_PARAM_LLONG:
+    {
+        long long val;
+        if (libvirt_longlongUnwrap(value, &val) < 0 ||
+            virTypedParamsAddLLong(params, n, max, keystr, val) < 0)
+            goto cleanup;
+        break;
+    }
+    case VIR_TYPED_PARAM_ULLONG:
+    {
+        unsigned long long val;
+        if (libvirt_ulonglongUnwrap(value, &val) < 0 ||
+            virTypedParamsAddULLong(params, n, max, keystr, val) < 0)
+            goto cleanup;
+        break;
+    }
+    case VIR_TYPED_PARAM_DOUBLE:
+    {
+        double val;
+        if (libvirt_doubleUnwrap(value, &val) < 0 ||
+            virTypedParamsAddDouble(params, n, max, keystr, val) < 0)
+            goto cleanup;
+        break;
+    }
+    case VIR_TYPED_PARAM_BOOLEAN:
+    {
+        bool val;
+        if (libvirt_boolUnwrap(value, &val) < 0 ||
+            virTypedParamsAddBoolean(params, n, max, keystr, val) < 0)
+            goto cleanup;
+        break;
+    }
+    case VIR_TYPED_PARAM_STRING:
+    {
+        char *val;;
+        if (libvirt_charPtrUnwrap(value, &val) < 0 ||
+            !val ||
+            virTypedParamsAddString(params, n, max, keystr, val) < 0) {
+            VIR_FREE(val);
+            goto cleanup;
+        }
+        VIR_FREE(val);
+        break;
+    }
+    case VIR_TYPED_PARAM_LAST:
+        break; /* unreachable */
+    }
+
+    rv = 0;
+
+ cleanup:
+    return rv;
+}
+
+
+/* Automatically convert dict into type parameters based on types reported
+ * by python. All integer types are converted into LLONG (in case of a negative
+ * value) or ULLONG (in case of a positive value). If you need different
+ * handling, use @hints to explicitly specify what types should be used for
+ * specific parameters.
+ */
+int
+virPyDictToTypedParams(PyObject *dict,
+                       virTypedParameterPtr *ret_params,
+                       int *ret_nparams,
+                       virPyTypedParamsHintPtr hints,
+                       int nhints)
+{
+    PyObject *key;
+    PyObject *value;
+#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 4
+    int pos = 0;
+#else
+    Py_ssize_t pos = 0;
+#endif
+    virTypedParameterPtr params = NULL;
+    int n = 0;
+    int max = 0;
+    int ret = -1;
+    char *keystr = NULL;
+
+    *ret_params = NULL;
+    *ret_nparams = 0;
+
+    if (PyDict_Size(dict) < 0)
+        return -1;
+
+    while (PyDict_Next(dict, &pos, &key, &value)) {
+        if (libvirt_charPtrUnwrap(key, &keystr) < 0 ||
+            !keystr)
+            goto cleanup;
+
+        if (PyList_Check(value) || PyTuple_Check(value)) {
+            Py_ssize_t i, size = PySequence_Size(value);
+
+            for (i = 0; i < size; i++) {
+                PyObject *v = PySequence_ITEM(value, i);
+                if (virPyDictToTypedParamOne(&params, &n, &max,
+                                             hints, nhints, keystr, v) < 0)
+                    goto cleanup;
+            }
+        } else if (virPyDictToTypedParamOne(&params, &n, &max,
+                                            hints, nhints, keystr, value) < 0)
+            goto cleanup;
+
+        VIR_FREE(keystr);
+    }
+
+    *ret_params = params;
+    *ret_nparams = n;
+    params = NULL;
+    ret = 0;
+
+cleanup:
+    VIR_FREE(keystr);
+    virTypedParamsFree(params, n);
+    return ret;
+}
+#endif /* LIBVIR_CHECK_VERSION(1, 1, 0) */
diff --git a/libvirt-utils.h b/libvirt-utils.h
index bef5489..9f80133 100644
--- a/libvirt-utils.h
+++ b/libvirt-utils.h
@@ -22,6 +22,9 @@
 #ifndef __LIBVIRT_UTILS_H__
 # define __LIBVIRT_UTILS_H__
 
+# include <Python.h>
+# include <libvirt/libvirt.h>
+
 # define STREQ(a,b) (strcmp(a,b) == 0)
 
 # ifndef MIN
@@ -135,6 +138,22 @@ int virReallocN(void *ptrptr, size_t size, size_t count)
     ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1);
 void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1);
 
+
+# if PY_MAJOR_VERSION > 2
+#  define libvirt_PyString_Check PyUnicode_Check
+# else
+#  define libvirt_PyString_Check PyString_Check
+# endif
+
+
+/* The two-statement sequence "Py_INCREF(Py_None); return Py_None;"
+   is so common that we encapsulate it here.  Now, each use is simply
+   return VIR_PY_NONE;  */
+#define VIR_PY_NONE (Py_INCREF (Py_None), Py_None)
+#define VIR_PY_INT_FAIL (libvirt_intWrap(-1))
+#define VIR_PY_INT_SUCCESS (libvirt_intWrap(0))
+
+
 /**
  * VIR_ALLOC:
  * @ptr: pointer to hold address of allocated memory
@@ -216,4 +235,36 @@ void virTypedParamsClear(virTypedParameterPtr params, int nparams);
 void virTypedParamsFree(virTypedParameterPtr params, int nparams);
 # endif /* ! LIBVIR_CHECK_VERSION(1, 0, 2) */
 
+char * py_str(PyObject *obj);
+PyObject * getPyVirTypedParameter(const virTypedParameter *params,
+                                  int nparams);
+virTypedParameterPtr setPyVirTypedParameter(PyObject *info,
+                                            const virTypedParameter *params,
+                                            int nparams)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
+
+# if LIBVIR_CHECK_VERSION(1, 1, 0)
+typedef struct {
+    const char *name;
+    int type;
+} virPyTypedParamsHint;
+typedef virPyTypedParamsHint *virPyTypedParamsHintPtr;
+
+
+int virPyDictToTypedPramaOne(virTypedParameterPtr *params,
+                             int *n,
+                             int *max,
+                             virPyTypedParamsHintPtr hints,
+                             int nhints,
+                             const char *keystr,
+                             PyObject *value);
+int virPyDictToTypedParams(PyObject *dict,
+                           virTypedParameterPtr *ret_params,
+                           int *ret_nparams,
+                           virPyTypedParamsHintPtr hints,
+                           int nhints)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+# endif /* LIBVIR_CHECK_VERSION(1, 1, 0) */
+
 #endif /* __LIBVIRT_UTILS_H__ */
-- 
2.5.3




More information about the libvir-list mailing list