docstr: A shape class for setting multiple valid shapes in InputType.
  
  Parameters
  ----------
  shapes: list of Shape objects, or Shape-compatible lists
      * The valid shapes of the inputs.
      * If input provided is not a :py:class:`Shape` object,
        but can be converted to a :py:class:`Shape`,
        the :py:class:`Shape` object would be stored in ``shapes`` instead.
  
  
  default: tuple of int or None
      * The default shape that is used for initiating the model, and set in
        the metadata of the model file.
      * If ``None``, then the first element in ``shapes`` is used.
  
  
  Examples
  --------
  .. sourcecode:: python
  
      sample_shape = ct.EnumeratedShapes(
         shapes=[
              (2, 4, 64, 64),
              (2, 4, 48, 48),
              (2, 4, 32, 32)
          ],
          default=(2, 4, 64, 64)
      )
  
      my_core_ml_model = ct.convert(
          my_model,
          inputs=[ct.TensorType(name="sample", shape=sample_shape)],
      )
docstr_tok: ["A","shape","class","for","setting","multiple","valid","shapes","in","InputType",".","Parameters","--","--","--","--","--","shapes",":","list","of","Shape","objects",",","or","Shape-compatible","lists","*","The","valid","shapes","of","the","inputs",".","*","If","input","provided","is","not","a",":","py",":","class",":","`","Shape","`","object",",","but","can","be","converted","to","a",":","py",":","class",":","`","Shape","`",",","the",":","py",":","class",":","`","Shape","`","object","would","be","stored","in","``","shapes","``","instead",".","default",":","tuple","of","int","or","None","*","The","default","shape","that","is","used","for","initiating","the","model",",","and","set","in","the","metadata","of","the","model","file",".","*","If","``","None","``",",","then","the","first","element","in","``","shapes","``","is","used",".","Examples","--","--","--","--","..","sourcecode",":",":","python","sample_shape","=","ct.EnumeratedShapes","(","shapes=","[","(","2",",","4",",","64",",","64",")",",","(","2",",","4",",","48",",","48",")",",","(","2",",","4",",","32",",","32",")","]",",","default=","(","2",",","4",",","64",",","64",")",")","my_core_ml_model","=","ct.convert","(","my_model",",","inputs=","[","ct.TensorType","(","name=","''","sample","''",",","shape=sample_shape",")","]",",",")"]
code: def __init__(self, shapes, default=None):
      """
      A shape class for setting multiple valid shapes in InputType.
  
      Parameters
      ----------
      shapes: list of Shape objects, or Shape-compatible lists
          * The valid shapes of the inputs.
          * If input provided is not a :py:class:`Shape` object,
            but can be converted to a :py:class:`Shape`,
            the :py:class:`Shape` object would be stored in ``shapes`` instead.
  
  
      default: tuple of int or None
          * The default shape that is used for initiating the model, and set in
            the metadata of the model file.
          * If ``None``, then the first element in ``shapes`` is used.
  
  
      Examples
      --------
      .. sourcecode:: python
  
          sample_shape = ct.EnumeratedShapes(
             shapes=[
                  (2, 4, 64, 64),
                  (2, 4, 48, 48),
                  (2, 4, 32, 32)
              ],
              default=(2, 4, 64, 64)
          )
  
          my_core_ml_model = ct.convert(
              my_model,
              inputs=[ct.TensorType(name="sample", shape=sample_shape)],
          )
      """
  
      # lazy import to avoid circular import
      from coremltools.converters.mil.mil import get_new_symbol
  
      if not isinstance(shapes, (list, tuple)):
          raise ValueError(
              "EnumeratedShapes should be list or tuple of shape, got type {} instead".format(
                  type(shapes)
              )
          )
      if len(shapes) < 2:
          raise ValueError(
              "EnumeratedShapes should be take a list or tuple with len >= 2, got {} instead".format(
                  len(shapes)
              )
          )
  
      self.shapes = []
      for idx, s in enumerate(shapes):
          if isinstance(s, Shape):
              self.shapes.append(s)
          else:
              self.shapes.append(Shape(s))
  
      self.symbolic_shape = self.shapes[0].symbolic_shape
      for shape in self.shapes:
          for idx, s in enumerate(shape.symbolic_shape):
              if is_symbolic(self.symbolic_shape[idx]):
                  continue
              elif is_symbolic(s):
                  self.symbolic_shape[idx] = s
              elif s != self.symbolic_shape[idx]:
                  self.symbolic_shape[idx] = get_new_symbol()
  
      if default is not None:
          if not isinstance(default, (list, tuple)):
              raise ValueError(
                  "Default shape should be list or tuple, got type {} instead".format(
                      type(default)
                  )
              )
          for idx, s in enumerate(default):
              if not isinstance(
                  s, (np.generic, int)
              ) and not is_symbolic(s):
                  raise ValueError(
                      "Default shape invalid, got error at index {} which is {}".format(
                          idx, s
                      )
                  )
      else:
          default = self.shapes[0].default
      self.default = default
  
imports: from enum import Enum
  from typing import Optional
  import numpy
  from coremltools.converters.mil.mil import types
  from coremltools.converters.mil.mil.types.symbolic import is_symbolic
  from coremltools.converters.mil.mil.types.type_mapping import is_builtin, numpy_type_to_builtin_type
label_desc: Use image node_id 1 to create a new EnumeratedShapes object  with example: obj = EnumeratedShapes(shapes, default)