From 3780986f330c2544a02b1650844f4fe7d22ef024 Mon Sep 17 00:00:00 2001
From: Oscar Gustafsson <oscar.gustafsson@gmail.com>
Date: Fri, 2 Jun 2023 16:49:59 +0200
Subject: [PATCH] Replace << connect operator with <<= and overload shift

---
 b_asic/architecture.py                        |   6 +-
 b_asic/operation.py                           |  12 +-
 b_asic/port.py                                |  28 +-
 b_asic/sfg_generators.py                      |   6 +-
 docs_sphinx/index.rst                         |   6 +-
 examples/connectmultiplesfgs.py               |   4 +-
 examples/firstorderiirfilter.py               |   4 +-
 examples/folding_example_with_architecture.py |   2 +-
 examples/lwdfallpass.py                       |   3 +-
 examples/schedulingexample.py                 |   2 +-
 examples/thirdorderblwdf.py                   |   2 +-
 test/fixtures/signal_flow_graph.py            |   6 +-
 test/test_operation.py                        |  23 ++
 test/test_schedule.py                         |   2 +-
 test/test_sfg.py                              | 245 ++++++++----------
 15 files changed, 178 insertions(+), 173 deletions(-)

diff --git a/b_asic/architecture.py b/b_asic/architecture.py
index 8daf5391..2638cb62 100644
--- a/b_asic/architecture.py
+++ b/b_asic/architecture.py
@@ -203,6 +203,10 @@ class Resource(HardwareBlock):
     def _info(self):
         return ""
 
+    @property
+    def _color(self):
+        raise NotImplementedError
+
     @property
     def schedule_time(self) -> int:
         # doc-string inherited
@@ -304,7 +308,7 @@ class Resource(HardwareBlock):
         """
         if isinstance(proc, OperatorProcess):
             # operation_type marks OperatorProcess associated operation.
-            if not isinstance(proc._operation, self.operation_type):
+            if not isinstance(proc.operation, self.operation_type):
                 raise TypeError(f"{proc} not of type {self.operation_type}")
         else:
             # operation_type is MemoryVariable or PlainMemoryVariable
diff --git a/b_asic/operation.py b/b_asic/operation.py
index 4e6edd5f..1c31f788 100644
--- a/b_asic/operation.py
+++ b/b_asic/operation.py
@@ -54,11 +54,10 @@ class Operation(GraphComponent, SignalSourceProvider):
     """
 
     @abstractmethod
-    def __lshift__(self, src: SignalSourceProvider) -> Signal:
+    def __ilshift__(self, src: SignalSourceProvider) -> "Operation":
         """
-        Overload the left shift operator to make it connect the provided signal source
-        to this operation's input, assuming it has exactly 1 input port.
-        Returns the new signal.
+        Overload the inline left shift operator to make it connect the provided signal
+        source to this operation's input, assuming it has exactly one input port.
         """
         raise NotImplementedError
 
@@ -541,14 +540,15 @@ class AbstractOperation(Operation, AbstractGraphComponent):
         """
         raise NotImplementedError
 
-    def __lshift__(self, src: SignalSourceProvider) -> Signal:
+    def __ilshift__(self, src: SignalSourceProvider) -> "Operation":
         if self.input_count != 1:
             diff = "more" if self.input_count > 1 else "less"
             raise TypeError(
                 f"{self.__class__.__name__} cannot be used as a destination"
                 f" because it has {diff} than 1 input"
             )
-        return self.input(0).connect(src)
+        self.input(0).connect(src)
+        return self
 
     def __str__(self) -> str:
         """Get a string representation of this operation."""
diff --git a/b_asic/port.py b/b_asic/port.py
index 0542f09e..8c7e0c21 100644
--- a/b_asic/port.py
+++ b/b_asic/port.py
@@ -18,8 +18,11 @@ if TYPE_CHECKING:
         Addition,
         ConstantMultiplication,
         Division,
+        LeftShift,
         Multiplication,
         Reciprocal,
+        RightShift,
+        Shift,
         Subtraction,
     )
     from b_asic.operation import Operation
@@ -247,6 +250,24 @@ class SignalSourceProvider(ABC):
                 return Division(Constant(src), self)
         return Division(src, self)
 
+    def __lshift__(self, src: int) -> Union["LeftShift", "Shift"]:
+        from b_asic.core_operations import LeftShift, Shift
+
+        if not isinstance(src, int):
+            raise TypeError("Can only shift with an int")
+        if src >= 0:
+            return LeftShift(src, self)
+        return Shift(src, self)
+
+    def __rshift__(self, src: int) -> Union["RightShift", "Shift"]:
+        from b_asic.core_operations import RightShift, Shift
+
+        if not isinstance(src, int):
+            raise TypeError("Can only shift with an int")
+        if src >= 0:
+            return RightShift(src, self)
+        return Shift(-src, self)
+
 
 class InputPort(AbstractPort):
     """
@@ -311,12 +332,13 @@ class InputPort(AbstractPort):
         # self._source_signal is set by the signal constructor.
         return Signal(source=src.source, destination=self, name=Name(name))
 
-    def __lshift__(self, src: SignalSourceProvider) -> Signal:
+    def __ilshift__(self, src: SignalSourceProvider) -> "InputPort":
         """
-        Overloads the left shift operator to make it connect the provided
+        Overloads the inline left shift operator to make it connect the provided
         signal source to this input port. Returns the new signal.
         """
-        return self.connect(src)
+        self.connect(src)
+        return self
 
 
 class OutputPort(AbstractPort, SignalSourceProvider):
diff --git a/b_asic/sfg_generators.py b/b_asic/sfg_generators.py
index e912d10b..8682db1b 100644
--- a/b_asic/sfg_generators.py
+++ b/b_asic/sfg_generators.py
@@ -117,7 +117,7 @@ def wdf_allpass(
                 signal_out = Signal(adaptor1.output(0))
             else:
                 signal_out = Signal(delay2)
-    output << signal_out
+    output <<= signal_out
     return SFG([input_op], [output], name=Name(name))
 
 
@@ -184,7 +184,7 @@ def direct_form_fir(
         if i < taps - 1:
             prev_delay = Delay(prev_delay)
 
-    output << prev_add
+    output <<= prev_add
 
     return SFG([input_op], [output], name=Name(name))
 
@@ -251,6 +251,6 @@ def transposed_direct_form_fir(
         if i < taps - 1:
             prev_delay = Delay(tmp_add)
 
-    output << tmp_add
+    output <<= tmp_add
 
     return SFG([input_op], [output], name=Name(name))
diff --git a/docs_sphinx/index.rst b/docs_sphinx/index.rst
index 1fcfdf32..bcbb9c1e 100644
--- a/docs_sphinx/index.rst
+++ b/docs_sphinx/index.rst
@@ -3,8 +3,8 @@
    You can adapt this file completely to your liking, but it should at least
    contain the root `toctree` directive.
 
-Welcome to B-ASIC's documentation!
-==================================
+B-ASIC's documentation
+======================
 
 B-ASIC is a toolbox for Python 3 that simplifies implementing application-specific
 circuits, primarily aimed at signal processing algorithms for both standard-cell and
@@ -24,7 +24,7 @@ The development of B-ASIC happens at
 
 It is not yet fully functional, but several parts of the design flow works,
 while others are missing/buggy. The goal is to have a working design path from
-algorithm downto a HDL-description of a custom architecture. Once it becomes a
+algorithm down to a HDL-description of a custom architecture. Once it becomes a
 bit more mature, we expect to make it available on pypi and conda-forge so
 that it will becomes easier to access.
 
diff --git a/examples/connectmultiplesfgs.py b/examples/connectmultiplesfgs.py
index 4ab897b4..a28f28fa 100644
--- a/examples/connectmultiplesfgs.py
+++ b/examples/connectmultiplesfgs.py
@@ -23,8 +23,8 @@ allpass1 = wdf_allpass([0.2, 0.5])
 allpass2 = wdf_allpass([-0.5, 0.2, 0.5])
 
 in_lwdf = Input()
-allpass1 << in_lwdf
-allpass2 << in_lwdf
+allpass1 <<= in_lwdf
+allpass2 <<= in_lwdf
 out_lwdf = Output((allpass1 + allpass2) * 0.5)
 
 # Create SFG of LWDF with two internal SFGs
diff --git a/examples/firstorderiirfilter.py b/examples/firstorderiirfilter.py
index d34cd5de..4dea6dcf 100644
--- a/examples/firstorderiirfilter.py
+++ b/examples/firstorderiirfilter.py
@@ -40,9 +40,9 @@ b1.input(0).connect(delay)
 # graph, e.g., for recursive algorithms. In this example, we could not connect the
 # output of the delay as that was not yet available.
 #
-# There is also a shorthand form to connect signals using the ``<<`` operator:
+# There is also a shorthand form to connect signals using the ``<<=`` operator:
 
-delay << first_addition
+delay <<= first_addition
 
 # %%
 # Naturally, it is also possible to write expressions when instantiating operations:
diff --git a/examples/folding_example_with_architecture.py b/examples/folding_example_with_architecture.py
index 85a7fc65..289b9d1c 100644
--- a/examples/folding_example_with_architecture.py
+++ b/examples/folding_example_with_architecture.py
@@ -30,7 +30,7 @@ d = ConstantMultiplication(0.6, T2, "d")
 add2 = a + c
 add1 = in1 + add2
 add3 = b + d
-T1 << add1
+T1 <<= add1
 out1 = Output(add1 + add3, "OUT")
 
 sfg = SFG(inputs=[in1], outputs=[out1], name="Bi-quad folding example")
diff --git a/examples/lwdfallpass.py b/examples/lwdfallpass.py
index 15609f6c..281856fe 100644
--- a/examples/lwdfallpass.py
+++ b/examples/lwdfallpass.py
@@ -1,5 +1,4 @@
 #!/usr/bin/env python3
-# -*- coding: utf-8 -*-
 """
 ================================
 LWDF first-order allpass section
@@ -19,7 +18,7 @@ d0 = Delay()
 adaptor0 = SymmetricTwoportAdaptor(
     0.5, in0, d0, latency_offsets={"in0": 0, "in1": 1, "out0": 5, "out1": 6}
 )
-d0 << adaptor0.output(1)
+d0 <<= adaptor0.output(1)
 out0 = Output(adaptor0.output(0))
 adaptor0.execution_time = 2
 sfg = SFG([in0], [out0])
diff --git a/examples/schedulingexample.py b/examples/schedulingexample.py
index e0e82b56..31663194 100644
--- a/examples/schedulingexample.py
+++ b/examples/schedulingexample.py
@@ -25,7 +25,7 @@ node7 = node6 + node4
 out = Output(node7)
 node5 = 0.75 * node4
 node3 = node2 + node5
-node4 << node3
+node4 <<= node3
 
 sfg = SFG([node1], [out], name="Scheduling example")
 # %%
diff --git a/examples/thirdorderblwdf.py b/examples/thirdorderblwdf.py
index df19a1ed..fc289e24 100644
--- a/examples/thirdorderblwdf.py
+++ b/examples/thirdorderblwdf.py
@@ -20,7 +20,7 @@ D0 = Delay(in0)
 D1 = Delay()
 D2 = Delay(D1)
 s = SymmetricTwoportAdaptor(-0.375, in0, D2)
-D1 << s.output(1)
+D1 <<= s.output(1)
 a = s.output(0) + D0
 out0 = Output(a, "y")
 
diff --git a/test/fixtures/signal_flow_graph.py b/test/fixtures/signal_flow_graph.py
index e8d4f5b4..173c4953 100644
--- a/test/fixtures/signal_flow_graph.py
+++ b/test/fixtures/signal_flow_graph.py
@@ -145,7 +145,7 @@ def sfg_accumulator():
     data_in = Input()
     reset = Input()
     t = Delay()
-    t << (t + data_in) * (1 - reset)
+    t <<= (t + data_in) * (1 - reset)
     data_out = Output(t)
     return SFG(inputs=[data_in, reset], outputs=[data_out])
 
@@ -164,7 +164,7 @@ def sfg_simple_accumulator():
     in1 = Input()
     t1 = Delay()
     add1 = in1 + t1
-    t1 << add1
+    t1 <<= add1
     out1 = Output(add1)
     return SFG(inputs=[in1], outputs=[out1])
 
@@ -330,5 +330,5 @@ def sfg_direct_form_iir_lp_filter():
     top_node = d0 * b1 + d1 * b2 + x
     d0.input(0).connect(top_node)
     d1.input(0).connect(d0)
-    y << a1 * d0 + a2 * d1 + a0 * top_node
+    y <<= a1 * d0 + a2 * d1 + a0 * top_node
     return SFG(inputs=[x], outputs=[y], name='Direct Form 2 IIR Lowpass filter')
diff --git a/test/test_operation.py b/test/test_operation.py
index 69bfda46..dc7ad0b1 100644
--- a/test/test_operation.py
+++ b/test/test_operation.py
@@ -12,8 +12,11 @@ from b_asic import (
     Constant,
     ConstantMultiplication,
     Division,
+    LeftShift,
     Multiplication,
     Reciprocal,
+    RightShift,
+    Shift,
     SquareRoot,
     Subtraction,
 )
@@ -116,6 +119,26 @@ class TestOperationOverloading:
         assert isinstance(div4, Reciprocal)
         assert div4.input(0).signals == div3.output(0).signals
 
+    def test_shift_overload(self):
+        """Tests multiplication overloading for both operation and number argument."""
+        add1 = Addition(None, None, "add1")
+
+        ls1 = add1 << 2
+        assert isinstance(ls1, LeftShift)
+        assert ls1.input(0).signals == add1.output(0).signals
+
+        ls2 = ls1 << -2
+        assert isinstance(ls2, Shift)
+        assert ls2.input(0).signals == ls1.output(0).signals
+
+        rs1 = ls2 >> 2
+        assert isinstance(rs1, RightShift)
+        assert rs1.input(0).signals == ls2.output(0).signals
+
+        rs2 = rs1 >> -2
+        assert isinstance(rs2, Shift)
+        assert rs2.input(0).signals == rs1.output(0).signals
+
 
 class TestTraverse:
     def test_traverse_single_tree(self, operation):
diff --git a/test/test_schedule.py b/test/test_schedule.py
index cfa66db0..c9e6c038 100644
--- a/test/test_schedule.py
+++ b/test/test_schedule.py
@@ -334,7 +334,7 @@ class TestRescheduling:
         d = Delay()
         a = d + in0
         out0 = Output(a)
-        d << a
+        d <<= a
         sfg = SFG([in0], [out0])
         sfg.set_latency_of_type(Addition.type_name(), 1)
         schedule = Schedule(sfg, cyclic=True)
diff --git a/test/test_sfg.py b/test/test_sfg.py
index 2f8c0455..2258081c 100644
--- a/test/test_sfg.py
+++ b/test/test_sfg.py
@@ -504,54 +504,40 @@ class TestGetPrecedenceList:
         # Cached precedence list
         assert len(precedence_sfg_delays._precedence_list) == 7
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[0]
-            ]
-        ) == {"IN1", "T1", "T2"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[0]
+        } == {"IN1", "T1", "T2"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[1]
-            ]
-        ) == {"C0", "B1", "B2", "A1", "A2"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[1]
+        } == {"C0", "B1", "B2", "A1", "A2"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[2]
-            ]
-        ) == {"ADD2", "ADD3"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[2]
+        } == {"ADD2", "ADD3"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[3]
-            ]
-        ) == {"ADD1"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[3]
+        } == {"ADD1"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[4]
-            ]
-        ) == {"Q1"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[4]
+        } == {"Q1"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[5]
-            ]
-        ) == {"A0"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[5]
+        } == {"A0"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[6]
-            ]
-        ) == {"ADD4"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[6]
+        } == {"ADD4"}
 
         # Trigger cache
         precedence_list = precedence_sfg_delays.get_precedence_list()
@@ -565,54 +551,40 @@ class TestGetPrecedenceList:
 
         assert len(precedence_list) == 7
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[0]
-            ]
-        ) == {"IN1", "T1", "CONST1"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[0]
+        } == {"IN1", "T1", "CONST1"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[1]
-            ]
-        ) == {"C0", "B1", "B2", "A1", "A2"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[1]
+        } == {"C0", "B1", "B2", "A1", "A2"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[2]
-            ]
-        ) == {"ADD2", "ADD3"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[2]
+        } == {"ADD2", "ADD3"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[3]
-            ]
-        ) == {"ADD1"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[3]
+        } == {"ADD1"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[4]
-            ]
-        ) == {"Q1"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[4]
+        } == {"Q1"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[5]
-            ]
-        ) == {"A0"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[5]
+        } == {"A0"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[6]
-            ]
-        ) == {"BFLY1.0", "BFLY1.1"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[6]
+        } == {"BFLY1.0", "BFLY1.1"}
 
     def test_precedence_multiple_outputs_same_precedence(
         self, sfg_two_inputs_two_outputs
@@ -635,26 +607,20 @@ class TestGetPrecedenceList:
 
         assert len(precedence_list) == 3
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[0]
-            ]
-        ) == {"IN1", "IN2"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[0]
+        } == {"IN1", "IN2"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[1]
-            ]
-        ) == {"CMUL1"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[1]
+        } == {"CMUL1"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[2]
-            ]
-        ) == {"NESTED_SFG.0", "NESTED_SFG.1"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[2]
+        } == {"NESTED_SFG.0", "NESTED_SFG.1"}
 
     def test_precedence_sfg_multiple_outputs_different_precedences(
         self, sfg_two_inputs_two_outputs_independent
@@ -676,26 +642,20 @@ class TestGetPrecedenceList:
 
         assert len(precedence_list) == 3
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[0]
-            ]
-        ) == {"IN1", "IN2"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[0]
+        } == {"IN1", "IN2"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[1]
-            ]
-        ) == {"CMUL1"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[1]
+        } == {"CMUL1"}
 
-        assert set(
-            [
-                port.operation.key(port.index, port.operation.name)
-                for port in precedence_list[2]
-            ]
-        ) == {"NESTED_SFG.0", "NESTED_SFG.1"}
+        assert {
+            port.operation.key(port.index, port.operation.name)
+            for port in precedence_list[2]
+        } == {"NESTED_SFG.0", "NESTED_SFG.1"}
 
 
 class TestPrintPrecedence:
@@ -924,8 +884,7 @@ class TestConnectExternalSignalsToComponentsMultipleComp:
         return SFG(inputs=[inp1, inp2], outputs=[out1])
 
     def test_connect_external_signals_to_components_many_op(self, large_operation_tree):
-        """Replaces an sfg component in a larger SFG with several component operations
-        """
+        """Replace an sfg component in a larger SFG with several component operations"""
         inp1 = Input("INP1")
         inp2 = Input("INP2")
         inp3 = Input("INP3")
@@ -963,8 +922,8 @@ class TestConnectExternalSignalsToComponentsMultipleComp:
         in2 = Input()
 
         output = Output(c1_sfg + c2_sfg)
-        c1_sfg << in1
-        c2_sfg << in2
+        c1_sfg <<= in1
+        c2_sfg <<= in2
 
         sfg = SFG([in1, in2], [output])
         assert not sfg.find_by_type_name(ConstantMultiplication.type_name())
@@ -1030,31 +989,29 @@ class TestRemove:
     def test_remove_single_input_outputs(self, sfg_simple_filter):
         new_sfg = sfg_simple_filter.remove_operation("cmul1")
 
-        assert set(
+        assert {
             op.name
             for op in sfg_simple_filter.find_by_name("T1")[0].subsequent_operations
-        ) == {"CMUL1", "OUT1"}
-        assert set(
+        } == {"CMUL1", "OUT1"}
+        assert {
             op.name for op in new_sfg.find_by_name("T1")[0].subsequent_operations
-        ) == {"ADD1", "OUT1"}
+        } == {"ADD1", "OUT1"}
 
-        assert set(
+        assert {
             op.name
             for op in sfg_simple_filter.find_by_name("ADD1")[0].preceding_operations
-        ) == {"CMUL1", "IN1"}
-        assert set(
+        } == {"CMUL1", "IN1"}
+        assert {
             op.name for op in new_sfg.find_by_name("ADD1")[0].preceding_operations
-        ) == {"T1", "IN1"}
+        } == {"T1", "IN1"}
 
-        assert "S1" in set(
-            [
-                sig.name
-                for sig in sfg_simple_filter.find_by_name("T1")[0].output(0).signals
-            ]
-        )
-        assert "S2" in set(
-            [sig.name for sig in new_sfg.find_by_name("T1")[0].output(0).signals]
-        )
+        assert "S1" in {
+            sig.name
+            for sig in sfg_simple_filter.find_by_name("T1")[0].output(0).signals
+        }
+        assert "S2" in {
+            sig.name for sig in new_sfg.find_by_name("T1")[0].output(0).signals
+        }
 
     def test_remove_multiple_inputs_outputs(self, butterfly_operation_tree):
         out1 = Output(butterfly_operation_tree.output(0), "OUT1")
@@ -1109,7 +1066,7 @@ class TestRemove:
         assert sfg_source_1.operation.name == "bfly2"
         assert new_sfg_source_1.operation.name == "bfly3"
 
-        assert "bfly2" not in set(op.name for op in new_sfg.operations)
+        assert "bfly2" not in {op.name for op in new_sfg.operations}
 
     def remove_different_number_inputs_outputs(self, sfg_simple_filter):
         with pytest.raises(ValueError):
@@ -1134,7 +1091,7 @@ class TestSaveLoadSFG:
 
         assert path.exists(path_)
 
-        with open(path_, "r") as file_obj:
+        with open(path_) as file_obj:
             assert file_obj.read() == result
 
         remove(path_)
@@ -1149,7 +1106,7 @@ class TestSaveLoadSFG:
 
         assert path.exists(path_)
 
-        with open(path_, "r") as file_obj:
+        with open(path_) as file_obj:
             assert file_obj.read() == result
 
         remove(path_)
-- 
GitLab