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

✨ Add parameter validation #111

Merged
merged 9 commits into from
Sep 16, 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
9 changes: 5 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.10"]
python-version: ["3.11"]
group: ["bionty-unit", "bionty-docs"]
timeout-minutes: 25

Expand Down Expand Up @@ -47,14 +47,15 @@ jobs:
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-central-1
- run: nox -s lint
if: matrix.python-version == '3.10' && matrix.group == 'bionty-unit'
if: matrix.python-version == '3.11' && matrix.group == 'bionty-unit'
- run: nox -s "build(group='${{ matrix.group }}')"
- uses: actions/upload-artifact@v3
with:
name: coverage--${{ matrix.group }}
path: .coverage
include-hidden-files: true
- uses: nwtgck/[email protected]
if: ${{ matrix.python-version == '3.10' && matrix.group == 'bionty-docs' }}
if: ${{ matrix.python-version == '3.11' && matrix.group == 'bionty-docs' }}
with:
publish-dir: "_build/html"
production-deploy: ${{ github.event_name == 'push' }}
Expand All @@ -71,7 +72,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.11"
- run: |
pip install -U pip uv
uv pip install --system coverage[toml]
Expand Down
36 changes: 31 additions & 5 deletions bionty/base/_public_ontology.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
from __future__ import annotations

import logging
from typing import (
TYPE_CHECKING,
Iterable,
Literal,
)
from typing import TYPE_CHECKING, Iterable, Literal, Union, get_args, get_origin

import numpy as np
import pandas as pd
Expand Down Expand Up @@ -52,6 +48,10 @@ def __init__(
include_id_prefixes: dict[str, list[str]] | None = None,
include_rel: str | None = None,
):
self._validate_param("organism", organism)
self._validate_param("source", source)
self._validate_param("version", version)

try:
self._fetch_sources()
try:
Expand Down Expand Up @@ -108,6 +108,26 @@ def __init__(
except AttributeError:
pass

def _validate_param(self, param_name: str, value: str | None) -> None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this equates type annotation checks, why not used typechecked or pydantic?

I assume it's because there is more going on.

Small note re naming: param in lamindb has a special meaning akin to feature. When we talk about plain Python function args, we say args aligned with Google-style docstrings.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Should at some point update the "Paramters" header and replace it with "Arguments".

"""Validates passed parameter values by comparing them against the typehints (Literals)."""
if value is not None:
hint = self.__class__.__init__.__annotations__.get(param_name)
valid_values = ()

if get_origin(hint) is Union: # This handles Optional
for arg in get_args(hint):
if get_origin(arg) is Literal:
valid_values = get_args(arg)
break
elif get_origin(hint) is Literal:
valid_values = get_args(hint)

if valid_values and value not in valid_values:
quoted_values = [f"'{v}'" for v in valid_values]
raise InvalidParamError(
f"Invalid {param_name}: '{value}'. Must be one of: {', '.join(quoted_values)}"
)

def __repr__(self) -> str:
# fmt: off
representation = (
Expand Down Expand Up @@ -635,6 +655,12 @@ def _convert_arrays_to_tuples(arr): # pragma: no cover
return new_entries, modified_entries


class InvalidParamError(Exception):
"""Custom exception for PublicOntology parameter validation errors."""

pass


class PublicOntologyField:
"""Field of a PublicOntology model."""

Expand Down
2 changes: 1 addition & 1 deletion bionty/base/entities/_bfxpipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def __init__(
self,
organism: Optional[Literal["all"]] = None,
source: Optional[Literal["lamin"]] = None,
version: Optional[str] = None,
version: Optional[Literal["1.0.0"]] = None,
**kwargs,
) -> None:
super().__init__(source=source, version=version, organism=organism, **kwargs)
2 changes: 1 addition & 1 deletion bionty/base/entities/_biosample.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def __init__(
self,
organism: Optional[Literal["all"]] = None,
source: Optional[Literal["ncbi"]] = None,
version: Optional[str] = None,
version: Optional[Literal["2023-09"]] = None,
**kwargs,
) -> None:
super().__init__(source=source, version=version, organism=organism, **kwargs)
2 changes: 1 addition & 1 deletion bionty/base/entities/_cellline.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(
self,
organism: Optional[Literal["all"]] = None,
source: Optional[Literal["clo", "depmap"]] = None,
version: Optional[str] = None,
version: Optional[Literal["2022-03-21", "2024-Q2"]] = None,
**kwargs,
) -> None:
super().__init__(
Expand Down
2 changes: 1 addition & 1 deletion bionty/base/entities/_cellmarker.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def __init__(
self,
organism: Optional[Literal["human", "mouse"]] = None,
source: Optional[Literal["cellmarker"]] = None,
version: Optional[str] = None,
version: Optional[Literal["2.0"]] = None,
**kwargs,
) -> None:
super().__init__(source=source, version=version, organism=organism, **kwargs)
12 changes: 11 additions & 1 deletion bionty/base/entities/_celltype.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,17 @@ def __init__(
self,
organism: Optional[Literal["all"]] = None,
source: Optional[Literal["cl"]] = None,
version: Optional[str] = None,
version: Optional[
Zethson marked this conversation as resolved.
Show resolved Hide resolved
Literal[
"2022-08-16",
"2023-02-15",
"2023-04-20",
"2023-08-24",
"2024-01-04",
"2024-02-13",
"2024-05-15",
]
] = None,
**kwargs,
) -> None:
super().__init__(
Expand Down
2 changes: 1 addition & 1 deletion bionty/base/entities/_developmentalstage.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def __init__(
self,
organism: Optional[Literal["human", "mouse"]] = None,
source: Optional[Literal["hsapdv", "mmusdv"]] = None,
version: Optional[str] = None,
version: Optional[Literal["2020-03-10", "2024-05-28"]] = None,
**kwargs,
) -> None:
super().__init__(
Expand Down
20 changes: 19 additions & 1 deletion bionty/base/entities/_disease.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,25 @@ def __init__(
self,
organism: Optional[Literal["all", "human"]] = None,
source: Optional[Literal["mondo", "doid", "icd"]] = None,
version: Optional[str] = None,
version: Optional[
Literal[
"icd-9-2011",
"icd-10-2020",
"icd-10-2024",
"icd-11-2023",
"2023-01-30",
"2023-03-31",
"2024-01-31",
"2024-05-29",
"2022-10-11",
"2023-02-06",
"2023-04-04",
"2023-08-02",
"2024-01-03",
"2024-02-06",
"2024-06-04",
]
] = None,
**kwargs,
) -> None:
super().__init__(
Expand Down
4 changes: 3 additions & 1 deletion bionty/base/entities/_drug.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ def __init__(
self,
organism: Optional[Literal["all"]] = None,
source: Optional[Literal["dron", "chebi"]] = None,
version: Optional[str] = None,
version: Optional[
Literal["2024-07-27", "2023-03-10", "2024-03-02", "2024-08-05"]
] = None,
**kwargs,
) -> None:
super().__init__(
Expand Down
2 changes: 1 addition & 1 deletion bionty/base/entities/_ethnicity.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def __init__(
self,
organism: Optional[Literal["human"]] = None,
source: Optional[Literal["hancestro"]] = None,
version: Optional[str] = None,
version: Optional[Literal["3.0"]] = None,
**kwargs,
) -> None:
super().__init__(
Expand Down
4 changes: 3 additions & 1 deletion bionty/base/entities/_experimentalfactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ def __init__(
self,
organism: Optional[Literal["all"]] = None,
source: Optional[Literal["efo"]] = None,
version: Optional[str] = None,
version: Optional[
Literal["3.48.0", "3.57.0", "3.62.0", "3.63.0", "3.66.0"]
] = None,
**kwargs,
) -> None:
super().__init__(
Expand Down
4 changes: 3 additions & 1 deletion bionty/base/entities/_gene.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ def __init__(
Literal["human", "mouse", "saccharomyces cerevisiae"]
] = None,
source: Optional[Literal["ensembl"]] = None,
version: Optional[str] = None,
version: Optional[
Literal["release-109", "release-110", "release-111", "release-112"]
] = None,
**kwargs,
):
super().__init__(
Expand Down
12 changes: 11 additions & 1 deletion bionty/base/entities/_organism.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,17 @@ def __init__(
Literal["vertebrates", "bacteria", "fungi", "metazoa", "plants", "all"]
] = None,
source: Optional[Literal["ensembl", "ncbitaxon"]] = None,
version: Optional[str] = None,
version: Optional[
Literal[
"2023-06-20",
"release-57",
"release-108",
"release-109",
"release-110",
"release-111",
"release-112",
]
] = None,
**kwargs,
):
super().__init__(organism=organism, source=source, version=version, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion bionty/base/entities/_pathway.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(
self,
organism: Optional[Literal["all"]] = None,
source: Optional[Literal["go", "pw"]] = None,
version: Optional[str] = None,
version: Optional[Literal["2023-05-10", "2024-06-17"]] = None,
**kwargs,
) -> None:
super().__init__(source=source, version=version, organism=organism, **kwargs)
19 changes: 18 additions & 1 deletion bionty/base/entities/_phenotype.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,24 @@ def __init__(
self,
organism: Optional[Literal["human", "mammalian", "zebrafish", "all"]] = None,
source: Optional[Literal["hp", "phe", "mp", "zp", "pato"]] = None,
version: Optional[str] = None,
version: Optional[
Literal[
"2023-05-18",
"2024-03-28",
"1.2",
"2022-12-17",
"2024-01-22",
"2024-04-18",
"2023-05-31",
"2024-02-07",
"2024-06-18",
"2023-01-27",
"2023-04-05",
"2023-06-17",
"2024-03-06",
"2024-04-26",
]
] = None,
**kwargs,
) -> None:
super().__init__(
Expand Down
2 changes: 1 addition & 1 deletion bionty/base/entities/_protein.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def __init__(
self,
organism: Optional[Literal["human", "mouse"]] = None,
source: Optional[Literal["uniprot"]] = None,
version: Optional[str] = None,
version: Optional[Literal["2023-02", "2023-03", "2024-03"]] = None,
**kwargs,
) -> None:
super().__init__(source=source, version=version, organism=organism, **kwargs)
13 changes: 12 additions & 1 deletion bionty/base/entities/_tissue.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,18 @@ def __init__(
self,
organism: Optional[Literal["all"]] = None,
source: Optional[Literal["uberon"]] = None,
version: Optional[str] = None,
version: Optional[
Literal[
"2022-08-19",
"2023-02-14",
"2023-04-19",
"2023-09-05",
"2024-01-18",
"2024-02-20",
"2024-05-13",
"2024-08-07",
]
] = None,
**kwargs,
) -> None:
super().__init__(
Expand Down
3 changes: 3 additions & 0 deletions bionty/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from . import ids
from ._bionty import encode_uid, lookup2kwargs
from .base import PublicOntology
from .base._public_ontology import InvalidParamError

if TYPE_CHECKING:
from pandas import DataFrame
Expand Down Expand Up @@ -394,6 +395,8 @@ def public(
return getattr(bionty_base, cls.__name__)(
organism=organism, source=source_name, version=version
)
except InvalidParamError as e:
raise ValueError(str(e)) from None
except (AttributeError, ValueError):
if source is None:
kwargs = {
Expand Down
3 changes: 2 additions & 1 deletion tests/test_bionty.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import bionty.base as bt_base
import pytest
from bionty.base._public_ontology import InvalidParamError
from bionty.base._settings import settings


def test_unavailable_sources():
with pytest.raises(ValueError):
with pytest.raises(InvalidParamError):
bt_base.CellType(source="random")


Expand Down
Loading