Skip to content

Commit

Permalink
Merge pull request #2 from tlambert03/fix-1
Browse files Browse the repository at this point in the history
fix: fix null to list
  • Loading branch information
tlambert03 authored Dec 12, 2024
2 parents d689cd0 + c8fd703 commit 38429a8
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 11 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ repos:
- id: validate-pyproject

- repo: https://github.com/crate-ci/typos
rev: typos-dict-v0.11.35
rev: typos-dict-v0.11.37
hooks:
- id: typos
args: [--force-exclude] # omitting --write-changes

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.4
rev: v0.8.3
hooks:
- id: ruff
args: [--fix] # may also add '--unsafe-fixes'
Expand Down
38 changes: 29 additions & 9 deletions src/fpbase/models.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,33 @@
"""Main fetching logic."""

from collections.abc import Sequence
from enum import Enum
from typing import TYPE_CHECKING, Any, Optional
from typing import TYPE_CHECKING, Annotated, Any, Optional, TypeVar

from pydantic import BaseModel, Field, computed_field, model_validator
from pydantic import (
BaseModel,
BeforeValidator,
Field,
computed_field,
model_validator,
)

if TYPE_CHECKING:
from collections.abc import Iterable


def _null_to_list(v: Any) -> list:
if v is None:
return []
elif isinstance(v, Sequence):
return list(v)
raise ValueError(f"Expected a list or None, got {v!r}") # pragma: no cover


T = TypeVar("T")
# type that accepts null as json input and returns an empty list
SafeList = Annotated[list[T], BeforeValidator(_null_to_list)]

__all__ = [
"Filter",
"FilterPlacement",
Expand Down Expand Up @@ -135,7 +155,7 @@ class State(BaseModel):
exhex: str = ""
ext_coeff: Optional[float] = Field(None, alias="extCoeff") # M^-1 cm^-1
qy: Optional[float] = None
spectra: list[Spectrum] = Field(default_factory=list)
spectra: SafeList[Spectrum] = Field(default_factory=list)
lifetime: Optional[float] = None # ns

@property
Expand All @@ -158,7 +178,7 @@ class Fluorophore(BaseModel):
name: str
id: str
default_state: Optional[State] = Field(None, alias="defaultState")
states: list[State] = Field(default_factory=list)
states: SafeList[State] = Field(default_factory=list)

@model_validator(mode="before")
@classmethod
Expand Down Expand Up @@ -193,14 +213,14 @@ def url(self) -> str:

class Protein(Fluorophore):
seq: Optional[str] = None
pdb: list[str] = Field(default_factory=list)
pdb: SafeList[str] = Field(default_factory=list)
genbank: Optional[str] = None
uniprot: Optional[str] = None
agg: Optional[Olig] = None
switch_type: Optional[SwitchType] = Field(None, alias="switchType")
primary_reference: Optional[Reference] = Field(None, alias="primaryReference")
references: list[Reference] = Field(default_factory=list)
states: list[State] = Field(default_factory=list)
references: SafeList[Reference] = Field(default_factory=list)
states: SafeList[State] = Field(default_factory=list)
# default_state: Optional[State] = Field(None, alias="defaultState")


Expand All @@ -216,7 +236,7 @@ class OpticalConfig(BaseModel):
"""A collection of filters and light sources."""

name: str
filters: list[FilterPlacement]
filters: SafeList[FilterPlacement]
camera: Optional["Camera"]
light: Optional["LightSource"]
laser: Optional[int]
Expand All @@ -227,7 +247,7 @@ class Microscope(BaseModel):

id: str
name: str
opticalConfigs: list[OpticalConfig]
opticalConfigs: SafeList[OpticalConfig]


class _MicroscopePayload(BaseModel):
Expand Down
5 changes: 5 additions & 0 deletions tests/test_fpbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,8 @@ def test_generic_gql_query() -> None:
q = "query getProtein($id: String!){ protein(id: $id){ name } }"
data = fpbase.graphql_query(q, {"id": "R9NL8"})
assert data["data"]["protein"]["name"] == "EGFP"


@pytest.mark.parametrize("name", ["Clover1.5", "6C", "dClover2 A206K"])
def test_fluors_with_no_pdb(name: str) -> None:
fpbase.get_fluorophore(name)

0 comments on commit 38429a8

Please sign in to comment.