capitests: Don't open test files with O_NONBLOCK.
[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       ) args;
328
329       if optargs <> [] then (
330         (* XXX This is horrible.  We have to use sentinel values on the
331          * Python side to denote values not set.
332          *)
333         (* Since we don't know if Python types will exactly match
334          * structure types, declare some local variables here.
335          *)
336         List.iter (
337           function
338           | Bool n
339           | Int n -> pr "  int optargs_t_%s = -1;\n" n
340           | Int64 n -> pr "  long long optargs_t_%s = -1;\n" n
341           | String n -> pr "  const char *optargs_t_%s = NULL;\n" n
342           | _ -> assert false
343         ) optargs
344       );
345
346       pr "\n";
347
348       if optargs <> [] then (
349         pr "  optargs_s.bitmask = 0;\n";
350         pr "\n"
351       );
352
353       (* Convert the required parameters. *)
354       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
355       List.iter (
356         function
357         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
358         | FileIn _ | FileOut _ -> pr "s"
359         | OptString _ -> pr "z"
360         | StringList _ | DeviceList _ -> pr "O"
361         | Bool _ -> pr "i" (* XXX Python has booleans? *)
362         | Int _ -> pr "i"
363         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
364                              * emulate C's int/long/long long in Python?
365                              *)
366         | BufferIn _ -> pr "s#"
367       ) args;
368
369       (* Optional parameters. *)
370       if optargs <> [] then (
371         List.iter (
372           function
373           | Bool _ | Int _ -> pr "i"
374           | Int64 _ -> pr "L"
375           | String _ -> pr "z" (* because we use None to mean not set *)
376           | _ -> assert false
377         ) optargs;
378       );
379
380       pr ":guestfs_%s\",\n" name;
381       pr "                         &py_g";
382       List.iter (
383         function
384         | Pathname n | Device n | Dev_or_Path n | String n | Key n
385         | FileIn n | FileOut n -> pr ", &%s" n
386         | OptString n -> pr ", &%s" n
387         | StringList n | DeviceList n -> pr ", &py_%s" n
388         | Bool n -> pr ", &%s" n
389         | Int n -> pr ", &%s" n
390         | Int64 n -> pr ", &%s" n
391         | BufferIn n -> pr ", &%s, &%s_size" n n
392       ) args;
393
394       List.iter (
395         function
396         | Bool n | Int n | Int64 n | String n -> pr ", &optargs_t_%s" n
397         | _ -> assert false
398       ) optargs;
399
400       pr "))\n";
401       pr "    return NULL;\n";
402
403       pr "  g = get_handle (py_g);\n";
404       List.iter (
405         function
406         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
407         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
408         | BufferIn _ -> ()
409         | StringList n | DeviceList n ->
410             pr "  %s = get_string_list (py_%s);\n" n n;
411             pr "  if (!%s) return NULL;\n" n
412       ) args;
413
414       pr "\n";
415
416       if optargs <> [] then (
417         let uc_name = String.uppercase name in
418         List.iter (
419           fun argt ->
420             let n = name_of_argt argt in
421             let uc_n = String.uppercase n in
422             pr "  if (optargs_t_%s != " n;
423             (match argt with
424              | Bool _ | Int _ | Int64 _ -> pr "-1"
425              | String _ -> pr "NULL"
426              | _ -> assert false
427             );
428             pr ") {\n";
429             pr "    optargs_s.%s = optargs_t_%s;\n" n n;
430             pr "    optargs_s.bitmask |= GUESTFS_%s_%s_BITMASK;\n" uc_name uc_n;
431             pr "  }\n"
432         ) optargs;
433         pr "\n"
434       );
435
436       if optargs = [] then
437         pr "  r = guestfs_%s " name
438       else
439         pr "  r = guestfs_%s_argv " name;
440       generate_c_call_args ~handle:"g" style;
441       pr ";\n";
442
443       List.iter (
444         function
445         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
446         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
447         | BufferIn _ -> ()
448         | StringList n | DeviceList n ->
449             pr "  free (%s);\n" n
450       ) args;
451
452       pr "  if (r == %s) {\n" error_code;
453       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
454       pr "    return NULL;\n";
455       pr "  }\n";
456       pr "\n";
457
458       (match ret with
459        | RErr ->
460            pr "  Py_INCREF (Py_None);\n";
461            pr "  py_r = Py_None;\n"
462        | RInt _
463        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
464        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
465        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
466        | RConstOptString _ ->
467            pr "  if (r)\n";
468            pr "    py_r = PyString_FromString (r);\n";
469            pr "  else {\n";
470            pr "    Py_INCREF (Py_None);\n";
471            pr "    py_r = Py_None;\n";
472            pr "  }\n"
473        | RString _ ->
474            pr "  py_r = PyString_FromString (r);\n";
475            pr "  free (r);\n"
476        | RStringList _ ->
477            pr "  py_r = put_string_list (r);\n";
478            pr "  free_strings (r);\n"
479        | RStruct (_, typ) ->
480            pr "  py_r = put_%s (r);\n" typ;
481            pr "  guestfs_free_%s (r);\n" typ
482        | RStructList (_, typ) ->
483            pr "  py_r = put_%s_list (r);\n" typ;
484            pr "  guestfs_free_%s_list (r);\n" typ
485        | RHashtable n ->
486            pr "  py_r = put_table (r);\n";
487            pr "  free_strings (r);\n"
488        | RBufferOut _ ->
489            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
490            pr "  free (r);\n"
491       );
492
493       pr "  return py_r;\n";
494       pr "}\n";
495       pr "\n"
496   ) all_functions;
497
498   (* Table of functions. *)
499   pr "static PyMethodDef methods[] = {\n";
500   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
501   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
502   List.iter (
503     fun (name, _, _, _, _, _, _) ->
504       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
505         name name
506   ) all_functions;
507   pr "  { NULL, NULL, 0, NULL }\n";
508   pr "};\n";
509   pr "\n";
510
511   (* Init function. *)
512   pr "\
513 void
514 initlibguestfsmod (void)
515 {
516   static int initialized = 0;
517
518   if (initialized) return;
519   Py_InitModule ((char *) \"libguestfsmod\", methods);
520   initialized = 1;
521 }
522 "
523
524 (* Generate Python module. *)
525 and generate_python_py () =
526   generate_header HashStyle LGPLv2plus;
527
528   pr "\
529 u\"\"\"Python bindings for libguestfs
530
531 import guestfs
532 g = guestfs.GuestFS ()
533 g.add_drive_opts (\"guest.img\", format=\"raw\")
534 g.launch ()
535 parts = g.list_partitions ()
536
537 The guestfs module provides a Python binding to the libguestfs API
538 for examining and modifying virtual machine disk images.
539
540 Amongst the things this is good for: making batch configuration
541 changes to guests, getting disk used/free statistics (see also:
542 virt-df), migrating between virtualization systems (see also:
543 virt-p2v), performing partial backups, performing partial guest
544 clones, cloning guests and changing registry/UUID/hostname info, and
545 much else besides.
546
547 Libguestfs uses Linux kernel and qemu code, and can access any type of
548 guest filesystem that Linux and qemu can, including but not limited
549 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
550 schemes, qcow, qcow2, vmdk.
551
552 Libguestfs provides ways to enumerate guest storage (eg. partitions,
553 LVs, what filesystem is in each LV, etc.).  It can also run commands
554 in the context of the guest.  Also you can access filesystems over
555 FUSE.
556
557 Errors which happen while using the API are turned into Python
558 RuntimeError exceptions.
559
560 To create a guestfs handle you usually have to perform the following
561 sequence of calls:
562
563 # Create the handle, call add_drive* at least once, and possibly
564 # several times if the guest has multiple block devices:
565 g = guestfs.GuestFS ()
566 g.add_drive_opts (\"guest.img\", format=\"raw\")
567
568 # Launch the qemu subprocess and wait for it to become ready:
569 g.launch ()
570
571 # Now you can issue commands, for example:
572 logvols = g.lvs ()
573
574 \"\"\"
575
576 import libguestfsmod
577
578 class GuestFS:
579     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
580
581     def __init__ (self):
582         \"\"\"Create a new libguestfs handle.\"\"\"
583         self._o = libguestfsmod.create ()
584
585     def __del__ (self):
586         libguestfsmod.close (self._o)
587
588 ";
589
590   List.iter (
591     fun (name, (ret, args, optargs), _, flags, _, _, longdesc) ->
592       pr "    def %s (self" name;
593       List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
594       List.iter (
595         function
596         | Bool n | Int n | Int64 n -> pr ", %s=-1" n
597         | String n -> pr ", %s=None" n
598         | _ -> assert false
599       ) optargs;
600       pr "):\n";
601
602       if not (List.mem NotInDocs flags) then (
603         let doc = replace_str longdesc "C<guestfs_" "C<g." in
604         let doc =
605           match ret with
606           | RErr | RInt _ | RInt64 _ | RBool _
607           | RConstOptString _ | RConstString _
608           | RString _ | RBufferOut _ -> doc
609           | RStringList _ ->
610               doc ^ "\n\nThis function returns a list of strings."
611           | RStruct (_, typ) ->
612               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
613           | RStructList (_, typ) ->
614               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
615           | RHashtable _ ->
616               doc ^ "\n\nThis function returns a dictionary." in
617         let doc =
618           if List.mem ProtocolLimitWarning flags then
619             doc ^ "\n\n" ^ protocol_limit_warning
620           else doc in
621         let doc =
622           if List.mem DangerWillRobinson flags then
623             doc ^ "\n\n" ^ danger_will_robinson
624           else doc in
625         let doc =
626           match deprecation_notice flags with
627           | None -> doc
628           | Some txt -> doc ^ "\n\n" ^ txt in
629         let doc = pod2text ~width:60 name doc in
630         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
631         let doc = String.concat "\n        " doc in
632         pr "        u\"\"\"%s\"\"\"\n" doc;
633       );
634       pr "        return libguestfsmod.%s (self._o" name;
635       List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (args@optargs);
636       pr ")\n\n";
637   ) all_functions