code: def test_remove_client(self):
      var1 = MyVariable("var1")
      var2 = MyVariable("var2")
      var3 = op1(var2, var1)
      var4 = op2(var3, var2)
      var5 = op3(var4, var2, var2)
      fg = FunctionGraph([var1, var2], [var3, var5], clone=False)
  
      assert fg.variables == {var1, var2, var3, var4, var5}
      assert fg.get_clients(var2) == [
          (var3.owner, 0),
          (var4.owner, 1),
          (var5.owner, 1),
          (var5.owner, 2),
      ]
  
      fg.remove_client(var2, (var4.owner, 1))
  
      assert fg.get_clients(var2) == [
          (var3.owner, 0),
          (var5.owner, 1),
          (var5.owner, 2),
      ]
  
      fg.remove_client(var1, (var3.owner, 1))
  
      assert fg.get_clients(var1) == []
  
      assert var4.owner in fg.apply_nodes
  
      # This next `remove_client` should trigger a complete removal of `var4`'s
      # variables and `Apply` node from the `FunctionGraph`.
      #
      # Also, notice that we already removed `var4` from `var2`'s client list
      # above, so, when we completely remove `var4`, `fg.remove_client` will
      # attempt to remove `(var4.owner, 1)` from `var2`'s client list again.
      # This attempt would previously raise a `ValueError` exception, because
      # the entry was not in the list.
      fg.remove_client(var4, (var5.owner, 0), reason="testing")
  
      assert var4.owner not in fg.apply_nodes
      assert var4.owner.tag.removed_by == ["testing"]
      assert not any(o in fg.variables for o in var4.owner.outputs)
  
imports: import pickle
  import numpy
  import pytest
  from pytensor.configdefaults import config
  from pytensor.graph.basic import NominalVariable
  from pytensor.graph.fg import FunctionGraph
  from pytensor.graph.utils import MissingInputError
  from tests.graph.utils import MyConstant, MyOp, MyType, MyVariable, MyVariable2, op1, op2, op3
label_desc: Use image node_id 4 for calling the TestFunctionGraph obj's underlying member method code with example usage: obj.test_remove_client() without return types