static GHashTable *bt_cc_ptr_to_py_cls;
-static void register_cc_ptr_to_py_cls(struct bt_component_class *bt_cc,
+static
+void register_cc_ptr_to_py_cls(struct bt_component_class *bt_cc,
PyObject *py_cls)
{
if (!bt_cc_ptr_to_py_cls) {
(gpointer) py_cls);
}
-static PyObject *lookup_cc_ptr_to_py_cls(const bt_component_class *bt_cc)
+static
+PyObject *lookup_cc_ptr_to_py_cls(const bt_component_class *bt_cc)
{
if (!bt_cc_ptr_to_py_cls) {
BT_LOGW("Cannot look up Python component class because hash table is NULL: "
static PyObject *py_mod_bt2_exc_invalid_query_object_type = NULL;
static PyObject *py_mod_bt2_exc_invalid_query_params_type = NULL;
-static void bt_py3_cc_init_from_bt2(void)
+static
+void bt_py3_cc_init_from_bt2(void)
{
/*
* This is called once the bt2 package is loaded.
BT_ASSERT(py_mod_bt2_exc_invalid_query_params_type);
}
-static void bt_py3_cc_exit_handler(void)
+static
+void bt_py3_cc_exit_handler(void)
{
/*
* This is an exit handler (set by the bt2 package).
/* Library destructor */
__attribute__((destructor))
-static void bt_py3_native_comp_class_dtor(void) {
+static
+void bt_py3_native_comp_class_dtor(void) {
/* Destroy component class association hash table */
if (bt_cc_ptr_to_py_cls) {
BT_LOGD_STR("Destroying native component class to Python component class hash table.");
}
}
-
-// TODO: maybe we can wrap code in the Python methods (e.g. _query_from_native)
-// in a try catch and print the error there instead, it would be simpler.
static
void bt2_py_loge_exception(void)
{
- PyObject *type = NULL;
- PyObject *value = NULL;
- PyObject *traceback = NULL;
- PyObject *traceback_module = NULL;
- PyObject *format_exception_func = NULL;
- PyObject *exc_str_list = NULL;
- GString *msg_buf = NULL;
- Py_ssize_t i;
+ GString *gstr;
BT_ASSERT(PyErr_Occurred() != NULL);
-
- PyErr_Fetch(&type, &value, &traceback);
-
- BT_ASSERT(type != NULL);
-
- /*
- * traceback can be NULL, when we fail to call a Python function from the
- * native code (there is no Python stack at that point). E.g.:
- *
- * TypeError: _query_from_native() takes 5 positional arguments but 8 were given
- */
-
-
- /* Make sure `value` is what we expected - an instance of `type`. */
- PyErr_NormalizeException(&type, &value, &traceback);
-
- traceback_module = PyImport_ImportModule("traceback");
- if (!traceback_module) {
- BT_LOGE_STR("Failed to log Python exception (could not import traceback module).");
- goto end;
- }
-
- format_exception_func = PyObject_GetAttrString(traceback_module,
- traceback ? "format_exception" : "format_exception_only");
- if (!format_exception_func) {
- BT_LOGE_STR("Failed to log Python exception (could not find format_exception).");
- goto end;
- }
-
- if (!PyCallable_Check(format_exception_func)) {
- BT_LOGE_STR("Failed to log Python exception (format_exception is not callable).");
- goto end;
- }
-
- exc_str_list = PyObject_CallFunctionObjArgs(format_exception_func, type, value, traceback, NULL);
- if (!exc_str_list) {
- PyErr_Print();
- BT_LOGE_STR("Failed to log Python exception (call to format_exception failed).");
+ gstr = bt_py_common_format_exception(BT_LOG_OUTPUT_LEVEL);
+ if (!gstr) {
+ /* bt_py_common_format_exception() logs errors */
goto end;
}
- msg_buf = g_string_new(NULL);
-
- for (i = 0; i < PyList_Size(exc_str_list); i++) {
- PyObject *exc_str = PyList_GetItem(exc_str_list, i);
- const char *str = PyUnicode_AsUTF8(exc_str);
- if (!str) {
- BT_LOGE_STR("Failed to log Python exception (failed to convert exception to string).");
- goto end;
- }
-
- g_string_append(msg_buf, str);
- }
-
- BT_LOGE_STR(msg_buf->str);
+ BT_LOGE_STR(gstr->str);
end:
- if (msg_buf) {
- g_string_free(msg_buf, TRUE);
+ if (gstr) {
+ g_string_free(gstr, TRUE);
}
- Py_XDECREF(exc_str_list);
- Py_XDECREF(format_exception_func);
- Py_XDECREF(traceback_module);
-
- /* PyErr_Restore takes our references. */
- PyErr_Restore(type, value, traceback);
}
-static bt_self_component_status bt_py3_exc_to_self_component_status(void)
+static
+bt_self_component_status bt_py3_exc_to_self_component_status(void)
{
bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK;
PyObject *exc = PyErr_Occurred();
/* Component class proxy methods (delegate to the attached Python object) */
-static bt_self_message_iterator_status
-bt_py3_exc_to_self_message_iterator_status(void)
+static
+bt_self_message_iterator_status bt_py3_exc_to_self_message_iterator_status(void)
{
enum bt_self_message_iterator_status status =
BT_SELF_MESSAGE_ITERATOR_STATUS_OK;
return status;
}
-static enum bt_query_status bt_py3_exc_to_query_status(void)
+static
+enum bt_query_status bt_py3_exc_to_query_status(void)
{
enum bt_query_status status = BT_QUERY_STATUS_OK;
PyObject *exc = PyErr_Occurred();
return status;
}
-static bt_self_component_status
-bt_py3_component_class_init(
+static
+bt_self_component_status bt_py3_component_class_init(
bt_self_component *self_component,
void *self_component_v,
swig_type_info *self_comp_cls_type_swig_type,
* of that class.
*/
-static bt_self_component_status
-bt_py3_component_class_source_init(bt_self_component_source *self_component_source,
+static
+bt_self_component_status bt_py3_component_class_source_init(
+ bt_self_component_source *self_component_source,
const bt_value *params, void *init_method_data)
{
bt_self_component *self_component = bt_self_component_source_as_self_component(self_component_source);
params, init_method_data);
}
-static bt_self_component_status
-bt_py3_component_class_filter_init(bt_self_component_filter *self_component_filter,
+static
+bt_self_component_status bt_py3_component_class_filter_init(
+ bt_self_component_filter *self_component_filter,
const bt_value *params, void *init_method_data)
{
bt_self_component *self_component = bt_self_component_filter_as_self_component(self_component_filter);
params, init_method_data);
}
-static bt_self_component_status
-bt_py3_component_class_sink_init(bt_self_component_sink *self_component_sink,
+static
+bt_self_component_status bt_py3_component_class_sink_init(
+ bt_self_component_sink *self_component_sink,
const bt_value *params, void *init_method_data)
{
bt_self_component *self_component = bt_self_component_sink_as_self_component(self_component_sink);
params, init_method_data);
}
-static void bt_py3_component_class_finalize(bt_self_component *self_component)
+static
+void bt_py3_component_class_finalize(bt_self_component *self_component)
{
PyObject *py_comp = bt_self_component_get_data(self_component);
BT_ASSERT(py_comp);
Py_DECREF(py_comp);
}
-static void
-bt_py3_component_class_source_finalize(bt_self_component_source *self_component_source)
+static
+void bt_py3_component_class_source_finalize(bt_self_component_source *self_component_source)
{
bt_self_component *self_component = bt_self_component_source_as_self_component(self_component_source);
bt_py3_component_class_finalize(self_component);
}
-static void
-bt_py3_component_class_filter_finalize(bt_self_component_filter *self_component_filter)
+static
+void bt_py3_component_class_filter_finalize(bt_self_component_filter *self_component_filter)
{
bt_self_component *self_component = bt_self_component_filter_as_self_component(self_component_filter);
bt_py3_component_class_finalize(self_component);
}
-static void
-bt_py3_component_class_sink_finalize(bt_self_component_sink *self_component_sink)
+static
+void bt_py3_component_class_sink_finalize(bt_self_component_sink *self_component_sink)
{
bt_self_component *self_component = bt_self_component_sink_as_self_component(self_component_sink);
bt_py3_component_class_finalize(self_component);
}
-static bt_self_component_status
-bt_py3_component_class_port_connected(
+static
+bt_bool bt_py3_component_class_can_seek_beginning(
+ bt_self_message_iterator *self_message_iterator)
+{
+ PyObject *py_iter;
+ PyObject *py_result = NULL;
+ bt_bool can_seek_beginning = false;
+
+ py_iter = bt_self_message_iterator_get_data(self_message_iterator);
+ BT_ASSERT(py_iter);
+
+ py_result = PyObject_GetAttrString(py_iter, "_can_seek_beginning_from_native");
+
+ BT_ASSERT(!py_result || PyBool_Check(py_result));
+
+ if (py_result) {
+ can_seek_beginning = PyObject_IsTrue(py_result);
+ } else {
+ /*
+ * Once can_seek_beginning can report errors, convert the
+ * exception to a status. For now, log and return false;
+ */
+ bt2_py_loge_exception();
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(py_result);
+
+ return can_seek_beginning;
+}
+
+static
+bt_self_message_iterator_status bt_py3_component_class_seek_beginning(
+ bt_self_message_iterator *self_message_iterator)
+{
+ PyObject *py_iter;
+ PyObject *py_result;
+ bt_self_message_iterator_status status;
+
+ py_iter = bt_self_message_iterator_get_data(self_message_iterator);
+ BT_ASSERT(py_iter);
+
+ py_result = PyObject_CallMethod(py_iter, "_seek_beginning_from_native", NULL);
+
+ BT_ASSERT(!py_result || py_result == Py_None);
+ status = bt_py3_exc_to_self_message_iterator_status();
+
+ Py_XDECREF(py_result);
+
+ return status;
+}
+
+static
+bt_self_component_status bt_py3_component_class_port_connected(
bt_self_component *self_component,
void *self_component_port,
swig_type_info *self_component_port_swig_type,
return status;
}
-static bt_self_component_status
-bt_py3_component_class_source_output_port_connected(
+static
+bt_self_component_status bt_py3_component_class_source_output_port_connected(
bt_self_component_source *self_component_source,
bt_self_component_port_output *self_component_port_output,
const bt_port_input *other_port_input)
SWIGTYPE_p_bt_port_input);
}
-static bt_self_component_status
-bt_py3_component_class_filter_input_port_connected(
+static
+bt_self_component_status bt_py3_component_class_filter_input_port_connected(
bt_self_component_filter *self_component_filter,
bt_self_component_port_input *self_component_port_input,
const bt_port_output *other_port_output)
SWIGTYPE_p_bt_port_output);
}
-static bt_self_component_status
-bt_py3_component_class_filter_output_port_connected(
+static
+bt_self_component_status bt_py3_component_class_filter_output_port_connected(
bt_self_component_filter *self_component_filter,
bt_self_component_port_output *self_component_port_output,
const bt_port_input *other_port_input)
SWIGTYPE_p_bt_port_input);
}
-static bt_self_component_status
-bt_py3_component_class_sink_input_port_connected(
+static
+bt_self_component_status bt_py3_component_class_sink_input_port_connected(
bt_self_component_sink *self_component_sink,
bt_self_component_port_input *self_component_port_input,
const bt_port_output *other_port_output)
SWIGTYPE_p_bt_port_output);
}
-static bt_self_component_status
-bt_py3_component_class_sink_graph_is_configured(bt_self_component_sink *self_component_sink)
+static
+bt_self_component_status bt_py3_component_class_sink_graph_is_configured(
+ bt_self_component_sink *self_component_sink)
{
PyObject *py_comp = NULL;
PyObject *py_method_result = NULL;
return status;
}
-static bt_query_status
-bt_py3_component_class_query(
+static
+bt_query_status bt_py3_component_class_query(
const bt_component_class *component_class,
const bt_query_executor *query_executor,
const char *object, const bt_value *params,
return status;
}
-static bt_query_status
-bt_py3_component_class_source_query(
+static
+bt_query_status bt_py3_component_class_source_query(
bt_self_component_class_source *self_component_class_source,
const bt_query_executor *query_executor,
const char *object, const bt_value *params,
return bt_py3_component_class_query(component_class, query_executor, object, params, log_level, result);
}
-static bt_query_status
-bt_py3_component_class_filter_query(
+static
+bt_query_status bt_py3_component_class_filter_query(
bt_self_component_class_filter *self_component_class_filter,
const bt_query_executor *query_executor,
const char *object, const bt_value *params,
return bt_py3_component_class_query(component_class, query_executor, object, params, log_level, result);
}
-static bt_query_status
-bt_py3_component_class_sink_query(
+static
+bt_query_status bt_py3_component_class_sink_query(
bt_self_component_class_sink *self_component_class_sink,
const bt_query_executor *query_executor,
const char *object, const bt_value *params,
return bt_py3_component_class_query(component_class, query_executor, object, params, log_level, result);
}
-static bt_self_message_iterator_status
-bt_py3_component_class_message_iterator_init(
+static
+bt_self_message_iterator_status bt_py3_component_class_message_iterator_init(
bt_self_message_iterator *self_message_iterator,
bt_self_component *self_component,
bt_self_component_port_output *self_component_port_output)
return status;
}
-static bt_self_message_iterator_status
-bt_py3_component_class_source_message_iterator_init(
+static
+bt_self_message_iterator_status bt_py3_component_class_source_message_iterator_init(
bt_self_message_iterator *self_message_iterator,
bt_self_component_source *self_component_source,
bt_self_component_port_output *self_component_port_output)
return bt_py3_component_class_message_iterator_init(self_message_iterator, self_component, self_component_port_output);
}
-static bt_self_message_iterator_status
-bt_py3_component_class_filter_message_iterator_init(
+static
+bt_self_message_iterator_status bt_py3_component_class_filter_message_iterator_init(
bt_self_message_iterator *self_message_iterator,
bt_self_component_filter *self_component_filter,
bt_self_component_port_output *self_component_port_output)
return bt_py3_component_class_message_iterator_init(self_message_iterator, self_component, self_component_port_output);
}
-static void
-bt_py3_component_class_message_iterator_finalize(
+static
+void bt_py3_component_class_message_iterator_finalize(
bt_self_message_iterator *message_iterator)
{
PyObject *py_message_iter = bt_self_message_iterator_get_data(message_iterator);
/* Valid for both sources and filters. */
-static bt_self_message_iterator_status
-bt_py3_component_class_message_iterator_next(
- bt_self_message_iterator *message_iterator,
- bt_message_array_const msgs, uint64_t capacity,
- uint64_t *count)
+static
+bt_self_message_iterator_status bt_py3_component_class_message_iterator_next(
+ bt_self_message_iterator *message_iterator,
+ bt_message_array_const msgs, uint64_t capacity,
+ uint64_t *count)
{
bt_self_message_iterator_status status = BT_SELF_MESSAGE_ITERATOR_STATUS_OK;
PyObject *py_message_iter = bt_self_message_iterator_get_data(message_iterator);
return status;
}
-static bt_self_component_status
-bt_py3_component_class_sink_consume(bt_self_component_sink *self_component_sink)
+static
+bt_self_component_status bt_py3_component_class_sink_consume(
+ bt_self_component_sink *self_component_sink)
{
bt_self_component *self_component = bt_self_component_sink_as_self_component(self_component_sink);
PyObject *py_comp = bt_self_component_get_data(self_component);
ret = bt_component_class_source_set_init_method(component_class_source, bt_py3_component_class_source_init);
BT_ASSERT(ret == 0);
- ret = bt_component_class_source_set_finalize_method (component_class_source, bt_py3_component_class_source_finalize);
+ ret = bt_component_class_source_set_finalize_method(component_class_source, bt_py3_component_class_source_finalize);
+ BT_ASSERT(ret == 0);
+ ret = bt_component_class_source_set_message_iterator_can_seek_beginning_method(component_class_source,
+ bt_py3_component_class_can_seek_beginning);
+ BT_ASSERT(ret == 0);
+ ret = bt_component_class_source_set_message_iterator_seek_beginning_method(component_class_source,
+ bt_py3_component_class_seek_beginning);
BT_ASSERT(ret == 0);
ret = bt_component_class_source_set_output_port_connected_method(component_class_source,
bt_py3_component_class_source_output_port_connected);
BT_ASSERT(ret == 0);
ret = bt_component_class_filter_set_finalize_method (component_class_filter, bt_py3_component_class_filter_finalize);
BT_ASSERT(ret == 0);
+ ret = bt_component_class_filter_set_message_iterator_can_seek_beginning_method(component_class_filter,
+ bt_py3_component_class_can_seek_beginning);
+ BT_ASSERT(ret == 0);
+ ret = bt_component_class_filter_set_message_iterator_seek_beginning_method(component_class_filter,
+ bt_py3_component_class_seek_beginning);
+ BT_ASSERT(ret == 0);
ret = bt_component_class_filter_set_input_port_connected_method(component_class_filter,
bt_py3_component_class_filter_input_port_connected);
BT_ASSERT(ret == 0);