Remove `skip-string-normalization` in Python formatter config
[babeltrace.git] / src / bindings / python / bt2 / bt2 / component.py
index 9ccd64528d0dc95c96b434c553a2ab575b669a21..7ae6fe25cee9124a017fc72485009d1a87e38254 100644 (file)
@@ -1,24 +1,6 @@
-# The MIT License (MIT)
+# SPDX-License-Identifier: MIT
 #
 # Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
 
 from bt2 import native_bt, object, utils
 from bt2 import message_iterator as bt2_message_iterator
@@ -195,7 +177,7 @@ class _ComponentConst:
         )
 
     def __eq__(self, other):
-        if not hasattr(other, 'addr'):
+        if not hasattr(other, "addr"):
             return False
 
         return self.addr == other.addr
@@ -345,17 +327,22 @@ def _create_component_class_from_const_ptr_and_get_ref(ptr, comp_cls_type):
 
 def _trim_docstring(docstring):
     lines = docstring.expandtabs().splitlines()
+
+    if len(lines) == 0:
+        return ""
+
     indent = sys.maxsize
 
-    for line in lines[1:]:
-        stripped = line.lstrip()
+    if len(lines) > 1:
+        for line in lines[1:]:
+            stripped = line.lstrip()
 
-        if stripped:
-            indent = min(indent, len(line) - len(stripped))
+            if stripped:
+                indent = min(indent, len(line) - len(stripped))
 
     trimmed = [lines[0].strip()]
 
-    if indent < sys.maxsize:
+    if indent < sys.maxsize and len(lines) > 1:
         for line in lines[1:]:
             trimmed.append(line[indent:].rstrip())
 
@@ -365,7 +352,7 @@ def _trim_docstring(docstring):
     while trimmed and not trimmed[0]:
         trimmed.pop(0)
 
-    return '\n'.join(trimmed)
+    return "\n".join(trimmed)
 
 
 # Metaclass for component classes defined by Python code.
@@ -400,14 +387,19 @@ def _trim_docstring(docstring):
 #         ...
 #
 # A user-defined Python component class can have an __init__() method
-# which must at least accept the `params` and `name` arguments:
+# which must accept the following parameters:
 #
-#     def __init__(self, params, name, something_else):
+#     def __init__(self, config, params, obj):
 #         ...
 #
-# The user-defined component class can also have a _finalize() method
-# (do NOT use __del__()) to be notified when the component object is
-# finalized.
+# The value of the `obj` parameter is what was passed as the `obj`
+# parameter if the component was instantiated from Python with
+# Graph.add_component().  If the component was not instantiated from
+# Python, is is always `None`.
+#
+# The user-defined component class can also have a _user_finalize()
+# method (do NOT use __del__()) to be notified when the component object
+# is finalized.
 #
 # User-defined source and filter component classes must use the
 # `message_iterator_class` class parameter to specify the
@@ -420,14 +412,16 @@ def _trim_docstring(docstring):
 #                    message_iterator_class=MyMessageIterator):
 #         ...
 #
-# This message iterator class must inherit
-# bt2._UserMessageIterator, and it must define the _get() and
-# _next() methods. The message iterator class can also define an
-# __init__() method: this method has access to the original Python
-# component object which was used to create it as the `component`
-# property. The message iterator class can also define a
-# _finalize() method (again, do NOT use __del__()): this is called when
-# the message iterator is (really) destroyed.
+# This message iterator class must inherit bt2._UserMessageIterator.
+# It can implement the __init__() method, which must accept the
+# following parameters:
+#
+#     def __init__(self, config, port):
+#         ...
+#
+# It can also implement the __next__() and _user_finalize() methods
+# (again, do NOT use __del__()), which don't accept any parameters
+# other than `self`.
 #
 # When the user-defined class is destroyed, this metaclass's __del__()
 # method is called: the native BT component class pointer is put (not
@@ -443,22 +437,22 @@ class _UserComponentType(type):
 
         # skip our own bases; they are never directly instantiated by the user
         own_bases = (
-            '_UserComponent',
-            '_UserFilterSinkComponent',
-            '_UserSourceComponent',
-            '_UserFilterComponent',
-            '_UserSinkComponent',
+            "_UserComponent",
+            "_UserFilterSinkComponent",
+            "_UserSourceComponent",
+            "_UserFilterComponent",
+            "_UserSinkComponent",
         )
 
         if class_name in own_bases:
             return
 
-        comp_cls_name = kwargs.get('name', class_name)
+        comp_cls_name = kwargs.get("name", class_name)
         utils._check_str(comp_cls_name)
         comp_cls_descr = None
         comp_cls_help = None
 
-        if hasattr(cls, '__doc__') and cls.__doc__ is not None:
+        if hasattr(cls, "__doc__") and cls.__doc__ is not None:
             utils._check_str(cls.__doc__)
             docstring = _trim_docstring(cls.__doc__)
             lines = docstring.splitlines()
@@ -467,9 +461,9 @@ class _UserComponentType(type):
                 comp_cls_descr = lines[0]
 
             if len(lines) >= 3:
-                comp_cls_help = '\n'.join(lines[2:])
+                comp_cls_help = "\n".join(lines[2:])
 
-        iter_cls = kwargs.get('message_iterator_class')
+        iter_cls = kwargs.get("message_iterator_class")
 
         if _UserSourceComponent in bases:
             _UserComponentType._bt_set_iterator_class(cls, iter_cls)
@@ -482,7 +476,7 @@ class _UserComponentType(type):
                 cls, comp_cls_name, comp_cls_descr, comp_cls_help
             )
         elif _UserSinkComponent in bases:
-            if not hasattr(cls, '_user_consume'):
+            if not hasattr(cls, "_user_consume"):
                 raise bt2._IncompleteUserClass(
                     "cannot create component class '{}': missing a _user_consume() method".format(
                         class_name
@@ -527,7 +521,7 @@ class _UserComponentType(type):
 
     def __call__(cls, *args, **kwargs):
         raise RuntimeError(
-            'cannot directly instantiate a user component from a Python module'
+            "cannot directly instantiate a user component from a Python module"
         )
 
     @staticmethod
@@ -546,15 +540,15 @@ class _UserComponentType(type):
                 )
             )
 
-        if not hasattr(iter_cls, '__next__'):
+        if not hasattr(iter_cls, "__next__"):
             raise bt2._IncompleteUserClass(
                 "cannot create component class '{}': message iterator class is missing a __next__() method".format(
                     cls.__name__
                 )
             )
 
-        if hasattr(iter_cls, '_user_can_seek_ns_from_origin') and not hasattr(
-            iter_cls, '_user_seek_ns_from_origin'
+        if hasattr(iter_cls, "_user_can_seek_ns_from_origin") and not hasattr(
+            iter_cls, "_user_seek_ns_from_origin"
         ):
             raise bt2._IncompleteUserClass(
                 "cannot create component class '{}': message iterator class implements _user_can_seek_ns_from_origin but not _user_seek_ns_from_origin".format(
@@ -562,8 +556,8 @@ class _UserComponentType(type):
                 )
             )
 
-        if hasattr(iter_cls, '_user_can_seek_beginning') and not hasattr(
-            iter_cls, '_user_seek_beginning'
+        if hasattr(iter_cls, "_user_can_seek_beginning") and not hasattr(
+            iter_cls, "_user_seek_beginning"
         ):
             raise bt2._IncompleteUserClass(
                 "cannot create component class '{}': message iterator class implements _user_can_seek_beginning but not _user_seek_beginning".format(
@@ -655,7 +649,7 @@ class _UserComponentType(type):
         return self._bt_as_component_class_ptr(self._bt_cc_ptr)
 
     def __del__(cls):
-        if hasattr(cls, '_bt_cc_ptr'):
+        if hasattr(cls, "_bt_cc_ptr"):
             cc_ptr = cls._bt_as_component_class_ptr(cls._bt_cc_ptr)
             native_bt.component_class_put_ref(cc_ptr)
             native_bt.bt2_unregister_cc_ptr_to_py_cls(cc_ptr)
@@ -759,7 +753,7 @@ class _UserComponent(metaclass=_UserComponentType):
         tc_ptr = native_bt.trace_class_create(ptr)
 
         if tc_ptr is None:
-            raise bt2._MemoryError('could not create trace class')
+            raise bt2._MemoryError("could not create trace class")
 
         tc = bt2_trace_class._TraceClass._create_from_ptr(tc_ptr)
         tc._assigns_automatic_stream_class_id = assigns_automatic_stream_class_id
@@ -784,7 +778,7 @@ class _UserComponent(metaclass=_UserComponentType):
         cc_ptr = native_bt.clock_class_create(ptr)
 
         if cc_ptr is None:
-            raise bt2._MemoryError('could not create clock class')
+            raise bt2._MemoryError("could not create clock class")
 
         cc = bt2_clock_class._ClockClass._create_from_ptr(cc_ptr)
 
@@ -839,13 +833,23 @@ class _UserSourceComponent(_UserComponent, _SourceComponentConst):
 
     def _add_output_port(self, name, user_data=None):
         utils._check_str(name)
+
+        if name in self._output_ports:
+            raise ValueError(
+                "source component `{}` already contains an output port named `{}`".format(
+                    self.name, name
+                )
+            )
+
         fn = native_bt.self_component_source_add_output_port
         comp_status, self_port_ptr = fn(self._bt_ptr, name, user_data)
         utils._handle_func_status(
-            comp_status, 'cannot add output port to source component object'
+            comp_status, "cannot add output port to source component object"
         )
         assert self_port_ptr is not None
-        return bt2_port._UserComponentOutputPort._create_from_ptr(self_port_ptr)
+        return bt2_port._UserComponentOutputPort._create_from_ptr_and_get_ref(
+            self_port_ptr
+        )
 
 
 class _UserFilterComponent(_UserComponent, _FilterComponentConst):
@@ -887,23 +891,43 @@ class _UserFilterComponent(_UserComponent, _FilterComponentConst):
 
     def _add_output_port(self, name, user_data=None):
         utils._check_str(name)
+
+        if name in self._output_ports:
+            raise ValueError(
+                "filter component `{}` already contains an output port named `{}`".format(
+                    self.name, name
+                )
+            )
+
         fn = native_bt.self_component_filter_add_output_port
         comp_status, self_port_ptr = fn(self._bt_ptr, name, user_data)
         utils._handle_func_status(
-            comp_status, 'cannot add output port to filter component object'
+            comp_status, "cannot add output port to filter component object"
         )
         assert self_port_ptr
-        return bt2_port._UserComponentOutputPort._create_from_ptr(self_port_ptr)
+        return bt2_port._UserComponentOutputPort._create_from_ptr_and_get_ref(
+            self_port_ptr
+        )
 
     def _add_input_port(self, name, user_data=None):
         utils._check_str(name)
+
+        if name in self._input_ports:
+            raise ValueError(
+                "filter component `{}` already contains an input port named `{}`".format(
+                    self.name, name
+                )
+            )
+
         fn = native_bt.self_component_filter_add_input_port
         comp_status, self_port_ptr = fn(self._bt_ptr, name, user_data)
         utils._handle_func_status(
-            comp_status, 'cannot add input port to filter component object'
+            comp_status, "cannot add input port to filter component object"
         )
         assert self_port_ptr
-        return bt2_port._UserComponentInputPort._create_from_ptr(self_port_ptr)
+        return bt2_port._UserComponentInputPort._create_from_ptr_and_get_ref(
+            self_port_ptr
+        )
 
 
 class _UserSinkComponent(_UserComponent, _SinkComponentConst):
@@ -937,24 +961,37 @@ class _UserSinkComponent(_UserComponent, _SinkComponentConst):
 
     def _add_input_port(self, name, user_data=None):
         utils._check_str(name)
+
+        if name in self._input_ports:
+            raise ValueError(
+                "sink component `{}` already contains an input port named `{}`".format(
+                    self.name, name
+                )
+            )
+
         fn = native_bt.self_component_sink_add_input_port
         comp_status, self_port_ptr = fn(self._bt_ptr, name, user_data)
         utils._handle_func_status(
-            comp_status, 'cannot add input port to sink component object'
+            comp_status, "cannot add input port to sink component object"
         )
         assert self_port_ptr
-        return bt2_port._UserComponentInputPort._create_from_ptr(self_port_ptr)
+        return bt2_port._UserComponentInputPort._create_from_ptr_and_get_ref(
+            self_port_ptr
+        )
 
-    def _create_input_port_message_iterator(self, input_port):
+    def _create_message_iterator(self, input_port):
         utils._check_type(input_port, bt2_port._UserComponentInputPort)
 
+        if not input_port.is_connected:
+            raise ValueError("input port is not connected")
+
         (
             status,
             msg_iter_ptr,
-        ) = native_bt.bt2_self_component_port_input_message_iterator_create_from_sink_component(
+        ) = native_bt.bt2_message_iterator_create_from_sink_component(
             self._bt_ptr, input_port._ptr
         )
-        utils._handle_func_status(status, 'cannot create message iterator object')
+        utils._handle_func_status(status, "cannot create message iterator object")
         assert msg_iter_ptr is not None
 
         return bt2_message_iterator._UserComponentInputPortMessageIterator(msg_iter_ptr)
This page took 0.027604 seconds and 4 git commands to generate.