-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #18 from TheJacksonLaboratory/task/add-api-respons…
…es-schemas Minor updates to some scehmas, adding api responses, adding sex enum
- Loading branch information
Showing
8 changed files
with
256 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[tool.poetry] | ||
name = "geneweaver-core" | ||
version = "0.9.0a8" | ||
version = "0.9.0a9" | ||
description = "The core of the Jax-Geneweaver Python library" | ||
authors = ["Jax Computational Sciences <[email protected]>"] | ||
readme = "README.md" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
"""Schemas for API Responses.""" | ||
|
||
from typing import List, Optional | ||
|
||
from pydantic import AnyUrl, BaseModel | ||
|
||
|
||
class PagingLinks(BaseModel): | ||
"""Schema for holding paging links.""" | ||
|
||
first: Optional[AnyUrl] = None | ||
previous: Optional[AnyUrl] = None | ||
next: Optional[AnyUrl] = None | ||
last: Optional[AnyUrl] = None | ||
|
||
|
||
class Paging(BaseModel): | ||
"""Schema for paging information.""" | ||
|
||
page: Optional[int] = None | ||
items: Optional[int] = None | ||
total_pages: Optional[int] = None | ||
total_items: Optional[int] = None | ||
links: Optional[PagingLinks] = None | ||
|
||
|
||
class CollectionResponse(BaseModel): | ||
"""Schema for API responses with collections.""" | ||
|
||
data: List | ||
paging: Optional[Paging] = None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,16 @@ | ||
"""A module for common complex types used by Geneweaver.""" | ||
|
||
from pathlib import Path | ||
from typing import Dict, Union | ||
from typing import Dict, List, Union | ||
|
||
from geneweaver.core.schema.gene import GeneValue | ||
|
||
StringOrPath = Union[str, Path] | ||
|
||
DictRow = Dict[str, Union[str, int]] | ||
|
||
GeneIds = List[str] | ||
|
||
GeneIdValues = List[GeneValue] | ||
|
||
StrainIds = List[str] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
"""Test the api_response schemas.""" | ||
|
||
from typing import List | ||
|
||
import pytest | ||
from geneweaver.core.schema.api_response import CollectionResponse, Paging, PagingLinks | ||
from geneweaver.core.schema.gene import Gene, GeneValue | ||
from geneweaver.core.schema.geneset import BatchUpload, Geneset, GenesetTier | ||
from geneweaver.core.schema.publication import Publication, PublicationInfo | ||
|
||
|
||
def test_paging_links(): | ||
"""Test the PagingLinks schema.""" | ||
links = PagingLinks( | ||
first="http://example.com/first", | ||
previous="http://example.com/previous", | ||
next="http://example.com/next", | ||
last="http://example.com/last", | ||
) | ||
assert links.first == "http://example.com/first" | ||
assert links.previous == "http://example.com/previous" | ||
assert links.next == "http://example.com/next" | ||
assert links.last == "http://example.com/last" | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"paging_links_kwargs", | ||
[ | ||
{"first": "not a link", "previous": "http://example.com/previous"}, | ||
{"first": "http://alink.com", "previous": "not a link"}, | ||
{ | ||
"first": "http://alink.com", | ||
"previous": "http://example.com/previous", | ||
"next": "not a link", | ||
}, | ||
{ | ||
"first": "http://alink.com", | ||
"previous": "http://alink.com", | ||
"next": "http://example.com/next", | ||
"last": "not a link", | ||
}, | ||
], | ||
) | ||
def test_paging_links_error(paging_links_kwargs): | ||
"""Test the PagingLinks schema in error cases.""" | ||
with pytest.raises(ValueError, match="validation error"): | ||
PagingLinks(**paging_links_kwargs) | ||
|
||
|
||
def test_paging(): | ||
"""Test the Paging schema in non-error cases.""" | ||
paging = Paging( | ||
page=1, | ||
items=10, | ||
total_pages=5, | ||
total_items=50, | ||
links=PagingLinks( | ||
first="http://example.com/first", | ||
previous="http://example.com/previous", | ||
next="http://example.com/next", | ||
last="http://example.com/last", | ||
), | ||
) | ||
assert paging.page == 1 | ||
assert paging.items == 10 | ||
assert paging.total_pages == 5 | ||
assert paging.total_items == 50 | ||
assert paging.links.first == "http://example.com/first" | ||
assert paging.links.previous == "http://example.com/previous" | ||
assert paging.links.next == "http://example.com/next" | ||
assert paging.links.last == "http://example.com/last" | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"paging_kwargs", | ||
[ | ||
{"page": "not a number", "items": 10}, | ||
{"page": 1, "items": "not a number"}, | ||
{"page": 1, "items": 10, "total_pages": "not a number"}, | ||
{"page": 1, "items": 10, "total_pages": 5, "total_items": "not a number"}, | ||
{ | ||
"page": 1, | ||
"items": 10, | ||
"total_pages": 5, | ||
"total_items": 50, | ||
"links": "not a link", | ||
}, | ||
], | ||
) | ||
def test_paging_errors(paging_kwargs): | ||
"""Test the Paging schema in error cases.""" | ||
with pytest.raises(ValueError, match="validation error"): | ||
Paging(**paging_kwargs) | ||
|
||
|
||
def test_collection_response(): | ||
"""Test the CollectionResponse schema in non-error cases.""" | ||
collection_response = CollectionResponse( | ||
data=[1, 2, 3], | ||
paging=Paging( | ||
page=1, | ||
items=10, | ||
total_pages=5, | ||
total_items=50, | ||
links=PagingLinks( | ||
first="http://example.com/first", | ||
previous="http://example.com/previous", | ||
next="http://example.com/next", | ||
last="http://example.com/last", | ||
), | ||
), | ||
) | ||
|
||
assert collection_response.data == [1, 2, 3] | ||
assert collection_response.paging.page == 1 | ||
assert collection_response.paging.items == 10 | ||
assert collection_response.paging.total_pages == 5 | ||
assert collection_response.paging.total_items == 50 | ||
assert collection_response.paging.links.first == "http://example.com/first" | ||
assert collection_response.paging.links.previous == "http://example.com/previous" | ||
assert collection_response.paging.links.next == "http://example.com/next" | ||
assert collection_response.paging.links.last == "http://example.com/last" | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"data_class", | ||
[GeneValue, Gene, BatchUpload, Geneset, GenesetTier, Publication, PublicationInfo], | ||
) | ||
def test_inherit_from_collection_response(data_class): | ||
"""Test that we can inherit from the CollectionResponse class.""" | ||
|
||
class CollectionResponseSubclass(CollectionResponse): | ||
data: List[data_class] | ||
|
||
collection_response = CollectionResponseSubclass( | ||
data=[], | ||
paging=None, | ||
) | ||
|
||
assert collection_response is not None | ||
|
||
|
||
def test_collection_response_error(): | ||
"""Test the CollectionResponse class in error cases.""" | ||
with pytest.raises(ValueError, match="validation error"): | ||
CollectionResponse(data="not a list") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
"""Test the enum.Sex enum.""" | ||
|
||
import pytest | ||
from geneweaver.core.enum import Sex | ||
|
||
|
||
def test_sex_enum_as_string(): | ||
"""Test that the Sex enum renders to string as expected.""" | ||
assert str(Sex.FEMALE) == "Female" | ||
assert str(Sex.MALE) == "Male" | ||
assert str(Sex.BOTH) == "Both" | ||
|
||
|
||
def test_initialize_sex_enum_from_string(): | ||
"""Test that we can initialize the Sex enum as expected.""" | ||
assert Sex("Female") == Sex.FEMALE | ||
assert Sex("Male") == Sex.MALE | ||
assert Sex("Both") == Sex.BOTH | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"invalid_sex_value", | ||
[ | ||
"test", | ||
"another", | ||
"CAPS", | ||
"MALE", | ||
"male", | ||
"FEMALE", | ||
"female", | ||
"BOTH", | ||
"both", | ||
"neither", | ||
"either", | ||
"none", | ||
"all", | ||
"unknown", | ||
"other", | ||
"12345", | ||
"1.2345", | ||
"0", | ||
"None", | ||
], | ||
) | ||
def test_sex_enum_raises_error_when_initialized_with_invalid_value(invalid_sex_value): | ||
"""Test that initializing the Sex enum with an invalid value raises an error.""" | ||
match_text = f"'{invalid_sex_value}' is not a valid Sex" | ||
with pytest.raises(ValueError, match=match_text): | ||
Sex(invalid_sex_value) |