Skip to content

Commit

Permalink
change models to use friendlier names for init (#22)
Browse files Browse the repository at this point in the history
* change models to use friendlier names for init

* higher res example

* reduce quality back
  • Loading branch information
mochic authored Jul 23, 2024
1 parent 2582c61 commit e7375ce
Show file tree
Hide file tree
Showing 12 changed files with 205 additions and 122 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pip install -e .[dev]
## Usage

### VScode
![](example-usage.gif)
![Example usage](example-usage.gif)

Requires the [pylance extension](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance) to be installed for similar functionality.

Expand Down
18 changes: 14 additions & 4 deletions src/aind_slims_api/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

from aind_slims_api import config
from aind_slims_api.exceptions import SlimsRecordNotFound
from aind_slims_api.models.attachment import SlimsAttachment
from aind_slims_api.models import SlimsAttachment
from aind_slims_api.models.base import SlimsBaseModel
from aind_slims_api.types import SLIMS_TABLES

Expand Down Expand Up @@ -105,10 +105,20 @@ def resolve_model_alias(
model: Type[SlimsBaseModelTypeVar],
attr_name: str,
) -> str:
"""Given a SlimsBaseModel object, resolve its pk to the actual value"""
"""Given a SlimsBaseModel object, resolve its pk to the actual value
Notes
-----
- Raises ValueError if the alias cannot be resolved
- Resolves the validation alias for a given field name
"""
for field_name, field_info in model.model_fields.items():
if field_name == attr_name and field_info.alias:
return field_info.alias
if (
field_name == attr_name
and field_info.validation_alias
and isinstance(field_info.validation_alias, str)
):
return field_info.validation_alias
else:
raise ValueError(f"Cannot resolve alias for {attr_name} on {model}")

Expand Down
15 changes: 12 additions & 3 deletions src/aind_slims_api/models/attachment.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ class SlimsAttachment(SlimsBaseModel):
Examples
--------
>>> from aind_slims_api import SlimsClient
>>> from aind_slims_api import models
>>> client = SlimsClient()
>>> rig_metadata_attachment = client.fetch_model(
... SlimsAttachment,
... models.SlimsAttachment,
... name="rig323_EPHYS1_OPTO_2024-02-12.json"
... )
>>> rig_metadata = client.fetch_attachment_content(
Expand All @@ -23,6 +24,14 @@ class SlimsAttachment(SlimsBaseModel):
'323_EPHYS1_OPTO_2024-02-12'
"""

pk: int = Field(..., alias="attm_pk")
name: str = Field(alias="attm_name")
pk: int = Field(
...,
serialization_alias="attm_pk",
validation_alias="attm_pk",
)
name: str = Field(
...,
serialization_alias="attm_name",
validation_alias="attm_name",
)
_slims_table = "Attachment"
1 change: 1 addition & 0 deletions src/aind_slims_api/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class SlimsBaseModel(
BaseModel,
from_attributes=True,
validate_assignment=True,
populate_by_name=True,
):
"""Pydantic model to represent a SLIMS record.
Subclass with fields matching those in the SLIMS record.
Expand Down
106 changes: 82 additions & 24 deletions src/aind_slims_api/models/behavior_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import logging
from datetime import datetime
from typing import ClassVar
from typing import ClassVar, Optional

from pydantic import Field

Expand All @@ -16,6 +16,27 @@
class SlimsBehaviorSession(SlimsBaseModel):
"""Model for an instance of the Behavior Session ContentEvent
Properties
----------
mouse_pk : Optional[int]
The primary key of the mouse associated with this behavior session.
instrument_pk : Optional[int]
The primary key of the instrument associated with this behavior session.
trainer_pks : Optional[list[int]]
The primary keys of the trainers associated with this behavior session.
task : Optional[str]
Name of the task associated with the session.
task_stage : Optional[str]
Name of the stage associated with the session.
task_schema_version : Optional[str]
Version of the task schema.
is_curriculum_suggestion : Optional[bool]
Whether the session is a curriculum suggestion.
date : Optional[datetime]
Date of the suggestion.
notes : Optional[str]
Notes about the session.
Examples
--------
Read a session.
Expand All @@ -35,15 +56,15 @@ class SlimsBehaviorSession(SlimsBaseModel):
>>> instrument = client.fetch_model(SlimsInstrument, name="323_EPHYS1_OPTO")
>>> added = client.add_model(
... SlimsBehaviorSession(
... cnvn_fk_content=mouse.pk,
... cnvn_cf_fk_instrument=instrument.pk,
... cnvn_cf_fk_trainer=[trainer.pk],
... cnvn_cf_notes="notes",
... cnvn_cf_taskStage="stage",
... cnvn_cf_task="task",
... cnvn_cf_taskSchemaVersion="0.0.1",
... cnvn_cf_stageIsOnCurriculum=True,
... cnvn_cf_scheduledDate=datetime(2021, 1, 2),
... mouse_pk=mouse.pk,
... instrument_pk=instrument.pk,
... trainer_pks=[trainer.pk],
... notes="notes",
... task_stage="stage",
... task="task",
... task_schema_version="0.0.1",
... is_curriculum_suggestion=True,
... date=datetime(2021, 1, 2),
... )
... )
Expand All @@ -57,27 +78,64 @@ class SlimsBehaviorSession(SlimsBaseModel):
... )
"""

pk: int | None = Field(default=None, alias="cnvn_pk")
mouse_pk: int | None = Field(
pk: Optional[int] = Field(
default=None,
serialization_alias="cnvn_pk",
validation_alias="cnvn_pk",
)
mouse_pk: Optional[int] = Field(
default=None,
alias="cnvn_fk_content",
serialization_alias="cnvn_fk_content",
validation_alias="cnvn_fk_content",
description=(
"The primary key of the mouse associated with this behavior session."
),
) # used as reference to mouse
notes: str | None = Field(default=None, alias="cnvn_cf_notes")
task_stage: str | None = Field(default=None, alias="cnvn_cf_taskStage")
instrument: int | None = Field(default=None, alias="cnvn_cf_fk_instrument")
trainers: list[int] = Field(default=[], alias="cnvn_cf_fk_trainer")
task: str | None = Field(default=None, alias="cnvn_cf_task")
is_curriculum_suggestion: bool | None = Field(
default=None, alias="cnvn_cf_stageIsOnCurriculum"
notes: Optional[str] = Field(
default=None,
serialization_alias="cnvn_cf_notes",
validation_alias="cnvn_cf_notes",
)
task_stage: Optional[str] = Field(
default=None,
serialization_alias="cnvn_cf_taskStage",
validation_alias="cnvn_cf_taskStage",
)
instrument_pk: Optional[int] = Field(
default=None,
serialization_alias="cnvn_fk_instrument",
validation_alias="cnvn_fk_instrument",
)
trainer_pks: Optional[list[int]] = Field(
default=[],
serialization_alias="cnvn_cf_fk_trainer",
validation_alias="cnvn_cf_fk_trainer",
)
task_schema_version: str | None = Field(
default=None, alias="cnvn_cf_taskSchemaVersion"
task: Optional[str] = Field(
default=None,
serialization_alias="cnvn_cf_task",
validation_alias="cnvn_cf_task",
)
is_curriculum_suggestion: Optional[bool] = Field(
default=None,
serialization_alias="cnvn_cf_stageIsOnCurriculum",
validation_alias="cnvn_cf_stageIsOnCurriculum",
)
task_schema_version: Optional[str] = Field(
default=None,
serialization_alias="cnvn_cf_taskSchemaVersion",
validation_alias="cnvn_cf_taskSchemaVersion",
)
software_version: Optional[str] = Field(
default=None,
serialization_alias="cnvn_cf_softwareVersion",
validation_alias="cnvn_cf_softwareVersion",
)
date: Optional[datetime] = Field(
default=None,
serialization_alias="cnvn_cf_scheduledDate",
validation_alias="cnvn_cf_scheduledDate",
)
software_version: str | None = Field(default=None, alias="cnvn_cf_softwareVersion")
date: datetime | None = Field(default=None, alias="cnvn_cf_scheduledDate")
cnvn_fk_contentEventType: int = 10 # pk of Behavior Session ContentEvent
_slims_table = "ContentEvent"
_base_fetch_filters: ClassVar[dict[str, str]] = {
Expand Down
12 changes: 10 additions & 2 deletions src/aind_slims_api/models/instrument.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Contains a model for the instrument content, and a method for fetching it"""

from typing import Optional

from pydantic import Field

from aind_slims_api.models.base import SlimsBaseModel
Expand All @@ -15,12 +17,18 @@ class SlimsInstrument(SlimsBaseModel):
>>> instrument = client.fetch_model(SlimsInstrument, name="323_EPHYS1_OPTO")
"""

# can't use alias for this due to https://github.com/pydantic/pydantic/issues/5893
name: str = Field(
...,
alias="nstr_name",
serialization_alias="nstr_name",
validation_alias="nstr_name",
description="The name of the instrument",
)
pk: int = Field(..., alias="nstr_pk")
pk: Optional[int] = Field(
default=None,
serialization_alias="nstr_pk",
validation_alias="nstr_pk",
)
_slims_table = "Instrument"

# todo add more useful fields
28 changes: 22 additions & 6 deletions src/aind_slims_api/models/mouse.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Contains a model for the mouse content, and a method for fetching it"""

from typing import Annotated, ClassVar
from typing import Annotated, ClassVar, Optional

from pydantic import BeforeValidator, Field

Expand All @@ -23,14 +23,30 @@ class SlimsMouseContent(SlimsBaseModel):
"""

baseline_weight_g: Annotated[float | None, UnitSpec("g")] = Field(
..., alias="cntn_cf_baselineWeight"
...,
serialization_alias="cntn_cf_baselineWeight",
validation_alias="cntn_cf_baselineWeight",
)
point_of_contact: Optional[str] = Field(
...,
serialization_alias="cntn_cf_scientificPointOfContact",
validation_alias="cntn_cf_scientificPointOfContact",
)
point_of_contact: str | None = Field(..., alias="cntn_cf_scientificPointOfContact")
water_restricted: Annotated[bool, BeforeValidator(lambda x: x or False)] = Field(
..., alias="cntn_cf_waterRestricted"
...,
serialization_alias="cntn_cf_waterRestricted",
validation_alias="cntn_cf_waterRestricted",
)
barcode: str = Field(
...,
serialization_alias="cntn_barCode",
validation_alias="cntn_barCode",
)
pk: Optional[int] = Field(
default=None,
serialization_alias="cntn_pk",
validation_alias="cntn_pk",
)
barcode: str = Field(..., alias="cntn_barCode")
pk: int = Field(..., alias="cntn_pk")

_slims_table = "Content"
_base_fetch_filters: ClassVar[dict[str, str]] = {
Expand Down
18 changes: 15 additions & 3 deletions src/aind_slims_api/models/unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,20 @@
class SlimsUnit(SlimsBaseModel):
"""Model for unit information in SLIMS"""

name: str = Field(..., alias="unit_name")
abbreviation: Optional[str] = Field("", alias="unit_abbreviation")
pk: int = Field(..., alias="unit_pk")
name: str = Field(
...,
serialization_alias="unit_name",
validation_alias="unit_name",
)
abbreviation: Optional[str] = Field(
"",
serialization_alias="unit_abbreviation",
validation_alias="unit_abbreviation",
)
pk: int = Field(
...,
serialization_alias="unit_pk",
validation_alias="unit_pk",
)

_slims_table = "Unit"
36 changes: 30 additions & 6 deletions src/aind_slims_api/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,35 @@ class SlimsUser(SlimsBaseModel):
>>> user = client.fetch_model(SlimsUser, username="LKim")
"""

username: str = Field(..., alias="user_userName")
first_name: Optional[str] = Field("", alias="user_firstName")
last_name: Optional[str] = Field("", alias="user_lastName")
full_name: Optional[str] = Field("", alias="user_fullName")
email: Optional[str] = Field("", alias="user_email")
pk: int = Field(..., alias="user_pk")
username: str = Field(
...,
serialization_alias="user_userName",
validation_alias="user_userName",
)
first_name: Optional[str] = Field(
"",
serialization_alias="user_firstName",
validation_alias="user_firstName",
)
last_name: Optional[str] = Field(
"",
serialization_alias="user_lastName",
validation_alias="user_lastName",
)
full_name: Optional[str] = Field(
"",
serialization_alias="user_fullName",
validation_alias="user_fullName",
)
email: Optional[str] = Field(
"",
serialization_alias="user_email",
validation_alias="user_email",
)
pk: int = Field(
...,
serialization_alias="user_pk",
validation_alias="user_pk",
)

_slims_table = "User"
Loading

0 comments on commit e7375ce

Please sign in to comment.