Add sport api
This commit is contained in:
parent
613a1a53aa
commit
8382956a96
5 changed files with 220 additions and 0 deletions
9
sport/Dockerfile
Normal file
9
sport/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"]
|
140
sport/main.py
Normal file
140
sport/main.py
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from flask import Flask, request, jsonify
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
SAVE_FILE: str = "./data/sport.json"
|
||||||
|
|
||||||
|
|
||||||
|
class Sport(BaseModel):
|
||||||
|
current_idx: int = 0
|
||||||
|
id: int
|
||||||
|
name: str
|
||||||
|
category: str
|
||||||
|
|
||||||
|
def modify_from_key(self, key, value):
|
||||||
|
if key == "name":
|
||||||
|
self.name = value
|
||||||
|
if key == "category":
|
||||||
|
self.category = value
|
||||||
|
|
||||||
|
def serialize(self):
|
||||||
|
return {
|
||||||
|
'id': self.id,
|
||||||
|
'name': self.name,
|
||||||
|
'category': self.category,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def load_sport_from_json(path: str) -> dict[int, Sport]:
|
||||||
|
if not os.path.isfile(path):
|
||||||
|
Sport.current_idx = 0
|
||||||
|
return {}
|
||||||
|
with open(path, "r") as file:
|
||||||
|
content = file.read()
|
||||||
|
list_test = json.loads(content)
|
||||||
|
if len(list_test) != 0:
|
||||||
|
Sport.current_idx = list_test[-1]['id']
|
||||||
|
else:
|
||||||
|
Sport.current_idx = 0
|
||||||
|
print(Sport.current_idx)
|
||||||
|
obj: dict[int, Sport] = {}
|
||||||
|
for element in list_test:
|
||||||
|
obj[int(element['id'])] = Sport(id=int(element['id']),
|
||||||
|
name=element['name'], category=element['category'])
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
def save_sport_in_json(path: str, sport_dict: dict[int, Sport]):
|
||||||
|
sport_list = []
|
||||||
|
for _, value in sport_dict.items():
|
||||||
|
sport_list.append(value.serialize())
|
||||||
|
with open(path, "w") as file:
|
||||||
|
file.write(json.dumps(sport_list))
|
||||||
|
|
||||||
|
|
||||||
|
@ app.route('/')
|
||||||
|
def root():
|
||||||
|
return jsonify({"name": "Jo API", "description": "An API to get information on 2024 olympic games"}), 200
|
||||||
|
|
||||||
|
|
||||||
|
@ app.route('/sport', methods=['GET', 'POST'])
|
||||||
|
def handleSport():
|
||||||
|
if request.method == 'POST':
|
||||||
|
return handleSportPOST()
|
||||||
|
else:
|
||||||
|
return handleSportGET()
|
||||||
|
|
||||||
|
|
||||||
|
def handleSportPOST():
|
||||||
|
sport_list: dict[int, Sport] = load_sport_from_json(SAVE_FILE)
|
||||||
|
try:
|
||||||
|
post_data = request.get_json()
|
||||||
|
id = Sport.current_idx + 1
|
||||||
|
name = post_data['name']
|
||||||
|
category = post_data['category']
|
||||||
|
sport = Sport(id=id, name=name, category=category)
|
||||||
|
sport_list[sport.id] = sport
|
||||||
|
Sport.current_idx += 1
|
||||||
|
save_sport_in_json(SAVE_FILE, sport_list)
|
||||||
|
except Exception:
|
||||||
|
return jsonify({"Message": "Bad request"}), 400
|
||||||
|
return jsonify({'id': sport.id}), 200
|
||||||
|
|
||||||
|
|
||||||
|
def handleSportGET():
|
||||||
|
sport_list: dict[int, Sport] = load_sport_from_json(SAVE_FILE)
|
||||||
|
ret: list(Sport) = []
|
||||||
|
for _, val in sport_list.items():
|
||||||
|
ret.append(val.serialize())
|
||||||
|
return jsonify(ret)
|
||||||
|
|
||||||
|
|
||||||
|
@ app.route('/sport/<id>', methods=['GET', 'PATCH', 'DELETE'])
|
||||||
|
def handleSportId(id: int):
|
||||||
|
if request.method == 'GET':
|
||||||
|
return handleSportIdGET(id)
|
||||||
|
elif request.method == 'PATCH':
|
||||||
|
return handleSportIdPATCH(id)
|
||||||
|
else:
|
||||||
|
return handleSportIdDELETE(id)
|
||||||
|
|
||||||
|
|
||||||
|
def handleSportIdGET(id: int):
|
||||||
|
sport_list: dict[int, Sport] = load_sport_from_json(SAVE_FILE)
|
||||||
|
try:
|
||||||
|
sport = sport_list[int(id)]
|
||||||
|
return jsonify(sport.serialize())
|
||||||
|
except Exception:
|
||||||
|
return jsonify({'Message': 'Not found'}), 404
|
||||||
|
|
||||||
|
|
||||||
|
def handleSportIdPATCH(id: int):
|
||||||
|
try:
|
||||||
|
sport_list: dict[int, Sport] = load_sport_from_json(
|
||||||
|
SAVE_FILE)
|
||||||
|
patch_data = request.get_json()
|
||||||
|
key_list = ['name', 'category']
|
||||||
|
print(patch_data)
|
||||||
|
_ = sport_list[int(id)]
|
||||||
|
for key, value in patch_data.items():
|
||||||
|
if key in key_list:
|
||||||
|
sport_list[int(id)].modify_from_key(key, value)
|
||||||
|
else:
|
||||||
|
return jsonify({'Message': 'Bad request'}), 400
|
||||||
|
save_sport_in_json(SAVE_FILE, sport_list)
|
||||||
|
return "OK", 200
|
||||||
|
except Exception:
|
||||||
|
return jsonify({'Message': 'Not found'}), 404
|
||||||
|
|
||||||
|
|
||||||
|
def handleSportIdDELETE(id: int):
|
||||||
|
sport_list: dict[int, Sport] = load_sport_from_json(SAVE_FILE)
|
||||||
|
try:
|
||||||
|
sport_list.pop(int(id))
|
||||||
|
save_sport_in_json(SAVE_FILE, sport_list)
|
||||||
|
except Exception:
|
||||||
|
return jsonify({"Message": "Not found"})
|
||||||
|
|
||||||
|
return "Ok"
|
3
sport/requirements.txt
Normal file
3
sport/requirements.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
flask
|
||||||
|
pydantic
|
||||||
|
gunicorn
|
9
sport/start_debug.sh
Executable file
9
sport/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
|
59
sport/test.py
Executable file
59
sport/test.py
Executable file
|
@ -0,0 +1,59 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
HOST = "http://localhost:5000"
|
||||||
|
|
||||||
|
# Get root
|
||||||
|
assert 200 == requests.get(HOST + "/").status_code
|
||||||
|
|
||||||
|
# Get list of sports as a json object
|
||||||
|
get_root = requests.get(HOST + "/sport").text
|
||||||
|
if get_root != "[]\n":
|
||||||
|
assert json.loads(get_root)
|
||||||
|
|
||||||
|
# Post on '/sport' With no data
|
||||||
|
assert 400 == requests.post(HOST + "/sport").status_code
|
||||||
|
|
||||||
|
# Post on '/sport' with uncorrect body
|
||||||
|
assert 400 == requests.post(
|
||||||
|
HOST + "/sport", json={"should": "fail"}).status_code
|
||||||
|
|
||||||
|
|
||||||
|
# Post on '/sport' with correct body
|
||||||
|
post_request = requests.post(
|
||||||
|
HOST + "/sport", json={"name": "test", "category": "aquatic"})
|
||||||
|
assert 200 == post_request.status_code
|
||||||
|
id = json.loads(post_request.text)['id']
|
||||||
|
|
||||||
|
# Get newly created object
|
||||||
|
expected_result = f"""{{
|
||||||
|
"category": "aquatic",
|
||||||
|
"id": {id},
|
||||||
|
"name": "test"
|
||||||
|
}}
|
||||||
|
"""
|
||||||
|
|
||||||
|
assert expected_result == requests.get(HOST + f"/sport/{id}").text
|
||||||
|
|
||||||
|
assert 400 == requests.patch(
|
||||||
|
HOST + f"/sport/{id}", json={"should": "fail"}).status_code
|
||||||
|
|
||||||
|
# Test to patch object
|
||||||
|
assert 200 == requests.patch(
|
||||||
|
HOST + f"/sport/{id}", json={"name": "modify"}).status_code
|
||||||
|
|
||||||
|
expected_result = f"""{{
|
||||||
|
"category": "aquatic",
|
||||||
|
"id": {id},
|
||||||
|
"name": "modify"
|
||||||
|
}}
|
||||||
|
"""
|
||||||
|
assert expected_result == requests.get(HOST + f"/sport/{id}").text
|
||||||
|
|
||||||
|
# test delete methode on the newly created sport
|
||||||
|
|
||||||
|
assert 200 == requests.delete(HOST + f"/sport/{id}").status_code
|
||||||
|
|
||||||
|
# verify that the object don't exist anymore
|
||||||
|
assert 404 == requests.get(HOST + f"/sport/{id}").status_code
|
Loading…
Reference in a new issue