summaryrefslogtreecommitdiffstats
path: root/generator/python.ml
diff options
context:
space:
mode:
Diffstat (limited to 'generator/python.ml')
-rw-r--r--generator/python.ml769
1 files changed, 769 insertions, 0 deletions
diff --git a/generator/python.ml b/generator/python.ml
new file mode 100644
index 00000000..482b189e
--- /dev/null
+++ b/generator/python.ml
@@ -0,0 +1,769 @@
+(* libguestfs
+ * Copyright (C) 2009-2012 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *)
+
+(* Please read generator/README first. *)
+
+open Printf
+
+open Types
+open Utils
+open Pr
+open Docstrings
+open Optgroups
+open Actions
+open Structs
+open C
+open Events
+
+(* Generate Python C module. *)
+let rec generate_python_c () =
+ generate_header CStyle LGPLv2plus;
+
+ pr "\
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include \"guestfs-py.h\"
+
+/* This list should be freed (but not the strings) after use. */
+static char **
+get_string_list (PyObject *obj)
+{
+ size_t i, len;
+ char **r;
+#ifndef HAVE_PYSTRING_ASSTRING
+ PyObject *bytes;
+#endif
+
+ assert (obj);
+
+ if (!PyList_Check (obj)) {
+ PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
+ return NULL;
+ }
+
+ Py_ssize_t slen = PyList_Size (obj);
+ if (slen == -1) {
+ PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
+ return NULL;
+ }
+ len = (size_t) slen;
+ r = malloc (sizeof (char *) * (len+1));
+ if (r == NULL) {
+ PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
+ return NULL;
+ }
+
+ for (i = 0; i < len; ++i) {
+#ifdef HAVE_PYSTRING_ASSTRING
+ r[i] = PyString_AsString (PyList_GetItem (obj, i));
+#else
+ bytes = PyUnicode_AsUTF8String (PyList_GetItem (obj, i));
+ r[i] = PyBytes_AS_STRING (bytes);
+#endif
+ }
+ r[len] = NULL;
+
+ return r;
+}
+
+static PyObject *
+put_string_list (char * const * const argv)
+{
+ PyObject *list;
+ size_t argc, i;
+
+ for (argc = 0; argv[argc] != NULL; ++argc)
+ ;
+
+ list = PyList_New (argc);
+ for (i = 0; i < argc; ++i) {
+#ifdef HAVE_PYSTRING_ASSTRING
+ PyList_SetItem (list, i, PyString_FromString (argv[i]));
+#else
+ PyList_SetItem (list, i, PyUnicode_FromString (argv[i]));
+#endif
+ }
+
+ return list;
+}
+
+static PyObject *
+put_table (char * const * const argv)
+{
+ PyObject *list, *item;
+ size_t argc, i;
+
+ for (argc = 0; argv[argc] != NULL; ++argc)
+ ;
+
+ list = PyList_New (argc >> 1);
+ for (i = 0; i < argc; i += 2) {
+ item = PyTuple_New (2);
+#ifdef HAVE_PYSTRING_ASSTRING
+ PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
+ PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
+#else
+ PyTuple_SetItem (item, 0, PyUnicode_FromString (argv[i]));
+ PyTuple_SetItem (item, 1, PyUnicode_FromString (argv[i+1]));
+#endif
+ PyList_SetItem (list, i >> 1, item);
+ }
+
+ return list;
+}
+
+static void
+free_strings (char **argv)
+{
+ size_t argc;
+
+ for (argc = 0; argv[argc] != NULL; ++argc)
+ free (argv[argc]);
+ free (argv);
+}
+
+";
+
+ let emit_put_list_function typ =
+ pr "static PyObject *\n";
+ pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
+ pr "{\n";
+ pr " PyObject *list;\n";
+ pr " size_t i;\n";
+ pr "\n";
+ pr " list = PyList_New (%ss->len);\n" typ;
+ pr " for (i = 0; i < %ss->len; ++i)\n" typ;
+ pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
+ pr " return list;\n";
+ pr "};\n";
+ pr "\n"
+ in
+
+ (* Structures, turned into Python dictionaries. *)
+ List.iter (
+ fun (typ, cols) ->
+ pr "static PyObject *\n";
+ pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
+ pr "{\n";
+ pr " PyObject *dict;\n";
+ pr "\n";
+ pr " dict = PyDict_New ();\n";
+ List.iter (
+ function
+ | name, FString ->
+ pr " PyDict_SetItemString (dict, \"%s\",\n" name;
+ pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
+ pr " PyString_FromString (%s->%s));\n"
+ typ name;
+ pr "#else\n";
+ pr " PyUnicode_FromString (%s->%s));\n"
+ typ name;
+ pr "#endif\n"
+ | name, FBuffer ->
+ pr " PyDict_SetItemString (dict, \"%s\",\n" name;
+ pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
+ pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
+ typ name typ name;
+ pr "#else\n";
+ pr " PyBytes_FromStringAndSize (%s->%s, %s->%s_len));\n"
+ typ name typ name;
+ pr "#endif\n"
+ | name, FUUID ->
+ pr " PyDict_SetItemString (dict, \"%s\",\n" name;
+ pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
+ pr " PyString_FromStringAndSize (%s->%s, 32));\n"
+ typ name;
+ pr "#else\n";
+ pr " PyBytes_FromStringAndSize (%s->%s, 32));\n"
+ typ name;
+ pr "#endif\n"
+ | name, (FBytes|FUInt64) ->
+ pr " PyDict_SetItemString (dict, \"%s\",\n" name;
+ pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
+ typ name
+ | name, FInt64 ->
+ pr " PyDict_SetItemString (dict, \"%s\",\n" name;
+ pr " PyLong_FromLongLong (%s->%s));\n"
+ typ name
+ | name, FUInt32 ->
+ pr " PyDict_SetItemString (dict, \"%s\",\n" name;
+ pr " PyLong_FromUnsignedLong (%s->%s));\n"
+ typ name
+ | name, FInt32 ->
+ pr " PyDict_SetItemString (dict, \"%s\",\n" name;
+ pr " PyLong_FromLong (%s->%s));\n"
+ typ name
+ | name, FOptPercent ->
+ pr " if (%s->%s >= 0)\n" typ name;
+ pr " PyDict_SetItemString (dict, \"%s\",\n" name;
+ pr " PyFloat_FromDouble ((double) %s->%s));\n"
+ typ name;
+ pr " else {\n";
+ pr " Py_INCREF (Py_None);\n";
+ pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
+ pr " }\n"
+ | name, FChar ->
+ pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
+ pr " PyDict_SetItemString (dict, \"%s\",\n" name;
+ pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name;
+ pr "#else\n";
+ pr " PyDict_SetItemString (dict, \"%s\",\n" name;
+ pr " PyUnicode_FromStringAndSize (&dirent->%s, 1));\n" name;
+ pr "#endif\n"
+ ) cols;
+ pr " return dict;\n";
+ pr "};\n";
+ pr "\n";
+
+ ) structs;
+
+ (* Emit a put_TYPE_list function definition only if that function is used. *)
+ List.iter (
+ function
+ | typ, (RStructListOnly | RStructAndList) ->
+ (* generate the function for typ *)
+ emit_put_list_function typ
+ | typ, _ -> () (* empty *)
+ ) (rstructs_used_by all_functions);
+
+ (* Python wrapper functions. *)
+ List.iter (
+ fun { name = name; style = (ret, args, optargs as style);
+ c_function = c_function; c_optarg_prefix = c_optarg_prefix } ->
+ pr "static PyObject *\n";
+ pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
+ pr "{\n";
+
+ pr " PyThreadState *py_save = NULL;\n";
+ pr " PyObject *py_g;\n";
+ pr " guestfs_h *g;\n";
+ pr " PyObject *py_r;\n";
+
+ if optargs <> [] then (
+ pr " struct %s optargs_s;\n" c_function;
+ pr " struct %s *optargs = &optargs_s;\n" c_function;
+ );
+
+ (match ret with
+ | RErr | RInt _ | RBool _ -> pr " int r;\n"
+ | RInt64 _ -> pr " int64_t r;\n"
+ | RConstString _ | RConstOptString _ ->
+ pr " const char *r;\n"
+ | RString _ -> pr " char *r;\n"
+ | RStringList _ | RHashtable _ -> pr " char **r;\n"
+ | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
+ | RStructList (_, typ) ->
+ pr " struct guestfs_%s_list *r;\n" typ
+ | RBufferOut _ ->
+ pr " char *r;\n";
+ pr " size_t size;\n"
+ );
+
+ List.iter (
+ function
+ | Pathname n | Device n | Dev_or_Path n | String n | Key n
+ | FileIn n | FileOut n ->
+ pr " const char *%s;\n" n
+ | OptString n -> pr " const char *%s;\n" n
+ | BufferIn n ->
+ pr " const char *%s;\n" n;
+ pr " Py_ssize_t %s_size;\n" n
+ | StringList n | DeviceList n ->
+ pr " PyObject *py_%s;\n" n;
+ pr " char **%s;\n" n
+ | Bool n -> pr " int %s;\n" n
+ | Int n -> pr " int %s;\n" n
+ | Int64 n -> pr " long long %s;\n" n
+ | Pointer (t, n) ->
+ pr " long long %s_int64;\n" n;
+ pr " %s %s;\n" t n
+ ) args;
+
+ (* Fetch the optional arguments as objects, so we can detect
+ * if they are 'None'.
+ *)
+ List.iter (
+ fun optarg ->
+ pr " PyObject *py_%s;\n" (name_of_optargt optarg)
+ ) optargs;
+
+ pr "\n";
+
+ if optargs <> [] then (
+ pr " optargs_s.bitmask = 0;\n";
+ pr "\n"
+ );
+
+ (* Convert the required parameters. *)
+ pr " if (!PyArg_ParseTuple (args, (char *) \"O";
+ List.iter (
+ function
+ | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
+ | FileIn _ | FileOut _ -> pr "s"
+ | OptString _ -> pr "z"
+ | StringList _ | DeviceList _ -> pr "O"
+ | Bool _ -> pr "i" (* XXX Python has booleans? *)
+ | Int _ -> pr "i"
+ | Int64 _ | Pointer _ ->
+ (* XXX Whoever thought it was a good idea to
+ * emulate C's int/long/long long in Python?
+ *)
+ pr "L"
+ | BufferIn _ -> pr "s#"
+ ) args;
+
+ (* Optional parameters. All objects, so we can detect None. *)
+ List.iter (fun _ -> pr "O") optargs;
+
+ pr ":guestfs_%s\",\n" name;
+ pr " &py_g";
+ List.iter (
+ function
+ | Pathname n | Device n | Dev_or_Path n | String n | Key n
+ | FileIn n | FileOut n -> pr ", &%s" n
+ | OptString n -> pr ", &%s" n
+ | StringList n | DeviceList n -> pr ", &py_%s" n
+ | Bool n -> pr ", &%s" n
+ | Int n -> pr ", &%s" n
+ | Int64 n -> pr ", &%s" n
+ | Pointer (_, n) -> pr ", &%s_int64" n
+ | BufferIn n -> pr ", &%s, &%s_size" n n
+ ) args;
+
+ List.iter (
+ fun optarg ->
+ pr ", &py_%s" (name_of_optargt optarg)
+ ) optargs;
+
+ pr "))\n";
+ pr " return NULL;\n";
+
+ pr " g = get_handle (py_g);\n";
+ List.iter (
+ function
+ | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
+ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
+ | BufferIn _ -> ()
+ | StringList n | DeviceList n ->
+ pr " %s = get_string_list (py_%s);\n" n n;
+ pr " if (!%s) return NULL;\n" n
+ | Pointer (t, n) ->
+ pr " %s = (%s) (intptr_t) %s_int64;\n" n t n
+ ) args;
+
+ pr "\n";
+
+ if optargs <> [] then (
+ List.iter (
+ fun optarg ->
+ let n = name_of_optargt optarg in
+ let uc_n = String.uppercase n in
+ pr " if (py_%s != Py_None) {\n" n;
+ pr " optargs_s.bitmask |= %s_%s_BITMASK;\n" c_optarg_prefix uc_n;
+ (match optarg with
+ | OBool _ | OInt _ ->
+ pr " optargs_s.%s = PyInt_AsLong (py_%s);\n" n n;
+ pr " if (PyErr_Occurred ()) return NULL;\n"
+ | OInt64 _ ->
+ pr " optargs_s.%s = PyLong_AsLongLong (py_%s);\n" n n;
+ pr " if (PyErr_Occurred ()) return NULL;\n"
+ | OString _ ->
+ pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
+ pr " optargs_s.%s = PyString_AsString (py_%s);\n" n n;
+ pr "#else\n";
+ pr " PyObject *bytes;\n";
+ pr " bytes = PyUnicode_AsUTF8String (py_%s);\n" n;
+ pr " optargs_s.%s = PyBytes_AS_STRING (bytes);\n" n;
+ pr "#endif\n";
+ | OStringList _ ->
+ pr " optargs_s.%s = get_string_list (py_%s);\n" n n;
+ pr " if (!optargs_s.%s) return NULL;\n" n;
+ );
+ pr " }\n";
+ ) optargs;
+ pr "\n"
+ );
+
+ (* Release Python GIL while running. This code is from
+ * libvirt/python/typewrappers.h. Thanks to Dan Berrange for
+ * showing us how to do this properly.
+ *)
+ pr " if (PyEval_ThreadsInitialized ())\n";
+ pr " py_save = PyEval_SaveThread ();\n";
+ pr "\n";
+
+ pr " r = %s " c_function;
+ generate_c_call_args ~handle:"g" style;
+ pr ";\n";
+
+ pr "\n";
+ pr " if (PyEval_ThreadsInitialized ())\n";
+ pr " PyEval_RestoreThread (py_save);\n";
+ pr "\n";
+
+ List.iter (
+ function
+ | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
+ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
+ | BufferIn _ | Pointer _ -> ()
+ | StringList n | DeviceList n ->
+ pr " free (%s);\n" n
+ ) args;
+
+ List.iter (
+ function
+ | OBool _ | OInt _ | OInt64 _ | OString _ -> ()
+ | OStringList n ->
+ pr " if (py_%s != Py_None)\n" n;
+ pr " free ((char **) optargs_s.%s);\n" n
+ ) optargs;
+
+ (match errcode_of_ret ret with
+ | `CannotReturnError -> ()
+ | `ErrorIsMinusOne ->
+ pr " if (r == -1) {\n";
+ pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
+ pr " return NULL;\n";
+ pr " }\n"
+ | `ErrorIsNULL ->
+ pr " if (r == NULL) {\n";
+ pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
+ pr " return NULL;\n";
+ pr " }\n"
+ );
+ pr "\n";
+
+ (match ret with
+ | RErr ->
+ pr " Py_INCREF (Py_None);\n";
+ pr " py_r = Py_None;\n"
+ | RInt _
+ | RBool _ -> pr " py_r = PyLong_FromLong ((long) r);\n"
+ | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
+ | RConstString _ ->
+ pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
+ pr " py_r = PyString_FromString (r);\n";
+ pr "#else\n";
+ pr " py_r = PyUnicode_FromString (r);\n";
+ pr "#endif\n"
+ | RConstOptString _ ->
+ pr " if (r) {\n";
+ pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
+ pr " py_r = PyString_FromString (r);\n";
+ pr "#else\n";
+ pr " py_r = PyUnicode_FromString (r);\n";
+ pr "#endif\n";
+ pr " } else {\n";
+ pr " Py_INCREF (Py_None);\n";
+ pr " py_r = Py_None;\n";
+ pr " }\n"
+ | RString _ ->
+ pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
+ pr " py_r = PyString_FromString (r);\n";
+ pr "#else\n";
+ pr " py_r = PyUnicode_FromString (r);\n";
+ pr "#endif\n";
+ pr " free (r);\n"
+ | RStringList _ ->
+ pr " py_r = put_string_list (r);\n";
+ pr " free_strings (r);\n"
+ | RStruct (_, typ) ->
+ pr " py_r = put_%s (r);\n" typ;
+ pr " guestfs_free_%s (r);\n" typ
+ | RStructList (_, typ) ->
+ pr " py_r = put_%s_list (r);\n" typ;
+ pr " guestfs_free_%s_list (r);\n" typ
+ | RHashtable n ->
+ pr " py_r = put_table (r);\n";
+ pr " free_strings (r);\n"
+ | RBufferOut _ ->
+ pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
+ pr " py_r = PyString_FromStringAndSize (r, size);\n";
+ pr "#else\n";
+ pr " py_r = PyBytes_FromStringAndSize (r, size);\n";
+ pr "#endif\n";
+ pr " free (r);\n"
+ );
+
+ pr " return py_r;\n";
+ pr "}\n";
+ pr "\n"
+ ) all_functions;
+
+ (* Table of functions. *)
+ pr "static PyMethodDef methods[] = {\n";
+ pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
+ pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
+ pr " { (char *) \"set_event_callback\",\n";
+ pr " py_guestfs_set_event_callback, METH_VARARGS, NULL },\n";
+ pr " { (char *) \"delete_event_callback\",\n";
+ pr " py_guestfs_delete_event_callback, METH_VARARGS, NULL },\n";
+ List.iter (
+ fun { name = name } ->
+ pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
+ name name
+ ) all_functions;
+ pr " { NULL, NULL, 0, NULL }\n";
+ pr "};\n";
+ pr "\n";
+
+ (* Init function. *)
+ pr "\
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ \"libguestfsmod\", /* m_name */
+ \"libguestfs module\", /* m_doc */
+ -1, /* m_size */
+ methods, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
+#endif
+
+static PyObject *
+moduleinit (void)
+{
+ PyObject *m;
+
+#if PY_MAJOR_VERSION >= 3
+ m = PyModule_Create (&moduledef);
+#else
+ m = Py_InitModule ((char *) \"libguestfsmod\", methods);
+#endif
+
+ return m; /* m might be NULL if module init failed */
+}
+
+#if PY_MAJOR_VERSION >= 3
+PyMODINIT_FUNC
+PyInit_libguestfsmod (void)
+{
+ return moduleinit ();
+}
+#else
+void
+initlibguestfsmod (void)
+{
+ (void) moduleinit ();
+}
+#endif
+"
+
+(* Generate Python module. *)
+and generate_python_py () =
+ (* This has to appear very near the top of the file, before the large
+ * header.
+ *)
+ pr "# coding: utf-8\n";
+
+ generate_header HashStyle LGPLv2plus;
+
+ pr "\
+\"\"\"Python bindings for libguestfs
+
+import guestfs
+g = guestfs.GuestFS ()
+g.add_drive_opts (\"guest.img\", format=\"raw\")
+g.launch ()
+parts = g.list_partitions ()
+
+The guestfs module provides a Python binding to the libguestfs API
+for examining and modifying virtual machine disk images.
+
+Amongst the things this is good for: making batch configuration
+changes to guests, getting disk used/free statistics (see also:
+virt-df), migrating between virtualization systems (see also:
+virt-p2v), performing partial backups, performing partial guest
+clones, cloning guests and changing registry/UUID/hostname info, and
+much else besides.
+
+Libguestfs uses Linux kernel and qemu code, and can access any type of
+guest filesystem that Linux and qemu can, including but not limited
+to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
+schemes, qcow, qcow2, vmdk.
+
+Libguestfs provides ways to enumerate guest storage (eg. partitions,
+LVs, what filesystem is in each LV, etc.). It can also run commands
+in the context of the guest. Also you can access filesystems over
+FUSE.
+
+Errors which happen while using the API are turned into Python
+RuntimeError exceptions.
+
+To create a guestfs handle you usually have to perform the following
+sequence of calls:
+
+# Create the handle, call add_drive* at least once, and possibly
+# several times if the guest has multiple block devices:
+g = guestfs.GuestFS ()
+g.add_drive_opts (\"guest.img\", format=\"raw\")
+
+# Launch the qemu subprocess and wait for it to become ready:
+g.launch ()
+
+# Now you can issue commands, for example:
+logvols = g.lvs ()
+
+\"\"\"
+
+import libguestfsmod
+
+";
+
+ List.iter (
+ fun (name, bitmask) ->
+ pr "EVENT_%s = 0x%x\n" (String.uppercase name) bitmask
+ ) events;
+ pr "\n";
+
+ pr "\
+class ClosedHandle(ValueError):
+ pass
+
+class GuestFS:
+ \"\"\"Instances of this class are libguestfs API handles.\"\"\"
+
+ def __init__ (self):
+ \"\"\"Create a new libguestfs handle.\"\"\"
+ self._o = libguestfsmod.create ()
+
+ def __del__ (self):
+ if self._o:
+ libguestfsmod.close (self._o)
+
+ def _check_not_closed (self):
+ if not self._o:
+ raise ClosedHandle (\"GuestFS: method called on closed handle\")
+
+ def close (self):
+ \"\"\"Explicitly close the guestfs handle.
+
+ The handle is closed implicitly when its reference count goes
+ to zero (eg. when it goes out of scope or the program ends).
+
+ This call is only needed if you want to force the handle to
+ close now. After calling this, the program must not call
+ any method on the handle (except the implicit call to
+ __del__ which happens when the final reference is cleaned up).
+ \"\"\"
+ self._check_not_closed ()
+ libguestfsmod.close (self._o)
+ self._o = None
+
+ def set_event_callback (self, cb, event_bitmask):
+ \"\"\"Register an event callback.
+
+ Register \"cb\" as a callback function for all of the
+ events in \"event_bitmask\". \"event_bitmask\" should be
+ one or more \"guestfs.EVENT_*\" flags logically or'd together.
+
+ This function returns an event handle which can be used
+ to delete the callback (see \"delete_event_callback\").
+
+ The callback function receives 4 parameters:
+
+ cb (event, event_handle, buf, array)
+
+ \"event\" is one of the \"EVENT_*\" flags. \"buf\" is a
+ message buffer (only for some types of events). \"array\"
+ is an array of integers (only for some types of events).
+
+ You should read the documentation for
+ \"guestfs_set_event_callback\" in guestfs(3) before using
+ this function.
+ \"\"\"
+ self._check_not_closed ()
+ return libguestfsmod.set_event_callback (self._o, cb, event_bitmask)
+
+ def delete_event_callback (self, event_handle):
+ \"\"\"Delete an event callback.\"\"\"
+ self._check_not_closed ()
+ libguestfsmod.delete_event_callback (self._o, event_handle)
+
+";
+
+ List.iter (
+ fun ({ name = name; style = ret, args, optargs; in_docs = in_docs;
+ longdesc = longdesc; non_c_aliases = non_c_aliases } as f) ->
+ pr " def %s (self" name;
+ List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
+ List.iter (
+ fun optarg ->
+ pr ", %s=None" (name_of_optargt optarg)
+ ) optargs;
+ pr "):\n";
+
+ if in_docs then (
+ let doc = replace_str longdesc "C<guestfs_" "C<g." in
+ let doc =
+ match ret with
+ | RErr | RInt _ | RInt64 _ | RBool _
+ | RConstOptString _ | RConstString _
+ | RString _ | RBufferOut _ -> doc
+ | RStringList _ ->
+ doc ^ "\n\nThis function returns a list of strings."
+ | RStruct (_, typ) ->
+ doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
+ | RStructList (_, typ) ->
+ doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
+ | RHashtable _ ->
+ doc ^ "\n\nThis function returns a dictionary." in
+ let doc =
+ if f.protocol_limit_warning then
+ doc ^ "\n\n" ^ protocol_limit_warning
+ else doc in
+ let doc =
+ match deprecation_notice f with
+ | None -> doc
+ | Some txt -> doc ^ "\n\n" ^ txt in
+ let doc = pod2text ~width:60 name doc in
+ let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
+ let doc = String.concat "\n " doc in
+ pr " \"\"\"%s\"\"\"\n" doc;
+ );
+ (* Callers might pass in iterables instead of plain lists;
+ * convert those to plain lists because the C side of things
+ * cannot deal with iterables. (RHBZ#693306).
+ *)
+ List.iter (
+ function
+ | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
+ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
+ | BufferIn _ | Pointer _ -> ()
+ | StringList n | DeviceList n ->
+ pr " %s = list (%s)\n" n n
+ ) args;
+ pr " self._check_not_closed ()\n";
+ pr " return libguestfsmod.%s (self._o" name;
+ List.iter (fun arg -> pr ", %s" (name_of_argt arg))
+ (args @ args_of_optargs optargs);
+ pr ")\n\n";
+
+ (* Aliases. *)
+ List.iter (
+ fun alias ->
+ pr " %s = %s\n\n" alias name
+ ) non_c_aliases
+ ) all_functions