build: xml-light is no longer required (thanks Maxim Koltsov).
[libguestfs.git] / generator / generator_python.ml
1 (* libguestfs
2  * Copyright (C) 2009-2010 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
32 (* Generate Python C module. *)
33 let rec generate_python_c () =
34   generate_header CStyle LGPLv2plus;
35
36   pr "\
37 #define PY_SSIZE_T_CLEAN 1
38 #include <Python.h>
39
40 #if PY_VERSION_HEX < 0x02050000
41 typedef int Py_ssize_t;
42 #define PY_SSIZE_T_MAX INT_MAX
43 #define PY_SSIZE_T_MIN INT_MIN
44 #endif
45
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <assert.h>
49
50 #include \"guestfs.h\"
51
52 #ifndef HAVE_PYCAPSULE_NEW
53 typedef struct {
54   PyObject_HEAD
55   guestfs_h *g;
56 } Pyguestfs_Object;
57 #endif
58
59 static guestfs_h *
60 get_handle (PyObject *obj)
61 {
62   assert (obj);
63   assert (obj != Py_None);
64 #ifndef HAVE_PYCAPSULE_NEW
65   return ((Pyguestfs_Object *) obj)->g;
66 #else
67   return (guestfs_h*) PyCapsule_GetPointer(obj, \"guestfs_h\");
68 #endif
69 }
70
71 static PyObject *
72 put_handle (guestfs_h *g)
73 {
74   assert (g);
75 #ifndef HAVE_PYCAPSULE_NEW
76   return
77     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
78 #else
79   return PyCapsule_New ((void *) g, \"guestfs_h\", NULL);
80 #endif
81 }
82
83 /* This list should be freed (but not the strings) after use. */
84 static char **
85 get_string_list (PyObject *obj)
86 {
87   size_t i, len;
88   char **r;
89
90   assert (obj);
91
92   if (!PyList_Check (obj)) {
93     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
94     return NULL;
95   }
96
97   Py_ssize_t slen = PyList_Size (obj);
98   if (slen == -1) {
99     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
100     return NULL;
101   }
102   len = (size_t) slen;
103   r = malloc (sizeof (char *) * (len+1));
104   if (r == NULL) {
105     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
106     return NULL;
107   }
108
109   for (i = 0; i < len; ++i)
110     r[i] = PyString_AsString (PyList_GetItem (obj, i));
111   r[len] = NULL;
112
113   return r;
114 }
115
116 static PyObject *
117 put_string_list (char * const * const argv)
118 {
119   PyObject *list;
120   int argc, i;
121
122   for (argc = 0; argv[argc] != NULL; ++argc)
123     ;
124
125   list = PyList_New (argc);
126   for (i = 0; i < argc; ++i)
127     PyList_SetItem (list, i, PyString_FromString (argv[i]));
128
129   return list;
130 }
131
132 static PyObject *
133 put_table (char * const * const argv)
134 {
135   PyObject *list, *item;
136   int argc, i;
137
138   for (argc = 0; argv[argc] != NULL; ++argc)
139     ;
140
141   list = PyList_New (argc >> 1);
142   for (i = 0; i < argc; i += 2) {
143     item = PyTuple_New (2);
144     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
145     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
146     PyList_SetItem (list, i >> 1, item);
147   }
148
149   return list;
150 }
151
152 static void
153 free_strings (char **argv)
154 {
155   int argc;
156
157   for (argc = 0; argv[argc] != NULL; ++argc)
158     free (argv[argc]);
159   free (argv);
160 }
161
162 static PyObject *
163 py_guestfs_create (PyObject *self, PyObject *args)
164 {
165   guestfs_h *g;
166
167   g = guestfs_create ();
168   if (g == NULL) {
169     PyErr_SetString (PyExc_RuntimeError,
170                      \"guestfs.create: failed to allocate handle\");
171     return NULL;
172   }
173   guestfs_set_error_handler (g, NULL, NULL);
174   /* This can return NULL, but in that case put_handle will have
175    * set the Python error string.
176    */
177   return put_handle (g);
178 }
179
180 static PyObject *
181 py_guestfs_close (PyObject *self, PyObject *args)
182 {
183   PyObject *py_g;
184   guestfs_h *g;
185
186   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
187     return NULL;
188   g = get_handle (py_g);
189
190   guestfs_close (g);
191
192   Py_INCREF (Py_None);
193   return Py_None;
194 }
195
196 ";
197
198   let emit_put_list_function typ =
199     pr "static PyObject *\n";
200     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
201     pr "{\n";
202     pr "  PyObject *list;\n";
203     pr "  size_t i;\n";
204     pr "\n";
205     pr "  list = PyList_New (%ss->len);\n" typ;
206     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
207     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
208     pr "  return list;\n";
209     pr "};\n";
210     pr "\n"
211   in
212
213   (* Structures, turned into Python dictionaries. *)
214   List.iter (
215     fun (typ, cols) ->
216       pr "static PyObject *\n";
217       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
218       pr "{\n";
219       pr "  PyObject *dict;\n";
220       pr "\n";
221       pr "  dict = PyDict_New ();\n";
222       List.iter (
223         function
224         | name, FString ->
225             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
226             pr "                        PyString_FromString (%s->%s));\n"
227               typ name
228         | name, FBuffer ->
229             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
230             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
231               typ name typ name
232         | name, FUUID ->
233             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
234             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
235               typ name
236         | name, (FBytes|FUInt64) ->
237             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
238             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
239               typ name
240         | name, FInt64 ->
241             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
242             pr "                        PyLong_FromLongLong (%s->%s));\n"
243               typ name
244         | name, FUInt32 ->
245             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
246             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
247               typ name
248         | name, FInt32 ->
249             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
250             pr "                        PyLong_FromLong (%s->%s));\n"
251               typ name
252         | name, FOptPercent ->
253             pr "  if (%s->%s >= 0)\n" typ name;
254             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
255             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
256               typ name;
257             pr "  else {\n";
258             pr "    Py_INCREF (Py_None);\n";
259             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
260             pr "  }\n"
261         | name, FChar ->
262             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
263             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
264       ) cols;
265       pr "  return dict;\n";
266       pr "};\n";
267       pr "\n";
268
269   ) structs;
270
271   (* Emit a put_TYPE_list function definition only if that function is used. *)
272   List.iter (
273     function
274     | typ, (RStructListOnly | RStructAndList) ->
275         (* generate the function for typ *)
276         emit_put_list_function typ
277     | typ, _ -> () (* empty *)
278   ) (rstructs_used_by all_functions);
279
280   (* Python wrapper functions. *)
281   List.iter (
282     fun (name, (ret, args, optargs as style), _, _, _, _, _) ->
283       pr "static PyObject *\n";
284       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
285       pr "{\n";
286
287       pr "  PyObject *py_g;\n";
288       pr "  guestfs_h *g;\n";
289       pr "  PyObject *py_r;\n";
290
291       if optargs <> [] then (
292         pr "  struct guestfs_%s_argv optargs_s;\n" name;
293         pr "  struct guestfs_%s_argv *optargs = &optargs_s;\n" name;
294       );
295
296       let error_code =
297         match ret with
298         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
299         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
300         | RConstString _ | RConstOptString _ ->
301             pr "  const char *r;\n"; "NULL"
302         | RString _ -> pr "  char *r;\n"; "NULL"
303         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
304         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
305         | RStructList (_, typ) ->
306             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
307         | RBufferOut _ ->
308             pr "  char *r;\n";
309             pr "  size_t size;\n";
310             "NULL" in
311
312       List.iter (
313         function
314         | Pathname n | Device n | Dev_or_Path n | String n | Key n
315         | FileIn n | FileOut n ->
316             pr "  const char *%s;\n" n
317         | OptString n -> pr "  const char *%s;\n" n
318         | BufferIn n ->
319             pr "  const char *%s;\n" n;
320             pr "  Py_ssize_t %s_size;\n" n
321         | StringList n | DeviceList n ->
322             pr "  PyObject *py_%s;\n" n;
323             pr "  char **%s;\n" n
324         | Bool n -> pr "  int %s;\n" n
325         | Int n -> pr "  int %s;\n" n
326         | Int64 n -> pr "  long long %s;\n" n
327         | Pointer (t, n) ->
328             pr "  long long %s_int64;\n" n;
329             pr "  %s %s;\n" t n
330       ) args;
331
332       if optargs <> [] then (
333         (* XXX This is horrible.  We have to use sentinel values on the
334          * Python side to denote values not set.
335          *)
336         (* Since we don't know if Python types will exactly match
337          * structure types, declare some local variables here.
338          *)
339         List.iter (
340           function
341           | Bool n
342           | Int n -> pr "  int optargs_t_%s = -1;\n" n
343           | Int64 n -> pr "  long long optargs_t_%s = -1;\n" n
344           | String n -> pr "  const char *optargs_t_%s = NULL;\n" n
345           | _ -> assert false
346         ) optargs
347       );
348
349       pr "\n";
350
351       if optargs <> [] then (
352         pr "  optargs_s.bitmask = 0;\n";
353         pr "\n"
354       );
355
356       (* Convert the required parameters. *)
357       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
358       List.iter (
359         function
360         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
361         | FileIn _ | FileOut _ -> pr "s"
362         | OptString _ -> pr "z"
363         | StringList _ | DeviceList _ -> pr "O"
364         | Bool _ -> pr "i" (* XXX Python has booleans? *)
365         | Int _ -> pr "i"
366         | Int64 _ | Pointer _ ->
367             (* XXX Whoever thought it was a good idea to
368              * emulate C's int/long/long long in Python?
369              *)
370             pr "L"
371         | BufferIn _ -> pr "s#"
372       ) args;
373
374       (* Optional parameters. *)
375       if optargs <> [] then (
376         List.iter (
377           function
378           | Bool _ | Int _ -> pr "i"
379           | Int64 _ -> pr "L"
380           | String _ -> pr "z" (* because we use None to mean not set *)
381           | _ -> assert false
382         ) optargs;
383       );
384
385       pr ":guestfs_%s\",\n" name;
386       pr "                         &py_g";
387       List.iter (
388         function
389         | Pathname n | Device n | Dev_or_Path n | String n | Key n
390         | FileIn n | FileOut n -> pr ", &%s" n
391         | OptString n -> pr ", &%s" n
392         | StringList n | DeviceList n -> pr ", &py_%s" n
393         | Bool n -> pr ", &%s" n
394         | Int n -> pr ", &%s" n
395         | Int64 n -> pr ", &%s" n
396         | Pointer (_, n) -> pr ", &%s_int64" n
397         | BufferIn n -> pr ", &%s, &%s_size" n n
398       ) args;
399
400       List.iter (
401         function
402         | Bool n | Int n | Int64 n | String n -> pr ", &optargs_t_%s" n
403         | _ -> assert false
404       ) optargs;
405
406       pr "))\n";
407       pr "    return NULL;\n";
408
409       pr "  g = get_handle (py_g);\n";
410       List.iter (
411         function
412         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
413         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
414         | BufferIn _ -> ()
415         | StringList n | DeviceList n ->
416             pr "  %s = get_string_list (py_%s);\n" n n;
417             pr "  if (!%s) return NULL;\n" n
418         | Pointer (t, n) ->
419             pr "  %s = (%s) (intptr_t) %s_int64;\n" n t n
420       ) args;
421
422       pr "\n";
423
424       if optargs <> [] then (
425         let uc_name = String.uppercase name in
426         List.iter (
427           fun argt ->
428             let n = name_of_argt argt in
429             let uc_n = String.uppercase n in
430             pr "  if (optargs_t_%s != " n;
431             (match argt with
432              | Bool _ | Int _ | Int64 _ -> pr "-1"
433              | String _ -> pr "NULL"
434              | _ -> assert false
435             );
436             pr ") {\n";
437             pr "    optargs_s.%s = optargs_t_%s;\n" n n;
438             pr "    optargs_s.bitmask |= GUESTFS_%s_%s_BITMASK;\n" uc_name uc_n;
439             pr "  }\n"
440         ) optargs;
441         pr "\n"
442       );
443
444       if optargs = [] then
445         pr "  r = guestfs_%s " name
446       else
447         pr "  r = guestfs_%s_argv " name;
448       generate_c_call_args ~handle:"g" style;
449       pr ";\n";
450
451       List.iter (
452         function
453         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
454         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
455         | BufferIn _ | Pointer _ -> ()
456         | StringList n | DeviceList n ->
457             pr "  free (%s);\n" n
458       ) args;
459
460       pr "  if (r == %s) {\n" error_code;
461       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
462       pr "    return NULL;\n";
463       pr "  }\n";
464       pr "\n";
465
466       (match ret with
467        | RErr ->
468            pr "  Py_INCREF (Py_None);\n";
469            pr "  py_r = Py_None;\n"
470        | RInt _
471        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
472        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
473        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
474        | RConstOptString _ ->
475            pr "  if (r)\n";
476            pr "    py_r = PyString_FromString (r);\n";
477            pr "  else {\n";
478            pr "    Py_INCREF (Py_None);\n";
479            pr "    py_r = Py_None;\n";
480            pr "  }\n"
481        | RString _ ->
482            pr "  py_r = PyString_FromString (r);\n";
483            pr "  free (r);\n"
484        | RStringList _ ->
485            pr "  py_r = put_string_list (r);\n";
486            pr "  free_strings (r);\n"
487        | RStruct (_, typ) ->
488            pr "  py_r = put_%s (r);\n" typ;
489            pr "  guestfs_free_%s (r);\n" typ
490        | RStructList (_, typ) ->
491            pr "  py_r = put_%s_list (r);\n" typ;
492            pr "  guestfs_free_%s_list (r);\n" typ
493        | RHashtable n ->
494            pr "  py_r = put_table (r);\n";
495            pr "  free_strings (r);\n"
496        | RBufferOut _ ->
497            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
498            pr "  free (r);\n"
499       );
500
501       pr "  return py_r;\n";
502       pr "}\n";
503       pr "\n"
504   ) all_functions;
505
506   (* Table of functions. *)
507   pr "static PyMethodDef methods[] = {\n";
508   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
509   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
510   List.iter (
511     fun (name, _, _, _, _, _, _) ->
512       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
513         name name
514   ) all_functions;
515   pr "  { NULL, NULL, 0, NULL }\n";
516   pr "};\n";
517   pr "\n";
518
519   (* Init function. *)
520   pr "\
521 void
522 initlibguestfsmod (void)
523 {
524   static int initialized = 0;
525
526   if (initialized) return;
527   Py_InitModule ((char *) \"libguestfsmod\", methods);
528   initialized = 1;
529 }
530 "
531
532 (* Generate Python module. *)
533 and generate_python_py () =
534   generate_header HashStyle LGPLv2plus;
535
536   pr "\
537 u\"\"\"Python bindings for libguestfs
538
539 import guestfs
540 g = guestfs.GuestFS ()
541 g.add_drive_opts (\"guest.img\", format=\"raw\")
542 g.launch ()
543 parts = g.list_partitions ()
544
545 The guestfs module provides a Python binding to the libguestfs API
546 for examining and modifying virtual machine disk images.
547
548 Amongst the things this is good for: making batch configuration
549 changes to guests, getting disk used/free statistics (see also:
550 virt-df), migrating between virtualization systems (see also:
551 virt-p2v), performing partial backups, performing partial guest
552 clones, cloning guests and changing registry/UUID/hostname info, and
553 much else besides.
554
555 Libguestfs uses Linux kernel and qemu code, and can access any type of
556 guest filesystem that Linux and qemu can, including but not limited
557 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
558 schemes, qcow, qcow2, vmdk.
559
560 Libguestfs provides ways to enumerate guest storage (eg. partitions,
561 LVs, what filesystem is in each LV, etc.).  It can also run commands
562 in the context of the guest.  Also you can access filesystems over
563 FUSE.
564
565 Errors which happen while using the API are turned into Python
566 RuntimeError exceptions.
567
568 To create a guestfs handle you usually have to perform the following
569 sequence of calls:
570
571 # Create the handle, call add_drive* at least once, and possibly
572 # several times if the guest has multiple block devices:
573 g = guestfs.GuestFS ()
574 g.add_drive_opts (\"guest.img\", format=\"raw\")
575
576 # Launch the qemu subprocess and wait for it to become ready:
577 g.launch ()
578
579 # Now you can issue commands, for example:
580 logvols = g.lvs ()
581
582 \"\"\"
583
584 import libguestfsmod
585
586 class GuestFS:
587     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
588
589     def __init__ (self):
590         \"\"\"Create a new libguestfs handle.\"\"\"
591         self._o = libguestfsmod.create ()
592
593     def __del__ (self):
594         libguestfsmod.close (self._o)
595
596 ";
597
598   List.iter (
599     fun (name, (ret, args, optargs), _, flags, _, _, longdesc) ->
600       pr "    def %s (self" name;
601       List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
602       List.iter (
603         function
604         | Bool n | Int n | Int64 n -> pr ", %s=-1" n
605         | String n -> pr ", %s=None" n
606         | _ -> assert false
607       ) optargs;
608       pr "):\n";
609
610       if not (List.mem NotInDocs flags) then (
611         let doc = replace_str longdesc "C<guestfs_" "C<g." in
612         let doc =
613           match ret with
614           | RErr | RInt _ | RInt64 _ | RBool _
615           | RConstOptString _ | RConstString _
616           | RString _ | RBufferOut _ -> doc
617           | RStringList _ ->
618               doc ^ "\n\nThis function returns a list of strings."
619           | RStruct (_, typ) ->
620               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
621           | RStructList (_, typ) ->
622               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
623           | RHashtable _ ->
624               doc ^ "\n\nThis function returns a dictionary." in
625         let doc =
626           if List.mem ProtocolLimitWarning flags then
627             doc ^ "\n\n" ^ protocol_limit_warning
628           else doc in
629         let doc =
630           if List.mem DangerWillRobinson flags then
631             doc ^ "\n\n" ^ danger_will_robinson
632           else doc in
633         let doc =
634           match deprecation_notice flags with
635           | None -> doc
636           | Some txt -> doc ^ "\n\n" ^ txt in
637         let doc = pod2text ~width:60 name doc in
638         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
639         let doc = String.concat "\n        " doc in
640         pr "        u\"\"\"%s\"\"\"\n" doc;
641       );
642       pr "        return libguestfsmod.%s (self._o" name;
643       List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (args@optargs);
644       pr ")\n\n";
645   ) all_functions