code: def test_local_track_shape_i(self):
      class IdentityNoShape(Op):
          """Op that does not infer the output shape from the input one"""
  
          def make_node(self, x):
              x = as_tensor_variable(x)
              return Apply(self, [x], [x.type()])
  
          def perform(self, node, inp, out_):
              (x,) = inp
              (out,) = out_
              out[0] = x.copy()
  
          # def infer_shape(self, fgraph, node, (xshp,)):
          # return [tuple([self.shape_i(i)(r) for i in range(r.ndim)])]
  
      identity_noshape = IdentityNoShape()
  
      class IdentityShape(Op):
          """Op that does infer the output shape from the input one"""
  
          def make_node(self, x):
              x = as_tensor_variable(x)
              return Apply(self, [x], [x.type()])
  
          def perform(self, node, inp, out_):
              (x,) = inp
              (out,) = out_
              out[0] = x.copy()
  
          def infer_shape(self, fgraph, node, xshp_):
              # Could also just return.
              (xshp,) = xshp_
              return (xshp,)
  
      identity_shape = IdentityShape()
  
      @node_rewriter([IdentityNoShape])
      def local_identity_noshape_to_identity_shape(fgraph, node):
          """Transform the first `Op` into the second."""
          if isinstance(node.op, IdentityNoShape):
              return [identity_shape(node.inputs[0])]
  
      mode = get_default_mode().including("ShapeOpt", "specialize")
      rng = np.random.default_rng(utt.fetch_seed())
      x = tensor3("x")
      ins_x = identity_noshape(x)
  
      # Without the rewrite
      f = function([x], ins_x.shape, mode=mode)
      xval = rng.standard_normal((3, 4, 7)).astype(config.floatX)
      assert np.all(f(xval) == [3, 4, 7])
      f_ops = [node.op for node in f.maker.fgraph.toposort()]
      assert len(f_ops) == 5
      assert identity_noshape in f_ops
      assert identity_shape not in f_ops
  
      # Register the rewrite
      register_specialize(local_identity_noshape_to_identity_shape)
  
      mode = get_default_mode().including("ShapeOpt", "specialize")
      # The `identity_shape` hOph should not be needed anymore to compute
      # the shape
      g = function([x], ins_x.shape, mode=mode)
      xval = rng.standard_normal((6, 1, 2)).astype(config.floatX)
      assert np.all(g(xval) == [6, 1, 2])
      g_ops = [node.op for node in g.maker.fgraph.toposort()]
      assert len(g_ops) == 4
      assert identity_noshape not in g_ops
      assert identity_shape not in g_ops
  
      # Test multiple applications of an `Op` without an `Op.infer_shape`
      ins_x3 = identity_noshape(identity_noshape(identity_noshape(x)))
      h = function([x], ins_x3.shape, mode=mode)
      xval = rng.standard_normal((6, 1, 2)).astype(config.floatX)
      assert np.all(h(xval) == [6, 1, 2])
      h_ops = [node.op for node in h.maker.fgraph.toposort()]
      assert len(h_ops) == 4
      assert identity_noshape not in h_ops
      assert identity_shape not in h_ops
  
imports: import copy
  import numpy
  import pytest
  import pytensor.tensor
  from pytensor import shared
  from pytensor.compile.function import function
  from pytensor.compile.mode import get_default_mode, get_mode
  from pytensor.compile.ops import deep_copy_op
  from pytensor.configdefaults import config
  from pytensor.graph.basic import Apply, Variable, equal_computations
  from pytensor.graph.fg import FunctionGraph
  from pytensor.graph.op import Op
  from pytensor.graph.rewriting.basic import check_stack_trace, node_rewriter, out2in
  from pytensor.graph.rewriting.utils import rewrite_graph
  from pytensor.graph.type import Type
  from pytensor.tensor.basic import alloc, as_tensor_variable
  from pytensor.tensor.elemwise import DimShuffle, Elemwise
  from pytensor.tensor.math import add, exp, maximum
  from pytensor.tensor.rewriting.basic import register_specialize
  from pytensor.tensor.rewriting.shape import ShapeFeature, local_reshape_to_dimshuffle, local_useless_reshape
  from pytensor.tensor.shape import Reshape, Shape_i, SpecifyShape, reshape, shape, specify_shape
  from pytensor.tensor.subtensor import set_subtensor
  from pytensor.tensor.type import fmatrix, iscalar, lscalar, matrix, scalar, tensor, tensor3, tensor4, vector
  from tests import unittest_tools
label_desc: Use image node_id 6 for calling the TestShapeRewriter obj's underlying member method code with example usage: obj.test_local_track_shape_i() and returns: Apply, Apply, xshp, list