bt2: check for _graph_is_configured method in user sink classes
authorSimon Marchi <simon.marchi@efficios.com>
Mon, 15 Jul 2019 03:19:24 +0000 (23:19 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 18 Jul 2019 05:27:30 +0000 (01:27 -0400)
Since a _graph_is_configured method is an essential method to implement
in any useful sink, check for the presence of that method when
instantiating a user sink component class in Python (that is, when the
Python class is created).  We already do that for the _consume method,
and I think it greatly helps the user writing a sink by telling them
what not to forget.

Change-Id: Ic8c3741b121eccc2857afac809521dd7213aa679
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/1707
Tested-by: jenkins <jenkins@lttng.org>
Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
src/bindings/python/bt2/bt2/component.py
tests/bindings/python/bt2/test_component.py
tests/bindings/python/bt2/test_component_class.py
tests/bindings/python/bt2/test_connection.py
tests/bindings/python/bt2/test_graph.py
tests/bindings/python/bt2/test_port.py
tests/bindings/python/bt2/test_query_executor.py
tests/bindings/python/bt2/utils.py
tests/python-plugin-provider/bt_plugin_test_python_plugin_provider.py

index 9834fa8cc565dc4dc6f25595ab31a2358e6786ad..18b502ac6c1e150fbb328bab9f7bac0451061678 100644 (file)
@@ -443,6 +443,9 @@ class _UserComponentType(type):
                                                                  comp_cls_descr,
                                                                  comp_cls_help)
         elif _UserSinkComponent in bases:
+            if not hasattr(cls, '_graph_is_configured'):
+                raise bt2.IncompleteUserClass("cannot create component class '{}': missing a _graph_is_configured() method".format(class_name))
+
             if not hasattr(cls, '_consume'):
                 raise bt2.IncompleteUserClass("cannot create component class '{}': missing a _consume() method".format(class_name))
 
index 4384c6654c8c951fad3545ebda3f2fceb89f7fed..69e5617b33808245ea0502f327fd699b1248da81 100644 (file)
@@ -40,6 +40,9 @@ class UserComponentTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         comp = self._create_comp(MySink, 'yaes')
 
     def test_logging_level(self):
@@ -50,6 +53,9 @@ class UserComponentTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         comp = self._create_comp(MySink, 'yaes', bt2.LoggingLevel.INFO)
 
     def test_class(self):
@@ -60,6 +66,9 @@ class UserComponentTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self._create_comp(MySink)
 
     def test_addr(self):
@@ -71,6 +80,9 @@ class UserComponentTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self._create_comp(MySink)
 
     def test_finalize(self):
@@ -80,6 +92,9 @@ class UserComponentTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             def _finalize(comp_self):
                 nonlocal finalized
                 finalized = True
@@ -107,6 +122,9 @@ class GenericComponentTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         comp = self._create_comp(MySink, 'yaes')
         self.assertEqual(comp.name, 'yaes')
 
@@ -115,6 +133,9 @@ class GenericComponentTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         comp = self._create_comp(MySink, 'yaes', bt2.LoggingLevel.WARNING)
         self.assertEqual(comp.logging_level, bt2.LoggingLevel.WARNING)
 
@@ -123,6 +144,9 @@ class GenericComponentTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         comp = self._create_comp(MySink)
         self.assertEqual(comp.cls, MySink)
 
@@ -131,6 +155,9 @@ class GenericComponentTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         comp = self._create_comp(MySink)
         self.assertIsInstance(comp.addr, int)
         self.assertNotEqual(comp.addr, 0)
index bc60606c72d2a5cbcf496f355c044d3df5d90aec..cece1a56b39aed8e1fa7a218f12dfa65720674b0 100644 (file)
@@ -53,6 +53,9 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self._test_no_init(MySink)
 
     def test_incomplete_source_no_msg_iter_cls(self):
@@ -109,11 +112,17 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
     def test_default_name(self):
         class MySink(bt2._UserSinkComponent):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self.assertEqual(MySink.name, 'MySink')
 
     def test_custom_name(self):
@@ -121,6 +130,9 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self.assertEqual(MySink.name, 'salut')
 
     def test_invalid_custom_name(self):
@@ -129,6 +141,9 @@ class UserComponentClassTestCase(unittest.TestCase):
                 def _consume(self):
                     pass
 
+                def _graph_is_configured(self):
+                    pass
+
     def test_description(self):
         class MySink(bt2._UserSinkComponent):
             """
@@ -144,6 +159,9 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self.assertEqual(MySink.description, 'The description.')
 
     def test_empty_description(self):
@@ -154,6 +172,9 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self.assertIsNone(MySink.description)
 
     def test_help(self):
@@ -169,6 +190,9 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self.assertEqual(MySink.help, 'The help\ntext is\nhere.')
 
     def test_addr(self):
@@ -176,6 +200,9 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self.assertIsInstance(MySink.addr, int)
         self.assertNotEqual(MySink.addr, 0)
 
@@ -184,6 +211,9 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         with self.assertRaises(bt2.Error):
             bt2.QueryExecutor().query(MySink, 'obj', 23)
 
@@ -192,6 +222,9 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 raise ValueError
@@ -204,6 +237,9 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 return ...
@@ -216,6 +252,9 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 nonlocal query_params
@@ -234,6 +273,9 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 nonlocal query_log_level
@@ -250,6 +292,9 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @staticmethod
             def _query(query_exec, obj, params, log_level):
                 return
@@ -262,6 +307,9 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 nonlocal query_params
@@ -280,6 +328,9 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 nonlocal query_params
@@ -313,6 +364,9 @@ class UserComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self.assertEqual(MySink, MySink)
 
 
@@ -327,6 +381,9 @@ class GenericComponentClassTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 return [obj, params, 23]
index 22ce8804a0fca4adb687ea844312385acf5fcb90..7c1cbe5715de45e2e2d8e61dd064ab0930c6eba0 100644 (file)
@@ -38,6 +38,9 @@ class ConnectionTestCase(unittest.TestCase):
             def _consume(self):
                 raise bt2.Stop
 
+            def _graph_is_configured(self):
+                pass
+
         graph = bt2.Graph()
         src = graph.add_component(MySource, 'src')
         sink = graph.add_component(MySink, 'sink')
@@ -62,6 +65,9 @@ class ConnectionTestCase(unittest.TestCase):
             def _consume(self):
                 raise bt2.Stop
 
+            def _graph_is_configured(self):
+                pass
+
         graph = bt2.Graph()
         src = graph.add_component(MySource, 'src')
         sink = graph.add_component(MySink, 'sink')
@@ -86,6 +92,9 @@ class ConnectionTestCase(unittest.TestCase):
             def _consume(self):
                 raise bt2.Stop
 
+            def _graph_is_configured(self):
+                pass
+
         graph = bt2.Graph()
         src = graph.add_component(MySource, 'src')
         sink = graph.add_component(MySink, 'sink')
index 852e3f01ce23e24c55f57fe15f64234fe9a6fa8d..cb447a5a7f7593d592af8ad58c8d3b104a5bd040 100644 (file)
@@ -63,6 +63,8 @@ class GraphTestCase(unittest.TestCase):
         class MySink(bt2._UserSinkComponent):
             def _consume(self):
                 pass
+            def _graph_is_configured(self):
+                pass
 
         comp = self._graph.add_component(MySink, 'salut')
         self.assertEqual(comp.name, 'salut')
@@ -71,6 +73,8 @@ class GraphTestCase(unittest.TestCase):
         class MySink(bt2._UserSinkComponent):
             def _consume(self):
                 pass
+            def _graph_is_configured(self):
+                pass
 
         comp = self._graph.add_component(MySink, 'salut')
         assert comp
@@ -87,6 +91,8 @@ class GraphTestCase(unittest.TestCase):
 
             def _consume(self):
                 pass
+            def _graph_is_configured(self):
+                pass
 
         params = {'hello': 23, 'path': '/path/to/stuff'}
         comp = self._graph.add_component(MySink, 'salut', params)
@@ -101,6 +107,8 @@ class GraphTestCase(unittest.TestCase):
         class MySink(bt2._UserSinkComponent):
             def _consume(self):
                 pass
+            def _graph_is_configured(self):
+                pass
 
         with self.assertRaises(TypeError):
             self._graph.add_component(MySink, 'salut', logging_level='yo')
@@ -109,6 +117,8 @@ class GraphTestCase(unittest.TestCase):
         class MySink(bt2._UserSinkComponent):
             def _consume(self):
                 pass
+            def _graph_is_configured(self):
+                pass
 
         with self.assertRaises(ValueError):
             self._graph.add_component(MySink, 'salut', logging_level=12345)
@@ -117,6 +127,8 @@ class GraphTestCase(unittest.TestCase):
         class MySink(bt2._UserSinkComponent):
             def _consume(self):
                 pass
+            def _graph_is_configured(self):
+                pass
 
         comp = self._graph.add_component(MySink, 'salut',
                                          logging_level=bt2.LoggingLevel.DEBUG)
@@ -139,6 +151,9 @@ class GraphTestCase(unittest.TestCase):
             def _consume(self):
                 raise bt2.Stop
 
+            def _graph_is_configured(self):
+                pass
+
         src = self._graph.add_component(MySource, 'src')
         sink = self._graph.add_component(MySink, 'sink')
 
@@ -166,6 +181,9 @@ class GraphTestCase(unittest.TestCase):
             def _consume(self):
                 raise bt2.Stop
 
+            def _graph_is_configured(self):
+                pass
+
         src = self._graph.add_component(MySource, 'src')
         sink = self._graph.add_component(MySink, 'sink')
 
@@ -393,6 +411,9 @@ class GraphTestCase(unittest.TestCase):
             def _consume(self):
                 raise bt2.Stop
 
+            def _graph_is_configured(self):
+                pass
+
             def _port_connected(self, port, other_port):
                 self._add_input_port('taste')
 
@@ -457,6 +478,9 @@ class GraphTestCase(unittest.TestCase):
             def _consume(self):
                 raise bt2.Stop
 
+            def _graph_is_configured(self):
+                pass
+
             def _port_connected(self, port, other_port):
                 self._add_input_port('taste')
 
@@ -473,6 +497,9 @@ class GraphTestCase(unittest.TestCase):
             def _consume(self):
                 raise bt2.Stop
 
+            def _graph_is_configured(self):
+                pass
+
         graph = bt2.Graph()
 
         with self.assertRaises(bt2.Error):
@@ -486,6 +513,9 @@ class GraphTestCase(unittest.TestCase):
             def _consume(self):
                 raise bt2.Stop
 
+            def _graph_is_configured(self):
+                pass
+
         def port_added_listener(component, port):
             raise ValueError('oh noes!')
 
@@ -512,6 +542,9 @@ class GraphTestCase(unittest.TestCase):
             def _consume(self):
                 raise bt2.Stop
 
+            def _graph_is_configured(self):
+                pass
+
         def ports_connected_listener(upstream_component, upstream_port,
                                      downstream_component, downstream_port):
             raise ValueError('oh noes!')
index 52bfc6a294637ed19264f4b020e31514e44a4b7f..c94bb920ac197393768b9d0845e8fc7d0451944a 100644 (file)
@@ -81,6 +81,9 @@ class PortTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         comp = self._create_comp(MySink)
         self.assertEqual(len(comp.input_ports), 1)
 
@@ -148,6 +151,9 @@ class PortTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self._create_comp(MySink)
 
     def test_user_src_output_ports_getitem_invalid_key(self):
@@ -214,6 +220,9 @@ class PortTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self._create_comp(MySink)
 
     def test_user_src_output_ports_len(self):
@@ -272,6 +281,9 @@ class PortTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self._create_comp(MySink)
 
     def test_user_src_output_ports_iter(self):
@@ -370,6 +382,9 @@ class PortTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self._create_comp(MySink)
 
     def test_gen_src_output_ports_getitem(self):
@@ -462,6 +477,9 @@ class PortTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         comp = self._create_comp(MySink)
         self.assertEqual(port3.addr, comp.input_ports['insert'].addr)
         self.assertEqual(port2.addr, comp.input_ports['print'].addr)
@@ -534,6 +552,9 @@ class PortTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         comp = self._create_comp(MySink)
 
         with self.assertRaises(KeyError):
@@ -594,6 +615,9 @@ class PortTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         comp = self._create_comp(MySink)
         self.assertEqual(len(comp.input_ports), 3)
 
@@ -711,6 +735,9 @@ class PortTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         comp = self._create_comp(MySink)
         ports = []
 
@@ -735,6 +762,9 @@ class PortTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         comp = self._create_comp(MySink)
         self.assertEqual(comp.input_ports['clear'].name, 'clear')
 
@@ -746,6 +776,9 @@ class PortTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         comp = self._create_comp(MySink)
         self.assertIsNone(comp.input_ports['clear'].connection)
 
@@ -757,6 +790,9 @@ class PortTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         comp = self._create_comp(MySink)
         self.assertFalse(comp.input_ports['clear'].is_connected)
 
@@ -769,6 +805,9 @@ class PortTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self._create_comp(MySink)
 
     def test_self_connection_none(self):
@@ -780,6 +819,9 @@ class PortTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self._create_comp(MySink)
 
     def test_self_is_connected_false(self):
@@ -791,6 +833,9 @@ class PortTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
         self._create_comp(MySink)
 
     def test_source_self_port_user_data(self):
index 30e5a2c9d6699c94881463f27f8f9fe37132f06a..3c4ba62fb264292111d865f50b6021eb68371368 100644 (file)
@@ -28,6 +28,9 @@ class QueryExecutorTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 nonlocal query_params
@@ -61,6 +64,9 @@ class QueryExecutorTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 nonlocal query_params
@@ -76,6 +82,9 @@ class QueryExecutorTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 nonlocal query_log_level
@@ -92,6 +101,9 @@ class QueryExecutorTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 raise ValueError
@@ -104,6 +116,9 @@ class QueryExecutorTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 raise bt2.InvalidObject
@@ -116,6 +131,9 @@ class QueryExecutorTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 pass
@@ -128,6 +146,9 @@ class QueryExecutorTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 pass
@@ -140,6 +161,9 @@ class QueryExecutorTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 raise bt2.InvalidParams
@@ -152,6 +176,9 @@ class QueryExecutorTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 raise bt2.TryAgain
@@ -170,6 +197,9 @@ class QueryExecutorTestCase(unittest.TestCase):
             def _consume(self):
                 pass
 
+            def _graph_is_configured(self):
+                pass
+
             @classmethod
             def _query(cls, query_exec, obj, params, log_level):
                 raise bt2.TryAgain
index d52a474c1e7337aefafb40e78c8a6a2d03947646..873a6514aa0f0034505de112c080d3a8d80de8fc 100644 (file)
@@ -32,6 +32,9 @@ def run_in_component_init(func):
         def _consume(self):
             pass
 
+        def _graph_is_configured(self):
+            pass
+
     g = bt2.Graph()
     res_bound = None
     g.add_component(MySink, 'comp')
index 5a0c893fc14766d3a019484f1f51206e6db775d5..d5274ae49d3cef72591ea88526fedf1b2d2db83c 100644 (file)
@@ -40,6 +40,9 @@ class MySink(bt2._UserSinkComponent):
     def _consume(self):
         pass
 
+    def _graph_is_configured(self):
+        pass
+
 
 bt2.register_plugin(__name__, 'sparkling', author='Philippe Proulx',
                     description='A delicious plugin.',
This page took 0.034826 seconds and 4 git commands to generate.