Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change models to use friendlier names for init #22

Merged
merged 3 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading