Repository: openvinotoolkit/datumaro

Issue:
Converting CVAT into Yolo
script

```
from datumaro.components.project import Environment
from datumaro.plugins.yolo_format.converter import YoloConverter

# Import and save a dataset
env = Environment()
dataset = env.make_importer("cvat")(str(self.dataset_path)).make_dataset()
 env.converters.get("yolo").convert(dataset, save_dir="dst/dir")
```
Dataset folder structure
```
---dataset
        |----report.xml
        |----images
                  |-----forest1
                           |-----1.jpg
                           |-----2.jpg
                  |-----forest2
                           |---3.jpg
```




While converting CVAT into yolo format  by using above code, got following error ,,

Traceback (most recent call last):
  File "main.py", line 118, in <module>
    app.run(main)
  File "/root/anaconda3/envs/aug/lib/python3.8/site-packages/absl/app.py", line 300, in run
    _run_main(main, args)
  File "/root/anaconda3/envs/aug/lib/python3.8/site-packages/absl/app.py", line 251, in _run_main
    sys.exit(main(argv))
  File "main.py", line 114, in main
    ss.produce()
  File "main.py", line 77, in produce
    handle_dataset.cvat2yolo()
  File "/home/sam/ss/utils/dataset_generator.py", line 135, in cvat2yolo
    dataset = env.make_importer("cvat")(str(self.dataset_path)).make_dataset()
  File "/root/anaconda3/envs/aug/lib/python3.8/site-packages/datumaro/components/project.py", line 600, in make_dataset
    return ProjectDataset(self)
  File "/root/anaconda3/envs/aug/lib/python3.8/site-packages/datumaro/components/project.py", line 318, in __init__
    sources[s_name] = env.make_extractor(s_format, url, **options)
  File "/root/anaconda3/envs/aug/lib/python3.8/site-packages/datumaro/components/project.py", line 284, in make_extractor
    return self.extractors.get(name)(*args, **kwargs)
  File "/root/anaconda3/envs/aug/lib/python3.8/site-packages/datumaro/plugins/cvat_format/extractor.py", line 33, in __init__
    items, categories = self._parse(path)
  File "/root/anaconda3/envs/aug/lib/python3.8/site-packages/datumaro/plugins/cvat_format/extractor.py", line 94, in _parse
    attr_value = float(attr_value)
TypeError: float() argument must be a string or a number, not 'NoneType'



Discussion:
Hi, could you share the `.xml` annotations (maybe privately)?
> Hi, could you share the `.xml` annotations (maybe privately)?

Thank you for your response .. I have sent the xml file to your mail id.. Please check it 



Resolving patch:
diff --git a/datumaro/plugins/cvat_format/extractor.py b/datumaro/plugins/cvat_format/extractor.py
--- a/datumaro/plugins/cvat_format/extractor.py
+++ b/datumaro/plugins/cvat_format/extractor.py
@@ -86,7 +86,7 @@ def _parse(cls, path):
                     }
             elif ev == 'end':
                 if el.tag == 'attribute' and attributes is not None:
-                    attr_value = el.text
+                    attr_value = el.text or ''
                     if el.text in ['true', 'false']:
                         attr_value = attr_value == 'true'
                     else:


Test patch:
diff --git a/tests/test_cvat_format.py b/tests/test_cvat_format.py
--- a/tests/test_cvat_format.py
+++ b/tests/test_cvat_format.py
@@ -150,7 +150,7 @@ def test_can_save_and_load(self):
         label_categories = LabelCategories()
         for i in range(10):
             label_categories.add(str(i))
-        label_categories.items[2].attributes.update(['a1', 'a2'])
+        label_categories.items[2].attributes.update(['a1', 'a2', 'empty'])
         label_categories.attributes.update(['occluded'])
 
         source_dataset = Dataset.from_iterable([
@@ -158,10 +158,10 @@ def test_can_save_and_load(self):
                 annotations=[
                     Polygon([0, 0, 4, 0, 4, 4],
                         label=1, group=4,
-                        attributes={ 'occluded': True }),
+                        attributes={ 'occluded': True}),
                     Points([1, 1, 3, 2, 2, 3],
                         label=2,
-                        attributes={ 'a1': 'x', 'a2': 42,
+                        attributes={ 'a1': 'x', 'a2': 42, 'empty': '',
                             'unknown': 'bar' }),
                     Label(1),
                     Label(2, attributes={ 'a1': 'y', 'a2': 44 }),
@@ -199,7 +199,7 @@ def test_can_save_and_load(self):
                         attributes={ 'occluded': True }),
                     Points([1, 1, 3, 2, 2, 3],
                         label=2,
-                        attributes={ 'occluded': False,
+                        attributes={ 'occluded': False, 'empty': '',
                             'a1': 'x', 'a2': 42 }),
                     Label(1),
                     Label(2, attributes={ 'a1': 'y', 'a2': 44 }),