def schema_from_feature_spec(
    feature_spec: Mapping[str, common_types.FeatureSpecType],
    domains: Optional[Mapping[str, common_types.DomainType]] = None
) -> schema_pb2.Schema:
  """Convert a feature spec to a Schema proto.

  Args:
    feature_spec: A TensorFlow feature spec
    domains: (optional) a dict whose keys are feature names and values are one
      of schema_pb2.IntDomain, schema_pb2.StringDomain or
      schema_pb2.FloatDomain.

  Returns:
    A Schema proto

  Raises:
    ValueError: If the feature spec cannot be converted to a Schema proto.
  """
  if domains is None:
    domains = {}

  result = schema_pb2.Schema()

  # Some feature specs can only be represented with the legacy schema, in
  # particular feature specs where any FixedLenFeature has default_value set.
  # We represent these (and only these) using a schema with
  # generate_legacy_feature_spec=True.  Note the generate_legacy_feature_spec
  # field is not part of the open source codebase.
  if schema_utils_legacy.should_set_generate_legacy_feature_spec(feature_spec):
    return _legacy_schema_from_feature_spec(feature_spec, domains)

  schema_utils_legacy.set_generate_legacy_feature_spec(result, False)

  # Add the features to the schema.
  for name, spec in sorted(feature_spec.items()):
    if isinstance(spec, tf.io.SparseFeature):
      (index_feature, value_feature, sparse_feature) = (
          _sparse_feature_from_feature_spec(spec, name, domains))
      for f in index_feature:
        result.feature.add().CopyFrom(f)
      result.feature.add().CopyFrom(value_feature)
      result.sparse_feature.add().CopyFrom(sparse_feature)

    elif isinstance(spec, tf.io.RaggedFeature):
      (value_feature, partitions_features, ragged_tensor_representation) = (
          _ragged_tensor_representation_from_feature_spec(spec, name, domains))
      result.feature.add().CopyFrom(value_feature)
      for f in partitions_features:
        result.feature.add().CopyFrom(f)
      tensor_representation_map = result.tensor_representation_group[
          TENSOR_REPRESENTATION_GROUP].tensor_representation
      tensor_representation_map[name].CopyFrom(ragged_tensor_representation)

    else:
      result.feature.add().CopyFrom(
          _feature_from_feature_spec(spec, name, domains))
  return result
Convert a feature spec to a Schema proto.

  Args:
    feature_spec: A TensorFlow feature spec
    domains: (optional) a dict whose keys are feature names and values are one
      of schema_pb2.IntDomain, schema_pb2.StringDomain or
      schema_pb2.FloatDomain.

  Returns:
    A Schema proto

  Raises:
    ValueError: If the feature spec cannot be converted to a Schema proto.
  
tensorflow_transform/tf_metadata/schema_utils.py