Skip to content
This repository was archived by the owner on Oct 1, 2024. It is now read-only.

Commit 1319b10

Browse files
sami-m-gjsvgoncalves
authored andcommitted
Add collections endpoint (#57)
Closes #43 Signed-off-by: sami-m-g <sami.mg@outlook.com> Reviewed-by: João Gonçalves <jsvgoncalves@gmail.com>
1 parent 472e7d6 commit 1319b10

13 files changed

Lines changed: 821 additions & 259 deletions

File tree

dds_glossary/database.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def get_concept_schemes(engine: Engine) -> list[ConceptScheme]:
9292
return session.query(ConceptScheme).all()
9393

9494

95-
def get_concept_scheme(engine: Engine, concept_scheme_iri: str) -> ConceptScheme | None:
95+
def get_concept_scheme(engine: Engine, concept_scheme_iri: str) -> ConceptScheme:
9696
"""
9797
Get the concept scheme from the database.
9898
@@ -101,7 +101,10 @@ def get_concept_scheme(engine: Engine, concept_scheme_iri: str) -> ConceptScheme
101101
concept_scheme_iri (str): The concept scheme IRI.
102102
103103
Returns:
104-
ConceptScheme | None: The concept scheme or None if not found.
104+
ConceptScheme: The concept scheme.
105+
106+
Raises:
107+
NoResultFound: If the concept scheme is not found.
105108
"""
106109
with Session(engine) as session:
107110
member_polymorphic = with_polymorphic(
@@ -113,11 +116,11 @@ def get_concept_scheme(engine: Engine, concept_scheme_iri: str) -> ConceptScheme
113116
session.query(ConceptScheme)
114117
.where(ConceptScheme.iri == concept_scheme_iri)
115118
.options(joinedload(ConceptScheme.members.of_type(member_polymorphic)))
116-
.one_or_none()
119+
.one()
117120
)
118121

119122

120-
def get_collection(engine: Engine, collection_iri: str) -> Collection | None:
123+
def get_collection(engine: Engine, collection_iri: str) -> Collection:
121124
"""
122125
Get the collection from the database.
123126
@@ -126,7 +129,10 @@ def get_collection(engine: Engine, collection_iri: str) -> Collection | None:
126129
collection_iri (str): The collection IRI.
127130
128131
Returns:
129-
Collection | None: The collection or None if not found.
132+
Collection: The collection.
133+
134+
Raises:
135+
NoResultFound: If the collection is not found.
130136
"""
131137
with Session(engine) as session:
132138
member_polymorphic = with_polymorphic(
@@ -138,27 +144,30 @@ def get_collection(engine: Engine, collection_iri: str) -> Collection | None:
138144
session.query(Collection)
139145
.where(Collection.iri == collection_iri)
140146
.options(joinedload(Collection.members.of_type(member_polymorphic)))
141-
.one_or_none()
147+
.one()
142148
)
143149

144150

145-
def get_concept(engine: Engine, concept_iri: str) -> Concept | None:
151+
def get_concept(engine: Engine, concept_iri: str) -> Concept:
146152
"""
147-
Get the concept from the database, if found.
153+
Get the concept from the database.
148154
149155
Args:
150156
engine (Engine): The database engine.
151157
concept_iri (str): The concept IRI.
152158
153159
Return:
154-
Concept | None: The concept or None if not found.
160+
Concept: The concept or None if not found.
161+
162+
Raises:
163+
NoResultFound: If the concept is not found.
155164
"""
156165
with Session(engine) as session:
157166
return (
158167
session.query(Concept)
159168
.where(Concept.iri == concept_iri)
160169
.options(joinedload(Concept.concept_schemes))
161-
.one_or_none()
170+
.one()
162171
)
163172

164173

dds_glossary/exceptions.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""Exception classes for the dds_glossary package."""
2+
3+
from http import HTTPStatus
4+
5+
from fastapi import HTTPException
6+
7+
8+
class DDSGlossaryException(HTTPException):
9+
"""Base class for exceptions in the dds_glossary package."""
10+
11+
12+
class EntityNotFound(DDSGlossaryException):
13+
"""Exception raised when an entity is not found."""
14+
15+
def __init__(self, entity_name: str, entity_iri: str) -> None:
16+
super().__init__(HTTPStatus.NOT_FOUND, f"{entity_name} {entity_iri} not found.")
17+
18+
19+
class ConceptSchemeNotFoundException(EntityNotFound):
20+
"""Exception raised when a concept scheme is not found."""
21+
22+
def __init__(self, concept_scheme_iri: str) -> None:
23+
super().__init__("Concept scheme", concept_scheme_iri)
24+
25+
26+
class ConceptNotFoundException(EntityNotFound):
27+
"""Exception raised when a concept is not found."""
28+
29+
def __init__(self, concept_iri: str) -> None:
30+
super().__init__("Concept", concept_iri)
31+
32+
33+
class CollectionNotFoundException(EntityNotFound):
34+
"""Exception raised when a collection is not found."""
35+
36+
def __init__(self, collection_iri: str) -> None:
37+
super().__init__("Collection", collection_iri)

dds_glossary/routes.py

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
"""Routes for the dds_glossary server."""
22

3-
from http import HTTPStatus
4-
53
from fastapi import APIRouter, Depends, Request
6-
from fastapi.responses import JSONResponse, RedirectResponse
4+
from fastapi.responses import RedirectResponse
75
from fastapi_versioning import version
86
from starlette.templating import Jinja2Templates, _TemplateResponse
97

@@ -12,7 +10,9 @@
1210
CollectionResponse,
1311
ConceptResponse,
1412
ConceptSchemeResponse,
15-
FullConeptResponse,
13+
EntityResponse,
14+
FullConceptResponse,
15+
FullConceptSchemeResponse,
1616
InitDatasetsResponse,
1717
VersionResponse,
1818
)
@@ -141,29 +141,47 @@ def get_concept_schemes(
141141
return controller.get_concept_schemes(lang=lang)
142142

143143

144-
@router_versioned.get("/concepts")
144+
@router_versioned.get("/scheme")
145145
@version(0, 1)
146-
def get_concepts(
146+
def get_concept_scheme(
147147
concept_scheme_iri: str,
148148
controller: GlossaryController = Depends(get_controller),
149149
lang: str = "en",
150-
) -> JSONResponse:
150+
) -> FullConceptSchemeResponse:
151151
"""
152-
Returns all the saved concepts for a concept scheme.
152+
Returns a concept scheme.
153153
154154
Args:
155155
concept_scheme_iri (str): The concept scheme IRI.
156156
controller (GlossaryController): The glossary controller.
157157
lang (str): The language. Defaults to "en".
158158
159159
Returns:
160-
JSONResponse: The concepts.
160+
FullConceptSchemeResponse: The concept scheme with member
161+
concepts and collections.
161162
"""
162-
return JSONResponse(
163-
content={"concepts": controller.get_concepts(concept_scheme_iri, lang=lang)},
164-
media_type="application/json",
165-
status_code=HTTPStatus.OK,
166-
)
163+
return controller.get_concept_scheme(concept_scheme_iri, lang=lang)
164+
165+
166+
@router_versioned.get("/collections")
167+
@version(0, 1)
168+
def get_collections(
169+
concept_scheme_iri: str,
170+
controller: GlossaryController = Depends(get_controller),
171+
lang: str = "en",
172+
) -> list[EntityResponse]:
173+
"""
174+
Returns all the collections.
175+
176+
Args:
177+
concept_scheme_iri (str): The concept scheme IRI.
178+
controller (GlossaryController): The glossary controller.
179+
lang (str): The language. Defaults to "en".
180+
181+
Returns:
182+
list[CollectionResponse]: The collections.
183+
"""
184+
return controller.get_collections(concept_scheme_iri, lang=lang)
167185

168186

169187
@router_versioned.get("/collection")
@@ -175,23 +193,47 @@ def get_collection(
175193
) -> CollectionResponse:
176194
"""
177195
Returns a collection.
196+
178197
Args:
179198
collection_iri (str): The collection IRI.
180199
controller (GlossaryController): The glossary controller.
181200
lang (str): The language. Defaults to "en".
201+
182202
Returns:
183-
JSONResponse: The collection.
203+
CollectionResponse: The collection with member collections
204+
and concepts.
184205
"""
185206
return controller.get_collection(collection_iri, lang=lang)
186207

187208

209+
@router_versioned.get("/concepts")
210+
@version(0, 1)
211+
def get_concepts(
212+
concept_scheme_iri: str,
213+
controller: GlossaryController = Depends(get_controller),
214+
lang: str = "en",
215+
) -> list[ConceptResponse]:
216+
"""
217+
Returns all the concepts in a concept scheme.
218+
219+
Args:
220+
concept_scheme_iri (str): The concept scheme IRI.
221+
controller (GlossaryController): The glossary controller.
222+
lang (str): The language. Defaults to "en".
223+
224+
Returns:
225+
list[ConceptResponse]: The concepts.
226+
"""
227+
return controller.get_concepts(concept_scheme_iri, lang=lang)
228+
229+
188230
@router_versioned.get("/concept")
189231
@version(0, 1)
190232
def get_concept(
191233
concept_iri: str,
192234
controller: GlossaryController = Depends(get_controller),
193235
lang: str = "en",
194-
) -> FullConeptResponse:
236+
) -> FullConceptResponse:
195237
"""
196238
Returns a concept.
197239
@@ -200,6 +242,6 @@ def get_concept(
200242
lang (str): The language. Defaults to "en".
201243
202244
Returns:
203-
FullConeptResponse: The concept with concept scheme and relations.
245+
FullConceptResponse: The concept with concept scheme and relations.
204246
"""
205247
return controller.get_concept(concept_iri, lang=lang)

dds_glossary/schema.py

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,6 @@ class ConceptSchemeResponse(EntityResponse):
5757
scopeNote: str
5858

5959

60-
class CollectionResponse(EntityResponse):
61-
"""
62-
Response model for the Collection model with members.
63-
64-
Attributes:
65-
members (list[EntityResponse]): The members of the collection.
66-
"""
67-
68-
members: list[EntityResponse]
69-
70-
7160
class RelationResponse(BaseModel):
7261
"""
7362
Response model for the SemanticRelation model.
@@ -98,7 +87,33 @@ class ConceptResponse(EntityResponse):
9887
altLabels: list[str]
9988

10089

101-
class FullConeptResponse(ConceptResponse):
90+
class FullConceptSchemeResponse(ConceptSchemeResponse):
91+
"""
92+
Response model for the ConceptScheme model with collections and concepts.
93+
94+
Attributes:
95+
collections (list[EntityResponse]): The collections.
96+
concepts (list[ConceptResponse]): The concepts.
97+
"""
98+
99+
collections: list[EntityResponse]
100+
concepts: list[ConceptResponse]
101+
102+
103+
class CollectionResponse(EntityResponse):
104+
"""
105+
Response model for the Collection model with members.
106+
107+
Attributes:
108+
collections (list[EntityResponse]): The collections.
109+
concepts (list[ConceptResponse]): The concepts.
110+
"""
111+
112+
collections: list[EntityResponse]
113+
concepts: list[ConceptResponse]
114+
115+
116+
class FullConceptResponse(ConceptResponse):
102117
"""
103118
Response model for the Concept model with concept schemes and relations.
104119

0 commit comments

Comments
 (0)