From b914f9ed86f3850a79239a4965d5aeb7019f6d63 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Tue, 24 Oct 2023 19:58:34 +0200 Subject: [PATCH 01/11] build app --- app.py | 20 ++++++++++++++++++++ main.py | 9 +++++++++ 2 files changed, 29 insertions(+) create mode 100644 app.py create mode 100644 main.py diff --git a/app.py b/app.py new file mode 100644 index 0000000..79793b3 --- /dev/null +++ b/app.py @@ -0,0 +1,20 @@ +from enum import Enum +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Category(Enum): + TOOLS = 'tools' + CONSUMABLES = 'consumables' + + +class Item(BaseModel): + name: str + price: float + count: int + id: int + category: Category + + diff --git a/main.py b/main.py new file mode 100644 index 0000000..94f3703 --- /dev/null +++ b/main.py @@ -0,0 +1,9 @@ +items = { + 0: Item(name="Hammer", price=9.99, count=20, id=0, category=Category.TOOLS), + 1: Item(name="Pliers", price=5.99, count=20, id=1, category=Category.TOOLS), + 2: Item(name="Nails", price=1.99, count=100, id=2, category=Category.CONSUMABLES), +} + +@app.get("/") +def index() -> dict[str, dict[int, Item]]: + return {"items": items} \ No newline at end of file From 276649451e906f459b8e98df3778d1d305a1885c Mon Sep 17 00:00:00 2001 From: Matthieu Date: Tue, 24 Oct 2023 20:36:01 +0200 Subject: [PATCH 02/11] build decorator --- app.py | 18 +++--------------- decorator.py | 14 ++++++++++++++ main.py | 35 ++++++++++++++++++++++++++--------- 3 files changed, 43 insertions(+), 24 deletions(-) create mode 100644 decorator.py diff --git a/app.py b/app.py index 79793b3..406b689 100644 --- a/app.py +++ b/app.py @@ -1,20 +1,8 @@ -from enum import Enum from fastapi import FastAPI -from pydantic import BaseModel app = FastAPI() -class Category(Enum): - TOOLS = 'tools' - CONSUMABLES = 'consumables' - - -class Item(BaseModel): - name: str - price: float - count: int - id: int - category: Category - - +@app.get("/") +def index(): + return {"items": 1} diff --git a/decorator.py b/decorator.py new file mode 100644 index 0000000..2a584f2 --- /dev/null +++ b/decorator.py @@ -0,0 +1,14 @@ +# In this script we build the decorator and the function we want to transform into an API + +def fast_api_decorator(func): + def example(*param, **param2): + print("Action avant") + func(*param, **param2) + print("Action après") + + return example + + +@fast_api_decorator +def function_to_transform(x, a): + return x**a diff --git a/main.py b/main.py index 94f3703..8fecc3b 100644 --- a/main.py +++ b/main.py @@ -1,9 +1,26 @@ -items = { - 0: Item(name="Hammer", price=9.99, count=20, id=0, category=Category.TOOLS), - 1: Item(name="Pliers", price=5.99, count=20, id=1, category=Category.TOOLS), - 2: Item(name="Nails", price=1.99, count=100, id=2, category=Category.CONSUMABLES), -} - -@app.get("/") -def index() -> dict[str, dict[int, Item]]: - return {"items": items} \ No newline at end of file +""" +FastApiDecoratorBuilder + +Description du Projet : +Votre défi dans le projet "FastApiDecoratorBuilder" est de concevoir un décorateur Python qui +transforme une fonction Python en une API FastAPI basée sur la fonction et des configurations +définies. + +Objectifs du Projet : +- Création de Décorateur: Construire un décorateur qui transforme une fonction Python en API FastAPI. +- Gestion de Configurations: Implanter un mécanisme de configuration pour l’API. + +Consignes : +1) Développement du Décorateur : Elaborez un décorateur qui, appliqué à une fonction, génère une API FastAPI +correspondante. +2) Configuration de l'API : Intégrez une méthode pour configurer les propriétés de l’API générée, telles que +les routes et les méthodes HTTP acceptées. +""" + +from decorator import fast_api_decorator, function_to_transform +from app import app +import requests + + +if __name__ == "__main__": + print(requests.get("http://127.0.0.1:8000/").json()) From 50c7ef3d50c4835faaa41496b8cd8f73795d7f06 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Tue, 24 Oct 2023 23:20:10 +0200 Subject: [PATCH 03/11] build decorator --- decorator.py | 24 +++++++++++++++--------- main.py | 5 +++-- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/decorator.py b/decorator.py index 2a584f2..ff4ed82 100644 --- a/decorator.py +++ b/decorator.py @@ -1,14 +1,20 @@ # In this script we build the decorator and the function we want to transform into an API +from app import app -def fast_api_decorator(func): - def example(*param, **param2): - print("Action avant") - func(*param, **param2) - print("Action après") - return example +def fast_api_decorator(route, methods): + def decorator(func): + def wrapper(x, a): + print("before func") + func(x, a) + print("after func") + # add root and function return to the API + app.add_api_route(route, wrapper, methods=methods) + return wrapper + return decorator -@fast_api_decorator -def function_to_transform(x, a): - return x**a + +@fast_api_decorator(route="/power", methods=["GET"]) +def power_function(x, a): + return {f"{x} to the power of {a}": x**a} diff --git a/main.py b/main.py index 8fecc3b..2b9c3f3 100644 --- a/main.py +++ b/main.py @@ -17,10 +17,11 @@ les routes et les méthodes HTTP acceptées. """ -from decorator import fast_api_decorator, function_to_transform +from decorator import power_function from app import app import requests if __name__ == "__main__": - print(requests.get("http://127.0.0.1:8000/").json()) + power_function(x=9, a=2) + print(requests.get("http://127.0.0.1:8000/power").json()) From 7cfe61b2e6b38236bf6feb8a0f23bc3ceb8a1617 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Wed, 25 Oct 2023 10:45:53 +0200 Subject: [PATCH 04/11] custom app --- app.py | 16 ++++++++++++++++ decorator.py | 5 +++-- main.py | 4 +++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/app.py b/app.py index 406b689..b735617 100644 --- a/app.py +++ b/app.py @@ -6,3 +6,19 @@ @app.get("/") def index(): return {"items": 1} + + +class CustomApp(FastAPI): + def get_func_result(self, func): + def wrapper(*args, **kwargs): + result = func(*args, **kwargs) + return result + return wrapper + + +custom_app = CustomApp() + + +@custom_app.get_func_result("/") +def example(): + return {"items": 2} diff --git a/decorator.py b/decorator.py index ff4ed82..a6400e4 100644 --- a/decorator.py +++ b/decorator.py @@ -4,10 +4,11 @@ def fast_api_decorator(route, methods): def decorator(func): - def wrapper(x, a): + def wrapper(*args, **kwargs): print("before func") - func(x, a) + func(*args, **kwargs) print("after func") + return func(*args, **kwargs) # add root and function return to the API app.add_api_route(route, wrapper, methods=methods) diff --git a/main.py b/main.py index 2b9c3f3..f870325 100644 --- a/main.py +++ b/main.py @@ -17,8 +17,10 @@ les routes et les méthodes HTTP acceptées. """ +# Use command : "python -m uvicorn main:app --reload" to lauch server and be able to request the "app" API. + from decorator import power_function -from app import app +from app import app, custom_app import requests From f2640fa62676966dbb7ce27b5ce60d2d4df16fda Mon Sep 17 00:00:00 2001 From: Matthieu Date: Sun, 29 Oct 2023 13:37:02 +0100 Subject: [PATCH 05/11] power function ok --- app.py | 38 ++++++++++++++++++++++++-------------- decorator.py | 19 ++++++++----------- main.py | 12 ++++++++---- 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/app.py b/app.py index b735617..40f1535 100644 --- a/app.py +++ b/app.py @@ -1,24 +1,34 @@ -from fastapi import FastAPI +from fastapi import FastAPI, APIRouter +my_router = APIRouter() app = FastAPI() +""" +def square_function(x: str): + return {f"{x} square equals": int(x)**2} -@app.get("/") -def index(): - return {"items": 1} +def power_function(x: str, a: str): + return {f"{x} to the power of {a}": int(x)**int(a)} -class CustomApp(FastAPI): - def get_func_result(self, func): - def wrapper(*args, **kwargs): - result = func(*args, **kwargs) - return result - return wrapper +route_path = '/power_function/{x}/{a}' +my_router.add_api_route(route_path, endpoint=power_function) +app.include_router(my_router) -custom_app = CustomApp() +""" -@custom_app.get_func_result("/") -def example(): - return {"items": 2} +def fast_api_decorator(func): + def wrapper(x, a): + my_router.add_api_route(path='/{func}/{x}/{a}', endpoint=func) + app.include_router(my_router) + return wrapper + + +@fast_api_decorator +def power_function(x: str, a: str): + return {f"{x} to the power of {a}": int(x)**int(a)} + + +power_function(x=0, a=0) diff --git a/decorator.py b/decorator.py index a6400e4..3e40809 100644 --- a/decorator.py +++ b/decorator.py @@ -1,21 +1,18 @@ # In this script we build the decorator and the function we want to transform into an API -from app import app +from app import app, my_router -def fast_api_decorator(route, methods): +def fast_api_decorator(route): def decorator(func): - def wrapper(*args, **kwargs): - print("before func") - func(*args, **kwargs) - print("after func") - return func(*args, **kwargs) - - # add root and function return to the API - app.add_api_route(route, wrapper, methods=methods) + def wrapper(x, a): + func(x, a) + return func(x, a) + my_router.add_api_route(path='/{func}/{x}/{a}', endpoint=wrapper) + app.include_router(my_router) return wrapper return decorator -@fast_api_decorator(route="/power", methods=["GET"]) +@fast_api_decorator(route="") def power_function(x, a): return {f"{x} to the power of {a}": x**a} diff --git a/main.py b/main.py index f870325..360823d 100644 --- a/main.py +++ b/main.py @@ -19,11 +19,15 @@ # Use command : "python -m uvicorn main:app --reload" to lauch server and be able to request the "app" API. -from decorator import power_function -from app import app, custom_app +from app import app, my_router, power_function import requests +def power(x, a): + print(requests.get(f"http://127.0.0.1:8000/power_function/{x}/{a}").json()) + + if __name__ == "__main__": - power_function(x=9, a=2) - print(requests.get("http://127.0.0.1:8000/power").json()) + power(x="9", a="2") + # power_function(x="9", a="2") + # print(requests.get("http://127.0.0.1:8000/power_function/10/2").json()) From 792b8890135418d675e32c09edaaedcc803edaf2 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Wed, 1 Nov 2023 13:32:41 +0100 Subject: [PATCH 06/11] add query params and specific route for each function --- app.py | 39 ++++++++++++++++++++------------------- main.py | 21 ++++++++++++++++----- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/app.py b/app.py index 40f1535..5356f99 100644 --- a/app.py +++ b/app.py @@ -3,32 +3,33 @@ my_router = APIRouter() app = FastAPI() -""" -def square_function(x: str): - return {f"{x} square equals": int(x)**2} +def fast_api_decorator(route, method): + def decorator(func): + def wrapper(*args, **kwargs): + my_router.add_api_route(path=route, endpoint=func, methods=method) + app.include_router(my_router) + return func(*args, **kwargs) + return wrapper + return decorator + +@fast_api_decorator(route="/power/", method=["GET"]) def power_function(x: str, a: str): return {f"{x} to the power of {a}": int(x)**int(a)} -route_path = '/power_function/{x}/{a}' -my_router.add_api_route(route_path, endpoint=power_function) -app.include_router(my_router) - -""" - +@fast_api_decorator(route="/add/", method=["GET"]) +def add_function(x: str, a: str): + return {f"{x} + {a} equals": int(x) + int(a)} -def fast_api_decorator(func): - def wrapper(x, a): - my_router.add_api_route(path='/{func}/{x}/{a}', endpoint=func) - app.include_router(my_router) - return wrapper - -@fast_api_decorator -def power_function(x: str, a: str): - return {f"{x} to the power of {a}": int(x)**int(a)} +@fast_api_decorator(route="/sous/", method=["POST"]) +def sous_function(x: str, a: str, b: str): + return {f"{x} - {a} - {b} equals": int(x) - int(a) - int(b)} -power_function(x=0, a=0) +# On "lance" les fonctions pour qu'elles soient lisibles par l'app FastAPI +power_function(x="0", a="0") +add_function(x="0", a="0") +sous_function(x="0", a="0", b="0") diff --git a/main.py b/main.py index 360823d..79dc920 100644 --- a/main.py +++ b/main.py @@ -19,15 +19,26 @@ # Use command : "python -m uvicorn main:app --reload" to lauch server and be able to request the "app" API. -from app import app, my_router, power_function +from app import app, power_function, add_function, sous_function import requests def power(x, a): - print(requests.get(f"http://127.0.0.1:8000/power_function/{x}/{a}").json()) + print(requests.get(f"http://127.0.0.1:8000/power/?x={x}&a={a}").json()) + + +def add(x, a): + print(requests.get(f"http://127.0.0.1:8000/add/?x={x}&a={a}").json()) + + +def sous(x, a, b): + print(requests.post(f"http://127.0.0.1:8000/sous/?x={x}&a={a}&b={b}").json()) if __name__ == "__main__": - power(x="9", a="2") - # power_function(x="9", a="2") - # print(requests.get("http://127.0.0.1:8000/power_function/10/2").json()) + power(x=9, a=2) + add(x=9, a=2) + sous(x=9, a=2, b=1) + print(power_function(x="9", a="2")) + print(add_function(x="9", a="2")) + print(sous_function(x="9", a="2", b="1")) From 3436c5b3591516eda47ce0cd3c0d30ce4f544264 Mon Sep 17 00:00:00 2001 From: Spydie78 <61595590+Spydie78@users.noreply.github.com> Date: Wed, 1 Nov 2023 19:21:30 +0100 Subject: [PATCH 07/11] Update README.md --- README.md | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1edc188..43b978f 100644 --- a/README.md +++ b/README.md @@ -1 +1,45 @@ -# Python_OOP_Project \ No newline at end of file +# Python_OOP_Project + +**FastApiDecoratorBuilder** + +"FastApiDecoratorBuilder" est un algorithme permettant de concevoir un décorateur Python qui transforme une fonction Python en une API FastAPI. + +**Installation** + +1. Télécharger les fichiers Python +2. Installer l'application FastAPI + pip install fastapi +3. Installer le serveur ASGI + pip install "uvicorn[standard]" +4. Lancer le serveur dans le terminal de l'application Python + python -m uvicorn main:app --reload +5. Le serveur API démarrera et sera accessible à http://127.0.0.1:8000. + +**Utilisation** +Pour utiliser les 3 fonctions comprisent dans l'API, il suffit d'entrer les points de terminaison suivants après le lien http://127.0.0.1:8000 + +1. Power + Description : Calcul de la puissance d'un nombre + Paramètres : + - 'x': Nombre (integer) + - 'a': La puissance (integer) + Exemple : '/power/?x=2&a=3' retournera le résultat de 2 à la puissance 3 + +2. Add + Description : Calcul l'addition de deux nombres + Paramètres : + - 'x': Nombre (integer) + - 'a': Nombre (integer) + Exemple : '/add/?x=2&a=3' retournera la somme de 2 et 3 + +3. Sous + Description : Calcul la soustraction de trois nombres + Paramètres : + - 'x': Nombre à soustraire(integer) + - 'a': Nombre (integer) + - 'b': Nombre (integer) + Exemple : '/sous/?x=10&a=3&b=2' pour soustraire 3 et 2 à 10 + + + + From a3e405f15686cbcb5e9a6be444778a28283f5629 Mon Sep 17 00:00:00 2001 From: Spydie78 <61595590+Spydie78@users.noreply.github.com> Date: Wed, 1 Nov 2023 19:22:44 +0100 Subject: [PATCH 08/11] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 43b978f..81d1d19 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ Pour utiliser les 3 fonctions comprisent dans l'API, il suffit d'entrer les poin Paramètres : - 'x': Nombre (integer) - 'a': La puissance (integer) + Exemple : '/power/?x=2&a=3' retournera le résultat de 2 à la puissance 3 2. Add @@ -30,6 +31,7 @@ Pour utiliser les 3 fonctions comprisent dans l'API, il suffit d'entrer les poin Paramètres : - 'x': Nombre (integer) - 'a': Nombre (integer) + Exemple : '/add/?x=2&a=3' retournera la somme de 2 et 3 3. Sous @@ -38,6 +40,7 @@ Pour utiliser les 3 fonctions comprisent dans l'API, il suffit d'entrer les poin - 'x': Nombre à soustraire(integer) - 'a': Nombre (integer) - 'b': Nombre (integer) + Exemple : '/sous/?x=10&a=3&b=2' pour soustraire 3 et 2 à 10 From fb9a9f6f7b3253e130adf415d065014c62d7ad37 Mon Sep 17 00:00:00 2001 From: Spydie78 <61595590+Spydie78@users.noreply.github.com> Date: Wed, 1 Nov 2023 19:45:26 +0100 Subject: [PATCH 09/11] Update README.md --- README.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 81d1d19..d53b588 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,24 @@ -# Python_OOP_Project - -**FastApiDecoratorBuilder** +# FastApiDecoratorBuilder "FastApiDecoratorBuilder" est un algorithme permettant de concevoir un décorateur Python qui transforme une fonction Python en une API FastAPI. -**Installation** +## Installation 1. Télécharger les fichiers Python 2. Installer l'application FastAPI - pip install fastapi + $ pip install fastapi 3. Installer le serveur ASGI - pip install "uvicorn[standard]" + $ pip install "uvicorn[standard]" 4. Lancer le serveur dans le terminal de l'application Python - python -m uvicorn main:app --reload + $ python -m uvicorn main:app --reload 5. Le serveur API démarrera et sera accessible à http://127.0.0.1:8000. -**Utilisation** -Pour utiliser les 3 fonctions comprisent dans l'API, il suffit d'entrer les points de terminaison suivants après le lien http://127.0.0.1:8000 +## Utilisation +Le décorateur 'Fast_api_decorator' ajoute une route avec un endpoint correspondant aux paramètres de la requête (paramètres de la fonction). Le décorateur appliqué à une fonction puis "lancée" sur le même script de l'instance FastAPI (app) permet de requêter l'API avec une route qui dépend de la fonction et de ses paramètres. +L'API est configurée directement grâce aux paramètres du décorateur avec les routes ("/power/", "/Add/" et "/Sous/") et les méthode HTTP ("GET" et "Post"). + +## Test +Dans le code suivant, il y a trois fonctions qui ont été implémenté dans l'API. Il suffit d'entrer les points de terminaison suivants après le lien 'http://127.0.0.1:8000'. 1. Power Description : Calcul de la puissance d'un nombre From fa6c6c7f4671c995686117fcef699335e336ba81 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Wed, 1 Nov 2023 19:49:15 +0100 Subject: [PATCH 10/11] readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d53b588..001a724 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ 5. Le serveur API démarrera et sera accessible à http://127.0.0.1:8000. ## Utilisation -Le décorateur 'Fast_api_decorator' ajoute une route avec un endpoint correspondant aux paramètres de la requête (paramètres de la fonction). Le décorateur appliqué à une fonction puis "lancée" sur le même script de l'instance FastAPI (app) permet de requêter l'API avec une route qui dépend de la fonction et de ses paramètres. -L'API est configurée directement grâce aux paramètres du décorateur avec les routes ("/power/", "/Add/" et "/Sous/") et les méthode HTTP ("GET" et "Post"). +Le décorateur 'fast_api_decorator' ajoute une route avec un endpoint correspondant aux paramètres de la requête (paramètres de la fonction). Le décorateur appliqué à une fonction puis "lancée" sur le même script de l'instance FastAPI (app) permet de requêter l'API avec une route qui dépend de la fonction et de ses propres paramètres. +L'API est configurée directement grâce aux paramètres du décorateur avec les routes ("/power/", "/add/" et "/sous/") et les méthodes HTTP ("GET", "POST", "PUT", "DELETE"). ## Test Dans le code suivant, il y a trois fonctions qui ont été implémenté dans l'API. Il suffit d'entrer les points de terminaison suivants après le lien 'http://127.0.0.1:8000'. From 6b79daaf5aa9d204b031a1080c0d455c81ee7d1a Mon Sep 17 00:00:00 2001 From: Matthieu Date: Fri, 10 Nov 2023 12:15:06 +0100 Subject: [PATCH 11/11] change struct --- app.py | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/app.py b/app.py index 5356f99..d201419 100644 --- a/app.py +++ b/app.py @@ -1,5 +1,6 @@ from fastapi import FastAPI, APIRouter + my_router = APIRouter() app = FastAPI() @@ -24,12 +25,45 @@ def add_function(x: str, a: str): return {f"{x} + {a} equals": int(x) + int(a)} -@fast_api_decorator(route="/sous/", method=["POST"]) -def sous_function(x: str, a: str, b: str): - return {f"{x} - {a} - {b} equals": int(x) - int(a) - int(b)} +@fast_api_decorator(route="/sous/", method=["GET"]) +def sous_function(x: str, lst): + return {f"{x} - {lst[0]} - {lst[1]} equals": int(x) - int(lst[0]) - int(lst[1])} # On "lance" les fonctions pour qu'elles soient lisibles par l'app FastAPI power_function(x="0", a="0") add_function(x="0", a="0") -sous_function(x="0", a="0", b="0") +sous_function(x="0", lst=[0, 0]) + +# résolution pb de lancement des fonctions +""" +from fastapi import FastAPI, APIRouter + +app = FastAPI() + +class PowerEndpoint: + router = APIRouter() + + @router.get("/power/") + async def power_function(self, x: str, a: str): + return {f"{x} to the power of {a}": int(x)**int(a)} + +class AddEndpoint: + router = APIRouter() + + @router.get("/add/") + async def add_function(self, x: str, a: str): + return {f"{x} + {a} equals": int(x) + int(a)} + +class SousEndpoint: + router = APIRouter() + + @router.get("/sous/") + async def sous_function(self, x: str, lst): + return {f"{x} - {lst[0]} - {lst[1]} equals": int(x) - int(lst[0]) - int(lst[1])} + +# Including the routers directly in the main app +app.include_router(PowerEndpoint.router, tags=["power"]) +app.include_router(AddEndpoint.router, tags=["add"]) +app.include_router(SousEndpoint.router, tags=["sous"]) +""" \ No newline at end of file