Skip to content

Commit

Permalink
Merge pull request galaxyproject#17628 from mvdbeek/add_basic_model_i…
Browse files Browse the repository at this point in the history
…mport_validation

[24.0] Add basic model import attribute validation
  • Loading branch information
mvdbeek authored Mar 11, 2024
2 parents f3239d0 + cdde216 commit 4e18d82
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 27 deletions.
44 changes: 27 additions & 17 deletions lib/galaxy/model/store/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@

from bdbag import bdbag_api as bdb
from boltons.iterutils import remap
from pydantic import (
BaseModel,
ConfigDict,
)
from rocrate.model.computationalworkflow import (
ComputationalWorkflow,
WorkflowDescription,
Expand Down Expand Up @@ -96,7 +100,10 @@
get_contributors,
write_to_file,
)
from galaxy.schema.schema import ModelStoreFormat
from galaxy.schema.schema import (
DatasetStateField,
ModelStoreFormat,
)
from galaxy.security.idencoding import IdEncodingHelper
from galaxy.util import (
FILENAME_VALID_CHARS,
Expand Down Expand Up @@ -174,6 +181,20 @@ class ImportDiscardedDataType(Enum):
FORCE = "force"


class DatasetAttributeImportModel(BaseModel):
state: Optional[DatasetStateField] = None
deleted: Optional[bool] = None
purged: Optional[bool] = None
external_filename: Optional[str] = None
_extra_files_path: Optional[str] = None
file_size: Optional[int] = None
object_store_id: Optional[str] = None
total_size: Optional[int] = None
created_from_basename: Optional[str] = None
uuid: Optional[str] = None
model_config = ConfigDict(extra="ignore")


DEFAULT_DISCARDED_DATA_TYPE = ImportDiscardedDataType.FORBID


Expand Down Expand Up @@ -444,22 +465,11 @@ def _import_datasets(
def handle_dataset_object_edit(dataset_instance, dataset_attrs):
if "dataset" in dataset_attrs:
assert self.import_options.allow_dataset_object_edit
dataset_attributes = [
"state",
"deleted",
"purged",
"external_filename",
"_extra_files_path",
"file_size",
"object_store_id",
"total_size",
"created_from_basename",
"uuid",
]

for attribute in dataset_attributes:
if attribute in dataset_attrs["dataset"]:
setattr(dataset_instance.dataset, attribute, dataset_attrs["dataset"][attribute])
dataset_attributes = DatasetAttributeImportModel(**dataset_attrs["dataset"]).model_dump(
exclude_unset=True,
)
for attribute, value in dataset_attributes.items():
setattr(dataset_instance.dataset, attribute, value)
self._attach_dataset_hashes(dataset_attrs["dataset"], dataset_instance)
self._attach_dataset_sources(dataset_attrs["dataset"], dataset_instance)
if "id" in dataset_attrs["dataset"] and self.import_options.allow_edit:
Expand Down
21 changes: 11 additions & 10 deletions lib/galaxy/schema/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
AnyHttpUrl,
AnyUrl,
BaseModel,
BeforeValidator,
ConfigDict,
Field,
Json,
Expand Down Expand Up @@ -151,11 +152,11 @@ class DatasetCollectionPopulatedState(str, Enum):
JobId = Annotated[EncodedDatabaseIdField, Field(..., title="Job ID")]


DatasetStateField: DatasetState = Field(
...,
title="State",
description="The current state of this dataset.",
)
DatasetStateField = Annotated[
DatasetState,
BeforeValidator(lambda v: "discarded" if v == "deleted" else v),
Field(..., title="State", description="The current state of this dataset."),
]

CreateTimeField = Field(
title="Create Time",
Expand Down Expand Up @@ -661,7 +662,7 @@ class HDASummary(HDACommon):
title="Dataset ID",
description="The encoded ID of the dataset associated with this item.",
)
state: DatasetState = DatasetStateField
state: DatasetStateField
extension: Optional[str] = Field(
...,
title="Extension",
Expand All @@ -679,7 +680,7 @@ class HDAInaccessible(HDACommon):
"""History Dataset Association information when the user can not access it."""

accessible: bool = AccessibleField
state: DatasetState = DatasetStateField
state: DatasetStateField


HdaLddaField = Field(
Expand Down Expand Up @@ -872,7 +873,7 @@ class HDAObject(Model, WithModelClass):
# If so at least merge models
id: HistoryDatasetAssociationId
model_class: HDA_MODEL_CLASS = ModelClassField(HDA_MODEL_CLASS)
state: DatasetState = DatasetStateField
state: DatasetStateField
hda_ldda: DatasetSourceType = HdaLddaField
history_id: HistoryID
tags: List[str]
Expand Down Expand Up @@ -3080,7 +3081,7 @@ class FileLibraryFolderItem(LibraryFolderItemBase):
date_uploaded: datetime
is_unrestricted: bool
is_private: bool
state: DatasetState = DatasetStateField
state: DatasetStateField
file_size: str
raw_size: int
ldda_id: EncodedDatabaseIdField
Expand Down Expand Up @@ -3650,7 +3651,7 @@ class DatasetSummary(Model):
id: EncodedDatabaseIdField
create_time: Optional[datetime] = CreateTimeField
update_time: Optional[datetime] = UpdateTimeField
state: DatasetState = DatasetStateField
state: DatasetStateField
deleted: bool
purged: bool
purgable: bool
Expand Down
12 changes: 12 additions & 0 deletions test/unit/schema/test_schema.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from uuid import uuid4

from pydantic import BaseModel

from galaxy.schema.schema import DatasetStateField
from galaxy.schema.tasks import (
GenerateInvocationDownload,
RequestUser,
Expand All @@ -22,3 +25,12 @@ def test_task_schema():
assert rehydrated_download.invocation_id == TEST_INVOCATION_ID
assert rehydrated_download.user.user_id == TEST_USER_ID
assert rehydrated_download.galaxy_url == TEST_GALAXY_URL


class StateModel(BaseModel):
state: DatasetStateField


def test_dataset_state_coercion():
assert StateModel(state="ok").state == "ok"
assert StateModel(state="deleted").state == "discarded"

0 comments on commit 4e18d82

Please sign in to comment.