Repository: ResearchObject/ro-crate-py (python)

Issue:
Entity getitem breaks for null JSON values
Example:

```javascript
    {
      "@id": "sort-and-change-case.ga",
      "@type": [
        "File",
        "SoftwareSourceCode",
        "ComputationalWorkflow"
      ],
      "programmingLanguage": {
        "@id": "#galaxy"
      },
      "name": null
    }
```

```pycon
>>> crate.mainEntity["name"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/simleo/git/ro-crate-py/rocrate/model/entity.py", line 81, in __getitem__
    deref_values = [self.crate.dereference(_["@id"], _["@id"]) for _ in values]
  File "/home/simleo/git/ro-crate-py/rocrate/model/entity.py", line 81, in <listcomp>
    deref_values = [self.crate.dereference(_["@id"], _["@id"]) for _ in values]
TypeError: 'NoneType' object is not subscriptable
```

Pull request:
Fix entity getitem when value is None (JSON null)
Fixes #101.

Patch:
diff --git a/rocrate/model/entity.py b/rocrate/model/entity.py
index 826b564..77d5671 100644
--- a/rocrate/model/entity.py
+++ b/rocrate/model/entity.py
@@ -75,7 +75,7 @@ class Entity(MutableMapping):
 
     def __getitem__(self, key):
         v = self._jsonld[key]
-        if isinstance(v, str) or key.startswith("@"):
+        if v is None or isinstance(v, str) or key.startswith("@"):
             return v
         values = v if isinstance(v, list) else [v]
         deref_values = [self.crate.dereference(_["@id"], _["@id"]) for _ in values]


Test patch:
diff --git a/test/test_model.py b/test/test_model.py
index 57fad30..e71bda8 100644
--- a/test/test_model.py
+++ b/test/test_model.py
@@ -295,6 +295,7 @@ def test_entity_as_mapping(tmpdir, helpers):
              "author": {"@id": orcid}},
             {"@id": orcid,
              "@type": "Person",
+             "name": None,
              "givenName": "Josiah",
              "familyName": "Carberry"}
         ]
@@ -305,18 +306,24 @@ def test_entity_as_mapping(tmpdir, helpers):
         json.dump(metadata, f, indent=4)
     crate = ROCrate(crate_dir)
     person = crate.dereference(orcid)
-    assert len(person) == 4
-    assert len(list(person)) == 4
-    assert set(person) == set(person.keys()) == {"@id", "@type", "givenName", "familyName"}
-    assert set(person.values()) == {orcid, "Person", "Josiah", "Carberry"}
+    exp_len = len(metadata["@graph"][2])
+    assert len(person) == exp_len
+    assert len(list(person)) == exp_len
+    assert set(person) == set(person.keys()) == {"@id", "@type", "name", "givenName", "familyName"}
+    assert set(person.values()) == {orcid, "Person", None, "Josiah", "Carberry"}
     assert set(person.items()) == set(zip(person.keys(), person.values()))
+    assert person.id == orcid
+    assert person.type == "Person"
+    assert person["name"] is None
+    assert person["givenName"] == "Josiah"
+    assert person["familyName"] == "Carberry"
     assert person.setdefault("givenName", "foo") == "Josiah"
-    assert len(person) == 4
+    assert len(person) == exp_len
     assert person.setdefault("award", "Oscar") == "Oscar"
-    assert len(person) == 5
+    assert len(person) == exp_len + 1
     assert "award" in person
     assert person.pop("award") == "Oscar"
-    assert len(person) == 4
+    assert len(person) == exp_len
     assert "award" not in person
     for key in "@id", "@type":
         with pytest.raises(KeyError):
@@ -326,8 +333,10 @@ def test_entity_as_mapping(tmpdir, helpers):
         with pytest.raises(KeyError):
             person.pop(key)
     twin = Person(crate, orcid, properties={
+        "name": None,
         "givenName": "Josiah",
         "familyName": "Carberry"
     })
     assert twin == person
     assert Person(crate, orcid) != person
+    assert crate.root_dataset["author"] is person