bt2: add `ComponentDescriptor` class and test
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Sat, 10 Aug 2019 18:53:32 +0000 (14:53 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Tue, 13 Aug 2019 00:28:02 +0000 (20:28 -0400)
The goal of a `ComponentDescriptor` object is to eventually be used
within an array of descriptors passed to a function which computes an
effective message interchange protocol version with the help of version
support component class methods.

I choose not to wrap the `bt_component_descriptor_set` API as this is
so simple and will be used at a single location.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Change-Id: Ifef9b4fb0a7cf0278dbf8bed2d18d0b47934a272
Reviewed-on: https://review.lttng.org/c/babeltrace/+/1873
Tested-by: jenkins <jenkins@lttng.org>
Reviewed-by: Simon Marchi <simon.marchi@efficios.com>
src/bindings/python/bt2/Makefile.am
src/bindings/python/bt2/bt2/__init__.py
src/bindings/python/bt2/bt2/component_descriptor.py [new file with mode: 0644]
tests/bindings/python/bt2/test_component_descriptor.py [new file with mode: 0644]
tests/bindings/python/bt2/test_package.py

index a0eb73a93c92c52cc69285fc31068e4767bb8440..75a656897caa474c157efe84f57e8ac027db2507 100644 (file)
@@ -57,6 +57,7 @@ STATIC_BINDINGS_DEPS =                                        \
        bt2/clock_class.py                              \
        bt2/clock_snapshot.py                           \
        bt2/component.py                                \
+       bt2/component_descriptor.py                     \
        bt2/connection.py                               \
        bt2/error.py                                    \
        bt2/event.py                                    \
index 0bead489b47ea3c78af3fbee0661df4609daf00b..9dd9f2e1957e7ffd9e50872c806eedad94a960e9 100644 (file)
@@ -33,6 +33,7 @@ from bt2.component import _SinkComponent
 from bt2.component import _UserSourceComponent
 from bt2.component import _UserFilterComponent
 from bt2.component import _UserSinkComponent
+from bt2.component_descriptor import ComponentDescriptor
 from bt2.error import ComponentClassType
 from bt2.error import _ErrorCause
 from bt2.error import _ComponentErrorCause
diff --git a/src/bindings/python/bt2/bt2/component_descriptor.py b/src/bindings/python/bt2/bt2/component_descriptor.py
new file mode 100644 (file)
index 0000000..f86928d
--- /dev/null
@@ -0,0 +1,90 @@
+# The MIT License (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 component as bt2_component
+import bt2
+
+
+def _is_source_comp_cls(comp_cls):
+    if isinstance(comp_cls, bt2_component._SourceComponentClass):
+        return True
+
+    try:
+        return issubclass(comp_cls, bt2_component._UserSourceComponent)
+    except:
+        return False
+
+
+def _is_filter_comp_cls(comp_cls):
+    if isinstance(comp_cls, bt2_component._FilterComponentClass):
+        return True
+
+    try:
+        return issubclass(comp_cls, bt2_component._UserFilterComponent)
+    except:
+        return False
+
+
+def _is_sink_comp_cls(comp_cls):
+    if isinstance(comp_cls, bt2_component._SinkComponentClass):
+        return True
+
+    try:
+        return issubclass(comp_cls, bt2_component._UserSinkComponent)
+    except:
+        return False
+
+
+class ComponentDescriptor:
+    def __init__(self, component_class, params=None, obj=None):
+        if (
+            not _is_source_comp_cls(component_class)
+            and not _is_filter_comp_cls(component_class)
+            and not _is_sink_comp_cls(component_class)
+        ):
+            raise TypeError(
+                "'{}' is not a component class".format(
+                    component_class.__class__.__name__
+                )
+            )
+
+        base_cc_ptr = component_class._bt_component_class_ptr()
+
+        if obj is not None and not native_bt.bt2_is_python_component_class(base_cc_ptr):
+            raise ValueError('cannot pass a Python object to a non-Python component')
+
+        self._comp_cls = component_class
+        self._params = bt2.create_value(params)
+        self._obj = obj
+
+    @property
+    def component_class(self):
+        return self._comp_cls
+
+    @property
+    def params(self):
+        return self._params
+
+    @property
+    def obj(self):
+        return self._obj
diff --git a/tests/bindings/python/bt2/test_component_descriptor.py b/tests/bindings/python/bt2/test_component_descriptor.py
new file mode 100644 (file)
index 0000000..1dfec54
--- /dev/null
@@ -0,0 +1,68 @@
+#
+# Copyright (C) 2019 EfficiOS Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; only version 2
+# of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+
+import unittest
+import bt2
+
+
+class _DummySink(bt2._UserSinkComponent):
+    def _user_consume(self):
+        pass
+
+
+class ComponentDescriptorTestCase(unittest.TestCase):
+    def setUp(self):
+        self._obj = object()
+        self._comp_descr = bt2.ComponentDescriptor(_DummySink, {'zoom': -23}, self._obj)
+
+    def _get_comp_cls_from_plugin(self):
+        plugin = bt2.find_plugin('text', find_in_user_dir=False, find_in_sys_dir=False)
+        assert plugin is not None
+        cc = plugin.source_component_classes['dmesg']
+        assert cc is not None
+        return cc
+
+    def test_init_invalid_cls_type(self):
+        with self.assertRaises(TypeError):
+            bt2.ComponentDescriptor(int)
+
+    def test_init_invalid_params_type(self):
+        with self.assertRaises(TypeError):
+            bt2.ComponentDescriptor(_DummySink, object())
+
+    def test_init_invalid_obj_non_python_comp_cls(self):
+        cc = self._get_comp_cls_from_plugin()
+
+        with self.assertRaises(ValueError):
+            bt2.ComponentDescriptor(cc, obj=57)
+
+    def test_init_with_user_comp_cls(self):
+        bt2.ComponentDescriptor(_DummySink)
+
+    def test_init_with_gen_comp_cls(self):
+        cc = self._get_comp_cls_from_plugin()
+        bt2.ComponentDescriptor(cc)
+
+    def test_attr_component_class(self):
+        self.assertIs(self._comp_descr.component_class, _DummySink)
+
+    def test_attr_params(self):
+        self.assertEqual(self._comp_descr.params, {'zoom': -23})
+
+    def test_attr_obj(self):
+        self.assertIs(self._comp_descr.obj, self._obj)
index 32c4791f4084ad38cbe5f2a46adc4d5d0543e68b..d118462b70ab5392f07b92f17f9ada41e92f13d1 100644 (file)
@@ -183,6 +183,9 @@ class PackageTestCase(unittest.TestCase):
     def test_has__CurrentArrayElementFieldPathItem(self):
         self._assert_in_bt2('_CurrentArrayElementFieldPathItem')
 
+    def test_has_ComponentDescriptor(self):
+        self._assert_in_bt2('ComponentDescriptor')
+
     def test_has_Graph(self):
         self._assert_in_bt2('Graph')
 
This page took 0.026851 seconds and 4 git commands to generate.