]> sigrok.org Git - libsigrok.git/blame - bindings/python/sigrok/core/classes.i
python: Give all enum values __doc__ strings.
[libsigrok.git] / bindings / python / sigrok / core / classes.i
CommitLineData
f7740954
ML
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2014 Martin Ling <martin-sigrok@earth.li>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
6a8c1d68
ML
20%define DOCSTRING
21"@mainpage API Reference
22
23Introduction
24------------
25
26The pysigrok API provides an object-oriented Python interface to the
52ff4f6a 27functionality in libsigrok. It is built on top of the libsigrokcxx C++ API.
6a8c1d68
ML
28
29Getting started
30---------------
31
32Usage of the pysigrok API needs to begin with a call to Context.create().
33This will create the global libsigrok context and returns a Context object.
34Methods on this object provide access to the hardware drivers, input and output
35formats supported by the library, as well as means of creating other objects
36such as sessions and triggers.
37
38Error handling
39--------------
40
41When any libsigrok C API call returns an error, an Error exception is raised,
42which provides access to the error code and description."
43%enddef
44
45%module(docstring=DOCSTRING) classes
f7740954
ML
46
47%{
aae2273b 48#include <stdio.h>
f7740954 49#include <pygobject.h>
e6672888 50#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
ed6b4c47 51#include <numpy/arrayobject.h>
f7740954 52
aae2273b 53PyObject *PyGObject_lib;
f7740954 54PyObject *GLib;
f7740954 55
0e1a7fe9 56#include "config.h"
abc7146d
ML
57
58#if PYGOBJECT_FLAGS_SIGNED
59typedef gint pyg_flags_type;
60#else
61typedef guint pyg_flags_type;
62#endif
63
f7740954
ML
64%}
65
66%init %{
aae2273b
AG
67 PyGObject_lib = pygobject_init(-1, -1, -1);
68 if (!PyGObject_lib)
69 fprintf(stderr, "pygobject initialization failed.\n");
f7740954 70 GLib = PyImport_ImportModule("gi.repository.GLib");
aae2273b
AG
71 /*
72 * This check can't save us if the import fails, but at least it gives us
73 * a starting point to trace the issue versus straight out crashing.
74 */
75 if (!GLib) {
76 fprintf(stderr, "Import of gi.repository.GLib failed.\n");
a2e4d882 77#if PY_VERSION_HEX >= 0x03000000
fa72105f 78 return nullptr;
a2e4d882 79#else
aae2273b 80 return;
a2e4d882 81#endif
aae2273b 82 }
ed6b4c47 83 import_array();
f7740954
ML
84%}
85
c7855def
ML
86%include "../../../swig/templates.i"
87
f7740954
ML
88/* Map file objects to file descriptors. */
89%typecheck(SWIG_TYPECHECK_POINTER) int fd {
90 $1 = (PyObject_AsFileDescriptor($input) != -1);
91}
92
f7740954
ML
93/* Map from Glib::Variant to native Python types. */
94%typemap(out) Glib::VariantBase {
95 GValue *value = g_new0(GValue, 1);
96 g_value_init(value, G_TYPE_VARIANT);
97 g_value_set_variant(value, $1.gobj());
98 PyObject *variant = pyg_value_as_pyobject(value, true);
99 $result = PyObject_CallMethod(variant,
fa72105f 100 const_cast<char *>("unpack"), nullptr);
f7740954
ML
101 Py_XDECREF(variant);
102 g_free(value);
103}
104
f7740954
ML
105/* Map from callable PyObject to LogCallbackFunction */
106%typecheck(SWIG_TYPECHECK_POINTER) sigrok::LogCallbackFunction {
107 $1 = PyCallable_Check($input);
108}
109
110%typemap(in) sigrok::LogCallbackFunction {
111 if (!PyCallable_Check($input))
112 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
113
682fb08c 114 $1 = [=] (const sigrok::LogLevel *loglevel, std::string message) {
f7740954
ML
115 auto gstate = PyGILState_Ensure();
116
117 auto log_obj = SWIG_NewPointerObj(
118 SWIG_as_voidptr(loglevel), SWIGTYPE_p_sigrok__LogLevel, 0);
119
120 auto string_obj = PyString_FromString(message.c_str());
121
122 auto arglist = Py_BuildValue("(OO)", log_obj, string_obj);
123
124 auto result = PyEval_CallObject($input, arglist);
125
126 Py_XDECREF(arglist);
127 Py_XDECREF(log_obj);
128 Py_XDECREF(string_obj);
75fb3036
ML
129
130 bool completed = !PyErr_Occurred();
131
132 if (!completed)
133 PyErr_Print();
134
135 bool valid_result = (completed && result == Py_None);
136
f7740954
ML
137 Py_XDECREF(result);
138
75fb3036
ML
139 if (completed && !valid_result)
140 {
141 PyErr_SetString(PyExc_TypeError,
142 "Log callback did not return None");
143 PyErr_Print();
144 }
145
f7740954 146 PyGILState_Release(gstate);
75fb3036
ML
147
148 if (!valid_result)
149 throw sigrok::Error(SR_ERR);
f7740954
ML
150 };
151
152 Py_XINCREF($input);
153}
154
2c3c9b99
DE
155/* Map from callable PyObject to SessionStoppedCallback */
156%typecheck(SWIG_TYPECHECK_POINTER) sigrok::SessionStoppedCallback {
157 $1 = PyCallable_Check($input);
158}
159
160%typemap(in) sigrok::SessionStoppedCallback {
161 if (!PyCallable_Check($input))
162 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
163
164 $1 = [=] () {
165 const auto gstate = PyGILState_Ensure();
166
167 const auto result = PyEval_CallObject($input, nullptr);
168 const bool completed = !PyErr_Occurred();
169 const bool valid_result = (completed && result == Py_None);
170
171 if (completed && !valid_result) {
172 PyErr_SetString(PyExc_TypeError,
173 "Session stop callback did not return None");
174 }
175 if (!valid_result)
176 PyErr_Print();
177
178 Py_XDECREF(result);
179 PyGILState_Release(gstate);
180
181 if (!valid_result)
182 throw sigrok::Error(SR_ERR);
183 };
184
185 Py_XINCREF($input);
186}
187
f7740954
ML
188/* Map from callable PyObject to DatafeedCallbackFunction */
189%typecheck(SWIG_TYPECHECK_POINTER) sigrok::DatafeedCallbackFunction {
190 $1 = PyCallable_Check($input);
191}
192
193%typemap(in) sigrok::DatafeedCallbackFunction {
194 if (!PyCallable_Check($input))
195 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
196
197 $1 = [=] (std::shared_ptr<sigrok::Device> device,
198 std::shared_ptr<sigrok::Packet> packet) {
199 auto gstate = PyGILState_Ensure();
200
201 auto device_obj = SWIG_NewPointerObj(
202 SWIG_as_voidptr(new std::shared_ptr<sigrok::Device>(device)),
203 SWIGTYPE_p_std__shared_ptrT_sigrok__Device_t, SWIG_POINTER_OWN);
204
205 auto packet_obj = SWIG_NewPointerObj(
206 SWIG_as_voidptr(new std::shared_ptr<sigrok::Packet>(packet)),
207 SWIGTYPE_p_std__shared_ptrT_sigrok__Packet_t, SWIG_POINTER_OWN);
208
209 auto arglist = Py_BuildValue("(OO)", device_obj, packet_obj);
210
211 auto result = PyEval_CallObject($input, arglist);
212
213 Py_XDECREF(arglist);
214 Py_XDECREF(device_obj);
215 Py_XDECREF(packet_obj);
75fb3036
ML
216
217 bool completed = !PyErr_Occurred();
218
219 if (!completed)
220 PyErr_Print();
221
222 bool valid_result = (completed && result == Py_None);
223
f7740954
ML
224 Py_XDECREF(result);
225
75fb3036
ML
226 if (completed && !valid_result)
227 {
228 PyErr_SetString(PyExc_TypeError,
229 "Datafeed callback did not return None");
230 PyErr_Print();
231 }
232
f7740954 233 PyGILState_Release(gstate);
75fb3036
ML
234
235 if (!valid_result)
236 throw sigrok::Error(SR_ERR);
f7740954
ML
237 };
238
239 Py_XINCREF($input);
240}
241
ea22dc10
ML
242/* Cast PacketPayload pointers to correct subclass type. */
243%ignore sigrok::Packet::payload;
244
245%extend sigrok::Packet
246{
247 std::shared_ptr<sigrok::Header> _payload_header()
248 {
249 return dynamic_pointer_cast<sigrok::Header>($self->payload());
250 }
251 std::shared_ptr<sigrok::Meta> _payload_meta()
252 {
253 return dynamic_pointer_cast<sigrok::Meta>($self->payload());
254 }
dd13d47a 255 std::shared_ptr<sigrok::Analog> _payload_analog()
ea22dc10 256 {
dd13d47a 257 return dynamic_pointer_cast<sigrok::Analog>($self->payload());
ea22dc10
ML
258 }
259 std::shared_ptr<sigrok::Logic> _payload_logic()
260 {
261 return dynamic_pointer_cast<sigrok::Logic>($self->payload());
262 }
263}
264
265%extend sigrok::Packet
266{
267%pythoncode
268{
269 def _payload(self):
270 if self.type == PacketType.HEADER:
271 return self._payload_header()
272 elif self.type == PacketType.META:
273 return self._payload_meta()
274 elif self.type == PacketType.LOGIC:
275 return self._payload_logic()
dd13d47a
UH
276 elif self.type == PacketType.ANALOG:
277 return self._payload_analog()
ea22dc10
ML
278 else:
279 return None
280
281 payload = property(_payload)
282}
283}
284
f7740954
ML
285%{
286
161dc24d 287#include "libsigrokcxx/libsigrokcxx.hpp"
f7740954
ML
288
289/* Convert from a Python dict to a std::map<std::string, std::string> */
58aa1f83 290std::map<std::string, std::string> dict_to_map_string(PyObject *dict)
f7740954
ML
291{
292 if (!PyDict_Check(dict))
293 throw sigrok::Error(SR_ERR_ARG);
294
295 std::map<std::string, std::string> output;
296
297 PyObject *py_key, *py_value;
298 Py_ssize_t pos = 0;
299
300 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
301 if (!PyString_Check(py_key))
302 throw sigrok::Error(SR_ERR_ARG);
303 if (!PyString_Check(py_value))
304 throw sigrok::Error(SR_ERR_ARG);
305 auto key = PyString_AsString(py_key);
306 auto value = PyString_AsString(py_value);
307 output[key] = value;
308 }
309
310 return output;
311}
312
313/* Convert from a Python type to Glib::Variant, according to config key data type. */
314Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::ConfigKey *key)
315{
9d229ecb 316 enum sr_datatype type = (enum sr_datatype) key->data_type()->id();
f7740954
ML
317
318 if (type == SR_T_UINT64 && PyInt_Check(input))
319 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
320 if (type == SR_T_UINT64 && PyLong_Check(input))
321 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
322 else if (type == SR_T_STRING && PyString_Check(input))
f90ed2d1 323 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
f7740954
ML
324 else if (type == SR_T_BOOL && PyBool_Check(input))
325 return Glib::Variant<bool>::create(input == Py_True);
326 else if (type == SR_T_FLOAT && PyFloat_Check(input))
327 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
328 else if (type == SR_T_INT32 && PyInt_Check(input))
329 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
330 else
331 throw sigrok::Error(SR_ERR_ARG);
332}
333
58aa1f83
ML
334/* Convert from a Python type to Glib::Variant, according to Option data type. */
335Glib::VariantBase python_to_variant_by_option(PyObject *input,
336 std::shared_ptr<sigrok::Option> option)
337{
3b161085 338 GVariantType *type = option->default_value().get_type().gobj();
58aa1f83
ML
339
340 if (type == G_VARIANT_TYPE_UINT64 && PyInt_Check(input))
341 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
342 if (type == G_VARIANT_TYPE_UINT64 && PyLong_Check(input))
343 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
344 else if (type == G_VARIANT_TYPE_STRING && PyString_Check(input))
f90ed2d1 345 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
58aa1f83
ML
346 else if (type == G_VARIANT_TYPE_BOOLEAN && PyBool_Check(input))
347 return Glib::Variant<bool>::create(input == Py_True);
348 else if (type == G_VARIANT_TYPE_DOUBLE && PyFloat_Check(input))
349 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
350 else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
351 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
352 else
353 throw sigrok::Error(SR_ERR_ARG);
354}
355
356/* Convert from a Python dict to a std::map<std::string, std::string> */
357std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
358 std::map<std::string, std::shared_ptr<sigrok::Option> > options)
359{
360 if (!PyDict_Check(dict))
361 throw sigrok::Error(SR_ERR_ARG);
362
363 std::map<std::string, Glib::VariantBase> output;
364
365 PyObject *py_key, *py_value;
366 Py_ssize_t pos = 0;
367
368 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
369 if (!PyString_Check(py_key))
370 throw sigrok::Error(SR_ERR_ARG);
371 auto key = PyString_AsString(py_key);
372 auto value = python_to_variant_by_option(py_value, options[key]);
373 output[key] = value;
374 }
375
376 return output;
377}
378
f7740954
ML
379%}
380
381/* Ignore these methods, we will override them below. */
dd13d47a 382%ignore sigrok::Analog::data;
f7740954 383%ignore sigrok::Driver::scan;
ca3291e3 384%ignore sigrok::InputFormat::create_input;
f7740954
ML
385%ignore sigrok::OutputFormat::create_output;
386
df979d6d 387%include "doc_start.i"
bd4fda24 388
062430a2 389%define %attributevector(Class, Type, Name, Get)
444d6a39
ML
390%rename(_ ## Get) sigrok::Class::Get;
391%extend sigrok::Class
392{
393%pythoncode
394{
395 Name = property(_ ## Get)
396}
397}
062430a2
ML
398%enddef
399
400%define %attributemap(Class, Type, Name, Get)
444d6a39
ML
401%rename(_ ## Get) sigrok::Class::Get;
402%extend sigrok::Class
403{
404%pythoncode
405{
406 Name = property(fget = lambda x: x._ ## Get().asdict(), doc=_ ## Get.__doc__)
407}
408}
062430a2
ML
409%enddef
410
7a36ceac 411%define %enumextras(Class)
f0c0dab5
ML
412%extend sigrok::Class
413{
414 long __hash__()
415 {
416 return (long) $self;
417 }
418
419%pythoncode
420{
421 def __eq__(self, other):
422 return (type(self) is type(other) and hash(self) == hash(other))
423
424 def __ne__(self, other):
425 return (type(self) is not type(other) or hash(self) != hash(other))
426}
427}
7a36ceac
ML
428%enddef
429
f7740954
ML
430%include "../../../swig/classes.i"
431
432/* Support Driver.scan() with keyword arguments. */
433%extend sigrok::Driver
434{
435 std::vector<std::shared_ptr<sigrok::HardwareDevice> > _scan_kwargs(PyObject *dict)
436 {
437 if (!PyDict_Check(dict))
438 throw sigrok::Error(SR_ERR_ARG);
439
440 PyObject *py_key, *py_value;
441 Py_ssize_t pos = 0;
442 std::map<const sigrok::ConfigKey *, Glib::VariantBase> options;
443
444 while (PyDict_Next(dict, &pos, &py_key, &py_value))
445 {
446 if (!PyString_Check(py_key))
447 throw sigrok::Error(SR_ERR_ARG);
0bc1a761 448 auto key = sigrok::ConfigKey::get_by_identifier(PyString_AsString(py_key));
f7740954
ML
449 auto value = python_to_variant_by_key(py_value, key);
450 options[key] = value;
451 }
452
453 return $self->scan(options);
454 }
455}
456
457%pythoncode
458{
459 def _Driver_scan(self, **kwargs):
460 return self._scan_kwargs(kwargs)
461
462 Driver.scan = _Driver_scan
463}
464
ca3291e3 465/* Support InputFormat.create_input() with keyword arguments. */
f7740954
ML
466%extend sigrok::InputFormat
467{
ca3291e3 468 std::shared_ptr<sigrok::Input> _create_input_kwargs(PyObject *dict)
f7740954 469 {
ca3291e3 470 return $self->create_input(
3b161085 471 dict_to_map_options(dict, $self->options()));
f7740954
ML
472 }
473}
474
475%pythoncode
476{
ca3291e3
ML
477 def _InputFormat_create_input(self, **kwargs):
478 return self._create_input(kwargs)
f7740954 479
ca3291e3 480 InputFormat.create_input = _InputFormat_create_input
f7740954
ML
481}
482
483/* Support OutputFormat.create_output() with keyword arguments. */
484%extend sigrok::OutputFormat
485{
486 std::shared_ptr<sigrok::Output> _create_output_kwargs(
487 std::shared_ptr<sigrok::Device> device, PyObject *dict)
488 {
58aa1f83 489 return $self->create_output(device,
3b161085 490 dict_to_map_options(dict, $self->options()));
f7740954
ML
491 }
492}
493
494%pythoncode
495{
496 def _OutputFormat_create_output(self, device, **kwargs):
497 return self._create_output_kwargs(device, kwargs)
498
499 OutputFormat.create_output = _OutputFormat_create_output
500}
501
502/* Support config_set() with Python input types. */
503%extend sigrok::Configurable
504{
505 void config_set(const ConfigKey *key, PyObject *input)
506 {
507 $self->config_set(key, python_to_variant_by_key(input, key));
508 }
509}
ed6b4c47 510
dd13d47a
UH
511/* Return NumPy array from Analog::data(). */
512%extend sigrok::Analog
ed6b4c47
ML
513{
514 PyObject * _data()
515 {
516 int nd = 2;
517 npy_intp dims[2];
518 dims[0] = $self->channels().size();
519 dims[1] = $self->num_samples();
520 int typenum = NPY_FLOAT;
521 void *data = $self->data_pointer();
522 return PyArray_SimpleNewFromData(nd, dims, typenum, data);
523 }
524
525%pythoncode
526{
527 data = property(_data)
528}
529}
df979d6d
ML
530
531%include "doc_end.i"