mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #15105 from mvdbeek/model_class_fix
Fix ``model_class`` field annotations
This commit is contained in:
@@ -18,12 +18,7 @@ from galaxy.structured_app import MinimalManagerApp
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def datetime_to_iso8601(utc_datetime: datetime) -> str:
|
||||
"""
|
||||
Returns the date as string with ISO8601 format.
|
||||
i.e: 2021-01-23T18:25:43.511Z
|
||||
"""
|
||||
return f"{utc_datetime.isoformat()}Z"
|
||||
SOME_EXAMPLE_DATE = "2021-01-23T18:25:43.511Z"
|
||||
|
||||
|
||||
class Metric(BaseModel):
|
||||
@@ -36,7 +31,7 @@ class Metric(BaseModel):
|
||||
..., # Required
|
||||
title="Timestamp",
|
||||
description="The timestamp in ISO format.",
|
||||
example=datetime_to_iso8601(datetime.utcnow()),
|
||||
example=SOME_EXAMPLE_DATE,
|
||||
)
|
||||
level: int = Field(
|
||||
..., # Required
|
||||
@@ -54,11 +49,7 @@ class CreateMetricsPayload(BaseModel):
|
||||
metrics: List[Metric] = Field(
|
||||
default=[],
|
||||
title="List of metrics to be recorded.",
|
||||
example=[
|
||||
Metric(
|
||||
namespace="test-source", time=datetime_to_iso8601(datetime.utcnow()), level=0, args='{"test":"value"}'
|
||||
)
|
||||
],
|
||||
example=[Metric(namespace="test-source", time=SOME_EXAMPLE_DATE, level=0, args='{"test":"value"}')],
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,10 @@ from typing import (
|
||||
)
|
||||
|
||||
from pydantic import Field
|
||||
from typing_extensions import (
|
||||
Annotated,
|
||||
Literal,
|
||||
)
|
||||
|
||||
from galaxy.schema.fields import (
|
||||
DecodedDatabaseIdField,
|
||||
@@ -16,10 +20,10 @@ from galaxy.schema.schema import (
|
||||
UserModel,
|
||||
)
|
||||
|
||||
QUOTA_MODEL_CLASS_NAME = "Quota"
|
||||
USER_QUOTA_ASSOCIATION_MODEL_CLASS_NAME = "UserQuotaAssociation"
|
||||
GROUP_QUOTA_ASSOCIATION_MODEL_CLASS_NAME = "GroupQuotaAssociation"
|
||||
DEFAULT_QUOTA_ASSOCIATION_MODEL_CLASS_NAME = "DefaultQuotaAssociation"
|
||||
QUOTA = Literal["Quota"]
|
||||
USER_QUOTA_ASSOCIATION = Literal["UserQuotaAssociation"]
|
||||
GROUP_QUOTA_ASSOCIATION = Literal["GroupQuotaAssociation"]
|
||||
DEFAULT_QUOTA_ASSOCIATION = Literal["DefaultQuotaAssociation"]
|
||||
|
||||
|
||||
class QuotaOperation(str, Enum):
|
||||
@@ -66,7 +70,7 @@ QuotaOperationField = Field(
|
||||
|
||||
|
||||
class DefaultQuota(Model): # TODO: should this replace lib.galaxy.model.DefaultQuotaAssociation at some point?
|
||||
model_class: str = ModelClassField(DEFAULT_QUOTA_ASSOCIATION_MODEL_CLASS_NAME)
|
||||
model_class: Annotated[DEFAULT_QUOTA_ASSOCIATION, ModelClassField()]
|
||||
type: DefaultQuotaTypes = Field(
|
||||
...,
|
||||
title="Type",
|
||||
@@ -79,7 +83,7 @@ class DefaultQuota(Model): # TODO: should this replace lib.galaxy.model.Default
|
||||
|
||||
|
||||
class UserQuota(Model):
|
||||
model_class: str = ModelClassField(USER_QUOTA_ASSOCIATION_MODEL_CLASS_NAME)
|
||||
model_class: Annotated[USER_QUOTA_ASSOCIATION, ModelClassField()]
|
||||
user: UserModel = Field(
|
||||
...,
|
||||
title="User",
|
||||
@@ -88,7 +92,7 @@ class UserQuota(Model):
|
||||
|
||||
|
||||
class GroupQuota(Model):
|
||||
model_class: str = ModelClassField(GROUP_QUOTA_ASSOCIATION_MODEL_CLASS_NAME)
|
||||
model_class: Annotated[GROUP_QUOTA_ASSOCIATION, ModelClassField()]
|
||||
group: GroupModel = Field(
|
||||
...,
|
||||
title="Group",
|
||||
@@ -99,7 +103,7 @@ class GroupQuota(Model):
|
||||
class QuotaBase(Model):
|
||||
"""Base model containing common fields for Quotas."""
|
||||
|
||||
model_class: str = ModelClassField(QUOTA_MODEL_CLASS_NAME)
|
||||
model_class: Annotated[QUOTA, ModelClassField()]
|
||||
id: DecodedDatabaseIdField = Field(
|
||||
...,
|
||||
title="ID",
|
||||
|
||||
@@ -94,15 +94,13 @@ class EncodedDatabaseIdField(str, BaseDatabaseIdField):
|
||||
return cls.security.decode_id(v)
|
||||
|
||||
|
||||
def ModelClassField(class_name: str) -> str:
|
||||
def ModelClassField():
|
||||
"""Represents a database model class name annotated as a constant
|
||||
pydantic Field.
|
||||
:param class_name: The name of the database class.
|
||||
:return: A constant pydantic Field with default annotations for model classes.
|
||||
"""
|
||||
return Field(
|
||||
class_name,
|
||||
title="Model class",
|
||||
description="The name of the database model class.",
|
||||
const=True, # Make this field constant
|
||||
)
|
||||
|
||||
+65
-61
@@ -50,15 +50,16 @@ from galaxy.schema.types import (
|
||||
RelativeUrl,
|
||||
)
|
||||
|
||||
USER_MODEL_CLASS_NAME = "User"
|
||||
GROUP_MODEL_CLASS_NAME = "Group"
|
||||
HDA_MODEL_CLASS_NAME = "HistoryDatasetAssociation"
|
||||
DC_MODEL_CLASS_NAME = "DatasetCollection"
|
||||
DCE_MODEL_CLASS_NAME = "DatasetCollectionElement"
|
||||
HDCA_MODEL_CLASS_NAME = "HistoryDatasetCollectionAssociation"
|
||||
HISTORY_MODEL_CLASS_NAME = "History"
|
||||
JOB_MODEL_CLASS_NAME = "Job"
|
||||
STORED_WORKFLOW_MODEL_CLASS_NAME = "StoredWorkflow"
|
||||
USER_MODEL_CLASS = Literal["User"]
|
||||
GROUP_MODEL_CLASS = Literal["Group"]
|
||||
HDA_MODEL_CLASS = Literal["HistoryDatasetAssociation"]
|
||||
DC_MODEL_CLASS = Literal["DatasetCollection"]
|
||||
DCE_MODEL_CLASS = Literal["DatasetCollectionElement"]
|
||||
HDCA_MODEL_CLASS = Literal["HistoryDatasetCollectionAssociation"]
|
||||
HISTORY_MODEL_CLASS = Literal["History"]
|
||||
JOB_MODEL_CLASS = Literal["Job"]
|
||||
STORED_WORKFLOW_MODEL_CLASS = Literal["StoredWorkflow"]
|
||||
PAGE_MODEL_CLASS = Literal["Page"]
|
||||
|
||||
|
||||
# Generic and common Field annotations that can be reused across models
|
||||
@@ -204,13 +205,13 @@ class UserModel(Model):
|
||||
active: bool = Field(title="Active", description="User is active")
|
||||
deleted: bool = Field(title="Deleted", description="User is deleted")
|
||||
last_password_change: Optional[datetime] = Field(title="Last password change", description="")
|
||||
model_class: str = ModelClassField(USER_MODEL_CLASS_NAME)
|
||||
model_class: Annotated[USER_MODEL_CLASS, ModelClassField()]
|
||||
|
||||
|
||||
class GroupModel(Model):
|
||||
"""User group model"""
|
||||
|
||||
model_class: str = ModelClassField(GROUP_MODEL_CLASS_NAME)
|
||||
model_class: Annotated[GROUP_MODEL_CLASS, ModelClassField()]
|
||||
id: DecodedDatabaseIdField = Field(
|
||||
..., # Required
|
||||
title="ID",
|
||||
@@ -448,7 +449,7 @@ HdaLddaField = Field(
|
||||
class HDADetailed(HDASummary):
|
||||
"""History Dataset Association detailed information."""
|
||||
|
||||
model_class: str = ModelClassField(HDA_MODEL_CLASS_NAME)
|
||||
model_class: Annotated[HDA_MODEL_CLASS, ModelClassField()]
|
||||
hda_ldda: DatasetSourceType = HdaLddaField
|
||||
accessible: bool = AccessibleField
|
||||
genome_build: Optional[str] = GenomeBuildField
|
||||
@@ -557,19 +558,21 @@ class HDADetailed(HDASummary):
|
||||
)
|
||||
annotation: Optional[str] = AnnotationField
|
||||
download_url: RelativeUrl = DownloadUrlField
|
||||
type: str = Field(
|
||||
"file",
|
||||
const=True,
|
||||
title="Type",
|
||||
description="This is always `file` for datasets.",
|
||||
)
|
||||
api_type: str = Field(
|
||||
"file",
|
||||
const=True,
|
||||
title="API Type",
|
||||
description="TODO",
|
||||
deprecated=False, # TODO: Should this field be deprecated as announced in release 16.04?
|
||||
)
|
||||
type: Annotated[
|
||||
Literal["file"],
|
||||
Field(
|
||||
title="Type",
|
||||
description="This is always `file` for datasets.",
|
||||
),
|
||||
] = "file"
|
||||
api_type: Annotated[
|
||||
Literal["file"],
|
||||
Field(
|
||||
title="API Type",
|
||||
description="TODO",
|
||||
deprecated=False, # TODO: Should this field be deprecated as announced in release 16.04?
|
||||
),
|
||||
] = "file"
|
||||
created_from_basename: Optional[str] = Field(
|
||||
None,
|
||||
title="Created from basename",
|
||||
@@ -600,7 +603,7 @@ class HDAExtended(HDADetailed):
|
||||
class DCSummary(Model):
|
||||
"""Dataset Collection summary information."""
|
||||
|
||||
model_class: str = ModelClassField(DC_MODEL_CLASS_NAME)
|
||||
model_class: Annotated[DC_MODEL_CLASS, ModelClassField()]
|
||||
id: DecodedDatabaseIdField = EntityIdField
|
||||
create_time: datetime = CreateTimeField
|
||||
update_time: datetime = UpdateTimeField
|
||||
@@ -614,7 +617,7 @@ class HDAObject(Model):
|
||||
"""History Dataset Association Object"""
|
||||
|
||||
id: DecodedDatabaseIdField = EntityIdField
|
||||
model_class: str = ModelClassField(HDA_MODEL_CLASS_NAME)
|
||||
model_class: Annotated[HDA_MODEL_CLASS, ModelClassField()]
|
||||
state: Dataset.states = DatasetStateField
|
||||
hda_ldda: DatasetSourceType = HdaLddaField
|
||||
history_id: DecodedDatabaseIdField = HistoryIdField
|
||||
@@ -627,7 +630,7 @@ class DCObject(Model):
|
||||
"""Dataset Collection Object"""
|
||||
|
||||
id: DecodedDatabaseIdField = EntityIdField
|
||||
model_class: str = ModelClassField(DC_MODEL_CLASS_NAME)
|
||||
model_class: Annotated[DC_MODEL_CLASS, ModelClassField()]
|
||||
collection_type: CollectionType = CollectionTypeField
|
||||
populated: Optional[bool] = PopulatedField
|
||||
element_count: Optional[int] = ElementCountField
|
||||
@@ -639,7 +642,7 @@ class DCESummary(Model):
|
||||
"""Dataset Collection Element summary information."""
|
||||
|
||||
id: DecodedDatabaseIdField = EntityIdField
|
||||
model_class: str = ModelClassField(DCE_MODEL_CLASS_NAME)
|
||||
model_class: Annotated[DCE_MODEL_CLASS, ModelClassField()]
|
||||
element_index: int = Field(
|
||||
...,
|
||||
title="Element Index",
|
||||
@@ -745,15 +748,14 @@ class HDCJobStateSummary(Model):
|
||||
class HDCASummary(HistoryItemCommon):
|
||||
"""History Dataset Collection Association summary information."""
|
||||
|
||||
model_class: str = ModelClassField(
|
||||
HDCA_MODEL_CLASS_NAME
|
||||
) # TODO: inconsistency? HDASummary does not have model_class only the detailed view has it...
|
||||
type: str = Field(
|
||||
"collection",
|
||||
const=True,
|
||||
title="Type",
|
||||
description="This is always `collection` for dataset collections.",
|
||||
)
|
||||
model_class: Annotated[HDCA_MODEL_CLASS, ModelClassField()]
|
||||
type: Annotated[
|
||||
Literal["collection"],
|
||||
Field(
|
||||
title="Type",
|
||||
description="This is always `collection` for dataset collections.",
|
||||
),
|
||||
] = "collection"
|
||||
collection_type: CollectionType = CollectionTypeField
|
||||
populated_state: DatasetCollection.populated_states = PopulatedStateField
|
||||
populated_state_message: Optional[str] = PopulatedStateMessageField
|
||||
@@ -904,7 +906,7 @@ class UpdateHistoryContentsPayload(HistoryBase):
|
||||
class HistorySummary(HistoryBase):
|
||||
"""History summary information."""
|
||||
|
||||
model_class: str = ModelClassField(HISTORY_MODEL_CLASS_NAME)
|
||||
model_class: Annotated[HISTORY_MODEL_CLASS, ModelClassField()]
|
||||
id: DecodedDatabaseIdField = EntityIdField
|
||||
name: str = Field(
|
||||
...,
|
||||
@@ -1467,7 +1469,7 @@ class JobIdResponse(Model):
|
||||
|
||||
class JobBaseModel(Model):
|
||||
id: DecodedDatabaseIdField = EntityIdField
|
||||
model_class: str = ModelClassField(JOB_MODEL_CLASS_NAME)
|
||||
model_class: Annotated[JOB_MODEL_CLASS, ModelClassField()]
|
||||
tool_id: str = Field(
|
||||
...,
|
||||
title="Tool ID",
|
||||
@@ -1506,21 +1508,24 @@ class JobImportHistoryResponse(JobBaseModel):
|
||||
)
|
||||
|
||||
|
||||
class JobStateSummary(Model):
|
||||
class ItemStateSummary(Model):
|
||||
id: DecodedDatabaseIdField = EntityIdField
|
||||
model: str = ModelClassField("Job")
|
||||
populated_state: DatasetCollection.populated_states = PopulatedStateField
|
||||
states: Dict[Job.states, int] = Field(
|
||||
{}, title="States", description=("A dictionary of job states and the number of jobs in that state.")
|
||||
)
|
||||
|
||||
|
||||
class ImplicitCollectionJobsStateSummary(JobStateSummary):
|
||||
model: str = ModelClassField("ImplicitCollectionJobs")
|
||||
class JobStateSummary(ItemStateSummary):
|
||||
model: Annotated[Literal["Job"], ModelClassField()]
|
||||
|
||||
|
||||
class WorkflowInvocationStateSummary(JobStateSummary):
|
||||
model: str = ModelClassField("WorkflowInvocation")
|
||||
class ImplicitCollectionJobsStateSummary(ItemStateSummary):
|
||||
model: Annotated[Literal["ImplicitCollectionJobs"], ModelClassField()]
|
||||
|
||||
|
||||
class WorkflowInvocationStateSummary(ItemStateSummary):
|
||||
model: Annotated[Literal["WorkflowInvocation"], ModelClassField()]
|
||||
|
||||
|
||||
class JobSummary(JobBaseModel):
|
||||
@@ -1687,7 +1692,7 @@ class JobFullDetails(JobDetails):
|
||||
|
||||
class StoredWorkflowSummary(Model):
|
||||
id: DecodedDatabaseIdField = EntityIdField
|
||||
model_class: str = ModelClassField(STORED_WORKFLOW_MODEL_CLASS_NAME)
|
||||
model_class: Annotated[STORED_WORKFLOW_MODEL_CLASS, ModelClassField()]
|
||||
create_time: datetime = CreateTimeField
|
||||
update_time: datetime = UpdateTimeField
|
||||
name: str = Field(
|
||||
@@ -2176,7 +2181,7 @@ class BasicRoleModel(Model):
|
||||
class RoleModel(BasicRoleModel):
|
||||
description: Optional[str] = RoleDescriptionField
|
||||
url: RelativeUrl = RelativeUrlField
|
||||
model_class: str = ModelClassField("Role")
|
||||
model_class: Annotated[Literal["Role"], ModelClassField()]
|
||||
|
||||
|
||||
class RoleDefinitionModel(Model):
|
||||
@@ -2252,7 +2257,7 @@ class InstalledRepositoryToolShedStatus(Model):
|
||||
|
||||
|
||||
class InstalledToolShedRepository(Model):
|
||||
model_class: str = ModelClassField("ToolShedRepository")
|
||||
model_class: Annotated[Literal["ToolShedRepository"], ModelClassField()] = "ToolShedRepository"
|
||||
id: EncodedDatabaseIdField = Field(
|
||||
...,
|
||||
title="ID",
|
||||
@@ -2306,7 +2311,7 @@ class LibraryPermissionScope(str, Enum):
|
||||
|
||||
|
||||
class LibraryLegacySummary(Model):
|
||||
model_class: str = ModelClassField("Library")
|
||||
model_class: Annotated[Literal["Library"], ModelClassField()]
|
||||
id: DecodedDatabaseIdField = Field(
|
||||
...,
|
||||
title="ID",
|
||||
@@ -2553,7 +2558,7 @@ class LibraryFolderPermissionsPayload(LibraryPermissionsPayloadBase):
|
||||
|
||||
|
||||
class LibraryFolderDetails(Model):
|
||||
model_class: str = ModelClassField("LibraryFolder")
|
||||
model_class: Annotated[Literal["LibraryFolder"], ModelClassField()]
|
||||
id: LibraryFolderDatabaseIdField = Field(
|
||||
...,
|
||||
title="ID",
|
||||
@@ -2811,12 +2816,16 @@ AnyHistoryContentItem = Union[
|
||||
]
|
||||
|
||||
|
||||
AnyJobStateSummary = Union[
|
||||
JobStateSummary,
|
||||
ImplicitCollectionJobsStateSummary,
|
||||
WorkflowInvocationStateSummary,
|
||||
AnyJobStateSummary = Annotated[
|
||||
Union[
|
||||
JobStateSummary,
|
||||
ImplicitCollectionJobsStateSummary,
|
||||
WorkflowInvocationStateSummary,
|
||||
],
|
||||
Field(..., discriminator="model"),
|
||||
]
|
||||
|
||||
|
||||
HistoryArchiveExportResult = Union[JobExportHistoryArchiveModel, JobIdResponse]
|
||||
|
||||
|
||||
@@ -3202,12 +3211,7 @@ class PageSummary(PageSummaryBase):
|
||||
title="ID",
|
||||
description="Encoded ID of the Page.",
|
||||
)
|
||||
model_class: str = Field(
|
||||
..., # Required
|
||||
title="Model class",
|
||||
description="The class of the model associated with the ID.",
|
||||
example="Page",
|
||||
)
|
||||
model_class: Annotated[PAGE_MODEL_CLASS, ModelClassField()]
|
||||
username: str = Field(
|
||||
..., # Required
|
||||
title="Username",
|
||||
|
||||
@@ -12,6 +12,10 @@ from pydantic import (
|
||||
Field,
|
||||
ValidationError,
|
||||
)
|
||||
from typing_extensions import (
|
||||
Annotated,
|
||||
Literal,
|
||||
)
|
||||
|
||||
from galaxy import exceptions
|
||||
from galaxy.datatypes.registry import Registry
|
||||
@@ -64,7 +68,7 @@ class DatasetCollectionAttributesResult(Model):
|
||||
dbkey: str = Field(..., description="TODO")
|
||||
# Are the following fields really used/needed?
|
||||
extension: str = Field(..., description="The dataset file extension.", example="txt")
|
||||
model_class: str = ModelClassField("HistoryDatasetCollectionAssociation")
|
||||
model_class: Annotated[Literal["HistoryDatasetCollectionAssociation"], ModelClassField()]
|
||||
dbkeys: Optional[Set[str]]
|
||||
extensions: Optional[Set[str]]
|
||||
tags: TagCollection
|
||||
|
||||
Reference in New Issue
Block a user