]> Git Repo - binutils.git/blob - gdb/python/py-param.c
Make it simpler to add events to Python
[binutils.git] / gdb / python / py-param.c
1 /* GDB parameters implemented in Python
2
3    Copyright (C) 2008-2017 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20
21 #include "defs.h"
22 #include "value.h"
23 #include "python-internal.h"
24 #include "charset.h"
25 #include "gdbcmd.h"
26 #include "cli/cli-decode.h"
27 #include "completer.h"
28 #include "language.h"
29 #include "arch-utils.h"
30 #include "py-ref.h"
31
32 /* Parameter constants and their values.  */
33 struct parm_constant
34 {
35   const char *name;
36   int value;
37 };
38
39 struct parm_constant parm_constants[] =
40 {
41   { "PARAM_BOOLEAN", var_boolean }, /* ARI: var_boolean */
42   { "PARAM_AUTO_BOOLEAN", var_auto_boolean },
43   { "PARAM_UINTEGER", var_uinteger },
44   { "PARAM_INTEGER", var_integer },
45   { "PARAM_STRING", var_string },
46   { "PARAM_STRING_NOESCAPE", var_string_noescape },
47   { "PARAM_OPTIONAL_FILENAME", var_optional_filename },
48   { "PARAM_FILENAME", var_filename },
49   { "PARAM_ZINTEGER", var_zinteger },
50   { "PARAM_ENUM", var_enum },
51   { NULL, 0 }
52 };
53
54 /* A union that can hold anything described by enum var_types.  */
55 union parmpy_variable
56 {
57   /* Hold an integer value, for boolean and integer types.  */
58   int intval;
59
60   /* Hold an auto_boolean.  */
61   enum auto_boolean autoboolval;
62
63   /* Hold an unsigned integer value, for uinteger.  */
64   unsigned int uintval;
65
66   /* Hold a string, for the various string types.  */
67   char *stringval;
68
69   /* Hold a string, for enums.  */
70   const char *cstringval;
71 };
72
73 /* A GDB parameter.  */
74 struct parmpy_object
75 {
76   PyObject_HEAD
77
78   /* The type of the parameter.  */
79   enum var_types type;
80
81   /* The value of the parameter.  */
82   union parmpy_variable value;
83
84   /* For an enum command, the possible values.  The vector is
85      allocated with xmalloc, as is each element.  It is
86      NULL-terminated.  */
87   const char **enumeration;
88 };
89
90 typedef struct parmpy_object parmpy_object;
91
92 extern PyTypeObject parmpy_object_type
93     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("parmpy_object");
94
95 /* Some handy string constants.  */
96 static PyObject *set_doc_cst;
97 static PyObject *show_doc_cst;
98
99 \f
100
101 /* Get an attribute.  */
102 static PyObject *
103 get_attr (PyObject *obj, PyObject *attr_name)
104 {
105   if (PyString_Check (attr_name)
106 #ifdef IS_PY3K
107       && ! PyUnicode_CompareWithASCIIString (attr_name, "value"))
108 #else
109       && ! strcmp (PyString_AsString (attr_name), "value"))
110 #endif
111     {
112       parmpy_object *self = (parmpy_object *) obj;
113
114       return gdbpy_parameter_value (self->type, &self->value);
115     }
116
117   return PyObject_GenericGetAttr (obj, attr_name);
118 }
119
120 /* Set a parameter value from a Python value.  Return 0 on success.  Returns
121    -1 on error, with a python exception set.  */
122 static int
123 set_parameter_value (parmpy_object *self, PyObject *value)
124 {
125   int cmp;
126
127   switch (self->type)
128     {
129     case var_string:
130     case var_string_noescape:
131     case var_optional_filename:
132     case var_filename:
133       if (! gdbpy_is_string (value)
134           && (self->type == var_filename
135               || value != Py_None))
136         {
137           PyErr_SetString (PyExc_RuntimeError,
138                            _("String required for filename."));
139
140           return -1;
141         }
142       if (value == Py_None)
143         {
144           xfree (self->value.stringval);
145           if (self->type == var_optional_filename)
146             self->value.stringval = xstrdup ("");
147           else
148             self->value.stringval = NULL;
149         }
150       else
151         {
152           gdb::unique_xmalloc_ptr<char>
153             string (python_string_to_host_string (value));
154           if (string == NULL)
155             return -1;
156
157           xfree (self->value.stringval);
158           self->value.stringval = string.release ();
159         }
160       break;
161
162     case var_enum:
163       {
164         int i;
165
166         if (! gdbpy_is_string (value))
167           {
168             PyErr_SetString (PyExc_RuntimeError,
169                              _("ENUM arguments must be a string."));
170             return -1;
171           }
172
173         gdb::unique_xmalloc_ptr<char>
174           str (python_string_to_host_string (value));
175         if (str == NULL)
176           return -1;
177         for (i = 0; self->enumeration[i]; ++i)
178           if (! strcmp (self->enumeration[i], str.get ()))
179             break;
180         if (! self->enumeration[i])
181           {
182             PyErr_SetString (PyExc_RuntimeError,
183                              _("The value must be member of an enumeration."));
184             return -1;
185           }
186         self->value.cstringval = self->enumeration[i];
187         break;
188       }
189
190     case var_boolean:
191       if (! PyBool_Check (value))
192         {
193           PyErr_SetString (PyExc_RuntimeError,
194                            _("A boolean argument is required."));
195           return -1;
196         }
197       cmp = PyObject_IsTrue (value);
198       if (cmp < 0)
199           return -1;
200       self->value.intval = cmp;
201       break;
202
203     case var_auto_boolean:
204       if (! PyBool_Check (value) && value != Py_None)
205         {
206           PyErr_SetString (PyExc_RuntimeError,
207                            _("A boolean or None is required"));
208           return -1;
209         }
210
211       if (value == Py_None)
212         self->value.autoboolval = AUTO_BOOLEAN_AUTO;
213       else
214         {
215           cmp = PyObject_IsTrue (value);
216           if (cmp < 0 )
217             return -1;  
218           if (cmp == 1)
219             self->value.autoboolval = AUTO_BOOLEAN_TRUE;
220           else
221             self->value.autoboolval = AUTO_BOOLEAN_FALSE;
222         }
223       break;
224
225     case var_integer:
226     case var_zinteger:
227     case var_uinteger:
228       {
229         long l;
230         int ok;
231
232         if (! PyInt_Check (value))
233           {
234             PyErr_SetString (PyExc_RuntimeError,
235                              _("The value must be integer."));
236             return -1;
237           }
238
239         if (! gdb_py_int_as_long (value, &l))
240           return -1;
241
242         if (self->type == var_uinteger)
243           {
244             ok = (l >= 0 && l <= UINT_MAX);
245             if (l == 0)
246               l = UINT_MAX;
247           }
248         else if (self->type == var_integer)
249           {
250             ok = (l >= INT_MIN && l <= INT_MAX);
251             if (l == 0)
252               l = INT_MAX;
253           }
254         else
255           ok = (l >= INT_MIN && l <= INT_MAX);
256
257         if (! ok)
258           {
259             PyErr_SetString (PyExc_RuntimeError,
260                              _("Range exceeded."));
261             return -1;
262           }
263
264         self->value.intval = (int) l;
265         break;
266       }
267
268     default:
269       PyErr_SetString (PyExc_RuntimeError,
270                        _("Unhandled type in parameter value."));
271       return -1;
272     }
273
274   return 0;
275 }
276
277 /* Set an attribute.  Returns -1 on error, with a python exception set.  */
278 static int
279 set_attr (PyObject *obj, PyObject *attr_name, PyObject *val)
280 {
281   if (PyString_Check (attr_name)
282 #ifdef IS_PY3K
283       && ! PyUnicode_CompareWithASCIIString (attr_name, "value"))
284 #else
285       && ! strcmp (PyString_AsString (attr_name), "value"))
286 #endif
287     {
288       if (!val)
289         {
290           PyErr_SetString (PyExc_RuntimeError,
291                            _("Cannot delete a parameter's value."));
292           return -1;
293         }
294       return set_parameter_value ((parmpy_object *) obj, val);
295     }
296
297   return PyObject_GenericSetAttr (obj, attr_name, val);
298 }
299
300 /* A helper function which returns a documentation string for an
301    object. */
302
303 static gdb::unique_xmalloc_ptr<char>
304 get_doc_string (PyObject *object, PyObject *attr)
305 {
306   gdb::unique_xmalloc_ptr<char> result;
307
308   if (PyObject_HasAttr (object, attr))
309     {
310       gdbpy_ref<> ds_obj (PyObject_GetAttr (object, attr));
311
312       if (ds_obj != NULL && gdbpy_is_string (ds_obj.get ()))
313         {
314           result = python_string_to_host_string (ds_obj.get ());
315           if (result == NULL)
316             gdbpy_print_stack ();
317         }
318     }
319   if (! result)
320     result.reset (xstrdup (_("This command is not documented.")));
321   return result;
322 }
323
324 /* Helper function which will execute a METHOD in OBJ passing the
325    argument ARG.  ARG can be NULL.  METHOD should return a Python
326    string.  If this function returns NULL, there has been an error and
327    the appropriate exception set.  */
328 static gdb::unique_xmalloc_ptr<char>
329 call_doc_function (PyObject *obj, PyObject *method, PyObject *arg)
330 {
331   gdb::unique_xmalloc_ptr<char> data;
332   gdbpy_ref<> result (PyObject_CallMethodObjArgs (obj, method, arg, NULL));
333
334   if (result == NULL)
335     return NULL;
336
337   if (gdbpy_is_string (result.get ()))
338     {
339       data = python_string_to_host_string (result.get ());
340       if (! data)
341         return NULL;
342     }
343   else
344     {
345       PyErr_SetString (PyExc_RuntimeError,
346                        _("Parameter must return a string value."));
347       return NULL;
348     }
349
350   return data;
351 }
352
353 /* A callback function that is registered against the respective
354    add_setshow_* set_doc prototype.  This function will either call
355    the Python function "get_set_string" or extract the Python
356    attribute "set_doc" and return the contents as a string.  If
357    neither exist, insert a string indicating the Parameter is not
358    documented.  */
359 static void
360 get_set_value (char *args, int from_tty,
361                struct cmd_list_element *c)
362 {
363   PyObject *obj = (PyObject *) get_cmd_context (c);
364   gdb::unique_xmalloc_ptr<char> set_doc_string;
365
366   gdbpy_enter enter_py (get_current_arch (), current_language);
367   gdbpy_ref<> set_doc_func (PyString_FromString ("get_set_string"));
368
369   if (set_doc_func == NULL)
370     {
371       gdbpy_print_stack ();
372       return;
373     }
374
375   if (PyObject_HasAttr (obj, set_doc_func.get ()))
376     {
377       set_doc_string = call_doc_function (obj, set_doc_func.get (), NULL);
378       if (! set_doc_string)
379         {
380           gdbpy_print_stack ();
381           return;
382         }
383     }
384   else
385     {
386       /* We have to preserve the existing < GDB 7.3 API.  If a
387          callback function does not exist, then attempt to read the
388          set_doc attribute.  */
389       set_doc_string  = get_doc_string (obj, set_doc_cst);
390     }
391
392   fprintf_filtered (gdb_stdout, "%s\n", set_doc_string.get ());
393 }
394
395 /* A callback function that is registered against the respective
396    add_setshow_* show_doc prototype.  This function will either call
397    the Python function "get_show_string" or extract the Python
398    attribute "show_doc" and return the contents as a string.  If
399    neither exist, insert a string indicating the Parameter is not
400    documented.  */
401 static void
402 get_show_value (struct ui_file *file, int from_tty,
403                 struct cmd_list_element *c,
404                 const char *value)
405 {
406   PyObject *obj = (PyObject *) get_cmd_context (c);
407   gdb::unique_xmalloc_ptr<char> show_doc_string;
408
409   gdbpy_enter enter_py (get_current_arch (), current_language);
410   gdbpy_ref<> show_doc_func (PyString_FromString ("get_show_string"));
411
412   if (show_doc_func == NULL)
413     {
414       gdbpy_print_stack ();
415       return;
416     }
417
418   if (PyObject_HasAttr (obj, show_doc_func.get ()))
419     {
420       gdbpy_ref<> val_obj (PyString_FromString (value));
421
422       if (val_obj == NULL)
423         {
424           gdbpy_print_stack ();
425           return;
426         }
427
428       show_doc_string = call_doc_function (obj, show_doc_func.get (),
429                                            val_obj.get ());
430       if (! show_doc_string)
431         {
432           gdbpy_print_stack ();
433           return;
434         }
435
436       fprintf_filtered (file, "%s\n", show_doc_string.get ());
437     }
438   else
439     {
440       /* We have to preserve the existing < GDB 7.3 API.  If a
441          callback function does not exist, then attempt to read the
442          show_doc attribute.  */
443       show_doc_string  = get_doc_string (obj, show_doc_cst);
444       fprintf_filtered (file, "%s %s\n", show_doc_string.get (), value);
445     }
446 }
447 \f
448
449 /* A helper function that dispatches to the appropriate add_setshow
450    function.  */
451 static void
452 add_setshow_generic (int parmclass, enum command_class cmdclass,
453                      char *cmd_name, parmpy_object *self,
454                      char *set_doc, char *show_doc, char *help_doc,
455                      struct cmd_list_element **set_list,
456                      struct cmd_list_element **show_list)
457 {
458   struct cmd_list_element *param = NULL;
459   const char *tmp_name = NULL;
460
461   switch (parmclass)
462     {
463     case var_boolean:
464
465       add_setshow_boolean_cmd (cmd_name, cmdclass,
466                                &self->value.intval, set_doc, show_doc,
467                                help_doc, get_set_value, get_show_value,
468                                set_list, show_list);
469
470       break;
471
472     case var_auto_boolean:
473       add_setshow_auto_boolean_cmd (cmd_name, cmdclass,
474                                     &self->value.autoboolval,
475                                     set_doc, show_doc, help_doc,
476                                     get_set_value, get_show_value,
477                                     set_list, show_list);
478       break;
479
480     case var_uinteger:
481       add_setshow_uinteger_cmd (cmd_name, cmdclass,
482                                 &self->value.uintval, set_doc, show_doc,
483                                 help_doc, get_set_value, get_show_value,
484                                 set_list, show_list);
485       break;
486
487     case var_integer:
488       add_setshow_integer_cmd (cmd_name, cmdclass,
489                                &self->value.intval, set_doc, show_doc,
490                                help_doc, get_set_value, get_show_value,
491                                set_list, show_list); break;
492
493     case var_string:
494       add_setshow_string_cmd (cmd_name, cmdclass,
495                               &self->value.stringval, set_doc, show_doc,
496                               help_doc, get_set_value, get_show_value,
497                               set_list, show_list); break;
498
499     case var_string_noescape:
500       add_setshow_string_noescape_cmd (cmd_name, cmdclass,
501                                        &self->value.stringval,
502                                        set_doc, show_doc, help_doc,
503                                        get_set_value, get_show_value,
504                                        set_list, show_list);
505
506       break;
507
508     case var_optional_filename:
509       add_setshow_optional_filename_cmd (cmd_name, cmdclass,
510                                          &self->value.stringval, set_doc,
511                                          show_doc, help_doc, get_set_value,
512                                          get_show_value, set_list,
513                                          show_list);
514       break;
515
516     case var_filename:
517       add_setshow_filename_cmd (cmd_name, cmdclass,
518                                 &self->value.stringval, set_doc, show_doc,
519                                 help_doc, get_set_value, get_show_value,
520                                 set_list, show_list); break;
521
522     case var_zinteger:
523       add_setshow_zinteger_cmd (cmd_name, cmdclass,
524                                 &self->value.intval, set_doc, show_doc,
525                                 help_doc, get_set_value, get_show_value,
526                                 set_list, show_list);
527       break;
528
529     case var_enum:
530       add_setshow_enum_cmd (cmd_name, cmdclass, self->enumeration,
531                             &self->value.cstringval, set_doc, show_doc,
532                             help_doc, get_set_value, get_show_value,
533                             set_list, show_list);
534       /* Initialize the value, just in case.  */
535       self->value.cstringval = self->enumeration[0];
536       break;
537     }
538
539   /* Lookup created parameter, and register Python object against the
540      parameter context.  Perform this task against both lists.  */
541   tmp_name = cmd_name;
542   param = lookup_cmd (&tmp_name, *show_list, "", 0, 1);
543   if (param)
544     set_cmd_context (param, self);
545
546   tmp_name = cmd_name;
547   param = lookup_cmd (&tmp_name, *set_list, "", 0, 1);
548   if (param)
549     set_cmd_context (param, self);
550 }
551
552 /* A helper which computes enum values.  Returns 1 on success.  Returns 0 on
553    error, with a python exception set.  */
554 static int
555 compute_enum_values (parmpy_object *self, PyObject *enum_values)
556 {
557   Py_ssize_t size, i;
558
559   if (! enum_values)
560     {
561       PyErr_SetString (PyExc_RuntimeError,
562                        _("An enumeration is required for PARAM_ENUM."));
563       return 0;
564     }
565
566   if (! PySequence_Check (enum_values))
567     {
568       PyErr_SetString (PyExc_RuntimeError,
569                        _("The enumeration is not a sequence."));
570       return 0;
571     }
572
573   size = PySequence_Size (enum_values);
574   if (size < 0)
575     return 0;
576   if (size == 0)
577     {
578       PyErr_SetString (PyExc_RuntimeError,
579                        _("The enumeration is empty."));
580       return 0;
581     }
582
583   gdb_argv holder (XCNEWVEC (char *, size + 1));
584   char **enumeration = holder.get ();
585
586   for (i = 0; i < size; ++i)
587     {
588       gdbpy_ref<> item (PySequence_GetItem (enum_values, i));
589
590       if (item == NULL)
591         return 0;
592       if (! gdbpy_is_string (item.get ()))
593         {
594           PyErr_SetString (PyExc_RuntimeError,
595                            _("The enumeration item not a string."));
596           return 0;
597         }
598       enumeration[i] = python_string_to_host_string (item.get ()).release ();
599       if (enumeration[i] == NULL)
600         return 0;
601     }
602
603   self->enumeration = const_cast<const char**> (holder.release ());
604   return 1;
605 }
606
607 /* Object initializer; sets up gdb-side structures for command.
608
609    Use: __init__(NAME, CMDCLASS, PARMCLASS, [ENUM])
610
611    NAME is the name of the parameter.  It may consist of multiple
612    words, in which case the final word is the name of the new command,
613    and earlier words must be prefix commands.
614
615    CMDCLASS is the kind of command.  It should be one of the COMMAND_*
616    constants defined in the gdb module.
617
618    PARMCLASS is the type of the parameter.  It should be one of the
619    PARAM_* constants defined in the gdb module.
620
621    If PARMCLASS is PARAM_ENUM, then the final argument should be a
622    collection of strings.  These strings are the valid values for this
623    parameter.
624
625    The documentation for the parameter is taken from the doc string
626    for the python class.
627
628    Returns -1 on error, with a python exception set.  */
629
630 static int
631 parmpy_init (PyObject *self, PyObject *args, PyObject *kwds)
632 {
633   parmpy_object *obj = (parmpy_object *) self;
634   const char *name;
635   char *set_doc, *show_doc, *doc;
636   char *cmd_name;
637   int parmclass, cmdtype;
638   PyObject *enum_values = NULL;
639   struct cmd_list_element **set_list, **show_list;
640
641   if (! PyArg_ParseTuple (args, "sii|O", &name, &cmdtype, &parmclass,
642                           &enum_values))
643     return -1;
644
645   if (cmdtype != no_class && cmdtype != class_run
646       && cmdtype != class_vars && cmdtype != class_stack
647       && cmdtype != class_files && cmdtype != class_support
648       && cmdtype != class_info && cmdtype != class_breakpoint
649       && cmdtype != class_trace && cmdtype != class_obscure
650       && cmdtype != class_maintenance)
651     {
652       PyErr_Format (PyExc_RuntimeError, _("Invalid command class argument."));
653       return -1;
654     }
655
656   if (parmclass != var_boolean /* ARI: var_boolean */
657       && parmclass != var_auto_boolean
658       && parmclass != var_uinteger && parmclass != var_integer
659       && parmclass != var_string && parmclass != var_string_noescape
660       && parmclass != var_optional_filename && parmclass != var_filename
661       && parmclass != var_zinteger && parmclass != var_enum)
662     {
663       PyErr_SetString (PyExc_RuntimeError,
664                        _("Invalid parameter class argument."));
665       return -1;
666     }
667
668   if (enum_values && parmclass != var_enum)
669     {
670       PyErr_SetString (PyExc_RuntimeError,
671                        _("Only PARAM_ENUM accepts a fourth argument."));
672       return -1;
673     }
674   if (parmclass == var_enum)
675     {
676       if (! compute_enum_values (obj, enum_values))
677         return -1;
678     }
679   else
680     obj->enumeration = NULL;
681   obj->type = (enum var_types) parmclass;
682   memset (&obj->value, 0, sizeof (obj->value));
683
684   cmd_name = gdbpy_parse_command_name (name, &set_list,
685                                        &setlist);
686
687   if (! cmd_name)
688     return -1;
689   xfree (cmd_name);
690   cmd_name = gdbpy_parse_command_name (name, &show_list,
691                                        &showlist);
692   if (! cmd_name)
693     return -1;
694
695   set_doc = get_doc_string (self, set_doc_cst).release ();
696   show_doc = get_doc_string (self, show_doc_cst).release ();
697   doc = get_doc_string (self, gdbpy_doc_cst).release ();
698
699   Py_INCREF (self);
700
701   TRY
702     {
703       add_setshow_generic (parmclass, (enum command_class) cmdtype,
704                            cmd_name, obj,
705                            set_doc, show_doc,
706                            doc, set_list, show_list);
707     }
708   CATCH (except, RETURN_MASK_ALL)
709     {
710       xfree (cmd_name);
711       xfree (set_doc);
712       xfree (show_doc);
713       xfree (doc);
714       Py_DECREF (self);
715       PyErr_Format (except.reason == RETURN_QUIT
716                     ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
717                     "%s", except.message);
718       return -1;
719     }
720   END_CATCH
721
722   return 0;
723 }
724
725 \f
726
727 /* Initialize the 'parameters' module.  */
728 int
729 gdbpy_initialize_parameters (void)
730 {
731   int i;
732
733   parmpy_object_type.tp_new = PyType_GenericNew;
734   if (PyType_Ready (&parmpy_object_type) < 0)
735     return -1;
736
737   set_doc_cst = PyString_FromString ("set_doc");
738   if (! set_doc_cst)
739     return -1;
740   show_doc_cst = PyString_FromString ("show_doc");
741   if (! show_doc_cst)
742     return -1;
743
744   for (i = 0; parm_constants[i].name; ++i)
745     {
746       if (PyModule_AddIntConstant (gdb_module,
747                                    parm_constants[i].name,
748                                    parm_constants[i].value) < 0)
749         return -1;
750     }
751
752   return gdb_pymodule_addobject (gdb_module, "Parameter",
753                                  (PyObject *) &parmpy_object_type);
754 }
755
756 \f
757
758 PyTypeObject parmpy_object_type =
759 {
760   PyVarObject_HEAD_INIT (NULL, 0)
761   "gdb.Parameter",                /*tp_name*/
762   sizeof (parmpy_object),         /*tp_basicsize*/
763   0,                              /*tp_itemsize*/
764   0,                              /*tp_dealloc*/
765   0,                              /*tp_print*/
766   0,                              /*tp_getattr*/
767   0,                              /*tp_setattr*/
768   0,                              /*tp_compare*/
769   0,                              /*tp_repr*/
770   0,                              /*tp_as_number*/
771   0,                              /*tp_as_sequence*/
772   0,                              /*tp_as_mapping*/
773   0,                              /*tp_hash */
774   0,                              /*tp_call*/
775   0,                              /*tp_str*/
776   get_attr,                       /*tp_getattro*/
777   set_attr,                       /*tp_setattro*/
778   0,                              /*tp_as_buffer*/
779   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
780   "GDB parameter object",         /* tp_doc */
781   0,                              /* tp_traverse */
782   0,                              /* tp_clear */
783   0,                              /* tp_richcompare */
784   0,                              /* tp_weaklistoffset */
785   0,                              /* tp_iter */
786   0,                              /* tp_iternext */
787   0,                              /* tp_methods */
788   0,                              /* tp_members */
789   0,                              /* tp_getset */
790   0,                              /* tp_base */
791   0,                              /* tp_dict */
792   0,                              /* tp_descr_get */
793   0,                              /* tp_descr_set */
794   0,                              /* tp_dictoffset */
795   parmpy_init,                    /* tp_init */
796   0,                              /* tp_alloc */
797 };
This page took 0.073556 seconds and 4 git commands to generate.