Skip to content

Commit

Permalink
chore: Improve type hints
Browse files Browse the repository at this point in the history
  • Loading branch information
TomBursch committed Oct 21, 2024
1 parent 72910d5 commit 8ee107d
Show file tree
Hide file tree
Showing 25 changed files with 301 additions and 274 deletions.
16 changes: 8 additions & 8 deletions backend/app/controller/shoppinglist/shoppinglist_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def deleteShoppinglist(id):
@shoppinglist.route("/<int:id>/item/<int:item_id>", methods=["POST", "PUT"])
@jwt_required()
@validate_args(UpdateDescription)
def updateItemDescription(args, id, item_id):
def updateItemDescription(args, id: int, item_id: int):
con = ShoppinglistItems.find_by_ids(id, item_id)
if not con:
shoppinglist = Shoppinglist.find_by_id(id)
Expand Down Expand Up @@ -305,13 +305,13 @@ def addShoppinglistItemByName(args, id):
@shoppinglist.route("/<int:id>/item", methods=["DELETE"])
@jwt_required()
@validate_args(RemoveItem)
def removeShoppinglistItem(args, id):
def removeShoppinglistItem(args, id: int):
shoppinglist = Shoppinglist.find_by_id(id)
if not shoppinglist:
raise NotFoundRequest()
shoppinglist.checkAuthorized()

con = removeShoppinglistItem(
con = removeShoppinglistItemFunc(
shoppinglist,
args["item_id"],
args["removed_at"] if "removed_at" in args else None,
Expand All @@ -332,14 +332,14 @@ def removeShoppinglistItem(args, id):
@shoppinglist.route("/<int:id>/items", methods=["DELETE"])
@jwt_required()
@validate_args(RemoveItems)
def removeShoppinglistItems(args, id):
def removeShoppinglistItems(args, id: int):
shoppinglist = Shoppinglist.find_by_id(id)
if not shoppinglist:
raise NotFoundRequest()
shoppinglist.checkAuthorized()

for arg in args["items"]:
con = removeShoppinglistItem(
con = removeShoppinglistItemFunc(
shoppinglist,
arg["item_id"],
arg["removed_at"] if "removed_at" in arg else None,
Expand All @@ -357,9 +357,9 @@ def removeShoppinglistItems(args, id):
return jsonify({"msg": "DONE"})


def removeShoppinglistItem(
shoppinglist: Shoppinglist, item_id: int, removed_at: int = None
) -> ShoppinglistItems:
def removeShoppinglistItemFunc(
shoppinglist: Shoppinglist, item_id: int, removed_at: int | None = None
) -> ShoppinglistItems | None:
item = Item.find_by_id(item_id)
if not item:
return None
Expand Down
2 changes: 1 addition & 1 deletion backend/app/helpers/db_list_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def process_bind_param(self, value, dialect):
else:
return "[]"

def process_result_value(self, value, dialect) -> set:
def process_result_value(self, value, dialect) -> list:
if type(value) is str:
return json.loads(value)
return list()
4 changes: 2 additions & 2 deletions backend/app/helpers/db_model_mixin.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from __future__ import annotations
from typing import Self
from app import db
from app.helpers.timestamp_mixin import TimestampMixin


class DbModelMixin(object):
class DbModelMixin(TimestampMixin):
def save(self) -> Self:
"""
Persist changes to current instance in db
Expand Down
14 changes: 10 additions & 4 deletions backend/app/helpers/timestamp_mixin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from datetime import datetime, timezone
from sqlalchemy import Column, DateTime
from sqlalchemy import DateTime
from sqlalchemy.orm import Mapped, mapped_column


class TimestampMixin(object):
Expand All @@ -8,11 +9,16 @@ class TimestampMixin(object):
"""

#: Timestamp for when this instance was created in UTC
created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), nullable=False)
created_at: Mapped[datetime] = mapped_column(
DateTime, default=lambda: datetime.now(timezone.utc), nullable=False
)

#: Timestamp for when this instance was last updated in UTC
updated_at = Column(
DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc), nullable=False
updated_at: Mapped[datetime] = mapped_column(
DateTime,
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
nullable=False,
)

created_at._creation_order = 9998
Expand Down
3 changes: 2 additions & 1 deletion backend/app/helpers/validate_args.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from marshmallow import Schema
from marshmallow.exceptions import ValidationError
from app.errors import InvalidUsage
from flask import request
from functools import wraps


def validate_args(schema_cls):
def validate_args(schema_cls: type[Schema]):
def validate(func):
@wraps(func)
def func_wrapper(*args, **kwargs):
Expand Down
21 changes: 11 additions & 10 deletions backend/app/models/association.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
from typing import Self
from app import db
from app.helpers import DbModelMixin, TimestampMixin
from app.helpers import DbModelMixin
from sqlalchemy.orm import Mapped


class Association(db.Model, DbModelMixin, TimestampMixin):
class Association(db.Model , DbModelMixin):
__tablename__ = "association"

id = db.Column(db.Integer, primary_key=True)
id: Mapped[int] = db.Column(db.Integer, primary_key=True)

antecedent_id = db.Column(db.Integer, db.ForeignKey("item.id"))
consequent_id = db.Column(db.Integer, db.ForeignKey("item.id"))
support = db.Column(db.Float)
confidence = db.Column(db.Float)
lift = db.Column(db.Float)
antecedent_id: Mapped[int] = db.Column(db.Integer, db.ForeignKey("item.id"))
consequent_id: Mapped[int] = db.Column(db.Integer, db.ForeignKey("item.id"))
support: Mapped[float] = db.Column(db.Float)
confidence: Mapped[float] = db.Column(db.Float)
lift: Mapped[float] = db.Column(db.Float)

antecedent = db.relationship(
antecedent: Mapped["Item"] = db.relationship(
"Item",
uselist=False,
foreign_keys=[antecedent_id],
back_populates="antecedents",
)
consequent = db.relationship(
consequent: Mapped["Item"] = db.relationship(
"Item",
uselist=False,
foreign_keys=[consequent_id],
Expand Down
23 changes: 12 additions & 11 deletions backend/app/models/category.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
from __future__ import annotations
from typing import Self
from typing import Self, List
from app import db
from app.helpers import DbModelMixin, TimestampMixin, DbModelAuthorizeMixin
from app.helpers import DbModelMixin, DbModelAuthorizeMixin
from sqlalchemy.orm import Mapped


class Category(db.Model, DbModelMixin, TimestampMixin, DbModelAuthorizeMixin):
class Category(db.Model , DbModelMixin, DbModelAuthorizeMixin):
__tablename__ = "category"

id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128))
default = db.Column(db.Boolean, default=False)
default_key = db.Column(db.String(128))
ordering = db.Column(db.Integer, default=0)
household_id = db.Column(
id: Mapped[int] = db.Column(db.Integer, primary_key=True)
name: Mapped[str] = db.Column(db.String(128))
default: Mapped[bool] = db.Column(db.Boolean, default=False)
default_key: Mapped[str] = db.Column(db.String(128))
ordering: Mapped[int] = db.Column(db.Integer, default=0)
household_id: Mapped[int] = db.Column(
db.Integer, db.ForeignKey("household.id"), nullable=False, index=True
)

household = db.relationship("Household", uselist=False)
items = db.relationship("Item", back_populates="category")
household: Mapped["Household"] = db.relationship("Household", uselist=False)
items: Mapped[List["Item"]] = db.relationship("Item", back_populates="category")

def obj_to_full_dict(self) -> dict:
res = super().obj_to_dict()
Expand Down
11 changes: 6 additions & 5 deletions backend/app/models/challenge_mail_verify.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
from typing import Self
import uuid
from app import db
from app.helpers import DbModelMixin, TimestampMixin
from app.helpers import DbModelMixin
from app.models.user import User
from sqlalchemy.orm import Mapped


class ChallengeMailVerify(db.Model, DbModelMixin, TimestampMixin):
challenge_hash = db.Column(db.String(256), primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
class ChallengeMailVerify(db.Model , DbModelMixin):
challenge_hash: Mapped[str] = db.Column(db.String(256), primary_key=True)
user_id: Mapped[int] = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)

user = db.relationship("User")
user: Mapped["User"] = db.relationship("User")

@classmethod
def find_by_challenge(cls, challenge: str) -> Self:
Expand Down
11 changes: 6 additions & 5 deletions backend/app/models/challenge_password_reset.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@
from typing import Self
import uuid
from app import db
from app.helpers import DbModelMixin, TimestampMixin
from app.helpers import DbModelMixin
from app.models.user import User
from sqlalchemy.orm import Mapped


class ChallengePasswordReset(db.Model, DbModelMixin, TimestampMixin):
challenge_hash = db.Column(db.String(256), primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
class ChallengePasswordReset(db.Model , DbModelMixin):
challenge_hash: Mapped[str] = db.Column(db.String(256), primary_key=True)
user_id: Mapped[int] = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)

user = db.relationship("User")
user: Mapped["User"] = db.relationship("User")

@classmethod
def find_by_challenge(cls, challenge: str) -> Self:
Expand Down
45 changes: 23 additions & 22 deletions backend/app/models/expense.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
from datetime import datetime
from typing import Self
from typing import Self, List
from app import db
from app.helpers import DbModelMixin, TimestampMixin, DbModelAuthorizeMixin
from app.helpers import DbModelMixin, DbModelAuthorizeMixin
from sqlalchemy.orm import Mapped


class Expense(db.Model, DbModelMixin, TimestampMixin, DbModelAuthorizeMixin):
class Expense(db.Model , DbModelMixin, DbModelAuthorizeMixin):
__tablename__ = "expense"

id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128))
amount = db.Column(db.Float())
date = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
category_id = db.Column(db.Integer, db.ForeignKey("expense_category.id"))
photo = db.Column(db.String(), db.ForeignKey("file.filename"))
paid_by_id = db.Column(db.Integer, db.ForeignKey("user.id"))
household_id = db.Column(
id: Mapped[int] = db.Column(db.Integer, primary_key=True)
name: Mapped[str] = db.Column(db.String(128))
amount: Mapped[float] = db.Column(db.Float())
date: Mapped[datetime] = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
category_id: Mapped[int] = db.Column(db.Integer, db.ForeignKey("expense_category.id"))
photo: Mapped[str] = db.Column(db.String(), db.ForeignKey("file.filename"))
paid_by_id: Mapped[int] = db.Column(db.Integer, db.ForeignKey("user.id"))
household_id: Mapped[int] = db.Column(
db.Integer, db.ForeignKey("household.id"), nullable=False, index=True
)
exclude_from_statistics = db.Column(db.Boolean, default=False, nullable=False)

household = db.relationship("Household", uselist=False)
category = db.relationship("ExpenseCategory")
paid_by = db.relationship("User")
paid_for = db.relationship(
household: Mapped["Household"] = db.relationship("Household", uselist=False)
category: Mapped["ExpenseCategory"] = db.relationship("ExpenseCategory")
paid_by: Mapped["User"] = db.relationship("User")
paid_for: Mapped[List["Household"]] = db.relationship(
"ExpensePaidFor", back_populates="expense", cascade="all, delete-orphan"
)
photo_file = db.relationship("File", back_populates="expense", uselist=False)
photo_file: Mapped["File"] = db.relationship("File", back_populates="expense", uselist=False)

def obj_to_dict(self) -> dict:
res = super().obj_to_dict()
Expand Down Expand Up @@ -72,15 +73,15 @@ def find_by_id(cls, id) -> Self:
)


class ExpensePaidFor(db.Model, DbModelMixin, TimestampMixin):
class ExpensePaidFor(db.Model , DbModelMixin):
__tablename__ = "expense_paid_for"

expense_id = db.Column(db.Integer, db.ForeignKey("expense.id"), primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"), primary_key=True)
factor = db.Column(db.Integer())
expense_id: Mapped[int] = db.Column(db.Integer, db.ForeignKey("expense.id"), primary_key=True)
user_id: Mapped[int] = db.Column(db.Integer, db.ForeignKey("user.id"), primary_key=True)
factor: Mapped[int] = db.Column(db.Integer())

expense = db.relationship("Expense", back_populates="paid_for")
user = db.relationship("User", back_populates="expenses_paid_for")
expense: Mapped["Expense"] = db.relationship("Expense", back_populates="paid_for")
user: Mapped["User"] = db.relationship("User", back_populates="expenses_paid_for")

def obj_to_user_dict(self):
res = self.user.obj_to_dict()
Expand Down
19 changes: 10 additions & 9 deletions backend/app/models/expense_category.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
from __future__ import annotations
from typing import Self
from typing import Self, List
from app import db
from app.helpers import DbModelMixin, TimestampMixin, DbModelAuthorizeMixin
from app.helpers import DbModelMixin, DbModelAuthorizeMixin
from sqlalchemy.orm import Mapped


class ExpenseCategory(db.Model, DbModelMixin, TimestampMixin, DbModelAuthorizeMixin):
class ExpenseCategory(db.Model , DbModelMixin, DbModelAuthorizeMixin):
__tablename__ = "expense_category"

id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128))
color = db.Column(db.BigInteger)
household_id = db.Column(db.Integer, db.ForeignKey("household.id"), nullable=False)
id: Mapped[int] = db.Column(db.Integer, primary_key=True)
name: Mapped[str] = db.Column(db.String(128))
color: Mapped[int] = db.Column(db.BigInteger)
household_id: Mapped[int] = db.Column(db.Integer, db.ForeignKey("household.id"), nullable=False)

household = db.relationship("Household", uselist=False)
expenses = db.relationship("Expense", back_populates="category")
household: Mapped["Household"] = db.relationship("Household", uselist=False)
expenses: Mapped[List["Household"]] = db.relationship("Expense", back_populates="category")

def obj_to_full_dict(self) -> dict:
res = super().obj_to_dict()
Expand Down
21 changes: 11 additions & 10 deletions backend/app/models/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,25 @@
from app import db
from app.config import UPLOAD_FOLDER
from app.errors import ForbiddenRequest
from app.helpers import DbModelMixin, TimestampMixin, DbModelAuthorizeMixin
from app.helpers import DbModelMixin, DbModelAuthorizeMixin
from app.models.user import User
import os
from sqlalchemy.orm import Mapped


class File(db.Model, DbModelMixin, TimestampMixin, DbModelAuthorizeMixin):
class File(db.Model , DbModelMixin, DbModelAuthorizeMixin):
__tablename__ = "file"

filename = db.Column(db.String(), primary_key=True)
blur_hash = db.Column(db.String(length=40), nullable=True)
created_by = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=True)
filename: Mapped[str] = db.Column(db.String(), primary_key=True)
blur_hash: Mapped[str] = db.Column(db.String(length=40), nullable=True)
created_by: Mapped[int] = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=True)

created_by_user = db.relationship("User", foreign_keys=[created_by], uselist=False)
created_by_user: Mapped["User"] = db.relationship("User", foreign_keys=[created_by], uselist=False)

household = db.relationship("Household", uselist=False)
recipe = db.relationship("Recipe", uselist=False)
expense = db.relationship("Expense", uselist=False)
profile_picture = db.relationship("User", foreign_keys=[User.photo], uselist=False)
household: Mapped["Household"] = db.relationship("Household", uselist=False)
recipe: Mapped["Recipe"] = db.relationship("Recipe", uselist=False)
expense: Mapped["Expense"] = db.relationship("Expense", uselist=False)
profile_picture: Mapped["User"] = db.relationship("User", foreign_keys=[User.photo], uselist=False)

def delete(self):
"""
Expand Down
Loading

0 comments on commit 8ee107d

Please sign in to comment.