code: def make_sparse_tensor_type_proto(
      elem_type: int,
      shape: Optional[Sequence[Union[str, int, None]]],
      shape_denotation: Optional[List[str]] = None,
  ) -> TypeProto:
      """Makes a SparseTensor TypeProto based on the data type and shape."""
      type_proto = TypeProto()
      sparse_tensor_type_proto = type_proto.sparse_tensor_type
      sparse_tensor_type_proto.elem_type = elem_type
      sparse_tensor_shape_proto = sparse_tensor_type_proto.shape
  
      if shape is not None:
          # You might think this is a no-op (extending a normal Python
          # list by [] certainly is), but protobuf lists work a little
          # differently; if a field is never set, it is omitted from the
          # resulting protobuf; a list that is explicitly set to be
          # empty will get an (empty) entry in the protobuf. This
          # difference is visible to our consumers, so make sure we emit
          # an empty shape!
          sparse_tensor_shape_proto.dim.extend([])
  
          if shape_denotation and len(shape_denotation) != len(shape):
              raise ValueError(
                  "Invalid shape_denotation. Must be of the same length as shape."
              )
  
          for i, d in enumerate(shape):
              dim = sparse_tensor_shape_proto.dim.add()
              if d is None:
                  pass
              elif isinstance(d, int):
                  dim.dim_value = d
              elif isinstance(d, str):
                  dim.dim_param = d
              else:
                  raise ValueError(
                      f"Invalid item in shape: {d}. Needs to be of int or text."
                  )
  
              if shape_denotation:
                  dim.denotation = shape_denotation[i]
  
      return type_proto
  
imports: import collections.abc
  import numbers
  import struct
  from cmath import isnan
  from typing import Any, Callable, Dict, KeysView, List, Optional, Sequence, Tuple, TypeVar, Union, cast
  import google.protobuf.message
  import numpy
  from onnx import IR_VERSION, AttributeProto, FunctionProto, GraphProto, MapProto, ModelProto, NodeProto, OperatorSetIdProto, OptionalProto, SequenceProto, SparseTensorProto, TensorProto, TensorShapeProto, TrainingInfoProto, TypeProto, ValueInfoProto, defs, mapping, subbyte
label_desc: Use image node_id 29 for calling a global function with example usage: make_sparse_tensor_type_proto(elem_type, shape, shape_denotation) and returns: type_proto