Add athlete api
This commit is contained in:
parent
0f5659bc9d
commit
f11c134b4f
6 changed files with 244 additions and 0 deletions
2
athlete/.dockerignore
Normal file
2
athlete/.dockerignore
Normal file
|
@ -0,0 +1,2 @@
|
|||
./venv
|
||||
./__pycache__/
|
9
athlete/Dockerfile
Normal file
9
athlete/Dockerfile
Normal file
|
@ -0,0 +1,9 @@
|
|||
FROM python:alpine3.19
|
||||
|
||||
COPY . /app
|
||||
WORKDIR /app
|
||||
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["gunicorn", "--bind", "0.0.0.0:80", "main:app"]
|
157
athlete/main.py
Normal file
157
athlete/main.py
Normal file
|
@ -0,0 +1,157 @@
|
|||
import json
|
||||
import os
|
||||
from flask import Flask, request, jsonify
|
||||
from pydantic import BaseModel
|
||||
|
||||
app = Flask(__name__)
|
||||
SAVE_FILE: str = "./data/athlete.json"
|
||||
|
||||
|
||||
class Athlete(BaseModel):
|
||||
current_idx: int = 0
|
||||
id: int
|
||||
name: str
|
||||
surname: str
|
||||
email: str
|
||||
country: str
|
||||
isDisabled: bool
|
||||
|
||||
def modify_from_key(self, key, value):
|
||||
if key == "name":
|
||||
self.name = value
|
||||
if key == "surname":
|
||||
self.surname = value
|
||||
if key == "email":
|
||||
self.email = value
|
||||
if key == "country":
|
||||
self.country = value
|
||||
if key == "isDisabled":
|
||||
self.isDisabled = bool(value)
|
||||
|
||||
def serialize(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'name': self.name,
|
||||
'surname': self.surname,
|
||||
'email': self.email,
|
||||
'country': self.country,
|
||||
'isDisabled': self.isDisabled,
|
||||
}
|
||||
|
||||
|
||||
def load_athlete_from_json(path: str) -> dict[int, Athlete]:
|
||||
if not os.path.isfile(path):
|
||||
Athlete.current_idx = 0
|
||||
return {}
|
||||
with open(path, "r") as file:
|
||||
content = file.read()
|
||||
list_test = json.loads(content)
|
||||
if len(list_test) != 0:
|
||||
Athlete.current_idx = list_test[-1]['id']
|
||||
else:
|
||||
Athlete.current_idx = 0
|
||||
obj: dict[int, Athlete] = {}
|
||||
for element in list_test:
|
||||
obj[int(element['id'])] = Athlete(
|
||||
id=int(element['id']), name=element['name'],
|
||||
surname=element['surname'], email=element['email'],
|
||||
country=element['country'], isDisabled=bool(element['isDisabled']))
|
||||
return obj
|
||||
|
||||
|
||||
def save_athlete_in_json(path: str, athlete_dict: dict[int, Athlete]):
|
||||
athlete_list = []
|
||||
for _, value in athlete_dict.items():
|
||||
athlete_list.append(value.serialize())
|
||||
with open(path, "w") as file:
|
||||
file.write(json.dumps(athlete_list))
|
||||
|
||||
|
||||
@ app.route('/')
|
||||
def root():
|
||||
return jsonify({"name": "Jo API", "description": "An API to get information on 2024 olympic games"}), 200
|
||||
|
||||
|
||||
@ app.route('/athlete', methods=['GET', 'POST'])
|
||||
def handleAthlete():
|
||||
if request.method == 'POST':
|
||||
return handleAthletePOST()
|
||||
else:
|
||||
return handleAthleteGET()
|
||||
|
||||
|
||||
def handleAthletePOST():
|
||||
athlete_list: dict[int, Athlete] = load_athlete_from_json(SAVE_FILE)
|
||||
try:
|
||||
post_data = request.get_json()
|
||||
id = Athlete.current_idx + 1
|
||||
name = post_data['name']
|
||||
surname = post_data['surname']
|
||||
email = post_data['email']
|
||||
country = post_data['country']
|
||||
isDisabled = bool(post_data['isDisabled'])
|
||||
athlete = Athlete(id=id, name=name, surname=surname,
|
||||
email=email, country=country, isDisabled=isDisabled)
|
||||
athlete_list[athlete.id] = athlete
|
||||
Athlete.current_idx += 1
|
||||
save_athlete_in_json(SAVE_FILE, athlete_list)
|
||||
except Exception:
|
||||
return jsonify({"Message": "Bad request"}), 400
|
||||
return jsonify({'id': athlete.id}), 200
|
||||
|
||||
|
||||
def handleAthleteGET():
|
||||
athlete_list: dict[int, Athlete] = load_athlete_from_json(SAVE_FILE)
|
||||
ret: list(Athlete) = []
|
||||
for _, val in athlete_list.items():
|
||||
ret.append(val.serialize())
|
||||
return jsonify(ret)
|
||||
|
||||
|
||||
@ app.route('/athlete/<id>', methods=['GET', 'PATCH', 'DELETE'])
|
||||
def handleAthleteId(id: int):
|
||||
if request.method == 'GET':
|
||||
return handleAthleteIdGET(id)
|
||||
elif request.method == 'PATCH':
|
||||
return handleAthleteIdPATCH(id)
|
||||
else:
|
||||
return handleAthleteIdDELETE(id)
|
||||
|
||||
|
||||
def handleAthleteIdGET(id: int):
|
||||
athlete_list: dict[int, Athlete] = load_athlete_from_json(SAVE_FILE)
|
||||
try:
|
||||
athlete = athlete_list[int(id)]
|
||||
return jsonify(athlete.serialize())
|
||||
except Exception:
|
||||
return jsonify({'Message': 'Not found'}), 404
|
||||
|
||||
|
||||
def handleAthleteIdPATCH(id: int):
|
||||
try:
|
||||
athlete_list: dict[int, Athlete] = load_athlete_from_json(
|
||||
SAVE_FILE)
|
||||
patch_data = request.get_json()
|
||||
key_list = ['name', 'surname', 'surname',
|
||||
'email', 'country', 'isDisabled']
|
||||
_ = athlete_list[int(id)]
|
||||
for key, value in patch_data.items():
|
||||
if key in key_list:
|
||||
athlete_list[int(id)].modify_from_key(key, value)
|
||||
else:
|
||||
return jsonify({'Message': 'Bad request'}), 400
|
||||
save_athlete_in_json(SAVE_FILE, athlete_list)
|
||||
return "OK", 200
|
||||
except Exception:
|
||||
return jsonify({'Message': 'Not found'}), 404
|
||||
|
||||
|
||||
def handleAthleteIdDELETE(id: int):
|
||||
athlete_list: dict[int, Athlete] = load_athlete_from_json(SAVE_FILE)
|
||||
try:
|
||||
athlete_list.pop(int(id))
|
||||
save_athlete_in_json(SAVE_FILE, athlete_list)
|
||||
except Exception:
|
||||
return jsonify({"Message": "Not found"})
|
||||
|
||||
return "Ok"
|
3
athlete/requirements.txt
Normal file
3
athlete/requirements.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
flask
|
||||
pydantic
|
||||
gunicorn
|
9
athlete/start_debug.sh
Executable file
9
athlete/start_debug.sh
Executable file
|
@ -0,0 +1,9 @@
|
|||
if [ ! -d "./venv" ]; then
|
||||
python3 -m venv ./venv
|
||||
fi
|
||||
|
||||
source ./venv/bin/activate
|
||||
|
||||
pip install flask pydantic
|
||||
|
||||
flask --app main run --reload --debug
|
64
athlete/test.py
Executable file
64
athlete/test.py
Executable file
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env python3
|
||||
import requests
|
||||
import json
|
||||
|
||||
HOST = "http://localhost:5000"
|
||||
|
||||
# Get root
|
||||
assert 200 == requests.get(HOST + "/").status_code
|
||||
|
||||
# Get list of athletes as a json object
|
||||
get_root = requests.get(HOST + "/athlete").text
|
||||
if get_root != "[]\n":
|
||||
assert json.loads(get_root)
|
||||
|
||||
# Post on '/athlete' With no data
|
||||
assert 400 == requests.post(HOST + "/athlete").status_code
|
||||
|
||||
# Post on '/athlete' with uncorrect body
|
||||
assert 400 == requests.post(
|
||||
HOST + "/athlete", json={"should": "fail"}).status_code
|
||||
|
||||
|
||||
# Post on '/athlete' with correct body
|
||||
post_request = requests.post(HOST + "/athlete", json={"name": "test", "surname": "tests",
|
||||
"email": "test.test@test.co", "country": "fr", "isDisabled": True})
|
||||
assert 200 == post_request.status_code
|
||||
id = json.loads(post_request.text)['id']
|
||||
|
||||
# Get newly created object
|
||||
expected_result = f"""{{
|
||||
"country": "fr",
|
||||
"email": "test.test@test.co",
|
||||
"id": {id},
|
||||
"isDisabled": true,
|
||||
"name": "test",
|
||||
"surname": "tests"
|
||||
}}
|
||||
"""
|
||||
assert expected_result == requests.get(HOST + f"/athlete/{id}").text
|
||||
|
||||
assert 400 == requests.patch(
|
||||
HOST + f"/athlete/{id}", json={"should": "fail"}).status_code
|
||||
|
||||
# Test to patch object
|
||||
assert 200 == requests.patch(
|
||||
HOST + f"/athlete/{id}", json={"name": "modify"}).status_code
|
||||
|
||||
expected_result = f"""{{
|
||||
"country": "fr",
|
||||
"email": "test.test@test.co",
|
||||
"id": {id},
|
||||
"isDisabled": true,
|
||||
"name": "modify",
|
||||
"surname": "tests"
|
||||
}}
|
||||
"""
|
||||
assert expected_result == requests.get(HOST + f"/athlete/{id}").text
|
||||
|
||||
# test delete methode on the newly created athlete
|
||||
|
||||
assert 200 == requests.delete(HOST + f"/athlete/{id}").status_code
|
||||
|
||||
# verify that the object don't exist anymore
|
||||
assert 404 == requests.get(HOST + f"/athlete/{id}").status_code
|
Loading…
Reference in a new issue