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