Skip to content

Commit 36030fa

Browse files
committed
Updated API and testsuite
1 parent 03e6e99 commit 36030fa

File tree

17 files changed

+549
-206
lines changed

17 files changed

+549
-206
lines changed

.idea/dataSources.xml

Lines changed: 7 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/mrmat-python-api-fastapi.iml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

requirements.dev.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ pytest==8.3.5 # MIT
1212
pytest-cov==6.0.0 # MIT
1313
mypy==1.15.0 # MIT
1414
types-PyYAML==6.0.12.20241230 # Apache 2.0
15+
httpx==0.28.1 # BSD-3-Clause

requirements.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
# Runtime requirements
33

44
fastapi==0.115.11 # MIT
5-
sqlalchemy[asyncio]==2.0.39 # MIT
6-
uvicorn==0.34.0 # BSD 3-Clause
7-
pydantic==2.10.6 # MIT
5+
sqlalchemy[asyncio]==2.0.40 # MIT
6+
uvicorn==0.34.0 # BSD 3-Clause
7+
pydantic==2.10.6 # MIT

src/mrmat_python_api_fastapi/apis/resource/__init__.py renamed to src/mrmat_python_api_fastapi/apis/platform/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@
2020
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
# SOFTWARE.
2222

23-
from .v1 import api_resource_v1
23+
from .v1 import api_platform_v1

src/mrmat_python_api_fastapi/apis/resource/v1/__init__.py renamed to src/mrmat_python_api_fastapi/apis/platform/v1/__init__.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,12 @@
2020
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
# SOFTWARE.
2222

23-
from .api import router as api_resource_v1
23+
from .api import router as api_platform_v1
24+
from .schema import (
25+
ResourceSchema,
26+
ResourceInputSchema,
27+
ResourceListSchema,
28+
OwnerSchema,
29+
OwnerInputSchema,
30+
OwnerListSchema
31+
)
Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
# MIT License
2+
#
3+
# Copyright (c) 2022 Mathieu Imfeld
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
from typing import Union
24+
from fastapi import APIRouter, Depends, status, HTTPException
25+
from fastapi.responses import JSONResponse, Response
26+
from sqlalchemy.exc import SQLAlchemyError
27+
from sqlalchemy.orm import Session
28+
29+
from mrmat_python_api_fastapi.db import get_db
30+
from mrmat_python_api_fastapi.apis import StatusSchema
31+
from .db import Resource, Owner
32+
from .schema import (
33+
ResourceSchema,
34+
ResourceInputSchema,
35+
ResourceListSchema,
36+
OwnerSchema,
37+
OwnerInputSchema,
38+
OwnerListSchema
39+
)
40+
41+
router = APIRouter()
42+
43+
44+
@router.get('/resources',
45+
name='list_resources',
46+
summary='List all known resources',
47+
description='Returns all currently known resources and their metadata',
48+
response_model=ResourceListSchema)
49+
async def get_resources(session: Session = Depends(get_db)) -> ResourceListSchema:
50+
try:
51+
resources = session.query(Resource).all()
52+
return ResourceListSchema(resources=resources)
53+
except SQLAlchemyError as e:
54+
# Handle the error appropriately, maybe raise an HTTPException
55+
raise HTTPException(status_code=500, detail="A database error occurred") from e
56+
57+
58+
@router.get('/resources/{uid}',
59+
name='get_resource',
60+
summary='Get a single resource',
61+
description='Return a single resource identified by its resource id',
62+
responses={
63+
status.HTTP_404_NOT_FOUND: {
64+
'description': 'The resource was not found',
65+
'model': StatusSchema
66+
},
67+
status.HTTP_200_OK: {
68+
'description': 'The requested resource',
69+
'model': ResourceSchema
70+
}
71+
})
72+
async def get_resource(uid: str,
73+
response: Response,
74+
session: Session = Depends(get_db)):
75+
try:
76+
resource = session.query(Resource).get(uid)
77+
if not resource:
78+
response.status_code = 404
79+
return StatusSchema(code=404, msg='The resource was not found')
80+
return resource
81+
except SQLAlchemyError as e:
82+
# Handle the error appropriately, maybe raise an HTTPException
83+
raise HTTPException(status_code=500, detail="A database error occurred") from e
84+
85+
@router.post('/resources',
86+
name='create_resource',
87+
summary='Create a resource',
88+
description='Create a resource owned by the authenticated user',
89+
responses={
90+
status.HTTP_201_CREATED: {
91+
'description': 'The resource was created',
92+
'model': ResourceSchema
93+
},
94+
})
95+
async def create_resource(data: ResourceInputSchema,
96+
response: Response,
97+
session: Session = Depends(get_db)):
98+
try:
99+
resource = Resource(name=data.name, owner_uid=data.owner_uid)
100+
session.add(resource)
101+
session.commit()
102+
response.status_code = 201
103+
return ResourceSchema(uid=resource.uid,
104+
owner_uid=resource.owner_uid,
105+
name=resource.name)
106+
except SQLAlchemyError as e:
107+
raise HTTPException(status_code=500, detail="A database error occurred") from e
108+
109+
110+
@router.put('/resources/{uid}',
111+
name='modify_resource',
112+
summary='Modify a resource',
113+
description='Modify a resource by its resource id',
114+
responses={
115+
status.HTTP_200_OK: {
116+
'description': 'The resource was modified',
117+
'model': ResourceSchema
118+
},
119+
status.HTTP_404_NOT_FOUND: {
120+
'description': 'The resource was not found',
121+
'model': StatusSchema
122+
}
123+
})
124+
async def modify_resource(uid: str,
125+
data: ResourceInputSchema,
126+
response: Response,
127+
db: Session = Depends(get_db)):
128+
try:
129+
resource = db.query(Resource).get(uid)
130+
if not resource:
131+
response.status_code = 404
132+
return StatusSchema(code=404, msg='Not found')
133+
resource.name = data.name
134+
db.add(resource)
135+
db.commit()
136+
return ResourceSchema(uid=resource.uid,
137+
owner_uid=resource.owner_uid,
138+
name=resource.name)
139+
except SQLAlchemyError as e:
140+
raise HTTPException(status_code=500, detail="A database error occurred") from e
141+
142+
143+
@router.delete('/resources/{uid}',
144+
name='remove_resource',
145+
summary='Remove a resource',
146+
description='Remove a resource by its resource id',
147+
status_code=204,
148+
responses={
149+
status.HTTP_204_NO_CONTENT: {
150+
'description': 'The resource was removed'
151+
},
152+
status.HTTP_410_GONE: {
153+
'description': 'The resource was already gone',
154+
'model': StatusSchema
155+
}
156+
})
157+
async def remove_resource(uid: str,
158+
response: Response,
159+
session: Session = Depends(get_db)):
160+
try:
161+
resource = session.query(Resource).get(uid)
162+
if not resource:
163+
response.status_code = 410
164+
return StatusSchema(code=410, msg='The resource was already gone')
165+
session.delete(resource)
166+
session.commit()
167+
response.status_code = 204
168+
return {}
169+
except SQLAlchemyError as e:
170+
raise HTTPException(status_code=500, detail="A database error occurred") from e
171+
172+
173+
174+
@router.get('/owners',
175+
name='list_owners',
176+
summary='List all known owners',
177+
description='Returns all currently known owners and their metadata',
178+
response_model=OwnerListSchema)
179+
async def get_owners(db: Session = Depends(get_db)):
180+
try:
181+
owners = db.query(Owner).all()
182+
return OwnerListSchema(owners=owners)
183+
except SQLAlchemyError as e:
184+
# Handle the error appropriately, maybe raise an HTTPException
185+
raise HTTPException(status_code=500, detail="A database error occurred") from e
186+
187+
188+
@router.get('/owners/{uid}',
189+
name='get_owner',
190+
summary='Get a single owner',
191+
description='Return a single owner identified by its owner id',
192+
responses={
193+
status.HTTP_404_NOT_FOUND: {
194+
'description': 'The owner was not found',
195+
'model': StatusSchema
196+
},
197+
status.HTTP_200_OK: {
198+
'description': 'The requested owner',
199+
'model': ResourceSchema
200+
}
201+
})
202+
async def get_owner(uid: str,
203+
response: Response,
204+
session: Session = Depends(get_db)):
205+
try:
206+
owner = session.query(Owner).get(uid)
207+
if not owner:
208+
response.status_code = 404
209+
return StatusSchema(code=404, msg='The owner was not found')
210+
return owner
211+
except SQLAlchemyError as e:
212+
raise HTTPException(status_code=500, detail="A database error occurred") from e
213+
214+
215+
@router.post('/owners',
216+
name='create_owner',
217+
summary='Create a owner',
218+
description='Create a owner',
219+
responses={
220+
status.HTTP_201_CREATED: {'description': 'The owner was created', 'model': OwnerSchema}
221+
})
222+
async def create_owner(data: OwnerInputSchema,
223+
response: Response,
224+
session: Session = Depends(get_db)):
225+
try:
226+
owner = Owner(name=data.name, client_id='TODO')
227+
session.add(owner)
228+
session.commit()
229+
response.status_code = 201
230+
return OwnerSchema(uid=owner.uid, name=owner.name)
231+
except SQLAlchemyError as e:
232+
# Handle the error appropriately, maybe raise an HTTPException
233+
raise HTTPException(status_code=500, detail="A database error occurred") from e
234+
235+
236+
@router.put('/owners/{uid}',
237+
name='modify_owner',
238+
summary='Modify a owner',
239+
description='Modify a owner by its owner id',
240+
responses={
241+
status.HTTP_200_OK: {
242+
'description': 'The owner was modified',
243+
'model': OwnerSchema
244+
},
245+
status.HTTP_404_NOT_FOUND: {
246+
'description': 'The owner was not found',
247+
'model': StatusSchema
248+
}
249+
})
250+
async def modify_owner(uid: str,
251+
data: OwnerInputSchema,
252+
response: Response,
253+
db: Session = Depends(get_db)):
254+
try:
255+
owner = db.query(Owner).get(uid)
256+
if not owner:
257+
response.status_code = 404
258+
return StatusSchema(code=404, msg='The owner was not found')
259+
owner.name = data.name
260+
db.add(owner)
261+
db.commit()
262+
return OwnerSchema(uid=owner.uid, name=owner.name)
263+
except SQLAlchemyError as e:
264+
raise HTTPException(status_code=500, detail="A database error occurred") from e
265+
266+
267+
@router.delete('/owners/{uid}',
268+
name='remove_owner',
269+
summary='Remove a owner',
270+
description='Remove a owner by its owner id',
271+
status_code=204,
272+
responses={
273+
status.HTTP_204_NO_CONTENT: {
274+
'description': 'The owner was removed'
275+
},
276+
status.HTTP_410_GONE: {
277+
'description': 'The owner was already gone',
278+
'model': StatusSchema
279+
}
280+
})
281+
async def remove_owner(uid: str,
282+
response: Response,
283+
db: Session = Depends(get_db)):
284+
owner = db.query(Owner).get(uid)
285+
if not owner:
286+
response.status_code = status.HTTP_410_GONE
287+
return
288+
db.delete(owner)
289+
db.commit()
290+
response.status_code = status.HTTP_204_NO_CONTENT

0 commit comments

Comments
 (0)