docstr: Get the op info of an op with both inputs and consumers.
docstr_tok: ["Get","the","op","info","of","an","op","with","both","inputs","and","consumers","."]
code: def testServeGraphOpInfoForOpWithInputsAndConsumers(self):
      """Get the op info of an op with both inputs and consumers."""
      _generate_tfdbg_v2_data(self.logdir)
      run = self._getExactlyOneRun()
      # First, look up the graph_id and name of the 1st AddV2 op.
      response = self.server.get(
          _ROUTE_PREFIX + "/graph_execution/digests?run=%s" % run
      )
      data = json.loads(response.get_data())
      digests = data["graph_execution_digests"]
      op_types = [digest["op_type"] for digest in digests]
      op_index = op_types.index("AddV2")
      graph_id = digests[op_index]["graph_id"]
      op_name = digests[op_index]["op_name"]
      # Actually query the /graphs/op_info route.
      response = self.server.get(
          _ROUTE_PREFIX
          + "/graphs/op_info?run=%s&graph_id=%s&op_name=%s"
          % (run, graph_id, op_name)
      )
      self.assertEqual(response.status_code, 200)
      data = json.loads(response.get_data())
  
      # Check op's self properties.
      self.assertEqual(data["op_type"], "AddV2")
      self.assertEqual(data["op_name"], digests[op_index]["op_name"])
      # TODO(cais): Assert on detailed device name when available.
      self.assertIn("device_name", data)
      # The op is inside a nested tf.function, so its graph stack must have a
      # height > 1.
      self.assertGreater(len(data["graph_ids"]), 1)
      # All graph_ids should be non-empty strings.
      self.assertTrue(all(data["graph_ids"]))
      # All graph_ids should be unique (graph recursion is not currently
      # allowed in TF.)
      self.assertLen(set(data["graph_ids"]), len(data["graph_ids"]))
      self.assertNotIn("graph_id", data)
      self.assertEqual(
          data["graph_ids"][-1], digests[op_index]["graph_id"]
      )
      self.assertNotIn("input_names", data)
      self.assertEqual(data["num_outputs"], 1)
      self.assertLen(data["output_tensor_ids"], 1)
      self.assertIsInstance(data["output_tensor_ids"][0], int)
      self.assertEqual(data["host_name"], _HOST_NAME)
      self.assertTrue(data["stack_frame_ids"])
  
      # Check input op properties.
      inputs = data["inputs"]
      # The two input tensors to the AddV2 op are from the same Unpack
      # (unstack) op that provides 4 outputs.
      self.assertTrue(inputs[0]["op_name"])
      self.assertEqual(inputs[0]["output_slot"], 0)
      self.assertTrue(inputs[1]["op_name"])
      self.assertEqual(inputs[1]["output_slot"], 1)
      input0 = inputs[0]["data"]
      input1 = inputs[1]["data"]
      for inpt in (input0, input1):
          self.assertEqual(inpt["op_type"], "Unpack")
          self.assertNotIn("input_names", inpt)
          self.assertEqual(inpt["num_outputs"], 4)
          self.assertLen(inpt["output_tensor_ids"], 4)
          self.assertEqual(inpt["host_name"], _HOST_NAME)
          self.assertEqual(inpt["graph_ids"], data["graph_ids"])
          self.assertLen(inpt["inputs"], 1)
          self.assertTrue(inpt["inputs"][0]["op_name"])
          self.assertIsInstance(inpt["inputs"][0]["op_name"], str)
          self.assertEqual(inpt["inputs"][0]["output_slot"], 0)
          self.assertNotIn("data", inpt["inputs"][0]["op_name"])
          self.assertLen(inpt["consumers"], 4)
          self.assertLen(inpt["consumers"][0], 1)
          self.assertEqual(inpt["consumers"][0][0]["input_slot"], 0)
          self.assertNotIn("data", inpt["consumers"][0][0])
          self.assertLen(inpt["consumers"][1], 1)
          self.assertEqual(inpt["consumers"][1][0]["input_slot"], 1)
          self.assertNotIn("data", inpt["consumers"][1][0])
          self.assertLen(inpt["consumers"][2], 1)
          self.assertEqual(inpt["consumers"][2][0]["input_slot"], 1)
          self.assertNotIn("data", inpt["consumers"][2][0])
          self.assertLen(inpt["consumers"][3], 1)
          self.assertEqual(inpt["consumers"][3][0]["input_slot"], 1)
          self.assertNotIn("data", inpt["consumers"][3][0])
  
      # Check consuming op properties.
      self.assertLen(data["consumers"], 1)
      self.assertLen(data["consumers"][0], 1)
      # The AddV2 is consumed by another AddV2 op in the same graph.
      self.assertTrue(data["consumers"][0][0]["op_name"])
      self.assertIsInstance(data["consumers"][0][0]["op_name"], str)
      self.assertEqual(data["consumers"][0][0]["input_slot"], 0)
      consumer = data["consumers"][0][0]["data"]
      self.assertEqual(consumer["op_type"], "AddV2")
      self.assertTrue(consumer["op_name"])
      self.assertNotEqual(consumer["op_name"], data["op_name"])
      self.assertEqual(consumer["num_outputs"], 1)
      self.assertLen(consumer["output_tensor_ids"], 1)
      self.assertIsInstance(consumer["output_tensor_ids"][0], int)
      self.assertEqual(consumer["host_name"], _HOST_NAME)
      self.assertTrue(consumer["stack_frame_ids"])
      self.assertLen(consumer["inputs"], 2)
      self.assertEqual(
          consumer["inputs"][0]["op_name"], data["op_name"]
      )
      self.assertEqual(consumer["inputs"][0]["output_slot"], 0)
      self.assertNotIn("data", consumer["inputs"][0])
      self.assertEqual(consumer["inputs"][1]["output_slot"], 2)
      self.assertNotIn("data", consumer["inputs"][1])
      self.assertLen(consumer["consumers"], 1)
      self.assertLen(consumer["consumers"][0], 1)
      self.assertTrue(consumer["consumers"][0][0]["op_name"])
      self.assertIsInstance(consumer["consumers"][0][0]["op_name"], str)
      self.assertEqual(consumer["consumers"][0][0]["input_slot"], 0)
      self.assertNotIn("data", consumer["consumers"][0][0])
  
imports: import collections
  import json
  import os
  import socket
  import threading
  import tensorflow
  from werkzeug import test
  from werkzeug import wrappers
  from tensorboard.backend import application
  from tensorboard.plugins import base_plugin
  from tensorboard.plugins.debugger_v2 import debug_data_multiplexer
  from tensorboard.plugins.debugger_v2 import debugger_v2_plugin
label_desc: Use image node_id 35 for calling the DebuggerV2PluginTest obj's underlying member method code with example usage: obj.testServeGraphOpInfoForOpWithInputsAndConsumers() without return types