generator: Create a separate type for optional arguments
[libguestfs.git] / generator / generator_python.ml
1 (* libguestfs
2  * Copyright (C) 2009-2011 Red Hat Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  *)
18
19 (* Please read generator/README first. *)
20
21 open Printf
22
23 open Generator_types
24 open Generator_utils
25 open Generator_pr
26 open Generator_docstrings
27 open Generator_optgroups
28 open Generator_actions
29 open Generator_structs
30 open Generator_c
31 open Generator_events
32
33 (* Generate Python C module. *)
34 let rec generate_python_c () =
35   generate_header CStyle LGPLv2plus;
36
37   pr "\
38 #include <config.h>
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <assert.h>
43
44 #include \"guestfs-py.h\"
45
46 /* This list should be freed (but not the strings) after use. */
47 static char **
48 get_string_list (PyObject *obj)
49 {
50   size_t i, len;
51   char **r;
52 #ifndef HAVE_PYSTRING_ASSTRING
53   PyObject *bytes;
54 #endif
55
56   assert (obj);
57
58   if (!PyList_Check (obj)) {
59     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
60     return NULL;
61   }
62
63   Py_ssize_t slen = PyList_Size (obj);
64   if (slen == -1) {
65     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
66     return NULL;
67   }
68   len = (size_t) slen;
69   r = malloc (sizeof (char *) * (len+1));
70   if (r == NULL) {
71     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
72     return NULL;
73   }
74
75   for (i = 0; i < len; ++i) {
76 #ifdef HAVE_PYSTRING_ASSTRING
77     r[i] = PyString_AsString (PyList_GetItem (obj, i));
78 #else
79     bytes = PyUnicode_AsUTF8String (PyList_GetItem (obj, i));
80     r[i] = PyBytes_AS_STRING (bytes);
81 #endif
82   }
83   r[len] = NULL;
84
85   return r;
86 }
87
88 static PyObject *
89 put_string_list (char * const * const argv)
90 {
91   PyObject *list;
92   int argc, i;
93
94   for (argc = 0; argv[argc] != NULL; ++argc)
95     ;
96
97   list = PyList_New (argc);
98   for (i = 0; i < argc; ++i) {
99 #ifdef HAVE_PYSTRING_ASSTRING
100     PyList_SetItem (list, i, PyString_FromString (argv[i]));
101 #else
102     PyList_SetItem (list, i, PyUnicode_FromString (argv[i]));
103 #endif
104   }
105
106   return list;
107 }
108
109 static PyObject *
110 put_table (char * const * const argv)
111 {
112   PyObject *list, *item;
113   int argc, i;
114
115   for (argc = 0; argv[argc] != NULL; ++argc)
116     ;
117
118   list = PyList_New (argc >> 1);
119   for (i = 0; i < argc; i += 2) {
120     item = PyTuple_New (2);
121 #ifdef HAVE_PYSTRING_ASSTRING
122     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
123     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
124 #else
125     PyTuple_SetItem (item, 0, PyUnicode_FromString (argv[i]));
126     PyTuple_SetItem (item, 1, PyUnicode_FromString (argv[i+1]));
127 #endif
128     PyList_SetItem (list, i >> 1, item);
129   }
130
131   return list;
132 }
133
134 static void
135 free_strings (char **argv)
136 {
137   int argc;
138
139   for (argc = 0; argv[argc] != NULL; ++argc)
140     free (argv[argc]);
141   free (argv);
142 }
143
144 ";
145
146   let emit_put_list_function typ =
147     pr "static PyObject *\n";
148     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
149     pr "{\n";
150     pr "  PyObject *list;\n";
151     pr "  size_t i;\n";
152     pr "\n";
153     pr "  list = PyList_New (%ss->len);\n" typ;
154     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
155     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
156     pr "  return list;\n";
157     pr "};\n";
158     pr "\n"
159   in
160
161   (* Structures, turned into Python dictionaries. *)
162   List.iter (
163     fun (typ, cols) ->
164       pr "static PyObject *\n";
165       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
166       pr "{\n";
167       pr "  PyObject *dict;\n";
168       pr "\n";
169       pr "  dict = PyDict_New ();\n";
170       List.iter (
171         function
172         | name, FString ->
173             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
174             pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
175             pr "                        PyString_FromString (%s->%s));\n"
176               typ name;
177             pr "#else\n";
178             pr "                        PyUnicode_FromString (%s->%s));\n"
179               typ name;
180             pr "#endif\n"
181         | name, FBuffer ->
182             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
183             pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
184             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
185               typ name typ name;
186             pr "#else\n";
187             pr "                        PyBytes_FromStringAndSize (%s->%s, %s->%s_len));\n"
188               typ name typ name;
189             pr "#endif\n"
190         | name, FUUID ->
191             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
192             pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
193             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
194               typ name;
195             pr "#else\n";
196             pr "                        PyBytes_FromStringAndSize (%s->%s, 32));\n"
197               typ name;
198             pr "#endif\n"
199         | name, (FBytes|FUInt64) ->
200             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
201             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
202               typ name
203         | name, FInt64 ->
204             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
205             pr "                        PyLong_FromLongLong (%s->%s));\n"
206               typ name
207         | name, FUInt32 ->
208             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
209             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
210               typ name
211         | name, FInt32 ->
212             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
213             pr "                        PyLong_FromLong (%s->%s));\n"
214               typ name
215         | name, FOptPercent ->
216             pr "  if (%s->%s >= 0)\n" typ name;
217             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
218             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
219               typ name;
220             pr "  else {\n";
221             pr "    Py_INCREF (Py_None);\n";
222             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
223             pr "  }\n"
224         | name, FChar ->
225             pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
226             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
227             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name;
228             pr "#else\n";
229             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
230             pr "                        PyUnicode_FromStringAndSize (&dirent->%s, 1));\n" name;
231             pr "#endif\n"
232       ) cols;
233       pr "  return dict;\n";
234       pr "};\n";
235       pr "\n";
236
237   ) structs;
238
239   (* Emit a put_TYPE_list function definition only if that function is used. *)
240   List.iter (
241     function
242     | typ, (RStructListOnly | RStructAndList) ->
243         (* generate the function for typ *)
244         emit_put_list_function typ
245     | typ, _ -> () (* empty *)
246   ) (rstructs_used_by all_functions);
247
248   (* Python wrapper functions. *)
249   List.iter (
250     fun (name, (ret, args, optargs as style), _, _, _, _, _) ->
251       pr "static PyObject *\n";
252       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
253       pr "{\n";
254
255       pr "  PyThreadState *py_save = NULL;\n";
256       pr "  PyObject *py_g;\n";
257       pr "  guestfs_h *g;\n";
258       pr "  PyObject *py_r;\n";
259
260       if optargs <> [] then (
261         pr "  struct guestfs_%s_argv optargs_s;\n" name;
262         pr "  struct guestfs_%s_argv *optargs = &optargs_s;\n" name;
263       );
264
265       (match ret with
266        | RErr | RInt _ | RBool _ -> pr "  int r;\n"
267        | RInt64 _ -> pr "  int64_t r;\n"
268        | RConstString _ | RConstOptString _ ->
269            pr "  const char *r;\n"
270        | RString _ -> pr "  char *r;\n"
271        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
272        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
273        | RStructList (_, typ) ->
274            pr "  struct guestfs_%s_list *r;\n" typ
275        | RBufferOut _ ->
276            pr "  char *r;\n";
277            pr "  size_t size;\n"
278       );
279
280       List.iter (
281         function
282         | Pathname n | Device n | Dev_or_Path n | String n | Key n
283         | FileIn n | FileOut n ->
284             pr "  const char *%s;\n" n
285         | OptString n -> pr "  const char *%s;\n" n
286         | BufferIn n ->
287             pr "  const char *%s;\n" n;
288             pr "  Py_ssize_t %s_size;\n" n
289         | StringList n | DeviceList n ->
290             pr "  PyObject *py_%s;\n" n;
291             pr "  char **%s;\n" n
292         | Bool n -> pr "  int %s;\n" n
293         | Int n -> pr "  int %s;\n" n
294         | Int64 n -> pr "  long long %s;\n" n
295         | Pointer (t, n) ->
296             pr "  long long %s_int64;\n" n;
297             pr "  %s %s;\n" t n
298       ) args;
299
300       if optargs <> [] then (
301         (* XXX This is horrible.  We have to use sentinel values on the
302          * Python side to denote values not set.
303          *)
304         (* Since we don't know if Python types will exactly match
305          * structure types, declare some local variables here.
306          *)
307         List.iter (
308           function
309           | OBool n
310           | OInt n -> pr "  int optargs_t_%s = -1;\n" n
311           | OInt64 n -> pr "  long long optargs_t_%s = -1;\n" n
312           | OString n -> pr "  const char *optargs_t_%s = NULL;\n" n
313         ) optargs
314       );
315
316       pr "\n";
317
318       if optargs <> [] then (
319         pr "  optargs_s.bitmask = 0;\n";
320         pr "\n"
321       );
322
323       (* Convert the required parameters. *)
324       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
325       List.iter (
326         function
327         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
328         | FileIn _ | FileOut _ -> pr "s"
329         | OptString _ -> pr "z"
330         | StringList _ | DeviceList _ -> pr "O"
331         | Bool _ -> pr "i" (* XXX Python has booleans? *)
332         | Int _ -> pr "i"
333         | Int64 _ | Pointer _ ->
334             (* XXX Whoever thought it was a good idea to
335              * emulate C's int/long/long long in Python?
336              *)
337             pr "L"
338         | BufferIn _ -> pr "s#"
339       ) args;
340
341       (* Optional parameters. *)
342       if optargs <> [] then (
343         List.iter (
344           function
345           | OBool _ | OInt _ -> pr "i"
346           | OInt64 _ -> pr "L"
347           | OString _ -> pr "z" (* because we use None to mean not set *)
348         ) optargs;
349       );
350
351       pr ":guestfs_%s\",\n" name;
352       pr "                         &py_g";
353       List.iter (
354         function
355         | Pathname n | Device n | Dev_or_Path n | String n | Key n
356         | FileIn n | FileOut n -> pr ", &%s" n
357         | OptString n -> pr ", &%s" n
358         | StringList n | DeviceList n -> pr ", &py_%s" n
359         | Bool n -> pr ", &%s" n
360         | Int n -> pr ", &%s" n
361         | Int64 n -> pr ", &%s" n
362         | Pointer (_, n) -> pr ", &%s_int64" n
363         | BufferIn n -> pr ", &%s, &%s_size" n n
364       ) args;
365
366       List.iter (
367         function
368         | OBool n | OInt n | OInt64 n | OString n -> pr ", &optargs_t_%s" n
369       ) optargs;
370
371       pr "))\n";
372       pr "    return NULL;\n";
373
374       pr "  g = get_handle (py_g);\n";
375       List.iter (
376         function
377         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
378         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
379         | BufferIn _ -> ()
380         | StringList n | DeviceList n ->
381             pr "  %s = get_string_list (py_%s);\n" n n;
382             pr "  if (!%s) return NULL;\n" n
383         | Pointer (t, n) ->
384             pr "  %s = (%s) (intptr_t) %s_int64;\n" n t n
385       ) args;
386
387       pr "\n";
388
389       if optargs <> [] then (
390         let uc_name = String.uppercase name in
391         List.iter (
392           fun argt ->
393             let n = name_of_optargt argt in
394             let uc_n = String.uppercase n in
395             pr "  if (optargs_t_%s != " n;
396             (match argt with
397              | OBool _ | OInt _ | OInt64 _ -> pr "-1"
398              | OString _ -> pr "NULL"
399             );
400             pr ") {\n";
401             pr "    optargs_s.%s = optargs_t_%s;\n" n n;
402             pr "    optargs_s.bitmask |= GUESTFS_%s_%s_BITMASK;\n" uc_name uc_n;
403             pr "  }\n"
404         ) optargs;
405         pr "\n"
406       );
407
408       (* Release Python GIL while running.  This code is from
409        * libvirt/python/typewrappers.h.  Thanks to Dan Berrange for
410        * showing us how to do this properly.
411        *)
412       pr "  if (PyEval_ThreadsInitialized ())\n";
413       pr "    py_save = PyEval_SaveThread ();\n";
414       pr "\n";
415
416       if optargs = [] then
417         pr "  r = guestfs_%s " name
418       else
419         pr "  r = guestfs_%s_argv " name;
420       generate_c_call_args ~handle:"g" style;
421       pr ";\n";
422
423       pr "\n";
424       pr "  if (PyEval_ThreadsInitialized ())\n";
425       pr "    PyEval_RestoreThread (py_save);\n";
426       pr "\n";
427
428       List.iter (
429         function
430         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
431         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
432         | BufferIn _ | Pointer _ -> ()
433         | StringList n | DeviceList n ->
434             pr "  free (%s);\n" n
435       ) args;
436
437       (match errcode_of_ret ret with
438        | `CannotReturnError -> ()
439        | `ErrorIsMinusOne ->
440            pr "  if (r == -1) {\n";
441            pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
442            pr "    return NULL;\n";
443            pr "  }\n"
444        | `ErrorIsNULL ->
445            pr "  if (r == NULL) {\n";
446            pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
447            pr "    return NULL;\n";
448            pr "  }\n"
449       );
450       pr "\n";
451
452       (match ret with
453        | RErr ->
454            pr "  Py_INCREF (Py_None);\n";
455            pr "  py_r = Py_None;\n"
456        | RInt _
457        | RBool _ -> pr "  py_r = PyLong_FromLong ((long) r);\n"
458        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
459        | RConstString _ ->
460            pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
461            pr "  py_r = PyString_FromString (r);\n";
462            pr "#else\n";
463            pr "  py_r = PyUnicode_FromString (r);\n";
464            pr "#endif\n"
465        | RConstOptString _ ->
466            pr "  if (r) {\n";
467            pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
468            pr "    py_r = PyString_FromString (r);\n";
469            pr "#else\n";
470            pr "    py_r = PyUnicode_FromString (r);\n";
471            pr "#endif\n";
472            pr "  } else {\n";
473            pr "    Py_INCREF (Py_None);\n";
474            pr "    py_r = Py_None;\n";
475            pr "  }\n"
476        | RString _ ->
477            pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
478            pr "  py_r = PyString_FromString (r);\n";
479            pr "#else\n";
480            pr "  py_r = PyUnicode_FromString (r);\n";
481            pr "#endif\n";
482            pr "  free (r);\n"
483        | RStringList _ ->
484            pr "  py_r = put_string_list (r);\n";
485            pr "  free_strings (r);\n"
486        | RStruct (_, typ) ->
487            pr "  py_r = put_%s (r);\n" typ;
488            pr "  guestfs_free_%s (r);\n" typ
489        | RStructList (_, typ) ->
490            pr "  py_r = put_%s_list (r);\n" typ;
491            pr "  guestfs_free_%s_list (r);\n" typ
492        | RHashtable n ->
493            pr "  py_r = put_table (r);\n";
494            pr "  free_strings (r);\n"
495        | RBufferOut _ ->
496            pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
497            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
498            pr "#else\n";
499            pr "  py_r = PyBytes_FromStringAndSize (r, size);\n";
500            pr "#endif\n";
501            pr "  free (r);\n"
502       );
503
504       pr "  return py_r;\n";
505       pr "}\n";
506       pr "\n"
507   ) all_functions;
508
509   (* Table of functions. *)
510   pr "static PyMethodDef methods[] = {\n";
511   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
512   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
513   pr "  { (char *) \"set_event_callback\",\n";
514   pr "    py_guestfs_set_event_callback, METH_VARARGS, NULL },\n";
515   pr "  { (char *) \"delete_event_callback\",\n";
516   pr "    py_guestfs_delete_event_callback, METH_VARARGS, NULL },\n";
517   List.iter (
518     fun (name, _, _, _, _, _, _) ->
519       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
520         name name
521   ) all_functions;
522   pr "  { NULL, NULL, 0, NULL }\n";
523   pr "};\n";
524   pr "\n";
525
526   (* Init function. *)
527   pr "\
528 #if PY_MAJOR_VERSION >= 3
529 static struct PyModuleDef moduledef = {
530   PyModuleDef_HEAD_INIT,
531   \"libguestfsmod\",     /* m_name */
532   \"libguestfs module\",   /* m_doc */
533   -1,                    /* m_size */
534   methods,               /* m_methods */
535   NULL,                  /* m_reload */
536   NULL,                  /* m_traverse */
537   NULL,                  /* m_clear */
538   NULL,                  /* m_free */
539 };
540 #endif
541
542 static PyObject *
543 moduleinit (void)
544 {
545   PyObject *m;
546
547 #if PY_MAJOR_VERSION >= 3
548   m = PyModule_Create (&moduledef);
549 #else
550   m = Py_InitModule ((char *) \"libguestfsmod\", methods);
551 #endif
552
553   return m; /* m might be NULL if module init failed */
554 }
555
556 #if PY_MAJOR_VERSION >= 3
557 PyMODINIT_FUNC
558 PyInit_libguestfsmod (void)
559 {
560   return moduleinit ();
561 }
562 #else
563 void
564 initlibguestfsmod (void)
565 {
566   (void) moduleinit ();
567 }
568 #endif
569 "
570
571 (* Generate Python module. *)
572 and generate_python_py () =
573   generate_header HashStyle LGPLv2plus;
574
575   pr "\
576 \"\"\"Python bindings for libguestfs
577
578 import guestfs
579 g = guestfs.GuestFS ()
580 g.add_drive_opts (\"guest.img\", format=\"raw\")
581 g.launch ()
582 parts = g.list_partitions ()
583
584 The guestfs module provides a Python binding to the libguestfs API
585 for examining and modifying virtual machine disk images.
586
587 Amongst the things this is good for: making batch configuration
588 changes to guests, getting disk used/free statistics (see also:
589 virt-df), migrating between virtualization systems (see also:
590 virt-p2v), performing partial backups, performing partial guest
591 clones, cloning guests and changing registry/UUID/hostname info, and
592 much else besides.
593
594 Libguestfs uses Linux kernel and qemu code, and can access any type of
595 guest filesystem that Linux and qemu can, including but not limited
596 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
597 schemes, qcow, qcow2, vmdk.
598
599 Libguestfs provides ways to enumerate guest storage (eg. partitions,
600 LVs, what filesystem is in each LV, etc.).  It can also run commands
601 in the context of the guest.  Also you can access filesystems over
602 FUSE.
603
604 Errors which happen while using the API are turned into Python
605 RuntimeError exceptions.
606
607 To create a guestfs handle you usually have to perform the following
608 sequence of calls:
609
610 # Create the handle, call add_drive* at least once, and possibly
611 # several times if the guest has multiple block devices:
612 g = guestfs.GuestFS ()
613 g.add_drive_opts (\"guest.img\", format=\"raw\")
614
615 # Launch the qemu subprocess and wait for it to become ready:
616 g.launch ()
617
618 # Now you can issue commands, for example:
619 logvols = g.lvs ()
620
621 \"\"\"
622
623 import libguestfsmod
624
625 ";
626
627   List.iter (
628     fun (name, bitmask) ->
629       pr "EVENT_%s = 0x%x\n" (String.uppercase name) bitmask
630   ) events;
631   pr "\n";
632
633   pr "\
634 class ClosedHandle(ValueError):
635     pass
636
637 class GuestFS:
638     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
639
640     def __init__ (self):
641         \"\"\"Create a new libguestfs handle.\"\"\"
642         self._o = libguestfsmod.create ()
643
644     def __del__ (self):
645         if self._o:
646             libguestfsmod.close (self._o)
647
648     def _check_not_closed (self):
649         if not self._o:
650             raise ClosedHandle (\"GuestFS: method called on closed handle\")
651
652     def close (self):
653         \"\"\"Explicitly close the guestfs handle.
654
655         The handle is closed implicitly when its reference count goes
656         to zero (eg. when it goes out of scope or the program ends).
657
658         This call is only needed if you want to force the handle to
659         close now.  After calling this, the program must not call
660         any method on the handle (except the implicit call to
661         __del__ which happens when the final reference is cleaned up).
662         \"\"\"
663         self._check_not_closed ()
664         libguestfsmod.close (self._o)
665         self._o = None
666
667     def set_event_callback (self, cb, event_bitmask):
668         \"\"\"Register an event callback.
669
670         Register \"cb\" as a callback function for all of the
671         events in \"event_bitmask\".  \"event_bitmask\" should be
672         one or more \"guestfs.EVENT_*\" flags logically or'd together.
673
674         This function returns an event handle which can be used
675         to delete the callback (see \"delete_event_callback\").
676
677         The callback function receives 4 parameters:
678
679         cb (event, event_handle, buf, array)
680
681         \"event\" is one of the \"EVENT_*\" flags.  \"buf\" is a
682         message buffer (only for some types of events).  \"array\"
683         is an array of integers (only for some types of events).
684
685         You should read the documentation for
686         \"guestfs_set_event_callback\" in guestfs(3) before using
687         this function.
688         \"\"\"
689         self._check_not_closed ()
690         return libguestfsmod.set_event_callback (self._o, cb, event_bitmask)
691
692     def delete_event_callback (self, event_handle):
693         \"\"\"Delete an event callback.\"\"\"
694         self._check_not_closed ()
695         libguestfsmod.delete_event_callback (self._o, event_handle)
696
697 ";
698
699   List.iter (
700     fun (name, (ret, args, optargs), _, flags, _, _, longdesc) ->
701       pr "    def %s (self" name;
702       List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
703       List.iter (
704         function
705         | OBool n | OInt n | OInt64 n -> pr ", %s=-1" n
706         | OString n -> pr ", %s=None" n
707       ) optargs;
708       pr "):\n";
709
710       if not (List.mem NotInDocs flags) then (
711         let doc = replace_str longdesc "C<guestfs_" "C<g." in
712         let doc =
713           match ret with
714           | RErr | RInt _ | RInt64 _ | RBool _
715           | RConstOptString _ | RConstString _
716           | RString _ | RBufferOut _ -> doc
717           | RStringList _ ->
718               doc ^ "\n\nThis function returns a list of strings."
719           | RStruct (_, typ) ->
720               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
721           | RStructList (_, typ) ->
722               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
723           | RHashtable _ ->
724               doc ^ "\n\nThis function returns a dictionary." in
725         let doc =
726           if List.mem ProtocolLimitWarning flags then
727             doc ^ "\n\n" ^ protocol_limit_warning
728           else doc in
729         let doc =
730           match deprecation_notice flags with
731           | None -> doc
732           | Some txt -> doc ^ "\n\n" ^ txt in
733         let doc = pod2text ~width:60 name doc in
734         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
735         let doc = String.concat "\n        " doc in
736         pr "        \"\"\"%s\"\"\"\n" doc;
737       );
738       (* Callers might pass in iterables instead of plain lists;
739        * convert those to plain lists because the C side of things
740        * cannot deal with iterables.  (RHBZ#693306).
741        *)
742       List.iter (
743         function
744         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
745         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
746         | BufferIn _ | Pointer _ -> ()
747         | StringList n | DeviceList n ->
748             pr "        %s = list (%s)\n" n n
749       ) args;
750       pr "        self._check_not_closed ()\n";
751       pr "        return libguestfsmod.%s (self._o" name;
752       List.iter (fun arg -> pr ", %s" (name_of_argt arg))
753         (args @ args_of_optargs optargs);
754       pr ")\n\n";
755   ) all_functions