diff --git a/swh/model/model.py b/swh/model/model.py index 5e00cc61b6e58bbc9ab42132209ecbffd7606158..1496831643dd1b5c80b28bebdb1a6d0390d24b20 100644 --- a/swh/model/model.py +++ b/swh/model/model.py @@ -1396,9 +1396,9 @@ class Directory(HashableObjectWithManifest, BaseModel): raw_manifest = git_objects.directory_git_object(invalid_directory) # 2. look for duplicated entries: - entries_by_name: Dict[ - bytes, Dict[str, List[DirectoryEntry]] - ] = collections.defaultdict(lambda: collections.defaultdict(list)) + entries_by_name: Dict[bytes, Dict[str, List[DirectoryEntry]]] = ( + collections.defaultdict(lambda: collections.defaultdict(list)) + ) for entry in entries: entries_by_name[entry.name][entry.type].append(entry) @@ -1523,7 +1523,7 @@ class Content(BaseContent): raise ValueError("ctime must be a timezone-aware datetime.") def to_dict(self): - content = super(Content, self.with_data()).to_dict() + content = super(Content, self.with_data(raise_if_missing=False)).to_dict() for k in ("get_data", "data", "ctime"): if content[k] is None: del content[k] @@ -1548,18 +1548,22 @@ class Content(BaseContent): d["ctime"] = dateutil.parser.parse(d["ctime"]) return super().from_dict(d, use_subclass=False) - def with_data(self) -> "Content": - """Loads the `data` attribute; meaning that it is guaranteed not to - be None after this call. + def with_data(self, raise_if_missing: bool = True) -> "Content": + """Loads the ``data`` attribute if ``get_data`` is not :const:`None`. This call is almost a no-op, but subclasses may overload this method - to lazy-load data (eg. from disk or objstorage).""" + to lazy-load data (eg. from disk or objstorage). + + Args: + raise_if_missing: if :const:`True` (default), raise :class:`MissingData` + exception if no data is attached to content object + """ if self.data is not None: return self new_data = None if self.get_data is not None: new_data = self.get_data() - if new_data is None: + if new_data is None and raise_if_missing: raise MissingData("Content data and get_data are both None.") return attr.evolve(self, data=new_data, get_data=None) diff --git a/swh/model/tests/test_from_disk.py b/swh/model/tests/test_from_disk.py index ee599538cdd224aeb2cacbd04046587fe1b72d27..234035f1da2fa9faa44aef2f0a70f7f555bbd910 100644 --- a/swh/model/tests/test_from_disk.py +++ b/swh/model/tests/test_from_disk.py @@ -79,8 +79,10 @@ class TestDiskBackedContent(unittest.TestCase): fd.write(b"foo bar") fd.seek(0) content_with_data = content.with_data() + assert content.to_dict() == content_with_data.to_dict() assert expected_content == content_with_data + assert expected_content.to_dict() == content_with_data.to_dict() def test_lazy_data(self): with tempfile.NamedTemporaryFile(mode="w+b") as fd: diff --git a/swh/model/tests/test_model.py b/swh/model/tests/test_model.py index 2a12ec6ef20da96630ce0baeb5c3e7fbb032e2f5..5fb20591c7a27c0983cc2bc60fccddc352711459 100644 --- a/swh/model/tests/test_model.py +++ b/swh/model/tests/test_model.py @@ -814,6 +814,15 @@ def test_content_data(): blake2s256=b"qux", ) assert c.with_data() == c + assert c.to_dict() == { + "sha1": b"foo", + "sha1_git": b"bar", + "sha256": b"baz", + "blake2s256": b"qux", + "length": 42, + "status": "visible", + "data": b"foo", + } def test_content_data_missing(): @@ -828,6 +837,15 @@ def test_content_data_missing(): with pytest.raises(MissingData): c.with_data() + assert c.to_dict() == { + "sha1": b"foo", + "sha1_git": b"bar", + "sha256": b"baz", + "blake2s256": b"qux", + "length": 42, + "status": "visible", + } + @given(strategies.present_contents_d()) def test_content_from_dict(content_d):