class_docstr: This class can create a struct of PyTensor types (like `TensorType`, etc.)
  to be used as a convenience `Op` parameter wrapping many data.
  
  `ParamsType` constructor takes key-value args.  Key will be the name of the
  attribute in the struct.  Value is the PyTensor type of this attribute,
  ie. an instance of (a subclass of) :class:`CType`
  (eg. ``TensorType('int64', (None,))``).
  
  In a Python code any attribute named ``key`` will be available via::
  
      structObject.key
  
  In a C code, any attribute named ``key`` will be available via:
  
  .. code-block:: c
  
      structObject->key;
  
  .. note::
  
      This `Type` is not complete and should never be used for regular graph
      operations.
class_docstr_tok: ["This","class","can","create","a","struct","of","PyTensor","types","(","like","`","TensorType","`",",","etc",".",")","to","be","used","as","a","convenience","`","Op","`","parameter","wrapping","many","data",".","`","ParamsType","`","constructor","takes","key-value","args",".","Key","will","be","the","name","of","the","attribute","in","the","struct",".","Value","is","the","PyTensor","type","of","this","attribute",",","ie",".","an","instance","of","(","a","subclass","of",")",":","class",":","`","CType","`","(","eg",".","``","TensorType","(","'int64","'",",","(","None",",",")",")","``",")",".","In","a","Python","code","any","attribute","named","``","key","``","will","be","available","via",":",":","structObject.key","In","a","C","code",",","any","attribute","named","``","key","``","will","be","available","via",":","..","code-block",":",":","c","structObject-",">","key",";","..","note",":",":","This","`","Type","`","is","not","complete","and","should","never","be","used","for","regular","graph","operations","."]
code: def c_support_code(self, **kwargs):
      sub = {"fail": "{this->setErrorOccurred(); return;}"}
      struct_name = self.name
      struct_name_defined = struct_name.upper()
      c_support_code_set = set()
      c_declare_list = []
      c_init_list = []
      c_cleanup_list = []
      c_extract_list = []
      for attribute_name, type_instance in zip(self.fields, self.types):
          try:
              # c_support_code() may return a code string or a list of code strings.
              support_code = type_instance.c_support_code()
              if not isinstance(support_code, list):
                  support_code = [support_code]
              c_support_code_set.update(support_code)
          except MethodNotDefined:
              pass
  
          c_declare_list.append(
              type_instance.c_declare(attribute_name, sub)
          )
  
          c_init_list.append(type_instance.c_init(attribute_name, sub))
  
          c_cleanup_list.append(
              type_instance.c_cleanup(attribute_name, sub)
          )
  
          c_extract_list.append(
              """
              void extract_%(attribute_name)s(PyObject* py_%(attribute_name)s) {
                  %(extract_code)s
              }
              """
              % {
                  "attribute_name": attribute_name,
                  "extract_code": type_instance.c_extract(
                      attribute_name, sub
                  ),
              }
          )
  
      struct_declare = "\n".join(c_declare_list)
      struct_init = "\n".join(c_init_list)
      struct_cleanup = "\n".join(c_cleanup_list)
      struct_extract = "\n\n".join(c_extract_list)
      struct_extract_method = """
          void extract(PyObject* object, int field_pos) {
              switch(field_pos) {
                  // Extraction cases.
                  %s
                  // Default case.
                  default:
                      PyErr_Format(PyExc_TypeError, "ParamsType: no extraction defined for a field %%d.", field_pos);
                      this->setErrorOccurred();
                      break;
              }
          }
          """ % (
          "\n".join(
              [
                  (
                      "case %d: extract_%s(object); break;"
                      % (i, self.fields[i])
                  )
                  for i in range(self.length)
              ]
          )
      )
      final_struct_code = """
          /** ParamsType %(struct_name)s **/
          #ifndef %(struct_name_defined)s
          #define %(struct_name_defined)s
          struct %(struct_name)s {
              /* Attributes, */
              int %(struct_name)s_error;
              %(struct_declare)s
  
              /* Constructor. */
              %(struct_name)s() {
                  %(struct_name)s_error = 0;
                  %(struct_init)s
              }
  
              /* Destructor. */
              ~%(struct_name)s() {
                  // cleanup() is defined below.
                  cleanup();
              }
  
              /* Cleanup method. */
              void cleanup() {
                  %(struct_cleanup)s
              }
  
              /* Extraction methods. */
              %(struct_extract)s
  
              /* Extract method. */
              %(struct_extract_method)s
  
              /* Other methods. */
              void setErrorOccurred() {
                  ++%(struct_name)s_error;
              }
              int errorOccurred() {
                  return %(struct_name)s_error;
              }
          };
          #endif
          /** End ParamsType %(struct_name)s **/
          """ % dict(
          struct_name_defined=struct_name_defined,
          struct_name=struct_name,
          struct_declare=struct_declare,
          struct_init=struct_init,
          struct_cleanup=struct_cleanup,
          struct_extract=struct_extract,
          struct_extract_method=struct_extract_method,
      )
  
      return sorted(c_support_code_set) + [final_struct_code]
  
imports: import hashlib
  import re
  from pytensor.graph.utils import MethodNotDefined
  from pytensor.link.c.type import CType, EnumType
label_desc: Use image node_id 25 for calling the ParamsType obj's underlying member method code with example usage: obj.c_support_code() and returns: unknown