dtype: ClassLabel is not parsed correctly in `features.py`
Opened by cmatKhan (closed)

`dtype: ClassLabel` in the README.md yaml metadata is parsed incorrectly and causes the data viewer to fail.

This yaml in my metadata ([source](https://huggingface.co/datasets/BrentLab/yeast_genome_resources/blob/main/README.md), though i changed `ClassLabel` to `string` to using different dtype in order to avoid the error):

```yaml
license: mit
pretty_name: BrentLab Yeast Genome Resources
size_categories:
  - 1K<n<10K
language:
  - en
dataset_info:
  features:
    - name: start
      dtype: int32
      description: Start coordinate (1-based, **inclusive**)
    - name: end
      dtype: int32
      description: End coordinate (1-based, **inclusive**)
    - name: strand
      dtype: ClassLabel
...
```

is producing the following error in the data viewer:

```
Error code:   ConfigNamesError
Exception:    ValueError
Message:      Feature type 'Classlabel' not found. Available feature types: ['Value', 'ClassLabel', 'Translation', 'TranslationVariableLanguages', 'LargeList', 'List', 'Array2D', 'Array3D', 'Array4D', 'Array5D', 'Audio', 'Image', 'Video', 'Pdf']
Traceback:    Traceback (most recent call last):
                File "/src/services/worker/src/worker/job_runners/dataset/config_names.py", line 66, in compute_config_names_response
                  config_names = get_dataset_config_names(
                File "/src/services/worker/.venv/lib/python3.9/site-packages/datasets/inspect.py", line 161, in get_dataset_config_names
                  dataset_module = dataset_module_factory(
                File "/src/services/worker/.venv/lib/python3.9/site-packages/datasets/load.py", line 1031, in dataset_module_factory
                  raise e1 from None
                File "/src/services/worker/.venv/lib/python3.9/site-packages/datasets/load.py", line 996, in dataset_module_factory
                  return HubDatasetModuleFactory(
                File "/src/services/worker/.venv/lib/python3.9/site-packages/datasets/load.py", line 605, in get_module
                  dataset_infos = DatasetInfosDict.from_dataset_card_data(dataset_card_data)
                File "/src/services/worker/.venv/lib/python3.9/site-packages/datasets/info.py", line 386, in from_dataset_card_data
                  dataset_info = DatasetInfo._from_yaml_dict(dataset_card_data["dataset_info"])
                File "/src/services/worker/.venv/lib/python3.9/site-packages/datasets/info.py", line 317, in _from_yaml_dict
                  yaml_data["features"] = Features._from_yaml_list(yaml_data["features"])
                File "/src/services/worker/.venv/lib/python3.9/site-packages/datasets/features/features.py", line 2027, in _from_yaml_list
                  return cls.from_dict(from_yaml_inner(yaml_data))
                File "/src/services/worker/.venv/lib/python3.9/site-packages/datasets/features/features.py", line 1872, in from_dict
                  obj = generate_from_dict(dic)
                File "/src/services/worker/.venv/lib/python3.9/site-packages/datasets/features/features.py", line 1459, in generate_from_dict
                  return {key: generate_from_dict(value) for key, value in obj.items()}
                File "/src/services/worker/.venv/lib/python3.9/site-packages/datasets/features/features.py", line 1459, in <dictcomp>
                  return {key: generate_from_dict(value) for key, value in obj.items()}
                File "/src/services/worker/.venv/lib/python3.9/site-packages/datasets/features/features.py", line 1465, in generate_from_dict
                  raise ValueError(f"Feature type '{_type}' not found. Available feature types: {list(_FEATURE_TYPES.keys())}")
              ValueError: Feature type 'Classlabel' not found. Available feature types: ['Value', 'ClassLabel', 'Translation', 'TranslationVariableLanguages', 'LargeList', 'List', 'Array2D', 'Array3D', 'Array4D', 'Array5D', 'Audio', 'Image', 'Video', 'Pdf']
```

I think that this is caused by this line

https://github.com/huggingface/datasets/blob/896616c6cb03d92a33248c3529b0796cda27e955/src/datasets/features/features.py#L2013

Reproducible example from [naming.py](https://github.com/huggingface/datasets/blob/896616c6cb03d92a33248c3529b0796cda27e955/src/datasets/naming.py)

```python
import itertools
import os
import re


_uppercase_uppercase_re = re.compile(r"([A-Z]+)([A-Z][a-z])")
_lowercase_uppercase_re = re.compile(r"([a-z\d])([A-Z])")

_single_underscore_re = re.compile(r"(?<!_)_(?!_)")
_multiple_underscores_re = re.compile(r"(_{2,})")

_split_re = r"^\w+(\.\w+)*$"

def snakecase_to_camelcase(name):
    """Convert snake-case string to camel-case string."""
    name = _single_underscore_re.split(name)
    name = [_multiple_underscores_re.split(n) for n in name]
    return "".join(n.capitalize() for n in itertools.chain.from_iterable(name) if n != "")

snakecase_to_camelcase("ClassLabel")
```

Result:

```raw
'Classlabel'
```

Comments:
I think it's "class_label"

> I think it's "class_label"

I see -- thank you. This works

```yaml
license: mit
language:
- en
tags:
- genomics
- yeast
- transcription
- perturbation
- response
- overexpression
pretty_name: Hackett, 2020 Overexpression
size_categories:
- 1M<n<10M
dataset_info:
  features:
    ...
    - name: mechanism
      dtype:
        class_label:
          names: ["GEV", "ZEV"]
      description: induction system (GEV or ZEV)
    - name: restriction
      dtype:
        class_label:
          names: ["M", "N", "P"]
      description: nutrient limitation (M, N or P)
```

I see the documentation for [datasets.ClassLabel](https://huggingface.co/docs/datasets/v4.0.0/en/package_reference/main_classes#datasets.ClassLabel). And the documentation for the [dataset cards](https://huggingface.co/docs/hub/en/datasets-cards). I don't see anything in either of those places, though, that specifies the pattern above.

I suppose rather than writing the yaml by hand, the expected workflow is to use `datasets` to construct these features?

I generally copy/paste and adapt a YAML from another dataset.

But it's also possible to generate it from `datasets` like that

```python
>>> import yaml
>>> print(yaml.dump(features._to_yaml_list(), sort_keys=False))
- name: start
  dtype: int32
- name: end
  dtype: int32
- name: restriction
  dtype:
    class_label:
      names: ["M", "N", "P"]
```