Skip to content

Commit

Permalink
Added better types to routes and helper functions
Browse files Browse the repository at this point in the history
  • Loading branch information
StefanVDWeide committed May 1, 2023
1 parent 5243290 commit 9d57fcf
Show file tree
Hide file tree
Showing 11 changed files with 69 additions and 60 deletions.
25 changes: 13 additions & 12 deletions app/auth/routes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from flask import request, jsonify
from flask import Response, request, jsonify

from app import db, jwt
from app.auth import bp
Expand All @@ -23,7 +23,8 @@
@jwt.token_in_blocklist_loader
def check_if_token_in_blacklist(jwt_header, jwt_data) -> bool:
"""
Helper function for checking if a token is present in the database revoked token table
Helper function for checking if a token is present in the database
revoked token table
Parameters
----------
Expand All @@ -42,7 +43,7 @@ def check_if_token_in_blacklist(jwt_header, jwt_data) -> bool:


@bp.post("/register")
def register() -> str:
def register() -> tuple[Response, int] | Response:
"""
Endpoint for adding a new user to the database
Expand All @@ -52,7 +53,7 @@ def register() -> str:
A JSON object containing the success message
"""
try:
result = user_schema.load(request.json)
result = user_schema.load(request.get_json())

except ValidationError as e:
return bad_request(e.messages)
Expand All @@ -63,7 +64,7 @@ def register() -> str:
if Users.query.filter_by(email=result["email"]).first():
return bad_request("Email already in use")

user = Users(
user: Users = Users(
username=result["username"],
first_name=result["first_name"],
last_name=result["last_name"],
Expand All @@ -80,7 +81,7 @@ def register() -> str:


@bp.post("/login")
def login() -> str:
def login() -> tuple[Response, int] | Response:
"""
Endpoint for authorizing a user and retrieving a JWT
Expand All @@ -90,7 +91,7 @@ def login() -> str:
A JSON object containing both the access JWT and the refresh JWT
"""
try:
result = user_schema.load(request.json)
result = user_schema.load(request.get_json())

except ValidationError as e:
return bad_request(e.messages)
Expand All @@ -110,7 +111,7 @@ def login() -> str:

@bp.post("/refresh")
@jwt_required(refresh=True)
def refresh() -> str:
def refresh() -> tuple[Response, int]:
"""
Endpoint in order to retrieve a new access JWT using the refresh JWT.
A non-fresh access token is returned because the password is not involved in this transaction
Expand All @@ -128,7 +129,7 @@ def refresh() -> str:


@bp.post("/fresh-login")
def fresh_login() -> str:
def fresh_login() -> tuple[Response, int] | Response:
"""
Endpoint for requesting a new fresh access token
Expand All @@ -138,7 +139,7 @@ def fresh_login() -> str:
A JSON object containing
"""
try:
result = user_schema.load(request.json)
result = user_schema.load(request.get_json())

except ValidationError as e:
return bad_request(e.messages)
Expand All @@ -156,7 +157,7 @@ def fresh_login() -> str:

@bp.delete("/logout/token")
@jwt_required()
def logout_access_token() -> str:
def logout_access_token() -> tuple[Response, int]:
"""
Endpoint for revoking the current user"s access token
Expand All @@ -174,7 +175,7 @@ def logout_access_token() -> str:

@bp.delete("/logout/fresh")
@jwt_required(refresh=True)
def logout_refresh_token() -> str:
def logout_refresh_token() -> tuple[Response, int]:
"""
Endpoint for revoking the current user"s refresh token
Expand Down
13 changes: 7 additions & 6 deletions app/comments/routes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from flask import request, jsonify
from typing import Any
from flask import request, jsonify, Response

from app import db
from app.comments import bp
Expand All @@ -20,7 +21,7 @@

@bp.get("/get/user/comments/post/<int:id>")
@jwt_required()
def get_comments_by_post_id(id: int) -> str:
def get_comments_by_post_id(id: int) -> Response:
"""
Endpoint for retrieving the user comments associated with a particular post
Expand All @@ -40,7 +41,7 @@ def get_comments_by_post_id(id: int) -> str:

@bp.post("/post/user/submit/comment")
@jwt_required()
def submit_comment() -> str:
def submit_comment() -> tuple[Response, int] | Response:
"""
Lets users submit a comment regarding a post
Expand All @@ -50,7 +51,7 @@ def submit_comment() -> str:
A JSON object containing a success message
"""
try:
result = comment_deserializing_schema.load(request.json)
result = comment_deserializing_schema.load(request.get_json())
except ValidationError as e:
return bad_request(e.messages)

Expand All @@ -72,7 +73,7 @@ def submit_comment() -> str:

@bp.delete("/delete/user/comment/<int:id>")
@jwt_required()
def delete_comment(id: int) -> str:
def delete_comment(id: int) -> tuple[Response, int] | Response:
"""
Lets users delete one of their own comments
Expand Down Expand Up @@ -102,7 +103,7 @@ def delete_comment(id: int) -> str:

@bp.get("/get/user/comments/async")
@jwt_required()
async def async_comments_api_call() -> str:
async def async_comments_api_call() -> dict[str, list[Any]]:
"""
Calls two endpoints from an external API as async demo
Expand Down
6 changes: 3 additions & 3 deletions app/errors/handlers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from flask import jsonify
from flask import Response, jsonify
from werkzeug.http import HTTP_STATUS_CODES


def error_response(status_code: int, message=None) -> str:
def error_response(status_code: int, message=None) -> Response:
"""
A catch all function which returns the error code and message back to the user
Expand All @@ -29,7 +29,7 @@ def error_response(status_code: int, message=None) -> str:
return response


def bad_request(message: str) -> str:
def bad_request(message: str) -> Response:
"""
Returns a 400 error code when a bad request has been made
Expand Down
1 change: 1 addition & 0 deletions app/helpers/task_helpers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from rq import get_current_job

from app import db
from app.models import Tasks

Expand Down
2 changes: 1 addition & 1 deletion app/helpers/test_helpers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
def register_and_login_test_user(c):
def register_and_login_test_user(c) -> str:
"""
Helper function that makes an HTTP request to register a test user
Expand Down
6 changes: 4 additions & 2 deletions app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
@jwt.user_lookup_loader
def user_loader_callback(jwt_header: dict, jwt_data: dict) -> object:
"""
HUser loader function which uses the JWT identity to retrieve a user object. Method is called on protected routes
HUser loader function which uses the JWT identity to retrieve a user object.
Method is called on protected routes
Parameters
----------
Expand Down Expand Up @@ -53,7 +54,8 @@ def set_password(self, password: str):

def check_password(self, password: str) -> bool:
"""
Helper function to verify the password hash agains the password provided by the user when logging in
Helper function to verify the password hash agains the password provided
by the user when logging in
Parameters
----------
Expand Down
14 changes: 7 additions & 7 deletions app/posts/routes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from flask import request, jsonify
from flask import request, jsonify, Response

from app import db
from app.posts import bp
Expand All @@ -20,7 +20,7 @@

@bp.get("get/user/posts")
@jwt_required()
def get_posts() -> str:
def get_posts() -> tuple[Response, int]:
"""
Returns all posts submitted by the user making the request
Expand All @@ -36,7 +36,7 @@ def get_posts() -> str:

@bp.get("/get/user/post/<int:id>")
@jwt_required()
def get_post_by_id(id: int) -> str:
def get_post_by_id(id: int) -> tuple[Response, int] | Response:
"""
Returns a specific post based on the ID in the URL
Expand All @@ -60,7 +60,7 @@ def get_post_by_id(id: int) -> str:

@bp.post("/post/user/submit/post")
@jwt_required()
def submit_post() -> str:
def submit_post() -> tuple[Response, int] | Response:
"""
Lets users retrieve a user profile when logged in
Expand All @@ -72,7 +72,7 @@ def submit_post() -> str:
try:
result = post_schema.load(request.json)
except ValidationError as e:
return bad_request(e.messages)
return bad_request(e.messages[0])

post = Posts(body=result["body"], user=current_user)

Expand All @@ -84,7 +84,7 @@ def submit_post() -> str:

@bp.delete("/delete/user/post/<int:id>")
@jwt_required()
def delete_post(id: int) -> str:
def delete_post(id: int) -> tuple[Response, int] | Response:
"""
Lets users retrieve a user profile when logged in
Expand Down Expand Up @@ -114,7 +114,7 @@ def delete_post(id: int) -> str:

@bp.get("/get/user/posts/async")
@jwt_required()
async def async_posts_api_call() -> str:
async def async_posts_api_call() -> tuple[dict, int]:
"""
Calls two endpoints from an external API as async demo
Expand Down
20 changes: 12 additions & 8 deletions app/tasks/long_running_jobs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import sys
from datetime import time

from app import create_app
from app.helpers.task_helpers import _set_task_progress
import sys

# Create the app in order to operate within the context of the app
app = create_app()
Expand All @@ -13,16 +14,19 @@ def count_seconds(**kwargs: int) -> None:
"""
with app.app_context():
try:
number = kwargs.get("number")
_set_task_progress(0)
number: int | None = kwargs.get("number")

if number:
_set_task_progress(0)

i = 0
i = 0

for i in range(0, number):
i += 1
time.sleep(1)
_set_task_progress(100 * i // number)
for i in range(0, number):
i += 1
time.sleep(1)
_set_task_progress(100 * i // number)

# TODO: Make this a specific except type, no bare except
except:
app.logger.error("Unhandled exception", exc_info=sys.exc_info())

Expand Down
17 changes: 7 additions & 10 deletions app/tasks/routes.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
from app.errors.handlers import bad_request
from re import T
from flask import jsonify
from flask import Response, jsonify
from flask_jwt_extended import current_user, jwt_required

from app import db
from app.tasks import bp
from app.errors.handlers import bad_request
from app.schemas import TasksSchema

from flask_jwt_extended import jwt_required, current_user

from app.tasks import bp

tasks_schema = TasksSchema(many=True)


@bp.get("/background-task/count-seconds/<int:number>")
@jwt_required()
def background_worker_count_seconds(number: int) -> str:
def background_worker_count_seconds(number: int) -> tuple[Response, int] | Response:
"""
Spawn a background task via RQ to perform a long running task
Expand All @@ -40,7 +37,7 @@ def background_worker_count_seconds(number: int) -> str:

@bp.get("/get/active-background-tasks")
@jwt_required()
def active_background_tasks() -> str:
def active_background_tasks() -> tuple[Response, int] | str:
"""
Endpoint to retrieve all the active background tasks
Expand All @@ -55,7 +52,7 @@ def active_background_tasks() -> str:

@bp.get("/get/finished-background-tasks")
@jwt_required()
def finished_background_tasks() -> str:
def finished_background_tasks() -> tuple[Response, int] | str:
"""
Endpoint to retrieve the finished background tasks
Expand Down
13 changes: 7 additions & 6 deletions app/users/routes.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from app.users import bp
from flask import Response
from flask_jwt_extended import current_user, jwt_required

from app.errors.handlers import bad_request
from app.models import Users
from app.schemas import UsersSchema
from app.errors.handlers import bad_request
from flask_jwt_extended import jwt_required, current_user

from app.users import bp

# Declare database schemas so they can be returned as JSON objects
user_schema = UsersSchema(exclude=("email", "password_hash"))
Expand All @@ -12,7 +13,7 @@

@bp.get("/get/user/profile")
@jwt_required()
def user_page() -> str:
def user_page() -> tuple[Response, int] | str:
"""
Let's users retrieve their own user information when logged in
Expand All @@ -26,7 +27,7 @@ def user_page() -> str:

@bp.get("/get/user/profile/<string:username>")
@jwt_required()
def get_user(username: str) -> str:
def get_user(username: str) -> tuple[Response, int] | Response:
"""
Lets users retrieve a user profile when logged in
Expand Down
Loading

0 comments on commit 9d57fcf

Please sign in to comment.