Repository: SciCatProject/scitacean

Issue:
Make `dataset.type` read-only
It seems strange and error-prone that it is possible to change the `type` of a dataset. In particular because it can lead to datasets that have the wrong fields set. Is there a valid use case for it?

Discussion:

Patch:
diff --git a/src/scitacean/_dataset_fields.py b/src/scitacean/_dataset_fields.py
index fa97195..a577e27 100644
--- a/src/scitacean/_dataset_fields.py
+++ b/src/scitacean/_dataset_fields.py
@@ -1054,11 +1054,6 @@ class DatasetBase:
         """Characterize type of dataset, either 'raw' or 'derived'. Autofilled when choosing the proper inherited models."""
         return self._type
 
-    @type.setter
-    def type(self, type: Union[DatasetType, Literal["raw", "derived"]]) -> None:
-        """Characterize type of dataset, either 'raw' or 'derived'. Autofilled when choosing the proper inherited models."""
-        self._type = DatasetType(type)
-
     @staticmethod
     def _prepare_fields_from_download(
         download_model: DownloadDataset,
diff --git a/src/scitacean/model.py b/src/scitacean/model.py
index 4f140a4..5a58eda 100644
--- a/src/scitacean/model.py
+++ b/src/scitacean/model.py
@@ -321,7 +321,6 @@ class UploadAttachment(BaseModel):
 class DownloadOrigDatablock(BaseModel):
     dataFileList: Optional[List[DownloadDataFile]] = None
     datasetId: Optional[PID] = None
-    ownerGroup: Optional[str] = None
     size: Optional[NonNegativeInt] = None
     id: Optional[str] = pydantic.Field(alias="_id", default=None)
     accessGroups: Optional[List[str]] = None
@@ -329,6 +328,7 @@ class DownloadOrigDatablock(BaseModel):
     createdAt: Optional[datetime] = None
     createdBy: Optional[str] = None
     instrumentGroup: Optional[str] = None
+    ownerGroup: Optional[str] = None
     updatedAt: Optional[datetime] = None
     updatedBy: Optional[str] = None
 
@@ -344,11 +344,11 @@ class DownloadOrigDatablock(BaseModel):
 class UploadOrigDatablock(BaseModel):
     dataFileList: List[UploadDataFile]
     datasetId: PID
-    ownerGroup: str
     size: NonNegativeInt
     accessGroups: Optional[List[str]] = None
     chkAlg: Optional[str] = None
     instrumentGroup: Optional[str] = None
+    ownerGroup: Optional[str] = None
 
     @classmethod
     def download_model_type(cls) -> Type[DownloadOrigDatablock]:
diff --git a/tools/model-generation/templates/dataset_fields.py.jinja b/tools/model-generation/templates/dataset_fields.py.jinja
index 45e0526..39524aa 100644
--- a/tools/model-generation/templates/dataset_fields.py.jinja
+++ b/tools/model-generation/templates/dataset_fields.py.jinja
@@ -193,11 +193,6 @@ class DatasetBase:
         """Characterize type of dataset, either 'raw' or 'derived'. Autofilled when choosing the proper inherited models."""
         return self._type
 
-    @type.setter
-    def type(self, type: Union[DatasetType, Literal["raw", "derived"]]) -> None:
-        """Characterize type of dataset, either 'raw' or 'derived'. Autofilled when choosing the proper inherited models."""
-        self._type = DatasetType(type)
-
     @staticmethod
     def _prepare_fields_from_download(
         download_model: DownloadDataset


Test patch:
diff --git a/tests/dataset_fields_test.py b/tests/dataset_fields_test.py
index 7dea8fd..0a12e7c 100644
--- a/tests/dataset_fields_test.py
+++ b/tests/dataset_fields_test.py
@@ -27,6 +27,8 @@ from scitacean.model import (
 # Fields whose types are not supported by hypothesis.
 # E.g. because they contain `Any`.
 _UNGENERATABLE_FIELDS = ("job_parameters", "meta")
+# Fields that are readonly, but still required in the constructor.
+_NOT_SETTABLE_FIELDS = ("type",)
 
 
 def test_init_dataset_with_only_type():
@@ -107,7 +109,11 @@ def test_can_init_writable_fields(field, data):
 
 @pytest.mark.parametrize(
     "field",
-    (f for f in Dataset.fields(read_only=False) if f.name not in _UNGENERATABLE_FIELDS),
+    (
+        f
+        for f in Dataset.fields(read_only=False)
+        if f.name not in _UNGENERATABLE_FIELDS and f.name not in _NOT_SETTABLE_FIELDS
+    ),
     ids=lambda f: f.name,
 )
 @given(st.data())