Cleanup: add trailing commas
[blender.git] / source / blender / python / bmesh / bmesh_py_ops.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (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 Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2012 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Campbell Barton
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/python/bmesh/bmesh_py_ops.c
27  *  \ingroup pybmesh
28  *
29  * This file defines the 'bmesh.ops' module.
30  * Operators from 'opdefines' are wrapped.
31  */
32
33 #include <Python.h>
34
35 #include "BLI_utildefines.h"
36 #include "BLI_dynstr.h"
37
38 #include "MEM_guardedalloc.h"
39
40
41 #include "bmesh.h"
42
43 #include "bmesh_py_ops_call.h"
44 #include "bmesh_py_ops.h"  /* own include */
45
46 /* bmesh operator 'bmesh.ops.*' callable types
47  * ******************************************* */
48 static PyTypeObject bmesh_op_Type;
49
50 static PyObject *bpy_bmesh_op_CreatePyObject(const char *opname)
51 {
52         BPy_BMeshOpFunc *self = PyObject_New(BPy_BMeshOpFunc, &bmesh_op_Type);
53
54         self->opname = opname;
55
56         return (PyObject *)self;
57 }
58
59 static PyObject *bpy_bmesh_op_repr(BPy_BMeshOpFunc *self)
60 {
61         return PyUnicode_FromFormat("<%.200s bmesh.ops.%.200s()>",
62                                     Py_TYPE(self)->tp_name,
63                                     self->opname);
64 }
65
66
67 /* methods
68  * ======= */
69
70
71 /* __doc__
72  * ------- */
73
74 static char *bmp_slots_as_args(const BMOSlotType slot_types[BMO_OP_MAX_SLOTS], const bool is_out)
75 {
76         DynStr *dyn_str = BLI_dynstr_new();
77         char *ret;
78         bool quoted;
79         bool set;
80
81         int i = 0;
82
83         while (*slot_types[i].name) {
84                 quoted = false;
85                 set = false;
86                 /* cut off '.out' by using a string size arg */
87                 const int name_len = is_out ?
88                         (strchr(slot_types[i].name, '.') - slot_types[i].name) :
89                         sizeof(slot_types[i].name);
90                 const char *value = "<Unknown>";
91                 switch (slot_types[i].type) {
92                         case BMO_OP_SLOT_BOOL:          value = "False"; break;
93                         case BMO_OP_SLOT_INT:
94                                 if (slot_types[i].subtype.intg == BMO_OP_SLOT_SUBTYPE_INT_ENUM) {
95                                         value = slot_types[i].enum_flags[0].identifier;
96                                         quoted = true;
97                                 }
98                                 else if (slot_types[i].subtype.intg == BMO_OP_SLOT_SUBTYPE_INT_FLAG) {
99                                         value = "";
100                                         set = true;
101                                 }
102                                 else {
103                                         value = "0";
104                                 }
105                                 break;
106                         case BMO_OP_SLOT_FLT:           value = "0.0"; break;
107                         case BMO_OP_SLOT_PTR:           value = "None"; break;
108                         case BMO_OP_SLOT_MAT:           value = "Matrix()"; break;
109                         case BMO_OP_SLOT_VEC:           value = "Vector()"; break;
110                         case BMO_OP_SLOT_ELEMENT_BUF:   value =
111                              (slot_types[i].subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) ? "None" : "[]"; break;
112                         case BMO_OP_SLOT_MAPPING:       value = "{}"; break;
113                 }
114                 BLI_dynstr_appendf(
115                         dyn_str, i ? ", %.*s=%s%s%s%s%s" : "%.*s=%s%s%s%s%s",
116                         name_len, slot_types[i].name,
117                         set ? "{" : "", quoted ? "'" : "",
118                         value,
119                         quoted ? "'" : "", set ? "}" : "");
120                 i++;
121         }
122
123         ret = BLI_dynstr_get_cstring(dyn_str);
124         BLI_dynstr_free(dyn_str);
125         return ret;
126 }
127
128 static PyObject *bpy_bmesh_op_doc_get(BPy_BMeshOpFunc *self, void *UNUSED(closure))
129 {
130         PyObject *ret;
131         char *slot_in;
132         char *slot_out;
133         int i;
134
135         i = BMO_opcode_from_opname(self->opname);
136
137         slot_in  = bmp_slots_as_args(bmo_opdefines[i]->slot_types_in, false);
138         slot_out = bmp_slots_as_args(bmo_opdefines[i]->slot_types_out, true);
139
140         ret = PyUnicode_FromFormat("%.200s bmesh.ops.%.200s(bmesh, %s)\n  -> dict(%s)",
141                                    Py_TYPE(self)->tp_name,
142                                    self->opname, slot_in, slot_out);
143
144         MEM_freeN(slot_in);
145         MEM_freeN(slot_out);
146
147         return ret;
148 }
149
150 static PyGetSetDef bpy_bmesh_op_getseters[] = {
151         {(char *)"__doc__", (getter)bpy_bmesh_op_doc_get, (setter)NULL, NULL, NULL},
152         {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
153 };
154
155
156 /* Types
157  * ===== */
158
159 static PyTypeObject bmesh_op_Type = {
160         PyVarObject_HEAD_INIT(NULL, 0)
161         "BMeshOpFunc",              /* tp_name */
162         sizeof(BPy_BMeshOpFunc),    /* tp_basicsize */
163         0,                          /* tp_itemsize */
164         /* methods */
165         NULL,                       /* tp_dealloc */
166         NULL,                       /* printfunc tp_print; */
167         NULL,                       /* getattrfunc tp_getattr; */
168         NULL,                       /* setattrfunc tp_setattr; */
169         NULL,                       /* tp_compare */ /* DEPRECATED in python 3.0! */
170         (reprfunc) bpy_bmesh_op_repr, /* tp_repr */
171
172         /* Method suites for standard classes */
173
174         NULL,                       /* PyNumberMethods *tp_as_number; */
175         NULL,                       /* PySequenceMethods *tp_as_sequence; */
176         NULL,                       /* PyMappingMethods *tp_as_mapping; */
177
178         /* More standard operations (here for binary compatibility) */
179
180         NULL,                       /* hashfunc tp_hash; */
181         (ternaryfunc)BPy_BMO_call,  /* ternaryfunc tp_call; */
182         NULL,                       /* reprfunc tp_str; */
183
184         /* will only use these if this is a subtype of a py class */
185         NULL,                       /* getattrofunc tp_getattro; */
186         NULL,                       /* setattrofunc tp_setattro; */
187
188         /* Functions to access object as input/output buffer */
189         NULL,                       /* PyBufferProcs *tp_as_buffer; */
190
191         /*** Flags to define presence of optional/expanded features ***/
192         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
193
194         NULL,                       /*  char *tp_doc;  Documentation string */
195         /*** Assigned meaning in release 2.0 ***/
196         /* call function for all accessible objects */
197         NULL,                       /* traverseproc tp_traverse; */
198
199         /* delete references to contained objects */
200         NULL,                       /* inquiry tp_clear; */
201
202         /***  Assigned meaning in release 2.1 ***/
203         /*** rich comparisons ***/
204         NULL,                       /* richcmpfunc tp_richcompare; */
205
206         /***  weak reference enabler ***/
207         0,
208         /*** Added in release 2.2 ***/
209         /*   Iterators */
210         NULL,                       /* getiterfunc tp_iter; */
211         NULL,                       /* iternextfunc tp_iternext; */
212
213         /*** Attribute descriptor and subclassing stuff ***/
214         NULL,                       /* struct PyMethodDef *tp_methods; */
215         NULL,                       /* struct PyMemberDef *tp_members; */
216         bpy_bmesh_op_getseters,     /* struct PyGetSetDef *tp_getset; */
217         NULL,                       /* struct _typeobject *tp_base; */
218         NULL,                       /* PyObject *tp_dict; */
219         NULL,                       /* descrgetfunc tp_descr_get; */
220         NULL,                       /* descrsetfunc tp_descr_set; */
221         0,                          /* long tp_dictoffset; */
222         NULL,                       /* initproc tp_init; */
223         NULL,                       /* allocfunc tp_alloc; */
224         NULL,                       /* newfunc tp_new; */
225         /*  Low-level free-memory routine */
226         NULL,                       /* freefunc tp_free;  */
227         /* For PyObject_IS_GC */
228         NULL,                       /* inquiry tp_is_gc;  */
229         NULL,                       /* PyObject *tp_bases; */
230         /* method resolution order */
231         NULL,                       /* PyObject *tp_mro;  */
232         NULL,                       /* PyObject *tp_cache; */
233         NULL,                       /* PyObject *tp_subclasses; */
234         NULL,                       /* PyObject *tp_weaklist; */
235         NULL,
236 };
237
238
239 /* bmesh fake module 'bmesh.ops'
240  * ***************************** */
241
242 static PyObject *bpy_bmesh_ops_fakemod_getattro(PyObject *UNUSED(self), PyObject *pyname)
243 {
244         const char *opname = _PyUnicode_AsString(pyname);
245
246         if (BMO_opcode_from_opname(opname) != -1) {
247                 return bpy_bmesh_op_CreatePyObject(opname);
248         }
249         else {
250                 PyErr_Format(PyExc_AttributeError,
251                              "BMeshOpsModule: operator \"%.200s\" doesn't exist",
252                              opname);
253                 return NULL;
254         }
255 }
256
257 static PyObject *bpy_bmesh_ops_fakemod_dir(PyObject *UNUSED(self))
258 {
259         const unsigned int tot = bmo_opdefines_total;
260         unsigned int i;
261         PyObject *ret;
262
263         ret = PyList_New(bmo_opdefines_total);
264
265         for (i = 0; i < tot; i++) {
266                 PyList_SET_ITEM(ret, i, PyUnicode_FromString(bmo_opdefines[i]->opname));
267         }
268
269         return ret;
270 }
271
272 static struct PyMethodDef bpy_bmesh_ops_fakemod_methods[] = {
273         {"__dir__", (PyCFunction)bpy_bmesh_ops_fakemod_dir, METH_NOARGS, NULL},
274         {NULL, NULL, 0, NULL}
275 };
276
277 static PyTypeObject bmesh_ops_fakemod_Type = {
278         PyVarObject_HEAD_INIT(NULL, 0)
279         "BMeshOpsModule",           /* tp_name */
280         0,                          /* tp_basicsize */
281         0,                          /* tp_itemsize */
282         /* methods */
283         NULL,                       /* tp_dealloc */
284         NULL,                       /* printfunc tp_print; */
285         NULL,                       /* getattrfunc tp_getattr; */
286         NULL,                       /* setattrfunc tp_setattr; */
287         NULL,                       /* tp_compare */ /* DEPRECATED in python 3.0! */
288         NULL,                       /* tp_repr */
289
290         /* Method suites for standard classes */
291
292         NULL,                       /* PyNumberMethods *tp_as_number; */
293         NULL,                       /* PySequenceMethods *tp_as_sequence; */
294         NULL,                       /* PyMappingMethods *tp_as_mapping; */
295
296         /* More standard operations (here for binary compatibility) */
297
298         NULL,                       /* hashfunc tp_hash; */
299         NULL,                       /* ternaryfunc tp_call; */
300         NULL,                       /* reprfunc tp_str; */
301
302         /* will only use these if this is a subtype of a py class */
303         bpy_bmesh_ops_fakemod_getattro,    /* getattrofunc tp_getattro; */
304         NULL,                       /* setattrofunc tp_setattro; */
305
306         /* Functions to access object as input/output buffer */
307         NULL,                       /* PyBufferProcs *tp_as_buffer; */
308
309         /*** Flags to define presence of optional/expanded features ***/
310         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
311
312         NULL,                       /*  char *tp_doc;  Documentation string */
313         /*** Assigned meaning in release 2.0 ***/
314         /* call function for all accessible objects */
315         NULL,                       /* traverseproc tp_traverse; */
316
317         /* delete references to contained objects */
318         NULL,                       /* inquiry tp_clear; */
319
320         /***  Assigned meaning in release 2.1 ***/
321         /*** rich comparisons ***/
322         NULL, /* subclassed */          /* richcmpfunc tp_richcompare; */
323
324         /***  weak reference enabler ***/
325         0,
326         /*** Added in release 2.2 ***/
327         /*   Iterators */
328         NULL,                       /* getiterfunc tp_iter; */
329         NULL,                       /* iternextfunc tp_iternext; */
330
331         /*** Attribute descriptor and subclassing stuff ***/
332         bpy_bmesh_ops_fakemod_methods,  /* struct PyMethodDef *tp_methods; */
333         NULL,                       /* struct PyMemberDef *tp_members; */
334         NULL,                       /* struct PyGetSetDef *tp_getset; */
335         NULL,                       /* struct _typeobject *tp_base; */
336         NULL,                       /* PyObject *tp_dict; */
337         NULL,                       /* descrgetfunc tp_descr_get; */
338         NULL,                       /* descrsetfunc tp_descr_set; */
339         0,                          /* long tp_dictoffset; */
340         NULL,                       /* initproc tp_init; */
341         NULL,                       /* allocfunc tp_alloc; */
342         NULL,                       /* newfunc tp_new; */
343         /*  Low-level free-memory routine */
344         NULL,                       /* freefunc tp_free;  */
345         /* For PyObject_IS_GC */
346         NULL,                       /* inquiry tp_is_gc;  */
347         NULL,                       /* PyObject *tp_bases; */
348         /* method resolution order */
349         NULL,                       /* PyObject *tp_mro;  */
350         NULL,                       /* PyObject *tp_cache; */
351         NULL,                       /* PyObject *tp_subclasses; */
352         NULL,                       /* PyObject *tp_weaklist; */
353         NULL,
354 };
355
356 PyObject *BPyInit_bmesh_ops(void)
357 {
358         PyObject *submodule;
359
360         if (PyType_Ready(&bmesh_ops_fakemod_Type) < 0)
361                 return NULL;
362
363         if (PyType_Ready(&bmesh_op_Type) < 0)
364                 return NULL;
365
366         submodule = PyObject_New(PyObject, &bmesh_ops_fakemod_Type);
367
368         /* prevent further creation of instances */
369         bmesh_ops_fakemod_Type.tp_init = NULL;
370         bmesh_ops_fakemod_Type.tp_new = NULL;
371
372         return submodule;
373 }