Repository: ResearchObject/ro-crate-py

Issue:
hasPart property on root dataset is assumed to be an array
Loading this dataset causes an error as the hasPart value is not an array but the code assumes it will be :

```json
{
    "@id": "./",
    "@type": "Dataset",
    "hasPart":  {"@id": "spam/foo.txt"} 
},
{
    "@id": "spam/foo.txt",
    "@type": "File"
}
```

This line is the culprit: https://github.com/ResearchObject/ro-crate-py/blob/dc3f75b0d0390dedbf9a830b6325b76dba468f1f/rocrate/rocrate.py#L145C1-L146C1

 parts = root_entity.pop('hasPart', [])

I added this to my copy  make it work but not sure if you have a general purpose way of doing this in this library:

        if not isinstance(parts, list):
            parts = [parts]



Discussion:

Patch:
diff --git a/rocrate/rocrate.py b/rocrate/rocrate.py
index 57bcd39..5d5a98d 100644
--- a/rocrate/rocrate.py
+++ b/rocrate/rocrate.py
@@ -142,7 +142,7 @@ class ROCrate():
 
         root_entity = entities.pop(root_id)
         assert root_id == root_entity.pop('@id')
-        parts = root_entity.pop('hasPart', [])
+        parts = as_list(root_entity.pop('hasPart', []))
         self.add(RootDataset(self, root_id, properties=root_entity))
         preview_entity = entities.pop(Preview.BASENAME, None)
         if preview_entity and not gen_preview:
@@ -167,7 +167,7 @@ class ROCrate():
                 else:
                     instance = cls(self, source / id_, id_, properties=entity)
             self.add(instance)
-            self.__add_parts(entity.get("hasPart", []), entities, source)
+            self.__add_parts(as_list(entity.get("hasPart", [])), entities, source)
 
     def __read_contextual_entities(self, entities):
         type_map = {_.__name__: _ for _ in subclasses(ContextEntity)}


Test patch:
diff --git a/test/test_read.py b/test/test_read.py
index 9aa3e96..43bf328 100644
--- a/test/test_read.py
+++ b/test/test_read.py
@@ -499,17 +499,17 @@ def test_indirect_data_entity(tmpdir):
             {
                 "@id": "./",
                 "@type": "Dataset",
-                "hasPart": [{"@id": "d1"}]
+                "hasPart": {"@id": "d1"}
             },
             {
                 "@id": "d1",
                 "@type": "Dataset",
-                "hasPart": [{"@id": "d1/d2"}]
+                "hasPart": {"@id": "d1/d2"}
             },
             {
                 "@id": "d1/d2",
                 "@type": "Dataset",
-                "hasPart": [{"@id": "d1/d2/f1"}]
+                "hasPart": {"@id": "d1/d2/f1"}
             },
             {
                 "@id": "d1/d2/f1",