Merge fixes from branch 'xorn'
[geda-gaf.git] / xorn / src / cpython / storage / module.c
blob1c84f4fd20c46b468d415922169597bbba107d32
1 /* Copyright (C) 2013-2020 Roland Lutz
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software Foundation,
15 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17 #include "module.h"
18 #include "data.h"
21 static PyObject *to_python_list(xorn_object_t *objects, size_t count)
23 PyObject *list;
24 size_t i;
26 list = PyList_New(count);
27 if (list == NULL)
28 return NULL;
30 for (i = 0; i < count; i++) {
31 PyObject *ob_item = build_object(objects[i]);
32 if (ob_item == NULL) {
33 Py_DECREF(list);
34 free(objects);
35 return NULL;
37 PyList_SET_ITEM(list, i, ob_item);
40 free(objects);
41 return list;
44 static PyObject *get_objects_attached_to(
45 PyObject *self, PyObject *args, PyObject *kwds)
47 PyObject *rev_arg = NULL, *ob_arg = NULL;
48 static char *kwlist[] = { "rev", "ob", NULL };
50 if (!PyArg_ParseTupleAndKeywords(
51 args, kwds, "O!O:get_objects_attached_to", kwlist,
52 &RevisionType, &rev_arg, &ob_arg))
53 return NULL;
55 if (ob_arg != Py_None &&
56 !PyObject_TypeCheck(ob_arg, &ObjectType)) {
57 char buf[BUFSIZ];
58 snprintf(buf, BUFSIZ, "get_objects_attached_to() argument 2 "
59 "must be %.50s or None, not %.50s",
60 ObjectType.tp_name,
61 ob_arg->ob_type->tp_name);
62 PyErr_SetString(PyExc_TypeError, buf);
63 return NULL;
66 if (ob_arg != Py_None &&
67 !xorn_object_exists_in_revision(((Revision *)rev_arg)->rev,
68 ((Object *)ob_arg)->ob)) {
69 PyErr_SetString(PyExc_KeyError, "object does not exist");
70 return NULL;
73 xorn_object_t *objects;
74 size_t count;
76 if (xorn_get_objects_attached_to(((Revision *)rev_arg)->rev,
77 ob_arg == Py_None ? NULL :
78 ((Object *)ob_arg)->ob,
79 &objects, &count) == -1)
80 return PyErr_NoMemory();
82 return to_python_list(objects, count);
85 static PyObject *get_selected_objects(
86 PyObject *self, PyObject *args, PyObject *kwds)
88 PyObject *rev_arg = NULL, *sel_arg = NULL;
89 static char *kwlist[] = { "rev", "sel", NULL };
91 if (!PyArg_ParseTupleAndKeywords(
92 args, kwds, "O!O!:get_selected_objects", kwlist,
93 &RevisionType, &rev_arg, &SelectionType, &sel_arg))
94 return NULL;
96 xorn_object_t *objects;
97 size_t count;
99 if (xorn_get_selected_objects(((Revision *)rev_arg)->rev,
100 ((Selection *)sel_arg)->sel,
101 &objects, &count) == -1)
102 return PyErr_NoMemory();
104 return to_python_list(objects, count);
107 static PyObject *get_added_objects(
108 PyObject *self, PyObject *args, PyObject *kwds)
110 PyObject *from_arg = NULL, *to_arg = NULL;
111 static char *kwlist[] = { "from", "to", NULL };
113 if (!PyArg_ParseTupleAndKeywords(
114 args, kwds, "O!O!:get_added_objects", kwlist,
115 &RevisionType, &from_arg, &RevisionType, &to_arg))
116 return NULL;
118 xorn_object_t *objects;
119 size_t count;
121 if (xorn_get_added_objects(((Revision *)from_arg)->rev,
122 ((Revision *)to_arg)->rev,
123 &objects, &count) == -1)
124 return PyErr_NoMemory();
126 return to_python_list(objects, count);
129 static PyObject *get_removed_objects(
130 PyObject *self, PyObject *args, PyObject *kwds)
132 PyObject *from_arg = NULL, *to_arg = NULL;
133 static char *kwlist[] = { "from", "to", NULL };
135 if (!PyArg_ParseTupleAndKeywords(
136 args, kwds, "O!O!:get_removed_objects", kwlist,
137 &RevisionType, &from_arg, &RevisionType, &to_arg))
138 return NULL;
140 xorn_object_t *objects;
141 size_t count;
143 if (xorn_get_removed_objects(((Revision *)from_arg)->rev,
144 ((Revision *)to_arg)->rev,
145 &objects, &count) == -1)
146 return PyErr_NoMemory();
148 return to_python_list(objects, count);
151 static PyObject *get_modified_objects(
152 PyObject *self, PyObject *args, PyObject *kwds)
154 PyObject *from_arg = NULL, *to_arg = NULL;
155 static char *kwlist[] = { "from", "to", NULL };
157 if (!PyArg_ParseTupleAndKeywords(
158 args, kwds, "O!O!:get_modified_objects", kwlist,
159 &RevisionType, &from_arg, &RevisionType, &to_arg))
160 return NULL;
162 xorn_object_t *objects;
163 size_t count;
165 if (xorn_get_modified_objects(((Revision *)from_arg)->rev,
166 ((Revision *)to_arg)->rev,
167 &objects, &count) == -1)
168 return PyErr_NoMemory();
170 return to_python_list(objects, count);
173 /****************************************************************************/
175 static PyObject *select_none(
176 PyObject *self, PyObject *args, PyObject *kwds)
178 xorn_selection_t sel = xorn_select_none();
179 return sel ? build_selection(sel) : PyErr_NoMemory();
182 static PyObject *select_object(
183 PyObject *self, PyObject *args, PyObject *kwds)
185 PyObject *ob_arg = NULL;
186 static char *kwlist[] = { "ob", NULL };
188 if (!PyArg_ParseTupleAndKeywords(
189 args, kwds, "O!:select_object", kwlist,
190 &ObjectType, &ob_arg))
191 return NULL;
193 xorn_selection_t sel = xorn_select_object(((Object *)ob_arg)->ob);
194 return sel ? build_selection(sel) : PyErr_NoMemory();
197 static PyObject *select_attached_to(
198 PyObject *self, PyObject *args, PyObject *kwds)
200 PyObject *rev_arg = NULL, *ob_arg = NULL;
201 static char *kwlist[] = { "rev", "ob", NULL };
203 if (!PyArg_ParseTupleAndKeywords(
204 args, kwds, "O!O:select_attached_to", kwlist,
205 &RevisionType, &rev_arg, &ob_arg))
206 return NULL;
208 if (ob_arg != Py_None &&
209 !PyObject_TypeCheck(ob_arg, &ObjectType)) {
210 char buf[BUFSIZ];
211 snprintf(buf, BUFSIZ, "select_attached_to() argument 2 "
212 "must be %.50s or None, not %.50s",
213 ObjectType.tp_name,
214 ob_arg->ob_type->tp_name);
215 PyErr_SetString(PyExc_TypeError, buf);
216 return NULL;
219 if (ob_arg != Py_None &&
220 !xorn_object_exists_in_revision(((Revision *)rev_arg)->rev,
221 ((Object *)ob_arg)->ob)) {
222 PyErr_SetString(PyExc_KeyError, "object does not exist");
223 return NULL;
226 xorn_selection_t sel = xorn_select_attached_to(
227 ((Revision *)rev_arg)->rev,
228 ob_arg == Py_None ? NULL : ((Object *)ob_arg)->ob);
229 return sel ? build_selection(sel) : PyErr_NoMemory();
232 static PyObject *select_all(
233 PyObject *self, PyObject *args, PyObject *kwds)
235 PyObject *rev_arg = NULL;
236 static char *kwlist[] = { "rev", NULL };
238 if (!PyArg_ParseTupleAndKeywords(
239 args, kwds, "O!:select_all", kwlist,
240 &RevisionType, &rev_arg))
241 return NULL;
243 xorn_selection_t sel = xorn_select_all(((Revision *)rev_arg)->rev);
244 return sel ? build_selection(sel) : PyErr_NoMemory();
247 static PyObject *select_all_except(
248 PyObject *self, PyObject *args, PyObject *kwds)
250 PyObject *rev_arg = NULL, *sel_arg = NULL;
251 static char *kwlist[] = { "rev", "sel", NULL };
253 if (!PyArg_ParseTupleAndKeywords(
254 args, kwds, "O!O!:select_all_except", kwlist,
255 &RevisionType, &rev_arg, &SelectionType, &sel_arg))
256 return NULL;
258 xorn_selection_t sel = xorn_select_all_except(
259 ((Revision *)rev_arg)->rev, ((Selection *)sel_arg)->sel);
260 return sel ? build_selection(sel) : PyErr_NoMemory();
263 static PyObject *select_including(
264 PyObject *self, PyObject *args, PyObject *kwds)
266 PyObject *sel_arg = NULL, *ob_arg = NULL;
267 static char *kwlist[] = { "sel", "ob", NULL };
269 if (!PyArg_ParseTupleAndKeywords(
270 args, kwds, "O!O!:select_including", kwlist,
271 &SelectionType, &sel_arg, &ObjectType, &ob_arg))
272 return NULL;
274 xorn_selection_t sel = xorn_select_including(
275 ((Selection *)sel_arg)->sel, ((Object *)ob_arg)->ob);
276 return sel ? build_selection(sel) : PyErr_NoMemory();
279 static PyObject *select_excluding(
280 PyObject *self, PyObject *args, PyObject *kwds)
282 PyObject *sel_arg = NULL, *ob_arg = NULL;
283 static char *kwlist[] = { "sel", "ob", NULL };
285 if (!PyArg_ParseTupleAndKeywords(
286 args, kwds, "O!O!:select_excluding", kwlist,
287 &SelectionType, &sel_arg, &ObjectType, &ob_arg))
288 return NULL;
290 xorn_selection_t sel = xorn_select_excluding(
291 ((Selection *)sel_arg)->sel, ((Object *)ob_arg)->ob);
292 return sel ? build_selection(sel) : PyErr_NoMemory();
295 static PyObject *select_union(
296 PyObject *self, PyObject *args, PyObject *kwds)
298 PyObject *sel0_arg = NULL, *sel1_arg = NULL;
299 static char *kwlist[] = { "sel0", "sel1", NULL };
301 if (!PyArg_ParseTupleAndKeywords(
302 args, kwds, "O!O!:select_union", kwlist,
303 &SelectionType, &sel0_arg, &SelectionType, &sel1_arg))
304 return NULL;
306 xorn_selection_t sel = xorn_select_union(((Selection *)sel0_arg)->sel,
307 ((Selection *)sel1_arg)->sel);
308 return sel ? build_selection(sel) : PyErr_NoMemory();
311 static PyObject *select_intersection(
312 PyObject *self, PyObject *args, PyObject *kwds)
314 PyObject *sel0_arg = NULL, *sel1_arg = NULL;
315 static char *kwlist[] = { "sel0", "sel1", NULL };
317 if (!PyArg_ParseTupleAndKeywords(
318 args, kwds, "O!O!:select_intersection", kwlist,
319 &SelectionType, &sel0_arg, &SelectionType, &sel1_arg))
320 return NULL;
322 xorn_selection_t sel = xorn_select_intersection(
323 ((Selection *)sel0_arg)->sel, ((Selection *)sel1_arg)->sel);
324 return sel ? build_selection(sel) : PyErr_NoMemory();
327 static PyObject *select_difference(
328 PyObject *self, PyObject *args, PyObject *kwds)
330 PyObject *sel0_arg = NULL, *sel1_arg = NULL;
331 static char *kwlist[] = { "sel0", "sel1", NULL };
333 if (!PyArg_ParseTupleAndKeywords(
334 args, kwds, "O!O!:select_difference", kwlist,
335 &SelectionType, &sel0_arg, &SelectionType, &sel1_arg))
336 return NULL;
338 xorn_selection_t sel = xorn_select_difference(
339 ((Selection *)sel0_arg)->sel, ((Selection *)sel1_arg)->sel);
340 return sel ? build_selection(sel) : PyErr_NoMemory();
343 static PyObject *selection_is_empty(
344 PyObject *self, PyObject *args, PyObject *kwds)
346 PyObject *rev_arg = NULL, *sel_arg = NULL;
347 static char *kwlist[] = { "rev", "sel", NULL };
349 if (!PyArg_ParseTupleAndKeywords(
350 args, kwds, "O!O!:selection_is_empty", kwlist,
351 &RevisionType, &rev_arg, &SelectionType, &sel_arg))
352 return NULL;
354 PyObject *result = xorn_selection_is_empty(
355 ((Revision *)rev_arg)->rev,
356 ((Selection *)sel_arg)->sel) ? Py_True : Py_False;
357 Py_INCREF(result);
358 return result;
361 static PyObject *object_is_selected(
362 PyObject *self, PyObject *args, PyObject *kwds)
364 PyObject *rev_arg = NULL, *sel_arg = NULL, *ob_arg = NULL;
365 static char *kwlist[] = { "rev", "sel", "ob", NULL };
367 if (!PyArg_ParseTupleAndKeywords(
368 args, kwds, "O!O!O!:object_is_selected", kwlist,
369 &RevisionType, &rev_arg, &SelectionType, &sel_arg,
370 &ObjectType, &ob_arg))
371 return NULL;
373 PyObject *result = xorn_object_is_selected(
374 ((Revision *)rev_arg)->rev,
375 ((Selection *)sel_arg)->sel,
376 ((Object *)ob_arg)->ob) ? Py_True : Py_False;
377 Py_INCREF(result);
378 return result;
381 static PyMethodDef methods[] = {
382 { "get_objects_attached_to",
383 (PyCFunction)get_objects_attached_to, METH_KEYWORDS,
384 PyDoc_STR("get_objects_attached_to(rev, ob) -> [Object] -- "
385 "a list of objects in a revision which are attached to a "
386 "certain object") },
387 { "get_selected_objects",
388 (PyCFunction)get_selected_objects, METH_KEYWORDS,
389 PyDoc_STR("get_selected_objects(rev, sel) -> [Object] -- "
390 "a list of objects which are in a revision as well as in "
391 "a selection") },
392 { "get_added_objects", (PyCFunction)get_added_objects, METH_KEYWORDS,
393 PyDoc_STR("get_added_objects(from, to) -> [Object] -- "
394 "a list of objects which are in one revision but not in "
395 "another") },
396 { "get_removed_objects",
397 (PyCFunction)get_removed_objects, METH_KEYWORDS,
398 PyDoc_STR("get_removed_objects(from, to) -> [Object] -- "
399 "a list of objects which are in one revision but not in "
400 "another") },
401 { "get_modified_objects",
402 (PyCFunction)get_modified_objects, METH_KEYWORDS,
403 PyDoc_STR("get_modified_objects(from, to) -> [Object] -- "
404 "a list of objects which exist in two revisions but have "
405 "different type or data") },
407 { "select_none", (PyCFunction)select_none, METH_NOARGS,
408 PyDoc_STR("select_none() -> Selection -- "
409 "an empty selection") },
410 { "select_object", (PyCFunction)select_object, METH_KEYWORDS,
411 PyDoc_STR("select_object(ob) -> Selection -- "
412 "a selection containing a single object") },
413 { "select_attached_to", (PyCFunction)select_attached_to, METH_KEYWORDS,
414 PyDoc_STR("select_attached_to(rev, ob) -> Selection -- "
415 "a selection containing all objects in a revision "
416 "attached to a given object") },
417 { "select_all", (PyCFunction)select_all, METH_KEYWORDS,
418 PyDoc_STR("select_all(rev) -> Selection -- "
419 "a selection containing all objects in a revision") },
420 { "select_all_except", (PyCFunction)select_all_except, METH_KEYWORDS,
421 PyDoc_STR("select_all_except(rev, sel) -> Selection -- "
422 "a selection containing all objects in a revision except "
423 "those in a given selection") },
424 { "select_including", (PyCFunction)select_including, METH_KEYWORDS,
425 PyDoc_STR("select_including(sel, ob) -> Selection -- "
426 "a selection which contains all the objects in an "
427 "existing selection plus a given object") },
428 { "select_excluding", (PyCFunction)select_excluding, METH_KEYWORDS,
429 PyDoc_STR("select_excluding(sel, ob) -> Selection -- "
430 "a selection which contains all the objects in an "
431 "existing selection minus a given object") },
432 { "select_union", (PyCFunction)select_union, METH_KEYWORDS,
433 PyDoc_STR("select_union(sel0, sel1) -> Selection -- "
434 "a selection containing the objects in either given "
435 "selection") },
436 { "select_intersection",
437 (PyCFunction)select_intersection, METH_KEYWORDS,
438 PyDoc_STR("select_intersection(sel0, sel1) -> Selection -- "
439 "a selection containing the objects in both given "
440 "selections") },
441 { "select_difference", (PyCFunction)select_difference, METH_KEYWORDS,
442 PyDoc_STR("select_difference(sel0, sel1) -> Selection -- "
443 "a selection containing the objects contained in one "
444 "given selection, but not the other") },
445 { "selection_is_empty", (PyCFunction)selection_is_empty, METH_KEYWORDS,
446 PyDoc_STR("selection_is_empty(rev, sel) -> bool -- "
447 "whether a selection is empty in a given revision") },
448 { "object_is_selected", (PyCFunction)object_is_selected, METH_KEYWORDS,
449 PyDoc_STR("object_is_selected(rev, sel, ob) -> bool -- "
450 "whether an object exists in a revision and is selected "
451 "in a selection") },
453 { NULL, NULL, 0, NULL } /* Sentinel */
456 static int add_type(PyObject *module, const char *name, PyTypeObject *value)
458 Py_INCREF(value);
459 return PyModule_AddObject(module, name, (PyObject *)value);
462 PyMODINIT_FUNC initstorage(void)
464 PyObject *m;
466 if (PyType_Ready(&RevisionType) == -1) return;
467 if (PyType_Ready(&ObjectType) == -1) return;
468 if (PyType_Ready(&SelectionType) == -1) return;
470 if (PyType_Ready(&ArcType) == -1) return;
471 if (PyType_Ready(&BoxType) == -1) return;
472 if (PyType_Ready(&CircleType) == -1) return;
473 if (PyType_Ready(&ComponentType) == -1) return;
474 if (PyType_Ready(&LineType) == -1) return;
475 if (PyType_Ready(&NetType) == -1) return;
476 if (PyType_Ready(&PathType) == -1) return;
477 if (PyType_Ready(&PictureType) == -1) return;
478 if (PyType_Ready(&TextType) == -1) return;
479 if (PyType_Ready(&LineAttrType) == -1) return;
480 if (PyType_Ready(&FillAttrType) == -1) return;
482 m = Py_InitModule3("storage", methods,
483 PyDoc_STR("Xorn storage backend"));
485 if (add_type(m, "Revision", &RevisionType) == -1) return;
486 if (add_type(m, "Object", &ObjectType) == -1) return;
487 if (add_type(m, "Selection", &SelectionType) == -1) return;
489 if (add_type(m, "Arc", &ArcType) == -1) return;
490 if (add_type(m, "Box", &BoxType) == -1) return;
491 if (add_type(m, "Circle", &CircleType) == -1) return;
492 if (add_type(m, "Component", &ComponentType) == -1) return;
493 if (add_type(m, "Line", &LineType) == -1) return;
494 if (add_type(m, "Net", &NetType) == -1) return;
495 if (add_type(m, "Path", &PathType) == -1) return;
496 if (add_type(m, "Picture", &PictureType) == -1) return;
497 if (add_type(m, "Text", &TextType) == -1) return;
498 if (add_type(m, "LineAttr", &LineAttrType) == -1) return;
499 if (add_type(m, "FillAttr", &FillAttrType) == -1) return;