From aec76d05d759270e8c409bd9e68c96dfcc7937f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gregor=20Jer=C5=A1e?= Date: Thu, 28 Nov 2024 21:02:08 +0100 Subject: [PATCH] Fix crash in annotation value endpoint when removing the delete markers. --- docs/CHANGELOG.rst | 5 +++++ resolwe/flow/models/annotations.py | 6 +++--- resolwe/flow/tests/test_annotations.py | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.rst b/docs/CHANGELOG.rst index a7e446ac9..3e3464f8e 100644 --- a/docs/CHANGELOG.rst +++ b/docs/CHANGELOG.rst @@ -14,10 +14,15 @@ Added ----- - Expose ``status`` on ``collection`` and ``entity`` viewset and allow filtering and sorting by it + Changed ------- - Make processing container startup script ``Python`` 3.12 compatible +Fixed +----- +- Fix ``AnnotationValueViewSet`` crash when removing the delete markers + =================== 42.0.1 - 2024-11-21 diff --git a/resolwe/flow/models/annotations.py b/resolwe/flow/models/annotations.py index 358df6d75..e80abd131 100644 --- a/resolwe/flow/models/annotations.py +++ b/resolwe/flow/models/annotations.py @@ -517,9 +517,9 @@ def delete_marker(self) -> bool: return self._value is None @property - def value(self) -> str | int | float | datetime.date: - """Get the actual value.""" - return self._value["value"] + def value(self) -> Optional[str | int | float | datetime.date]: + """Get the actual value or None if object is delete marker.""" + return None if self.delete_marker else self._value["value"] @value.setter def value(self, value: str | int | float | datetime.date): diff --git a/resolwe/flow/tests/test_annotations.py b/resolwe/flow/tests/test_annotations.py index 4c6bc7147..e9896f92c 100644 --- a/resolwe/flow/tests/test_annotations.py +++ b/resolwe/flow/tests/test_annotations.py @@ -1270,6 +1270,20 @@ def test_list_filter_values(self): self.assertTrue(response.data[0]["value"], "string") self.assertTrue(response.data[0]["label"], "label string") + # Test delete markers are handled properly. + delete_marker = AnnotationValue.objects.create( + entity=self.annotation_value1.entity, + field=self.annotation_value1.field, + _value=None, + contributor=self.annotation_value1.contributor, + ) + request = factory.get("/", {"entity": self.entity1.pk}, format="json") + force_authenticate(request, self.contributor) + response = self.annotationvalue_viewset(request) + self.assertTrue(response.status_code, status.HTTP_200_OK) + self.assertEqual(len(response.data), 0) + delete_marker.delete() + # Another authenticated request. self.annotation_value2.entity = self.entity1 self.annotation_value2.save()