def METHOD_NAME(
    df: pd.DataFrame,
    features,
    entities,
    timestamp_key: str = None,
    entity_columns=None,
    options: InferOptions = InferOptions.Null,
):
    """infer feature set schema from dataframe"""
    timestamp_fields = []
    current_entities = list(entities.keys())
    entity_columns = entity_columns or []
    index_columns = dict()
    def upsert_entity(name, value_type):
        if name in current_entities:
            old_type = entities[name].value_type
            if old_type != value_type:
                logger.warning(
                    f"Overriding type of entity '{name}' from '{old_type}' to '{value_type}'. "
                    "This may result in errors or unusable data."
                )
                entities[name].value_type = value_type
        else:
            entities[name] = {"name": name, "value_type": value_type}
    # remove index column if no name provided
    if not df.index.name and df.index.is_numeric():
        df = df.reset_index().drop("index", axis=1)
    schema = pyarrow.Schema.from_pandas(df)
    for i in range(len(schema)):
        column = schema.names[i]
        value_type = pa_type_to_value_type(schema.types[i])
        if column in df.index.names:
            index_columns[column] = value_type
            continue
        is_entity = column in entity_columns or column in current_entities
        if is_entity:
            upsert_entity(column, value_type)
        elif (
            InferOptions.get_common_options(options, InferOptions.Features)
            and column != timestamp_key
        ):
            if column in features.keys():
                features[column].value_type = value_type
            else:
                features[column] = {"name": column, "value_type": value_type}
        if value_type == "datetime" and not is_entity:
            timestamp_fields.append(column)
    index_type = None
    if InferOptions.get_common_options(options, InferOptions.Index):
        # infer types of index fields
        if df.index.name:
            if df.index.name in index_columns:
                index_type = index_columns[df.index.name]
            if not index_type:
                field = convert_pandas_type_to_json_field(df.index)
                index_type = pd_schema_to_value_type(field["type"])
            # Workaround to infer a boolean index correctly, and not as 'str'.
            upsert_entity(df.index.name, index_type)
        elif df.index.nlevels > 1:
            for level, name in zip(df.index.levels, df.index.names):
                if name in index_columns:
                    index_type = index_columns[name]
                else:
                    field = convert_pandas_type_to_json_field(df.index)
                    index_type = pd_schema_to_value_type(field["type"])
                upsert_entity(name, index_type)
                if index_type == "datetime":
                    timestamp_fields.append(name)
    return timestamp_key