From 5465dcac57cfeff2c34640561693acc0b9b102ae Mon Sep 17 00:00:00 2001 From: TriHard Date: Thu, 15 Feb 2024 06:17:23 -0700 Subject: [PATCH 1/7] Add type stub for Flask globals --- typings/flask/__init__.pyi | 65 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 typings/flask/__init__.pyi diff --git a/typings/flask/__init__.pyi b/typings/flask/__init__.pyi new file mode 100644 index 000000000..7f142f821 --- /dev/null +++ b/typings/flask/__init__.pyi @@ -0,0 +1,65 @@ +from files.classes.user import User +from flask.ctx import _AppCtxGlobals +from sqlalchemy.orm import Session +from sqlalchemy.schema import Column +import typing as t + +# According to PEP 484, "all objects imported into a stub using `from ... import *` are considered +# exported", but this didn't work with Pyright for some reason, so everything has to be exported +# manually. The alternative is to put `def __getattr__(name: str) -> t.Any: ...` here instead, but +# then any symbol not in this file will be treated as Any, which prevents it from being checked. +from flask import json as json +from flask.app import Flask as Flask +from flask.blueprints import Blueprint as Blueprint +from flask.config import Config as Config +from flask.ctx import after_this_request as after_this_request +from flask.ctx import copy_current_request_context as copy_current_request_context +from flask.ctx import has_app_context as has_app_context +from flask.ctx import has_request_context as has_request_context +from flask.globals import current_app as current_app +from flask.globals import request as request +from flask.globals import session as session +from flask.helpers import abort as abort +from flask.helpers import flash as flash +from flask.helpers import get_flashed_messages as get_flashed_messages +from flask.helpers import get_template_attribute as get_template_attribute +from flask.helpers import make_response as make_response +from flask.helpers import redirect as redirect +from flask.helpers import send_file as send_file +from flask.helpers import send_from_directory as send_from_directory +from flask.helpers import stream_with_context as stream_with_context +from flask.helpers import url_for as url_for +from flask.json import jsonify as jsonify +from flask.signals import appcontext_popped as appcontext_popped +from flask.signals import appcontext_pushed as appcontext_pushed +from flask.signals import appcontext_tearing_down as appcontext_tearing_down +from flask.signals import before_render_template as before_render_template +from flask.signals import got_request_exception as got_request_exception +from flask.signals import message_flashed as message_flashed +from flask.signals import request_finished as request_finished +from flask.signals import request_started as request_started +from flask.signals import request_tearing_down as request_tearing_down +from flask.signals import template_rendered as template_rendered +from flask.templating import render_template as render_template +from flask.templating import render_template_string as render_template_string +from flask.templating import stream_template as stream_template +from flask.templating import stream_template_string as stream_template_string +from flask.wrappers import Request as Request +from flask.wrappers import Response as Response + +class Globals(_AppCtxGlobals): + agent: str + browser: t.Literal["webview", "firefox", "iphone", "mac", "chromium"] + db: Session + desires_auth: bool + is_api_or_xhr: bool + is_tor: bool + loggedin_chat: int + loggedin_counter: int + loggedout_counter: int + nonce: str + show_nsfw: bool + username: Column[str] + v: User | None + +g: Globals -- 2.34.1 From ecd64e1999a02d4b39c6e583e902346a8f8ec39e Mon Sep 17 00:00:00 2001 From: TriHard Date: Thu, 15 Feb 2024 06:17:23 -0700 Subject: [PATCH 2/7] declarative_base -> DeclarativeBase --- files/classes/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/files/classes/__init__.py b/files/classes/__init__.py index 88f8ab9fc..94a356ec4 100644 --- a/files/classes/__init__.py +++ b/files/classes/__init__.py @@ -1,6 +1,7 @@ # load sqlalchemy's declarative base... -from sqlalchemy.ext.declarative import declarative_base -Base = declarative_base() +from sqlalchemy.orm import DeclarativeBase +class Base(DeclarativeBase): + pass # then load all of our classes :) from .alts import * -- 2.34.1 From 7b0632bdc7d260d0333c5670b67efe0bc6a1c418 Mon Sep 17 00:00:00 2001 From: TriHard Date: Thu, 15 Feb 2024 06:17:23 -0700 Subject: [PATCH 3/7] Column -> mapped_column --- files/classes/alts.py | 11 +- files/classes/award.py | 22 +-- files/classes/badges.py | 22 +-- files/classes/casino_game.py | 22 +-- files/classes/clients.py | 26 ++-- files/classes/comment.py | 82 +++++----- files/classes/domains.py | 8 +- files/classes/emoji.py | 19 +-- files/classes/follows.py | 10 +- files/classes/group.py | 13 +- files/classes/group_membership.py | 14 +- files/classes/hats.py | 26 ++-- files/classes/hole.py | 27 ++-- files/classes/hole_logs.py | 22 +-- files/classes/hole_relationship.py | 12 +- files/classes/ip_logs.py | 12 +- files/classes/lottery.py | 17 ++- files/classes/media.py | 13 +- files/classes/mod_logs.py | 20 +-- files/classes/notifications.py | 12 +- files/classes/orgy.py | 17 ++- files/classes/polls.py | 40 ++--- files/classes/post.py | 94 ++++++------ files/classes/push_subscriptions.py | 9 +- files/classes/reports.py | 20 +-- files/classes/saves.py | 16 +- files/classes/subscriptions.py | 10 +- files/classes/transactions.py | 14 +- files/classes/user.py | 226 ++++++++++++++-------------- files/classes/userblock.py | 10 +- files/classes/usermute.py | 10 +- files/classes/views.py | 12 +- files/classes/votes.py | 28 ++-- 33 files changed, 460 insertions(+), 456 deletions(-) diff --git a/files/classes/alts.py b/files/classes/alts.py index 2cff4b7c2..28f853d63 100644 --- a/files/classes/alts.py +++ b/files/classes/alts.py @@ -1,6 +1,7 @@ import time -from sqlalchemy import Column, ForeignKey +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -8,10 +9,10 @@ from files.classes import Base class Alt(Base): __tablename__ = "alts" - user1 = Column(Integer, ForeignKey("users.id"), primary_key=True) - user2 = Column(Integer, ForeignKey("users.id"), primary_key=True) - is_manual = Column(Boolean, default=False) - created_utc = Column(Integer) + user1: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + user2: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + is_manual: Mapped[bool] = mapped_column(default=False) + created_utc: Mapped[int] def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/award.py b/files/classes/award.py index c7538fadd..8f658226d 100644 --- a/files/classes/award.py +++ b/files/classes/award.py @@ -1,7 +1,7 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -12,15 +12,15 @@ from files.helpers.lazy import lazy class AwardRelationship(Base): __tablename__ = "award_relationships" - id = Column(Integer, primary_key=True) - user_id = Column(Integer, ForeignKey("users.id")) - post_id = Column(Integer, ForeignKey("posts.id")) - comment_id = Column(Integer, ForeignKey("comments.id")) - kind = Column(String) - awarded_utc = Column(Integer) - created_utc = Column(Integer) - price_paid = Column(Integer, default = 0) - note = Column(String) + id: Mapped[int] = mapped_column(primary_key=True) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + post_id: Mapped[int] = mapped_column(ForeignKey("posts.id")) + comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id")) + kind: Mapped[str] + awarded_utc: Mapped[int] + created_utc: Mapped[int] + price_paid: Mapped[int] = mapped_column(default = 0) + note: Mapped[str] user = relationship("User", primaryjoin="AwardRelationship.user_id==User.id", back_populates="awards") post = relationship("Post", primaryjoin="AwardRelationship.post_id==Post.id", back_populates="awards") diff --git a/files/classes/badges.py b/files/classes/badges.py index c6230c645..4bce446a4 100644 --- a/files/classes/badges.py +++ b/files/classes/badges.py @@ -1,7 +1,7 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -11,10 +11,10 @@ from files.helpers.lazy import lazy class BadgeDef(Base): __tablename__ = "badge_defs" - id = Column(Integer, primary_key=True, autoincrement=True) - name = Column(String) - description = Column(String) - created_utc = Column(Integer) + id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) + name: Mapped[str] + description: Mapped[str] + created_utc: Mapped[int] def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) @@ -32,11 +32,11 @@ class Badge(Base): __tablename__ = "badges" - user_id = Column(Integer, ForeignKey('users.id'), primary_key=True) - badge_id = Column(Integer, ForeignKey('badge_defs.id'), primary_key=True) - description = Column(String) - url = Column(String) - created_utc = Column(Integer) + user_id: Mapped[int] = mapped_column(ForeignKey('users.id'), primary_key=True) + badge_id: Mapped[int] = mapped_column(ForeignKey('badge_defs.id'), primary_key=True) + description: Mapped[str] + url: Mapped[str] + created_utc: Mapped[int] user = relationship("User", back_populates="badges") badge = relationship("BadgeDef", primaryjoin="Badge.badge_id == BadgeDef.id", lazy="joined", innerjoin=True) diff --git a/files/classes/casino_game.py b/files/classes/casino_game.py index 8864204ea..23380d0e5 100644 --- a/files/classes/casino_game.py +++ b/files/classes/casino_game.py @@ -1,8 +1,8 @@ import json import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -13,15 +13,15 @@ CASINO_GAME_KINDS = ['blackjack', 'slots', 'roulette'] class CasinoGame(Base): __tablename__ = "casino_games" - id = Column(Integer, primary_key=True) - user_id = Column(Integer, ForeignKey("users.id")) - created_utc = Column(Integer) - active = Column(Boolean, default=True) - currency = Column(String) - wager = Column(Integer) - winnings = Column(Integer) - kind = Column(String) - game_state = Column(JSON) + id: Mapped[int] = mapped_column(primary_key=True) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + created_utc: Mapped[int] + active: Mapped[bool] = mapped_column(default=True) + currency: Mapped[str] + wager: Mapped[int] + winnings: Mapped[int] + kind: Mapped[str] + game_state: Mapped[str] = mapped_column(JSON) user = relationship("User") diff --git a/files/classes/clients.py b/files/classes/clients.py index f4bebecfb..8034cd697 100644 --- a/files/classes/clients.py +++ b/files/classes/clients.py @@ -1,8 +1,8 @@ import time from flask import g -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship, load_only +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, load_only, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -15,13 +15,13 @@ from .post import Post class OauthApp(Base): __tablename__ = "oauth_apps" - id = Column(Integer, primary_key=True) - client_id = Column(String) - app_name = Column(String) - redirect_uri = Column(String) - description = Column(String) - author_id = Column(Integer, ForeignKey("users.id")) - created_utc = Column(Integer) + id: Mapped[int] = mapped_column(primary_key=True) + client_id: Mapped[str] + app_name: Mapped[str] + redirect_uri: Mapped[str] + description: Mapped[str] + author_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + created_utc: Mapped[int] author = relationship("User", back_populates="apps") @@ -51,10 +51,10 @@ class OauthApp(Base): class ClientAuth(Base): __tablename__ = "client_auths" - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - oauth_client = Column(Integer, ForeignKey("oauth_apps.id"), primary_key=True) - access_token = Column(String) - created_utc = Column(Integer) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + oauth_client: Mapped[int] = mapped_column(ForeignKey("oauth_apps.id"), primary_key=True) + access_token: Mapped[str] + created_utc: Mapped[int] user = relationship("User") application = relationship("OauthApp") diff --git a/files/classes/comment.py b/files/classes/comment.py index 18b775815..a275f04c4 100644 --- a/files/classes/comment.py +++ b/files/classes/comment.py @@ -4,9 +4,9 @@ from random import randint from urllib.parse import parse_qs, urlencode, urlparse from flask import g -from sqlalchemy import Column, ForeignKey +from sqlalchemy import ForeignKey from sqlalchemy.dialects.postgresql import TSVECTOR -from sqlalchemy.orm import relationship +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.schema import FetchedValue from sqlalchemy.sql.sqltypes import * @@ -172,47 +172,47 @@ def add_options(self, body, v): class Comment(Base): __tablename__ = "comments" - id = Column(Integer, primary_key=True) - author_id = Column(Integer, ForeignKey("users.id")) - parent_post = Column(Integer, ForeignKey("posts.id")) - wall_user_id = Column(Integer, ForeignKey("users.id")) - created_utc = Column(Integer) - edited_utc = Column(Integer, default=0) - is_banned = Column(Boolean, default=False) - ghost = Column(Boolean, default=False) - bannedfor = Column(String) - chuddedfor = Column(String) - distinguished = Column(Boolean, default=False) - deleted_utc = Column(Integer, default=0) - is_approved = Column(Integer, ForeignKey("users.id")) - level = Column(Integer, default=1) - parent_comment_id = Column(Integer, ForeignKey("comments.id")) - top_comment_id = Column(Integer) - is_bot = Column(Boolean, default=False) - stickied = Column(String) - stickied_utc = Column(Integer) - num_of_pinned_children = Column(Integer, default=0) - sentto = Column(Integer, ForeignKey("users.id")) - app_id = Column(Integer, ForeignKey("oauth_apps.id")) - upvotes = Column(Integer, default=1) - downvotes = Column(Integer, default=0) - realupvotes = Column(Integer, default=1) - body = Column(String) - body_html = Column(String) - body_ts = Column(TSVECTOR(), server_default=FetchedValue()) - ban_reason = Column(String) - treasure_amount = Column(String) - slots_result = Column(String) - ping_cost = Column(Integer, default=0) - blackjack_result = Column(String) - casino_game_id = Column(Integer, ForeignKey("casino_games.id")) - chudded = Column(Boolean, default=False) - rainbowed = Column(Boolean, default=False) - queened = Column(Boolean, default=False) - sharpened = Column(Boolean, default=False) + id: Mapped[int] = mapped_column(primary_key=True) + author_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + parent_post: Mapped[int] = mapped_column(ForeignKey("posts.id")) + wall_user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + created_utc: Mapped[int] + edited_utc: Mapped[int] = mapped_column(default=0) + is_banned: Mapped[bool] = mapped_column(default=False) + ghost: Mapped[bool] = mapped_column(default=False) + bannedfor: Mapped[str] + chuddedfor: Mapped[str] + distinguished: Mapped[bool] = mapped_column(default=False) + deleted_utc: Mapped[int] = mapped_column(default=0) + is_approved: Mapped[int] = mapped_column(ForeignKey("users.id")) + level: Mapped[int] = mapped_column(default=1) + parent_comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id")) + top_comment_id: Mapped[int] + is_bot: Mapped[bool] = mapped_column(default=False) + stickied: Mapped[str] + stickied_utc: Mapped[int] + num_of_pinned_children: Mapped[int] = mapped_column(default=0) + sentto: Mapped[int] = mapped_column(ForeignKey("users.id")) + app_id: Mapped[int] = mapped_column(ForeignKey("oauth_apps.id")) + upvotes: Mapped[int] = mapped_column(default=1) + downvotes: Mapped[int] = mapped_column(default=0) + realupvotes: Mapped[int] = mapped_column(default=1) + body: Mapped[str] + body_html: Mapped[str] + body_ts: Mapped[str] = mapped_column(TSVECTOR(), server_default=FetchedValue()) + ban_reason: Mapped[str] + treasure_amount: Mapped[str] + slots_result: Mapped[str] + ping_cost: Mapped[int] = mapped_column(default=0) + blackjack_result: Mapped[str] + casino_game_id: Mapped[int] = mapped_column(ForeignKey("casino_games.id")) + chudded: Mapped[bool] = mapped_column(default=False) + rainbowed: Mapped[bool] = mapped_column(default=False) + queened: Mapped[bool] = mapped_column(default=False) + sharpened: Mapped[bool] = mapped_column(default=False) if FEATURES['NSFW_MARKING']: - nsfw = Column(Boolean, default=False) + nsfw: Mapped[bool] = mapped_column(default=False) else: nsfw = False diff --git a/files/classes/domains.py b/files/classes/domains.py index 4c6bf820c..36d27ef0a 100644 --- a/files/classes/domains.py +++ b/files/classes/domains.py @@ -1,15 +1,15 @@ import time -from sqlalchemy import Column +from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import * from files.classes import Base class BannedDomain(Base): __tablename__ = "banneddomains" - domain = Column(String, primary_key=True) - reason = Column(String) - created_utc = Column(Integer) + domain: Mapped[str] = mapped_column(primary_key=True) + reason: Mapped[str] + created_utc: Mapped[int] def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/emoji.py b/files/classes/emoji.py index 1b43d5719..7b1c1a8db 100644 --- a/files/classes/emoji.py +++ b/files/classes/emoji.py @@ -1,6 +1,7 @@ import time -from sqlalchemy import Column, ForeignKey +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -8,14 +9,14 @@ from files.classes import Base class Emoji(Base): __tablename__ = "emojis" - name = Column(String, primary_key=True) - kind = Column(String) - author_id = Column(Integer, ForeignKey("users.id")) - tags = Column(String) - count = Column(Integer, default=0) - submitter_id = Column(Integer, ForeignKey("users.id")) - created_utc = Column(Integer) - nsfw = Column(Boolean, default=False) + name: Mapped[str] = mapped_column(primary_key=True) + kind: Mapped[str] + author_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + tags: Mapped[str] + count: Mapped[int] = mapped_column(default=0) + submitter_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + created_utc: Mapped[int] + nsfw: Mapped[bool] = mapped_column(default=False) def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/follows.py b/files/classes/follows.py index 67e253eec..0229a86bb 100644 --- a/files/classes/follows.py +++ b/files/classes/follows.py @@ -1,16 +1,16 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base class Follow(Base): __tablename__ = "follows" - target_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - created_utc = Column(Integer) + target_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + created_utc: Mapped[int] user = relationship("User", uselist=False, primaryjoin="User.id==Follow.user_id", back_populates="following") target = relationship("User", uselist=False, primaryjoin="User.id==Follow.target_id", back_populates="followers") diff --git a/files/classes/group.py b/files/classes/group.py index 525e607f2..cae7a3768 100644 --- a/files/classes/group.py +++ b/files/classes/group.py @@ -1,7 +1,6 @@ import time -from sqlalchemy import Column -from sqlalchemy.orm import relationship +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.types import Integer from files.classes import Base @@ -12,11 +11,11 @@ from .group_membership import * class Group(Base): __tablename__ = "groups" - name = Column(String, primary_key=True) - created_utc = Column(Integer) - owner_id = Column(Integer, ForeignKey("users.id")) - description = Column(String) - description_html = Column(String) + name: Mapped[str] = mapped_column(primary_key=True) + created_utc: Mapped[int] + owner_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + description: Mapped[str] + description_html: Mapped[str] memberships = relationship("GroupMembership", primaryjoin="GroupMembership.group_name==Group.name", order_by="GroupMembership.approved_utc") owner = relationship("User", primaryjoin="Group.owner_id==User.id") diff --git a/files/classes/group_membership.py b/files/classes/group_membership.py index e0adf493d..733158be1 100644 --- a/files/classes/group_membership.py +++ b/files/classes/group_membership.py @@ -1,18 +1,18 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.types import Integer, String, Boolean from files.classes import Base class GroupMembership(Base): __tablename__ = "group_memberships" - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - group_name = Column(String, ForeignKey("groups.name"), primary_key=True) - created_utc = Column(Integer) - approved_utc = Column(Integer) - is_mod = Column(Boolean, default=False) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + group_name: Mapped[str] = mapped_column(ForeignKey("groups.name"), primary_key=True) + created_utc: Mapped[int] + approved_utc: Mapped[int] + is_mod: Mapped[bool] = mapped_column(default=False) user = relationship("User", uselist=False) diff --git a/files/classes/hats.py b/files/classes/hats.py index 746ffc73f..2e7bd9f42 100644 --- a/files/classes/hats.py +++ b/files/classes/hats.py @@ -1,7 +1,7 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from flask import g @@ -12,13 +12,13 @@ from files.helpers.slurs_and_profanities import censor_slurs_profanities class HatDef(Base): __tablename__ = "hat_defs" - id = Column(Integer, primary_key=True) - name = Column(String) - description = Column(String) - author_id = Column(Integer, ForeignKey('users.id')) - price = Column(Integer) - submitter_id = Column(Integer, ForeignKey("users.id")) - created_utc = Column(Integer) + id: Mapped[int] = mapped_column(primary_key=True) + name: Mapped[str] + description: Mapped[str] + author_id: Mapped[int] = mapped_column(ForeignKey('users.id')) + price: Mapped[int] + submitter_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + created_utc: Mapped[int] author = relationship("User", primaryjoin="HatDef.author_id == User.id", back_populates="designed_hats") submitter = relationship("User", primaryjoin="HatDef.submitter_id == User.id") @@ -48,10 +48,10 @@ class HatDef(Base): class Hat(Base): __tablename__ = "hats" - user_id = Column(Integer, ForeignKey('users.id'), primary_key=True) - hat_id = Column(Integer, ForeignKey('hat_defs.id'), primary_key=True) - equipped = Column(Boolean, default=False) - created_utc = Column(Integer) + user_id: Mapped[int] = mapped_column(ForeignKey('users.id'), primary_key=True) + hat_id: Mapped[int] = mapped_column(ForeignKey('hat_defs.id'), primary_key=True) + equipped: Mapped[bool] = mapped_column(default=False) + created_utc: Mapped[int] hat_def = relationship("HatDef") owners = relationship("User", back_populates="owned_hats") diff --git a/files/classes/hole.py b/files/classes/hole.py index b4cc4200c..3e9ae7958 100644 --- a/files/classes/hole.py +++ b/files/classes/hole.py @@ -1,10 +1,9 @@ import random import time +from typing import Annotated -from sqlalchemy import Column from sqlalchemy.ext.mutable import MutableList -from sqlalchemy.orm import relationship, deferred -from sqlalchemy.types import * +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.dialects.postgresql import ARRAY from files.classes import Base @@ -15,20 +14,20 @@ from .hole_relationship import * class Hole(Base): __tablename__ = "holes" - name = Column(String, primary_key=True) - sidebar = Column(String) - sidebar_html = Column(String) - sidebarurls = Column(MutableList.as_mutable(ARRAY(String)), default=MutableList([])) - bannerurls = Column(MutableList.as_mutable(ARRAY(String)), default=MutableList([])) - marseyurl = Column(String) - css = deferred(Column(String)) - stealth = Column(Boolean, default=False) - public_use = Column(Boolean, default=False) - created_utc = Column(Integer) + name: Mapped[str] = mapped_column(primary_key=True) + sidebar: Mapped[str] + sidebar_html: Mapped[str] + sidebarurls: Mapped[list[str]] = mapped_column(MutableList.as_mutable(ARRAY(String)), default=MutableList([])) + bannerurls: Mapped[list[str]] = mapped_column(MutableList.as_mutable(ARRAY(String)), default=MutableList([])) + marseyurl: Mapped[str] + css: Mapped[str] = mapped_column(deferred=True) + stealth: Mapped[bool] = mapped_column(default=False) + public_use: Mapped[bool] = mapped_column(default=False) + created_utc: Mapped[int] if SITE_NAME == 'WPD': snappy_quotes = None else: - snappy_quotes = deferred(Column(String)) + snappy_quotes: Mapped[Annotated[str, HOLE_SNAPPY_QUOTES_LENGTH]] = mapped_column(deferred=True) blocks = relationship("HoleBlock", primaryjoin="HoleBlock.hole==Hole.name") followers = relationship("HoleFollow", primaryjoin="HoleFollow.hole==Hole.name") diff --git a/files/classes/hole_logs.py b/files/classes/hole_logs.py index aa45dc484..1c7bf7233 100644 --- a/files/classes/hole_logs.py +++ b/files/classes/hole_logs.py @@ -1,7 +1,7 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from flask import g @@ -13,15 +13,15 @@ from files.helpers.sorting_and_time import make_age_string class HoleAction(Base): __tablename__ = "hole_actions" - id = Column(Integer, primary_key=True) - hole = Column(String, ForeignKey("holes.name")) - user_id = Column(Integer, ForeignKey("users.id")) - kind = Column(String) - target_user_id = Column(Integer, ForeignKey("users.id")) - target_post_id = Column(Integer, ForeignKey("posts.id")) - target_comment_id = Column(Integer, ForeignKey("comments.id")) - _note = Column(String) - created_utc = Column(Integer) + id: Mapped[int] = mapped_column(primary_key=True) + hole: Mapped[str] = mapped_column(ForeignKey("holes.name")) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + kind: Mapped[str] + target_user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + target_post_id: Mapped[int] = mapped_column(ForeignKey("posts.id")) + target_comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id")) + _note: Mapped[str] + created_utc: Mapped[int] user = relationship("User", primaryjoin="User.id==HoleAction.user_id") target_user = relationship("User", primaryjoin="User.id==HoleAction.target_user_id") diff --git a/files/classes/hole_relationship.py b/files/classes/hole_relationship.py index a231ad862..07b70031f 100644 --- a/files/classes/hole_relationship.py +++ b/files/classes/hole_relationship.py @@ -1,7 +1,7 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, relationship, mapped_column from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -10,9 +10,9 @@ class HoleRelationship(Base): __tablename__ = NotImplemented __abstract__ = True - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - hole = Column(String, ForeignKey("holes.name"), primary_key=True) - created_utc = Column(Integer) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + hole: Mapped[str] = mapped_column(ForeignKey("holes.name"), primary_key=True) + created_utc: Mapped[int] def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) @@ -35,5 +35,5 @@ class Mod(HoleRelationship): class Exile(HoleRelationship): __tablename__ = "exiles" - exiler_id = Column(Integer, ForeignKey("users.id")) + exiler_id: Mapped[int] = mapped_column(ForeignKey("users.id")) exiler = relationship("User", primaryjoin="User.id==Exile.exiler_id") diff --git a/files/classes/ip_logs.py b/files/classes/ip_logs.py index 3d6d3db37..d19941df0 100644 --- a/files/classes/ip_logs.py +++ b/files/classes/ip_logs.py @@ -1,17 +1,17 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base class IPLog(Base): __tablename__ = "ip_logs" - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - ip = Column(String, primary_key=True) - created_utc = Column(Integer) - last_used = Column(Integer) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + ip: Mapped[str] = mapped_column(primary_key=True) + created_utc: Mapped[int] + last_used: Mapped[int] user = relationship("User") diff --git a/files/classes/lottery.py b/files/classes/lottery.py index abde47b0b..794ea7617 100644 --- a/files/classes/lottery.py +++ b/files/classes/lottery.py @@ -1,6 +1,7 @@ import time -from sqlalchemy import Column, ForeignKey +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -10,13 +11,13 @@ from files.helpers.lazy import lazy class Lottery(Base): __tablename__ = "lotteries" - id = Column(Integer, primary_key=True) - is_active = Column(Boolean, default=False) - ends_at = Column(Integer) - prize = Column(Integer, default=0) - tickets_sold = Column(Integer, default=0) - winner_id = Column(Integer, ForeignKey("users.id")) - created_utc = Column(Integer) + id: Mapped[int] = mapped_column(primary_key=True) + is_active: Mapped[bool] = mapped_column(default=False) + ends_at: Mapped[int] + prize: Mapped[int] = mapped_column(default=0) + tickets_sold: Mapped[int] = mapped_column(default=0) + winner_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + created_utc: Mapped[int] def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/media.py b/files/classes/media.py index 574c0a3c4..0e144ad4f 100644 --- a/files/classes/media.py +++ b/files/classes/media.py @@ -1,16 +1,17 @@ import time -from sqlalchemy import Column, ForeignKey +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import * from files.classes import Base class Media(Base): __tablename__ = "media" - kind = Column(String, primary_key=True) - filename = Column(String, primary_key=True) - user_id = Column(Integer, ForeignKey("users.id")) - created_utc = Column(Integer) - size = Column(Integer) + kind: Mapped[str] = mapped_column(primary_key=True) + filename: Mapped[str] = mapped_column(primary_key=True) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + created_utc: Mapped[int] + size: Mapped[int] def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/mod_logs.py b/files/classes/mod_logs.py index 94a009ad3..747fbe79b 100644 --- a/files/classes/mod_logs.py +++ b/files/classes/mod_logs.py @@ -1,7 +1,7 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from flask import g @@ -13,14 +13,14 @@ from files.helpers.sorting_and_time import make_age_string class ModAction(Base): __tablename__ = "modactions" - id = Column(Integer, primary_key=True) - user_id = Column(Integer, ForeignKey("users.id")) - kind = Column(String) - target_user_id = Column(Integer, ForeignKey("users.id")) - target_post_id = Column(Integer, ForeignKey("posts.id")) - target_comment_id = Column(Integer, ForeignKey("comments.id")) - _note = Column(String) - created_utc = Column(Integer) + id: Mapped[int] = mapped_column(primary_key=True) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + kind: Mapped[str] + target_user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + target_post_id: Mapped[int] = mapped_column(ForeignKey("posts.id")) + target_comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id")) + _note: Mapped[str] + created_utc: Mapped[int] user = relationship("User", primaryjoin="User.id==ModAction.user_id") target_user = relationship("User", primaryjoin="User.id==ModAction.target_user_id") diff --git a/files/classes/notifications.py b/files/classes/notifications.py index 5ad09c049..4e50e63b1 100644 --- a/files/classes/notifications.py +++ b/files/classes/notifications.py @@ -1,7 +1,7 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -9,10 +9,10 @@ from files.classes import Base class Notification(Base): __tablename__ = "notifications" - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - comment_id = Column(Integer, ForeignKey("comments.id"), primary_key=True) - read = Column(Boolean, default=False) - created_utc = Column(Integer) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id"), primary_key=True) + read: Mapped[bool] = mapped_column(default=False) + created_utc: Mapped[int] comment = relationship("Comment") user = relationship("User") diff --git a/files/classes/orgy.py b/files/classes/orgy.py index 80bee5d2f..01708e643 100644 --- a/files/classes/orgy.py +++ b/files/classes/orgy.py @@ -2,7 +2,8 @@ import time from flask import g, abort import requests -from sqlalchemy import Column, or_ +from sqlalchemy import or_ +from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -13,13 +14,13 @@ from files.helpers.config.const import * class Orgy(Base): __tablename__ = "orgies" - created_utc = Column(Integer, primary_key=True) - type = Column(String) - data = Column(String) - title = Column(String) - start_utc = Column(Integer) - end_utc = Column(Integer) - started = Column(Boolean, default=False) + created_utc: Mapped[int] = mapped_column(primary_key=True) + type: Mapped[str] + data: Mapped[str] + title: Mapped[str] + start_utc: Mapped[int] + end_utc: Mapped[int] + started: Mapped[bool] = mapped_column(default=False) def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/polls.py b/files/classes/polls.py index 3b7923e1e..d0b297100 100644 --- a/files/classes/polls.py +++ b/files/classes/polls.py @@ -1,7 +1,7 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -10,11 +10,11 @@ from files.helpers.lazy import lazy class PostOption(Base): __tablename__ = "post_options" - id = Column(Integer, primary_key=True) - parent_id = Column(Integer, ForeignKey("posts.id")) - body_html = Column(Text) - exclusive = Column(Integer) - created_utc = Column(Integer) + id: Mapped[int] = mapped_column(primary_key=True) + parent_id: Mapped[int] = mapped_column(ForeignKey("posts.id")) + body_html: Mapped[str] = mapped_column(Text) + exclusive: Mapped[int] + created_utc: Mapped[int] votes = relationship("PostOptionVote") parent = relationship("Post", back_populates="options") @@ -40,10 +40,10 @@ class PostOptionVote(Base): __tablename__ = "post_option_votes" - option_id = Column(Integer, ForeignKey("post_options.id"), primary_key=True) - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - created_utc = Column(Integer) - post_id = Column(Integer, ForeignKey("posts.id")) + option_id: Mapped[int] = mapped_column(ForeignKey("post_options.id"), primary_key=True) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + created_utc: Mapped[int] + post_id: Mapped[int] = mapped_column(ForeignKey("posts.id")) user = relationship("User") @@ -59,11 +59,11 @@ class CommentOption(Base): __tablename__ = "comment_options" - id = Column(Integer, primary_key=True) - parent_id = Column(Integer, ForeignKey("comments.id")) - body_html = Column(Text) - exclusive = Column(Integer) - created_utc = Column(Integer) + id: Mapped[int] = mapped_column(primary_key=True) + parent_id: Mapped[int] = mapped_column(ForeignKey("comments.id")) + body_html: Mapped[str] = mapped_column(Text) + exclusive: Mapped[int] + created_utc: Mapped[int] votes = relationship("CommentOptionVote") parent = relationship("Comment", back_populates="options") @@ -89,10 +89,10 @@ class CommentOptionVote(Base): __tablename__ = "comment_option_votes" - option_id = Column(Integer, ForeignKey("comment_options.id"), primary_key=True) - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - created_utc = Column(Integer) - comment_id = Column(Integer, ForeignKey("comments.id")) + option_id: Mapped[int] = mapped_column(ForeignKey("comment_options.id"), primary_key=True) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + created_utc: Mapped[int] + comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id")) user = relationship("User") diff --git a/files/classes/post.py b/files/classes/post.py index 5fc1b5a6d..af110938e 100644 --- a/files/classes/post.py +++ b/files/classes/post.py @@ -3,8 +3,8 @@ import time from urllib.parse import urlparse from flask import g -from sqlalchemy import Column, FetchedValue, ForeignKey -from sqlalchemy.orm import deferred, relationship +from sqlalchemy import FetchedValue, ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -25,57 +25,57 @@ from .saves import SaveRelationship class Post(Base): __tablename__ = "posts" - id = Column(Integer, primary_key=True) - author_id = Column(Integer, ForeignKey("users.id")) - edited_utc = Column(Integer, default=0) - created_utc = Column(Integer) - thumburl = Column(String) - posterurl = Column(String) - is_banned = Column(Boolean, default=False) - bannedfor = Column(String) - chuddedfor = Column(String) - ghost = Column(Boolean, default=False) - effortpost = Column(Boolean, default=False) - views = Column(Integer, default=0) - deleted_utc = Column(Integer, default=0) - distinguished = Column(Boolean, default=False) - stickied = Column(String) - stickied_utc = Column(Integer) - hole_pinned = Column(String) - hole = Column(String, ForeignKey("holes.name")) - is_pinned = Column(Boolean, default=False) - private = Column(Boolean, default=False) - comment_count = Column(Integer, default=0) - is_approved = Column(Integer, ForeignKey("users.id")) - is_bot = Column(Boolean, default=False) - upvotes = Column(Integer, default=1) - downvotes = Column(Integer, default=0) - realupvotes = Column(Integer, default=1) - app_id = Column(Integer, ForeignKey("oauth_apps.id")) - title = Column(String) - title_html = Column(String) - url = Column(String) - body = Column(String) - body_html = Column(String) - flair = Column(String) - ban_reason = Column(String) - embed = Column(String) - new = Column(Boolean) - notify = Column(Boolean) - chudded = Column(Boolean, default=False) - rainbowed = Column(Boolean, default=False) - queened = Column(Boolean, default=False) - sharpened = Column(Boolean, default=False) - ping_cost = Column(Integer, default=0) - bump_utc = Column(Integer) + id: Mapped[int] = mapped_column(primary_key=True) + author_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + edited_utc: Mapped[int] = mapped_column(default=0) + created_utc: Mapped[int] + thumburl: Mapped[str] + posterurl: Mapped[str] + is_banned: Mapped[bool] = mapped_column(default=False) + bannedfor: Mapped[str] + chuddedfor: Mapped[str] + ghost: Mapped[bool] = mapped_column(default=False) + effortpost: Mapped[bool] = mapped_column(default=False) + views: Mapped[int] = mapped_column(default=0) + deleted_utc: Mapped[int] = mapped_column(default=0) + distinguished: Mapped[bool] = mapped_column(default=False) + stickied: Mapped[str] + stickied_utc: Mapped[int] + hole_pinned: Mapped[str] + hole: Mapped[str] = mapped_column(ForeignKey("holes.name")) + is_pinned: Mapped[bool] = mapped_column(default=False) + private: Mapped[bool] = mapped_column(default=False) + comment_count: Mapped[int] = mapped_column(default=0) + is_approved: Mapped[int] = mapped_column(ForeignKey("users.id")) + is_bot: Mapped[bool] = mapped_column(default=False) + upvotes: Mapped[int] = mapped_column(default=1) + downvotes: Mapped[int] = mapped_column(default=0) + realupvotes: Mapped[int] = mapped_column(default=1) + app_id: Mapped[int] = mapped_column(ForeignKey("oauth_apps.id")) + title: Mapped[str] + title_html: Mapped[str] + url: Mapped[str] + body: Mapped[str] + body_html: Mapped[str] + flair: Mapped[str] + ban_reason: Mapped[str] + embed: Mapped[str] + new: Mapped[bool] + notify: Mapped[bool] + chudded: Mapped[bool] = mapped_column(default=False) + rainbowed: Mapped[bool] = mapped_column(default=False) + queened: Mapped[bool] = mapped_column(default=False) + sharpened: Mapped[bool] = mapped_column(default=False) + ping_cost: Mapped[int] = mapped_column(default=0) + bump_utc: Mapped[int] if FEATURES['NSFW_MARKING']: - nsfw = Column(Boolean, default=False) + nsfw: Mapped[bool] = mapped_column(default=False) else: nsfw = False if SITE_NAME == 'WPD': - cw = Column(Boolean, default=False) + cw: Mapped[bool] = mapped_column(default=False) author = relationship("User", primaryjoin="Post.author_id==User.id") oauth_app = relationship("OauthApp") diff --git a/files/classes/push_subscriptions.py b/files/classes/push_subscriptions.py index 0a34763a9..ca1d91c54 100644 --- a/files/classes/push_subscriptions.py +++ b/files/classes/push_subscriptions.py @@ -1,15 +1,16 @@ import time -from sqlalchemy import Column, ForeignKey +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import * from files.classes import Base class PushSubscription(Base): __tablename__ = "push_subscriptions" - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - subscription_json = Column(String, primary_key=True) - created_utc = Column(Integer) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + subscription_json: Mapped[str] = mapped_column(primary_key=True) + created_utc: Mapped[int] def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/reports.py b/files/classes/reports.py index f05e391f2..877804473 100644 --- a/files/classes/reports.py +++ b/files/classes/reports.py @@ -1,7 +1,7 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -11,10 +11,10 @@ from files.helpers.slurs_and_profanities import censor_slurs_profanities class Report(Base): __tablename__ = "reports" - post_id = Column(Integer, ForeignKey("posts.id"), primary_key=True) - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - reason = Column(String) - created_utc = Column(Integer) + post_id: Mapped[int] = mapped_column(ForeignKey("posts.id"), primary_key=True) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + reason: Mapped[str] + created_utc: Mapped[int] user = relationship("User", primaryjoin = "Report.user_id == User.id", uselist = False) @@ -39,10 +39,10 @@ class Report(Base): class CommentReport(Base): __tablename__ = "commentreports" - comment_id = Column(Integer, ForeignKey("comments.id"), primary_key=True) - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - reason = Column(String) - created_utc = Column(Integer) + comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id"), primary_key=True) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + reason: Mapped[str] + created_utc: Mapped[int] user = relationship("User", primaryjoin = "CommentReport.user_id == User.id", uselist = False) diff --git a/files/classes/saves.py b/files/classes/saves.py index 0eeef40d7..4d02a50d8 100644 --- a/files/classes/saves.py +++ b/files/classes/saves.py @@ -1,7 +1,7 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -9,9 +9,9 @@ from files.classes import Base class SaveRelationship(Base): __tablename__ = "save_relationship" - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - post_id = Column(Integer, ForeignKey("posts.id"), primary_key=True) - created_utc = Column(Integer) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + post_id: Mapped[int] = mapped_column(ForeignKey("posts.id"), primary_key=True) + created_utc: Mapped[int] post = relationship("Post", uselist=False) @@ -27,9 +27,9 @@ class CommentSaveRelationship(Base): __tablename__ = "comment_save_relationship" - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - comment_id = Column(Integer, ForeignKey("comments.id"), primary_key=True) - created_utc = Column(Integer) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id"), primary_key=True) + created_utc: Mapped[int] comment = relationship("Comment", uselist=False) diff --git a/files/classes/subscriptions.py b/files/classes/subscriptions.py index 46d746fed..aa7b0b034 100644 --- a/files/classes/subscriptions.py +++ b/files/classes/subscriptions.py @@ -1,16 +1,16 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base class Subscription(Base): __tablename__ = "subscriptions" - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - post_id = Column(Integer, ForeignKey("posts.id"), primary_key=True) - created_utc = Column(Integer) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + post_id: Mapped[int] = mapped_column(ForeignKey("posts.id"), primary_key=True) + created_utc: Mapped[int] user = relationship("User", uselist=False) post = relationship("Post", uselist=False) diff --git a/files/classes/transactions.py b/files/classes/transactions.py index 4b5457537..c18fa11df 100644 --- a/files/classes/transactions.py +++ b/files/classes/transactions.py @@ -1,16 +1,16 @@ -from sqlalchemy import Column +from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import * from files.classes import Base class Transaction(Base): __tablename__ = "transactions" - id = Column(String, primary_key=True) - created_utc = Column(Integer) - type = Column(String) - amount = Column(Integer) - email = Column(String) - claimed = Column(Boolean) + id: Mapped[str] = mapped_column(primary_key=True) + created_utc: Mapped[int] + type: Mapped[str] + amount: Mapped[int] + email: Mapped[str] + claimed: Mapped[bool] def __repr__(self): return f"<{self.__class__.__name__}(id={self.id})>" diff --git a/files/classes/user.py b/files/classes/user.py index a419110c7..eefc857e2 100644 --- a/files/classes/user.py +++ b/files/classes/user.py @@ -2,8 +2,8 @@ import random from operator import * import pyotp -from sqlalchemy import Column, ForeignKey, FetchedValue -from sqlalchemy.orm import aliased, deferred, Query +from sqlalchemy import ForeignKey, FetchedValue +from sqlalchemy.orm import Mapped, Query, aliased, deferred, mapped_column from sqlalchemy.sql import case, func, literal from sqlalchemy.sql.expression import not_, and_, or_ from sqlalchemy.sql.sqltypes import * @@ -49,106 +49,106 @@ else: class User(Base): __tablename__ = "users" - id = Column(Integer, primary_key=True) - username = Column(String) - namecolor = Column(String, default=DEFAULT_COLOR) - background = Column(String) - profile_background = Column(String) - flair = deferred(Column(String)) - flair_html = Column(String) - flaircolor = Column(String, default=DEFAULT_COLOR) - theme = Column(String, default=DEFAULT_THEME) - themecolor = Column(String, default=DEFAULT_COLOR) - song = Column(String) - highres = Column(String) - profileurl = Column(String) - bannerurl = Column(String) - house = Column(String, default='') - old_house = Column(String, default='') - patron = Column(Integer, default=0) - patron_utc = Column(Integer, default=0) - verified = Column(String) - verifiedcolor = Column(String) - hieroglyphs = Column(Integer, default=0) - rehab = Column(Integer, default=0) - longpost = Column(Integer, default=0) - bird = Column(Integer, default=0) - email = deferred(Column(String)) - css = Column(String) - profilecss = deferred(Column(String)) - passhash = deferred(Column(String)) - post_count = Column(Integer, default=0) - comment_count = Column(Integer, default=0) - received_award_count = Column(Integer, default=0) - created_utc = Column(Integer) - admin_level = Column(Integer, default=DEFAULT_ADMIN_LEVEL) - last_active = Column(Integer) - coins_spent = Column(Integer, default=0) - coins_spent_on_hats = Column(Integer, default=0) - lootboxes_bought = Column(Integer, default=0) - chud = Column(Integer, default=0) - queen = Column(Integer, default=0) - chud_phrase = Column(String) - email_verified = Column(Boolean, default=False) - shadowbanned = Column(Integer, ForeignKey("users.id")) - chudded_by = Column(Integer, ForeignKey("users.id")) - slurreplacer = Column(Integer, default=1) - profanityreplacer = Column(Integer, default=1) - flairchanged = Column(Integer, default=0) - namechanged = Column(Integer, default=0) - newtab = Column(Boolean, default=False) - newtabexternal = Column(Boolean, default=True) - frontsize = Column(Integer, default=25) - bio = deferred(Column(String)) - bio_html = Column(String) - sig = deferred(Column(String)) - sig_html = Column(String) - show_sigs = Column(Boolean, default=True) - progressivestack = Column(Integer, default=0) - deflector = Column(Integer, default=0) - friends = deferred(Column(String)) - friends_html = deferred(Column(String)) - enemies = deferred(Column(String)) - enemies_html = deferred(Column(String)) - is_banned = Column(Integer, ForeignKey("users.id")) - unban_utc = Column(Integer) - ban_reason = deferred(Column(String)) - shadowban_reason = deferred(Column(String)) - is_muted = Column(Boolean, default=False) - login_nonce = Column(Integer, default=0) - coins = Column(Integer, default=DEFAULT_COINS) - truescore = Column(Integer, default=0) - marseybux = Column(Integer, default=DEFAULT_MARSEYBUX) - mfa_secret = deferred(Column(String)) - is_private = Column(Boolean, default=False) - stored_subscriber_count = Column(Integer, default=0) - defaultsortingcomments = Column(String, default="hot") - defaultsorting = Column(String, default="hot") - defaulttime = Column(String, default=DEFAULT_TIME_FILTER) - custom_filter_list = Column(String) - original_username = Column(String) - extra_username = Column(String) - prelock_username = Column(String) - referred_by = Column(Integer, ForeignKey("users.id")) - currently_held_lottery_tickets = Column(Integer, default=0) - total_held_lottery_tickets = Column(Integer, default=0) - total_lottery_winnings = Column(Integer, default=0) - last_viewed_modmail_notifs = Column(Integer, default=0) - last_viewed_post_notifs = Column(Integer, default=0) - last_viewed_log_notifs = Column(Integer, default=0) - last_viewed_offsite_notifs = Column(Integer, default=0) - bite = Column(Integer, default=0) - owoify = Column(Integer, default=0) - sharpen = Column(Integer, default=0) - marsify = Column(Integer, default=0) - rainbow = Column(Integer, default=0) - spider = Column(Integer, default=0) - lifetimedonated = Column(Integer, default=0) - lifetimedonated_visible = Column(Boolean, default=False) - blacklisted_by = Column(Integer, ForeignKey("users.id")) - grinch = Column(Boolean, default=SITE_NAME != 'rDrama') #don't put in an if condition, it will cause an error bc it has a not-null constraint - group_creation_notifs = Column(Boolean, default=False) - effortpost_notifs = Column(Boolean, default=False) + id: Mapped[int] = mapped_column(primary_key=True) + username: Mapped[str] + namecolor: Mapped[str] = mapped_column(default=DEFAULT_COLOR) + background: Mapped[str] + profile_background: Mapped[str] + flair: Mapped[str] = mapped_column(deferred=True) + flair_html: Mapped[str] + flaircolor: Mapped[str] = mapped_column(default=DEFAULT_COLOR) + theme: Mapped[str] = mapped_column(default=DEFAULT_THEME) + themecolor: Mapped[str] = mapped_column(default=DEFAULT_COLOR) + song: Mapped[str] + highres: Mapped[str] + profileurl: Mapped[str] + bannerurl: Mapped[str] + house: Mapped[str] = mapped_column(default='') + old_house: Mapped[str] = mapped_column(default='') + patron: Mapped[int] = mapped_column(default=0) + patron_utc: Mapped[int] = mapped_column(default=0) + verified: Mapped[str] + verifiedcolor: Mapped[str] + hieroglyphs: Mapped[int] = mapped_column(default=0) + rehab: Mapped[int] = mapped_column(default=0) + longpost: Mapped[int] = mapped_column(default=0) + bird: Mapped[int] = mapped_column(default=0) + email: Mapped[str] = mapped_column(deferred=True) + css: Mapped[str] + profilecss: Mapped[str] = mapped_column(deferred=True) + passhash: Mapped[str] = mapped_column(deferred=True) + post_count: Mapped[int] = mapped_column(default=0) + comment_count: Mapped[int] = mapped_column(default=0) + received_award_count: Mapped[int] = mapped_column(default=0) + created_utc: Mapped[int] + admin_level: Mapped[int] = mapped_column(default=DEFAULT_ADMIN_LEVEL) + last_active: Mapped[int] + coins_spent: Mapped[int] = mapped_column(default=0) + coins_spent_on_hats: Mapped[int] = mapped_column(default=0) + lootboxes_bought: Mapped[int] = mapped_column(default=0) + chud: Mapped[int] = mapped_column(default=0) + queen: Mapped[int] = mapped_column(default=0) + chud_phrase: Mapped[str] + email_verified: Mapped[bool] = mapped_column(default=False) + shadowbanned: Mapped[int] = mapped_column(ForeignKey("users.id")) + chudded_by: Mapped[int] = mapped_column(ForeignKey("users.id")) + slurreplacer: Mapped[int] = mapped_column(default=1) + profanityreplacer: Mapped[int] = mapped_column(default=1) + flairchanged: Mapped[int] = mapped_column(default=0) + namechanged: Mapped[int] = mapped_column(default=0) + newtab: Mapped[bool] = mapped_column(default=False) + newtabexternal: Mapped[bool] = mapped_column(default=True) + frontsize: Mapped[int] = mapped_column(default=25) + bio: Mapped[str] = mapped_column(deferred=True) + bio_html: Mapped[str] + sig: Mapped[str] = mapped_column(deferred=True) + sig_html: Mapped[str] + show_sigs: Mapped[bool] = mapped_column(default=True) + progressivestack: Mapped[int] = mapped_column(default=0) + deflector: Mapped[int] = mapped_column(default=0) + friends: Mapped[str] = mapped_column(deferred=True) + friends_html: Mapped[str] = mapped_column(deferred=True) + enemies: Mapped[str] = mapped_column(deferred=True) + enemies_html: Mapped[str] = mapped_column(deferred=True) + is_banned: Mapped[int] = mapped_column(ForeignKey("users.id")) + unban_utc: Mapped[int] + ban_reason: Mapped[str] = mapped_column(deferred=True) + shadowban_reason: Mapped[str] = mapped_column(deferred=True) + is_muted: Mapped[bool] = mapped_column(default=False) + login_nonce: Mapped[int] = mapped_column(default=0) + coins: Mapped[int] = mapped_column(default=DEFAULT_COINS) + truescore: Mapped[int] = mapped_column(default=0) + marseybux: Mapped[int] = mapped_column(default=DEFAULT_MARSEYBUX) + mfa_secret: Mapped[str] = mapped_column(deferred=True) + is_private: Mapped[bool] = mapped_column(default=False) + stored_subscriber_count: Mapped[int] = mapped_column(default=0) + defaultsortingcomments: Mapped[str] = mapped_column(default="hot") + defaultsorting: Mapped[str] = mapped_column(default="hot") + defaulttime: Mapped[str] = mapped_column(default=DEFAULT_TIME_FILTER) + custom_filter_list: Mapped[str] + original_username: Mapped[str] + extra_username: Mapped[str] + prelock_username: Mapped[str] + referred_by: Mapped[int] = mapped_column(ForeignKey("users.id")) + currently_held_lottery_tickets: Mapped[int] = mapped_column(default=0) + total_held_lottery_tickets: Mapped[int] = mapped_column(default=0) + total_lottery_winnings: Mapped[int] = mapped_column(default=0) + last_viewed_modmail_notifs: Mapped[int] = mapped_column(default=0) + last_viewed_post_notifs: Mapped[int] = mapped_column(default=0) + last_viewed_log_notifs: Mapped[int] = mapped_column(default=0) + last_viewed_offsite_notifs: Mapped[int] = mapped_column(default=0) + bite: Mapped[int] = mapped_column(default=0) + owoify: Mapped[int] = mapped_column(default=0) + sharpen: Mapped[int] = mapped_column(default=0) + marsify: Mapped[int] = mapped_column(default=0) + rainbow: Mapped[int] = mapped_column(default=0) + spider: Mapped[int] = mapped_column(default=0) + lifetimedonated: Mapped[int] = mapped_column(default=0) + lifetimedonated_visible: Mapped[bool] = mapped_column(default=False) + blacklisted_by: Mapped[int] = mapped_column(ForeignKey("users.id")) + grinch: Mapped[bool] = mapped_column(default=SITE_NAME != 'rDrama') #don't put in an if condition, it will cause an error bc it has a not-null constraint + group_creation_notifs: Mapped[bool] = mapped_column(default=False) + effortpost_notifs: Mapped[bool] = mapped_column(default=False) if SITE_NAME == 'WPD': nitter = False @@ -158,22 +158,22 @@ class User(Base): pronouns = 'they/them' earlylife = 0 hole_creation_notifs = False - hidevotedon = Column(Boolean, default=False) - hide_cw = Column(Boolean, default=False) + hidevotedon: Mapped[bool] = mapped_column(default=False) + hide_cw: Mapped[bool] = mapped_column(default=False) else: - nitter = Column(Boolean, default=False) - imgsed = Column(Boolean, default=False) - controversial = Column(Boolean, default=False) - reddit = Column(String, default='old.reddit.com') - pronouns = Column(String, default='they/them') - earlylife = Column(Integer, default=0) - hole_creation_notifs = Column(Boolean, default=True) + nitter: Mapped[bool] = mapped_column(default=False) + imgsed: Mapped[bool] = mapped_column(default=False) + controversial: Mapped[bool] = mapped_column(default=False) + reddit: Mapped[str] = mapped_column(default='old.reddit.com') + pronouns: Mapped[str] = mapped_column(default='they/them') + earlylife: Mapped[int] = mapped_column(default=0) + hole_creation_notifs: Mapped[bool] = mapped_column(default=True) hidevotedon = False hide_cw = False if IS_HOMOWEEN(): - zombie = Column(Integer, default=0) # > 0 vaxxed; < 0 zombie - jumpscare = Column(Integer, default=0) + zombie: Mapped[int] = mapped_column(default=0) # > 0 vaxxed; < 0 zombie + jumpscare: Mapped[int] = mapped_column(default=0) badges = relationship("Badge", order_by="Badge.created_utc", back_populates="user") subscriptions = relationship("Subscription", back_populates="user") diff --git a/files/classes/userblock.py b/files/classes/userblock.py index 7e17ebf4b..5d815179d 100644 --- a/files/classes/userblock.py +++ b/files/classes/userblock.py @@ -1,16 +1,16 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base class UserBlock(Base): __tablename__ = "userblocks" - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - target_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - created_utc = Column(Integer) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + target_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + created_utc: Mapped[int] user = relationship("User", primaryjoin="User.id==UserBlock.user_id", back_populates="blocking") target = relationship("User", primaryjoin="User.id==UserBlock.target_id", back_populates="blocked") diff --git a/files/classes/usermute.py b/files/classes/usermute.py index 10db9750d..48c0d1566 100644 --- a/files/classes/usermute.py +++ b/files/classes/usermute.py @@ -1,16 +1,16 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base class UserMute(Base): __tablename__ = "usermutes" - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - target_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - created_utc = Column(Integer) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + target_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + created_utc: Mapped[int] user = relationship("User", primaryjoin="User.id==UserMute.user_id") target = relationship("User", primaryjoin="User.id==UserMute.target_id") diff --git a/files/classes/views.py b/files/classes/views.py index b8984db8f..654eeee93 100644 --- a/files/classes/views.py +++ b/files/classes/views.py @@ -1,7 +1,7 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -11,10 +11,10 @@ from files.helpers.sorting_and_time import make_age_string class ViewerRelationship(Base): __tablename__ = "viewers" - user_id = Column(Integer, ForeignKey('users.id'), primary_key=True) - viewer_id = Column(Integer, ForeignKey('users.id'), primary_key=True) - last_view_utc = Column(Integer) - created_utc = Column(Integer) + user_id: Mapped[int] = mapped_column(ForeignKey('users.id'), primary_key=True) + viewer_id: Mapped[int] = mapped_column(ForeignKey('users.id'), primary_key=True) + last_view_utc: Mapped[int] + created_utc: Mapped[int] viewer = relationship("User", primaryjoin="ViewerRelationship.viewer_id == User.id") diff --git a/files/classes/votes.py b/files/classes/votes.py index a2d96e112..7d19add0b 100644 --- a/files/classes/votes.py +++ b/files/classes/votes.py @@ -1,7 +1,7 @@ import time -from sqlalchemy import Column, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base @@ -10,12 +10,12 @@ from files.helpers.lazy import lazy class Vote(Base): __tablename__ = "votes" - post_id = Column(Integer, ForeignKey("posts.id"), primary_key=True) - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - vote_type = Column(Integer) - real = Column(Boolean, default=True) - coins = Column(Integer, default=1) - created_utc = Column(Integer) + post_id: Mapped[int] = mapped_column(ForeignKey("posts.id"), primary_key=True) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + vote_type: Mapped[int] + real: Mapped[bool] = mapped_column(default=True) + coins: Mapped[int] = mapped_column(default=1) + created_utc: Mapped[int] user = relationship("User") @@ -40,12 +40,12 @@ class CommentVote(Base): __tablename__ = "commentvotes" - comment_id = Column(Integer, ForeignKey("comments.id"), primary_key=True) - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - vote_type = Column(Integer) - real = Column(Boolean, default=True) - coins = Column(Integer, default=1) - created_utc = Column(Integer) + comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id"), primary_key=True) + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + vote_type: Mapped[int] + real: Mapped[bool] = mapped_column(default=True) + coins: Mapped[int] = mapped_column(default=1) + created_utc: Mapped[int] user = relationship("User") -- 2.34.1 From 6cb4c88b75ecbf2f01bdbf42d38d2c629430b168 Mon Sep 17 00:00:00 2001 From: TriHard Date: Thu, 15 Feb 2024 06:17:23 -0700 Subject: [PATCH 4/7] Add Mapped types to relationships --- files/classes/award.py | 10 +++++++--- files/classes/badges.py | 9 +++++++-- files/classes/casino_game.py | 6 +++++- files/classes/clients.py | 11 ++++++++--- files/classes/comment.py | 24 ++++++++++++++---------- files/classes/follows.py | 9 +++++++-- files/classes/group.py | 9 +++++++-- files/classes/group_membership.py | 7 ++++++- files/classes/hats.py | 13 +++++++++---- files/classes/hole.py | 8 ++++---- files/classes/hole_logs.py | 13 +++++++++---- files/classes/hole_relationship.py | 7 ++++++- files/classes/ip_logs.py | 7 ++++++- files/classes/mod_logs.py | 13 +++++++++---- files/classes/notifications.py | 9 +++++++-- files/classes/polls.py | 17 +++++++++++------ files/classes/post.py | 21 +++++++++++++-------- files/classes/reports.py | 9 +++++++-- files/classes/saves.py | 10 ++++++++-- files/classes/subscriptions.py | 9 +++++++-- files/classes/user.py | 30 +++++++++++++++--------------- files/classes/userblock.py | 9 +++++++-- files/classes/usermute.py | 9 +++++++-- files/classes/views.py | 7 ++++++- files/classes/votes.py | 9 +++++++-- 25 files changed, 199 insertions(+), 86 deletions(-) diff --git a/files/classes/award.py b/files/classes/award.py index 8f658226d..f472c51b2 100644 --- a/files/classes/award.py +++ b/files/classes/award.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -8,6 +9,9 @@ from files.classes import Base from files.helpers.config.awards import AWARDS, HOUSE_AWARDS from files.helpers.lazy import lazy +if TYPE_CHECKING: + from files.classes import Comment, Post, User + class AwardRelationship(Base): __tablename__ = "award_relationships" @@ -22,9 +26,9 @@ class AwardRelationship(Base): price_paid: Mapped[int] = mapped_column(default = 0) note: Mapped[str] - user = relationship("User", primaryjoin="AwardRelationship.user_id==User.id", back_populates="awards") - post = relationship("Post", primaryjoin="AwardRelationship.post_id==Post.id", back_populates="awards") - comment = relationship("Comment", primaryjoin="AwardRelationship.comment_id==Comment.id", back_populates="awards") + user: Mapped["User"] = relationship(primaryjoin="AwardRelationship.user_id==User.id", back_populates="awards") + post: Mapped["Post"] = relationship(primaryjoin="AwardRelationship.post_id==Post.id", back_populates="awards") + comment: Mapped["Comment"] = relationship(primaryjoin="AwardRelationship.comment_id==Comment.id", back_populates="awards") def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/badges.py b/files/classes/badges.py index 4bce446a4..5f139d749 100644 --- a/files/classes/badges.py +++ b/files/classes/badges.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -8,6 +9,10 @@ from files.classes import Base from files.helpers.config.const import * from files.helpers.lazy import lazy +if TYPE_CHECKING: + from files.classes import User + + class BadgeDef(Base): __tablename__ = "badge_defs" @@ -38,8 +43,8 @@ class Badge(Base): url: Mapped[str] created_utc: Mapped[int] - user = relationship("User", back_populates="badges") - badge = relationship("BadgeDef", primaryjoin="Badge.badge_id == BadgeDef.id", lazy="joined", innerjoin=True) + user: Mapped["User"] = relationship(back_populates="badges") + badge: Mapped["BadgeDef"] = relationship(primaryjoin="Badge.badge_id == BadgeDef.id", lazy="joined", innerjoin=True) def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: diff --git a/files/classes/casino_game.py b/files/classes/casino_game.py index 23380d0e5..fdf8a8d39 100644 --- a/files/classes/casino_game.py +++ b/files/classes/casino_game.py @@ -1,5 +1,6 @@ import json import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -8,6 +9,9 @@ from sqlalchemy.sql.sqltypes import * from files.classes import Base from files.helpers.lazy import lazy +if TYPE_CHECKING: + from files.classes import User + CASINO_GAME_KINDS = ['blackjack', 'slots', 'roulette'] class CasinoGame(Base): @@ -23,7 +27,7 @@ class CasinoGame(Base): kind: Mapped[str] game_state: Mapped[str] = mapped_column(JSON) - user = relationship("User") + user: Mapped["User"] = relationship() def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: diff --git a/files/classes/clients.py b/files/classes/clients.py index 8034cd697..37271968e 100644 --- a/files/classes/clients.py +++ b/files/classes/clients.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from flask import g from sqlalchemy import ForeignKey @@ -12,6 +13,10 @@ from files.helpers.lazy import lazy from .comment import Comment from .post import Post +if TYPE_CHECKING: + from files.classes import User + + class OauthApp(Base): __tablename__ = "oauth_apps" @@ -23,7 +28,7 @@ class OauthApp(Base): author_id: Mapped[int] = mapped_column(ForeignKey("users.id")) created_utc: Mapped[int] - author = relationship("User", back_populates="apps") + author: Mapped["User"] = relationship(back_populates="apps") def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) @@ -56,8 +61,8 @@ class ClientAuth(Base): access_token: Mapped[str] created_utc: Mapped[int] - user = relationship("User") - application = relationship("OauthApp") + user: Mapped["User"] = relationship() + application: Mapped["OauthApp"] = relationship() def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/comment.py b/files/classes/comment.py index a275f04c4..f4c6e2ad0 100644 --- a/files/classes/comment.py +++ b/files/classes/comment.py @@ -1,6 +1,7 @@ import time from math import floor from random import randint +from typing import TYPE_CHECKING from urllib.parse import parse_qs, urlencode, urlparse from flask import g @@ -21,6 +22,9 @@ from files.helpers.bleach_body import * from .saves import CommentSaveRelationship +if TYPE_CHECKING: + from files.classes import AwardRelationship, CasinoGame, CommentOption, CommentReport, OauthApp, Post, User + def get_emoji_awards_emojis(obj, v, kind, NSFW_EMOJIS): if g.show_nsfw: emojis = [x.note for x in obj.awards if x.kind == kind] @@ -216,16 +220,16 @@ class Comment(Base): else: nsfw = False - oauth_app = relationship("OauthApp") - post = relationship("Post", back_populates="comments") - author = relationship("User", primaryjoin="User.id==Comment.author_id") - senttouser = relationship("User", primaryjoin="User.id==Comment.sentto") - parent_comment = relationship("Comment", remote_side=[id]) - awards = relationship("AwardRelationship", order_by="AwardRelationship.awarded_utc.desc()", back_populates="comment") - reports = relationship("CommentReport", order_by="CommentReport.created_utc") - options = relationship("CommentOption", order_by="CommentOption.id") - casino_game = relationship("CasinoGame") - wall_user = relationship("User", primaryjoin="User.id==Comment.wall_user_id") + oauth_app: Mapped["OauthApp"] = relationship() + post: Mapped["Post"] = relationship(back_populates="comments") + author: Mapped["User"] = relationship(primaryjoin="User.id==Comment.author_id") + senttouser: Mapped["User"] = relationship(primaryjoin="User.id==Comment.sentto") + parent_comment: Mapped["Comment"] = relationship(remote_side=[id]) + awards: Mapped[list["AwardRelationship"]] = relationship(order_by="AwardRelationship.awarded_utc.desc()", back_populates="comment") + reports: Mapped[list["CommentReport"]] = relationship(order_by="CommentReport.created_utc") + options: Mapped[list["CommentOption"]] = relationship(order_by="CommentOption.id") + casino_game: Mapped["CasinoGame"] = relationship() + wall_user: Mapped["User"] = relationship(primaryjoin="User.id==Comment.wall_user_id") def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: diff --git a/files/classes/follows.py b/files/classes/follows.py index 0229a86bb..0a8e7cc7c 100644 --- a/files/classes/follows.py +++ b/files/classes/follows.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -6,14 +7,18 @@ from sqlalchemy.sql.sqltypes import * from files.classes import Base +if TYPE_CHECKING: + from files.classes import User + + class Follow(Base): __tablename__ = "follows" target_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) created_utc: Mapped[int] - user = relationship("User", uselist=False, primaryjoin="User.id==Follow.user_id", back_populates="following") - target = relationship("User", uselist=False, primaryjoin="User.id==Follow.target_id", back_populates="followers") + user: Mapped["User"] = relationship(uselist=False, primaryjoin="User.id==Follow.user_id", back_populates="following") + target: Mapped["User"] = relationship(uselist=False, primaryjoin="User.id==Follow.target_id", back_populates="followers") def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/group.py b/files/classes/group.py index cae7a3768..52c2e00a7 100644 --- a/files/classes/group.py +++ b/files/classes/group.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.types import Integer @@ -9,6 +10,10 @@ from files.helpers.config.const import * from .group_membership import * +if TYPE_CHECKING: + from files.classes import User + + class Group(Base): __tablename__ = "groups" name: Mapped[str] = mapped_column(primary_key=True) @@ -17,8 +22,8 @@ class Group(Base): description: Mapped[str] description_html: Mapped[str] - memberships = relationship("GroupMembership", primaryjoin="GroupMembership.group_name==Group.name", order_by="GroupMembership.approved_utc") - owner = relationship("User", primaryjoin="Group.owner_id==User.id") + memberships: Mapped[list["GroupMembership"]] = relationship(primaryjoin="GroupMembership.group_name==Group.name", order_by="GroupMembership.approved_utc") + owner: Mapped["User"] = relationship(primaryjoin="Group.owner_id==User.id") def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/group_membership.py b/files/classes/group_membership.py index 733158be1..127ef7dce 100644 --- a/files/classes/group_membership.py +++ b/files/classes/group_membership.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -6,6 +7,10 @@ from sqlalchemy.types import Integer, String, Boolean from files.classes import Base +if TYPE_CHECKING: + from files.classes.user import User + + class GroupMembership(Base): __tablename__ = "group_memberships" user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) @@ -14,7 +19,7 @@ class GroupMembership(Base): approved_utc: Mapped[int] is_mod: Mapped[bool] = mapped_column(default=False) - user = relationship("User", uselist=False) + user: Mapped["User"] = relationship(uselist=False) def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/hats.py b/files/classes/hats.py index 2e7bd9f42..024c132da 100644 --- a/files/classes/hats.py +++ b/files/classes/hats.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -9,6 +10,10 @@ from files.classes import Base from files.helpers.lazy import lazy from files.helpers.slurs_and_profanities import censor_slurs_profanities +if TYPE_CHECKING: + from files.classes import User + + class HatDef(Base): __tablename__ = "hat_defs" @@ -20,8 +25,8 @@ class HatDef(Base): submitter_id: Mapped[int] = mapped_column(ForeignKey("users.id")) created_utc: Mapped[int] - author = relationship("User", primaryjoin="HatDef.author_id == User.id", back_populates="designed_hats") - submitter = relationship("User", primaryjoin="HatDef.submitter_id == User.id") + author: Mapped["User"] = relationship(primaryjoin="HatDef.author_id == User.id", back_populates="designed_hats") + submitter: Mapped["User"] = relationship(primaryjoin="HatDef.submitter_id == User.id") def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) @@ -53,8 +58,8 @@ class Hat(Base): equipped: Mapped[bool] = mapped_column(default=False) created_utc: Mapped[int] - hat_def = relationship("HatDef") - owners = relationship("User", back_populates="owned_hats") + hat_def: Mapped["HatDef"] = relationship() + owners: Mapped[list["User"]] = relationship(back_populates="owned_hats") def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/hole.py b/files/classes/hole.py index 3e9ae7958..b1a6d77e9 100644 --- a/files/classes/hole.py +++ b/files/classes/hole.py @@ -3,7 +3,7 @@ import time from typing import Annotated from sqlalchemy.ext.mutable import MutableList -from sqlalchemy.orm import Mapped, mapped_column, relationship +from sqlalchemy.orm import DynamicMapped, Mapped, mapped_column, relationship from sqlalchemy.dialects.postgresql import ARRAY from files.classes import Base @@ -29,9 +29,9 @@ class Hole(Base): else: snappy_quotes: Mapped[Annotated[str, HOLE_SNAPPY_QUOTES_LENGTH]] = mapped_column(deferred=True) - blocks = relationship("HoleBlock", primaryjoin="HoleBlock.hole==Hole.name") - followers = relationship("HoleFollow", primaryjoin="HoleFollow.hole==Hole.name") - stealth_hole_unblocks = relationship("StealthHoleUnblock", lazy="dynamic", primaryjoin="StealthHoleUnblock.hole==Hole.name") + blocks: Mapped[list["HoleBlock"]] = relationship(primaryjoin="HoleBlock.hole==Hole.name") + followers: Mapped[list["HoleFollow"]] = relationship(primaryjoin="HoleFollow.hole==Hole.name") + stealth_hole_unblocks: DynamicMapped["StealthHoleUnblock"] = relationship(primaryjoin="StealthHoleUnblock.hole==Hole.name") def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/hole_logs.py b/files/classes/hole_logs.py index 1c7bf7233..1488c27bd 100644 --- a/files/classes/hole_logs.py +++ b/files/classes/hole_logs.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -11,6 +12,10 @@ from files.helpers.lazy import lazy from files.helpers.slurs_and_profanities import censor_slurs_profanities from files.helpers.sorting_and_time import make_age_string +if TYPE_CHECKING: + from files.classes import Comment, Post, User + + class HoleAction(Base): __tablename__ = "hole_actions" id: Mapped[int] = mapped_column(primary_key=True) @@ -23,10 +28,10 @@ class HoleAction(Base): _note: Mapped[str] created_utc: Mapped[int] - user = relationship("User", primaryjoin="User.id==HoleAction.user_id") - target_user = relationship("User", primaryjoin="User.id==HoleAction.target_user_id") - target_post = relationship("Post") - target_comment = relationship("Comment") + user: Mapped["User"] = relationship(primaryjoin="User.id==HoleAction.user_id") + target_user: Mapped["User"] = relationship(primaryjoin="User.id==HoleAction.target_user_id") + target_post: Mapped["Post"] = relationship() + target_comment: Mapped["Comment"] = relationship() def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/hole_relationship.py b/files/classes/hole_relationship.py index 07b70031f..e581992c8 100644 --- a/files/classes/hole_relationship.py +++ b/files/classes/hole_relationship.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, relationship, mapped_column @@ -6,6 +7,10 @@ from sqlalchemy.sql.sqltypes import * from files.classes import Base +if TYPE_CHECKING: + from files.classes import User + + class HoleRelationship(Base): __tablename__ = NotImplemented __abstract__ = True @@ -36,4 +41,4 @@ class Mod(HoleRelationship): class Exile(HoleRelationship): __tablename__ = "exiles" exiler_id: Mapped[int] = mapped_column(ForeignKey("users.id")) - exiler = relationship("User", primaryjoin="User.id==Exile.exiler_id") + exiler: Mapped["User"] = relationship(primaryjoin="User.id==Exile.exiler_id") diff --git a/files/classes/ip_logs.py b/files/classes/ip_logs.py index d19941df0..7fb965aff 100644 --- a/files/classes/ip_logs.py +++ b/files/classes/ip_logs.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -6,6 +7,10 @@ from sqlalchemy.sql.sqltypes import * from files.classes import Base +if TYPE_CHECKING: + from files.classes import User + + class IPLog(Base): __tablename__ = "ip_logs" user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) @@ -13,7 +18,7 @@ class IPLog(Base): created_utc: Mapped[int] last_used: Mapped[int] - user = relationship("User") + user: Mapped["User"] = relationship() def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: diff --git a/files/classes/mod_logs.py b/files/classes/mod_logs.py index 747fbe79b..f8c1f3725 100644 --- a/files/classes/mod_logs.py +++ b/files/classes/mod_logs.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -11,6 +12,10 @@ from files.helpers.lazy import lazy from files.helpers.slurs_and_profanities import censor_slurs_profanities from files.helpers.sorting_and_time import make_age_string +if TYPE_CHECKING: + from files.classes import Comment, Post, User + + class ModAction(Base): __tablename__ = "modactions" id: Mapped[int] = mapped_column(primary_key=True) @@ -22,10 +27,10 @@ class ModAction(Base): _note: Mapped[str] created_utc: Mapped[int] - user = relationship("User", primaryjoin="User.id==ModAction.user_id") - target_user = relationship("User", primaryjoin="User.id==ModAction.target_user_id") - target_post = relationship("Post") - target_comment = relationship("Comment") + user: Mapped["User"] = relationship(primaryjoin="User.id==ModAction.user_id") + target_user: Mapped["User"] = relationship(primaryjoin="User.id==ModAction.target_user_id") + target_post: Mapped["Post"] = relationship() + target_comment: Mapped["Comment"] = relationship() def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/notifications.py b/files/classes/notifications.py index 4e50e63b1..c0a2ca651 100644 --- a/files/classes/notifications.py +++ b/files/classes/notifications.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -6,6 +7,10 @@ from sqlalchemy.sql.sqltypes import * from files.classes import Base +if TYPE_CHECKING: + from files.classes import Comment, User + + class Notification(Base): __tablename__ = "notifications" @@ -14,8 +19,8 @@ class Notification(Base): read: Mapped[bool] = mapped_column(default=False) created_utc: Mapped[int] - comment = relationship("Comment") - user = relationship("User") + comment: Mapped["Comment"] = relationship() + user: Mapped["User"] = relationship() def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/polls.py b/files/classes/polls.py index d0b297100..847745f23 100644 --- a/files/classes/polls.py +++ b/files/classes/polls.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -7,6 +8,10 @@ from sqlalchemy.sql.sqltypes import * from files.classes import Base from files.helpers.lazy import lazy +if TYPE_CHECKING: + from files.classes import Comment, Post, User + + class PostOption(Base): __tablename__ = "post_options" @@ -16,8 +21,8 @@ class PostOption(Base): exclusive: Mapped[int] created_utc: Mapped[int] - votes = relationship("PostOptionVote") - parent = relationship("Post", back_populates="options") + votes: Mapped[list["PostOptionVote"]] = relationship() + parent: Mapped["Post"] = relationship(back_populates="options") def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) @@ -45,7 +50,7 @@ class PostOptionVote(Base): created_utc: Mapped[int] post_id: Mapped[int] = mapped_column(ForeignKey("posts.id")) - user = relationship("User") + user: Mapped["User"] = relationship() def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) @@ -65,8 +70,8 @@ class CommentOption(Base): exclusive: Mapped[int] created_utc: Mapped[int] - votes = relationship("CommentOptionVote") - parent = relationship("Comment", back_populates="options") + votes: Mapped[list["CommentOptionVote"]] = relationship() + parent: Mapped["Comment"] = relationship(back_populates="options") def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) @@ -94,7 +99,7 @@ class CommentOptionVote(Base): created_utc: Mapped[int] comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id")) - user = relationship("User") + user: Mapped["User"] = relationship() def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/post.py b/files/classes/post.py index af110938e..dfc596d47 100644 --- a/files/classes/post.py +++ b/files/classes/post.py @@ -1,5 +1,6 @@ import random import time +from typing import TYPE_CHECKING from urllib.parse import urlparse from flask import g @@ -22,6 +23,10 @@ from .hole import * from .subscriptions import * from .saves import SaveRelationship +if TYPE_CHECKING: + from files.classes import OauthApp, Report + + class Post(Base): __tablename__ = "posts" @@ -77,14 +82,14 @@ class Post(Base): if SITE_NAME == 'WPD': cw: Mapped[bool] = mapped_column(default=False) - author = relationship("User", primaryjoin="Post.author_id==User.id") - oauth_app = relationship("OauthApp") - approved_by = relationship("User", uselist=False, primaryjoin="Post.is_approved==User.id") - awards = relationship("AwardRelationship", order_by="AwardRelationship.awarded_utc.desc()", back_populates="post") - reports = relationship("Report", order_by="Report.created_utc") - comments = relationship("Comment", primaryjoin="Comment.parent_post==Post.id", back_populates="post") - hole_obj = relationship("Hole", primaryjoin="foreign(Post.hole)==remote(Hole.name)") - options = relationship("PostOption", order_by="PostOption.id") + author: Mapped["User"] = relationship(primaryjoin="Post.author_id==User.id") + oauth_app: Mapped["OauthApp"] = relationship() + approved_by: Mapped["User"] = relationship(uselist=False, primaryjoin="Post.is_approved==User.id") + awards: Mapped[list["AwardRelationship"]] = relationship(order_by="AwardRelationship.awarded_utc.desc()", back_populates="post") + reports: Mapped[list["Report"]] = relationship(order_by="Report.created_utc") + comments: Mapped[list["Comment"]] = relationship(primaryjoin="Comment.parent_post==Post.id", back_populates="post") + hole_obj: Mapped["Hole"] = relationship(primaryjoin="foreign(Post.hole)==remote(Hole.name)") + options: Mapped[list["PostOption"]] = relationship(order_by="PostOption.id") def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: diff --git a/files/classes/reports.py b/files/classes/reports.py index 877804473..d1b512a40 100644 --- a/files/classes/reports.py +++ b/files/classes/reports.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -8,6 +9,10 @@ from files.classes import Base from files.helpers.lazy import lazy from files.helpers.slurs_and_profanities import censor_slurs_profanities +if TYPE_CHECKING: + from files.classes import User + + class Report(Base): __tablename__ = "reports" @@ -16,7 +21,7 @@ class Report(Base): reason: Mapped[str] created_utc: Mapped[int] - user = relationship("User", primaryjoin = "Report.user_id == User.id", uselist = False) + user: Mapped["User"] = relationship(primaryjoin = "Report.user_id == User.id", uselist = False) def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) @@ -44,7 +49,7 @@ class CommentReport(Base): reason: Mapped[str] created_utc: Mapped[int] - user = relationship("User", primaryjoin = "CommentReport.user_id == User.id", uselist = False) + user: Mapped["User"] = relationship(primaryjoin = "CommentReport.user_id == User.id", uselist = False) def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/saves.py b/files/classes/saves.py index 4d02a50d8..2a072e5d3 100644 --- a/files/classes/saves.py +++ b/files/classes/saves.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -6,6 +7,11 @@ from sqlalchemy.sql.sqltypes import * from files.classes import Base +if TYPE_CHECKING: + from files.classes.comment import Comment + from files.classes.post import Post + + class SaveRelationship(Base): __tablename__ = "save_relationship" @@ -13,7 +19,7 @@ class SaveRelationship(Base): post_id: Mapped[int] = mapped_column(ForeignKey("posts.id"), primary_key=True) created_utc: Mapped[int] - post = relationship("Post", uselist=False) + post: Mapped["Post"] = relationship(uselist=False) def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) @@ -31,7 +37,7 @@ class CommentSaveRelationship(Base): comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id"), primary_key=True) created_utc: Mapped[int] - comment = relationship("Comment", uselist=False) + comment: Mapped["Comment"] = relationship(uselist=False) def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/subscriptions.py b/files/classes/subscriptions.py index aa7b0b034..5c579d3d5 100644 --- a/files/classes/subscriptions.py +++ b/files/classes/subscriptions.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -6,14 +7,18 @@ from sqlalchemy.sql.sqltypes import * from files.classes import Base +if TYPE_CHECKING: + from files.classes import Post, User + + class Subscription(Base): __tablename__ = "subscriptions" user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) post_id: Mapped[int] = mapped_column(ForeignKey("posts.id"), primary_key=True) created_utc: Mapped[int] - user = relationship("User", uselist=False) - post = relationship("Post", uselist=False) + user: Mapped["User"] = relationship(uselist=False) + post: Mapped["Post"] = relationship(uselist=False) def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/user.py b/files/classes/user.py index eefc857e2..d64bac889 100644 --- a/files/classes/user.py +++ b/files/classes/user.py @@ -3,7 +3,7 @@ from operator import * import pyotp from sqlalchemy import ForeignKey, FetchedValue -from sqlalchemy.orm import Mapped, Query, aliased, deferred, mapped_column +from sqlalchemy.orm import DynamicMapped, Mapped, Query, aliased, deferred, mapped_column from sqlalchemy.sql import case, func, literal from sqlalchemy.sql.expression import not_, and_, or_ from sqlalchemy.sql.sqltypes import * @@ -175,20 +175,20 @@ class User(Base): zombie: Mapped[int] = mapped_column(default=0) # > 0 vaxxed; < 0 zombie jumpscare: Mapped[int] = mapped_column(default=0) - badges = relationship("Badge", order_by="Badge.created_utc", back_populates="user") - subscriptions = relationship("Subscription", back_populates="user") - following = relationship("Follow", primaryjoin="Follow.user_id==User.id", back_populates="user") - followers = relationship("Follow", primaryjoin="Follow.target_id==User.id", back_populates="target") - blocking = relationship("UserBlock", lazy="dynamic", primaryjoin="User.id==UserBlock.user_id", back_populates="user") - blocked = relationship("UserBlock", lazy="dynamic", primaryjoin="User.id==UserBlock.target_id", back_populates="target") - authorizations = relationship("ClientAuth", back_populates="user") - apps = relationship("OauthApp", back_populates="author") - awards = relationship("AwardRelationship", primaryjoin="User.id==AwardRelationship.user_id", back_populates="user") - referrals = relationship("User", primaryjoin="User.id==User.referred_by", order_by="User.created_utc") - designed_hats = relationship("HatDef", primaryjoin="User.id==HatDef.author_id", back_populates="author") - owned_hats = relationship("Hat", back_populates="owners") - hats_equipped = relationship("Hat", lazy="raise", viewonly=True) - hole_mods = relationship("Mod", primaryjoin="User.id == Mod.user_id", lazy="raise") + badges: Mapped[list["Badge"]] = relationship(order_by="Badge.created_utc", back_populates="user") + subscriptions: Mapped[list["Subscription"]] = relationship(back_populates="user") + following: Mapped[list["Follow"]] = relationship(primaryjoin="Follow.user_id==User.id", back_populates="user") + followers: Mapped[list["Follow"]] = relationship(primaryjoin="Follow.target_id==User.id", back_populates="target") + blocking: DynamicMapped["UserBlock"] = relationship(primaryjoin="User.id==UserBlock.user_id", back_populates="user") + blocked: DynamicMapped["UserBlock"] = relationship(primaryjoin="User.id==UserBlock.target_id", back_populates="target") + authorizations: Mapped[list["ClientAuth"]] = relationship(back_populates="user") + apps: Mapped[list["OauthApp"]] = relationship(back_populates="author") + awards: Mapped[list["AwardRelationship"]] = relationship(primaryjoin="User.id==AwardRelationship.user_id", back_populates="user") + referrals: Mapped[list["User"]] = relationship(primaryjoin="User.id==User.referred_by", order_by="User.created_utc") + designed_hats: Mapped[list["HatDef"]] = relationship(primaryjoin="User.id==HatDef.author_id", back_populates="author") + owned_hats: Mapped[list["Hat"]] = relationship(back_populates="owners") + hats_equipped: Mapped[list["Hat"]] = relationship(lazy="raise", viewonly=True) + hole_mods: Mapped[list["Mod"]] = relationship(primaryjoin="User.id == Mod.user_id", lazy="raise") def __init__(self, **kwargs): diff --git a/files/classes/userblock.py b/files/classes/userblock.py index 5d815179d..139e6c255 100644 --- a/files/classes/userblock.py +++ b/files/classes/userblock.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -6,14 +7,18 @@ from sqlalchemy.sql.sqltypes import * from files.classes import Base +if TYPE_CHECKING: + from files.classes import User + + class UserBlock(Base): __tablename__ = "userblocks" user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) target_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) created_utc: Mapped[int] - user = relationship("User", primaryjoin="User.id==UserBlock.user_id", back_populates="blocking") - target = relationship("User", primaryjoin="User.id==UserBlock.target_id", back_populates="blocked") + user: Mapped["User"] = relationship(primaryjoin="User.id==UserBlock.user_id", back_populates="blocking") + target: Mapped["User"] = relationship(primaryjoin="User.id==UserBlock.target_id", back_populates="blocked") def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/usermute.py b/files/classes/usermute.py index 48c0d1566..2a8da2b3e 100644 --- a/files/classes/usermute.py +++ b/files/classes/usermute.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -6,14 +7,18 @@ from sqlalchemy.sql.sqltypes import * from files.classes import Base +if TYPE_CHECKING: + from files.classes import User + + class UserMute(Base): __tablename__ = "usermutes" user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) target_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) created_utc: Mapped[int] - user = relationship("User", primaryjoin="User.id==UserMute.user_id") - target = relationship("User", primaryjoin="User.id==UserMute.target_id") + user: Mapped["User"] = relationship(primaryjoin="User.id==UserMute.user_id") + target: Mapped["User"] = relationship(primaryjoin="User.id==UserMute.target_id") def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/views.py b/files/classes/views.py index 654eeee93..d914276a0 100644 --- a/files/classes/views.py +++ b/files/classes/views.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -8,6 +9,10 @@ from files.classes import Base from files.helpers.lazy import * from files.helpers.sorting_and_time import make_age_string +if TYPE_CHECKING: + from files.classes import User + + class ViewerRelationship(Base): __tablename__ = "viewers" @@ -16,7 +21,7 @@ class ViewerRelationship(Base): last_view_utc: Mapped[int] created_utc: Mapped[int] - viewer = relationship("User", primaryjoin="ViewerRelationship.viewer_id == User.id") + viewer: Mapped["User"] = relationship(primaryjoin="ViewerRelationship.viewer_id == User.id") def __init__(self, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/votes.py b/files/classes/votes.py index 7d19add0b..4c8a079e4 100644 --- a/files/classes/votes.py +++ b/files/classes/votes.py @@ -1,4 +1,5 @@ import time +from typing import TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -7,6 +8,10 @@ from sqlalchemy.sql.sqltypes import * from files.classes import Base from files.helpers.lazy import lazy +if TYPE_CHECKING: + from files.classes import User + + class Vote(Base): __tablename__ = "votes" @@ -17,7 +22,7 @@ class Vote(Base): coins: Mapped[int] = mapped_column(default=1) created_utc: Mapped[int] - user = relationship("User") + user: Mapped["User"] = relationship() def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) @@ -47,7 +52,7 @@ class CommentVote(Base): coins: Mapped[int] = mapped_column(default=1) created_utc: Mapped[int] - user = relationship("User") + user: Mapped["User"] = relationship() def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) -- 2.34.1 From 778c2272f55a3ba9c73cc366ffe5c24f9b952bd1 Mon Sep 17 00:00:00 2001 From: TriHard Date: Thu, 15 Feb 2024 06:17:23 -0700 Subject: [PATCH 5/7] Apply Optional to nullable columns --- files/classes/alts.py | 3 +- files/classes/award.py | 12 ++-- files/classes/badges.py | 8 +-- files/classes/clients.py | 8 +-- files/classes/comment.py | 38 +++++----- files/classes/domains.py | 3 +- files/classes/emoji.py | 3 +- files/classes/group.py | 8 +-- files/classes/group_membership.py | 4 +- files/classes/hats.py | 8 +-- files/classes/hole.py | 16 ++--- files/classes/hole_logs.py | 14 ++-- files/classes/hole_relationship.py | 4 +- files/classes/lottery.py | 5 +- files/classes/mod_logs.py | 14 ++-- files/classes/orgy.py | 3 +- files/classes/polls.py | 10 +-- files/classes/post.py | 38 +++++----- files/classes/reports.py | 6 +- files/classes/saves.py | 6 +- files/classes/subscriptions.py | 4 +- files/classes/transactions.py | 4 +- files/classes/user.py | 107 +++++++++++++++-------------- files/classes/userblock.py | 4 +- files/classes/usermute.py | 4 +- files/classes/views.py | 4 +- 26 files changed, 173 insertions(+), 165 deletions(-) diff --git a/files/classes/alts.py b/files/classes/alts.py index 28f853d63..cf4448c81 100644 --- a/files/classes/alts.py +++ b/files/classes/alts.py @@ -1,4 +1,5 @@ import time +from typing import Optional from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column @@ -12,7 +13,7 @@ class Alt(Base): user1: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) user2: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) is_manual: Mapped[bool] = mapped_column(default=False) - created_utc: Mapped[int] + created_utc: Mapped[Optional[int]] def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/award.py b/files/classes/award.py index f472c51b2..0a72ee9da 100644 --- a/files/classes/award.py +++ b/files/classes/award.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -18,13 +18,13 @@ class AwardRelationship(Base): id: Mapped[int] = mapped_column(primary_key=True) user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) - post_id: Mapped[int] = mapped_column(ForeignKey("posts.id")) - comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id")) + post_id: Mapped[Optional[int]] = mapped_column(ForeignKey("posts.id")) + comment_id: Mapped[Optional[int]] = mapped_column(ForeignKey("comments.id")) kind: Mapped[str] - awarded_utc: Mapped[int] - created_utc: Mapped[int] + awarded_utc: Mapped[Optional[int]] + created_utc: Mapped[Optional[int]] price_paid: Mapped[int] = mapped_column(default = 0) - note: Mapped[str] + note: Mapped[Optional[str]] user: Mapped["User"] = relationship(primaryjoin="AwardRelationship.user_id==User.id", back_populates="awards") post: Mapped["Post"] = relationship(primaryjoin="AwardRelationship.post_id==Post.id", back_populates="awards") diff --git a/files/classes/badges.py b/files/classes/badges.py index 5f139d749..3ecbff807 100644 --- a/files/classes/badges.py +++ b/files/classes/badges.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -18,7 +18,7 @@ class BadgeDef(Base): id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) name: Mapped[str] - description: Mapped[str] + description: Mapped[Optional[str]] created_utc: Mapped[int] def __init__(self, *args, **kwargs): @@ -39,8 +39,8 @@ class Badge(Base): user_id: Mapped[int] = mapped_column(ForeignKey('users.id'), primary_key=True) badge_id: Mapped[int] = mapped_column(ForeignKey('badge_defs.id'), primary_key=True) - description: Mapped[str] - url: Mapped[str] + description: Mapped[Optional[str]] + url: Mapped[Optional[str]] created_utc: Mapped[int] user: Mapped["User"] = relationship(back_populates="badges") diff --git a/files/classes/clients.py b/files/classes/clients.py index 37271968e..1788a0867 100644 --- a/files/classes/clients.py +++ b/files/classes/clients.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Annotated, Optional, TYPE_CHECKING from flask import g from sqlalchemy import ForeignKey @@ -21,12 +21,12 @@ class OauthApp(Base): __tablename__ = "oauth_apps" id: Mapped[int] = mapped_column(primary_key=True) - client_id: Mapped[str] + client_id: Mapped[Optional[Annotated[str, 64]]] app_name: Mapped[str] redirect_uri: Mapped[str] description: Mapped[str] author_id: Mapped[int] = mapped_column(ForeignKey("users.id")) - created_utc: Mapped[int] + created_utc: Mapped[Optional[int]] author: Mapped["User"] = relationship(back_populates="apps") @@ -59,7 +59,7 @@ class ClientAuth(Base): user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) oauth_client: Mapped[int] = mapped_column(ForeignKey("oauth_apps.id"), primary_key=True) access_token: Mapped[str] - created_utc: Mapped[int] + created_utc: Mapped[Optional[int]] user: Mapped["User"] = relationship() application: Mapped["OauthApp"] = relationship() diff --git a/files/classes/comment.py b/files/classes/comment.py index f4c6e2ad0..6ae808aa4 100644 --- a/files/classes/comment.py +++ b/files/classes/comment.py @@ -1,7 +1,7 @@ import time from math import floor from random import randint -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from urllib.parse import parse_qs, urlencode, urlparse from flask import g @@ -178,38 +178,38 @@ class Comment(Base): id: Mapped[int] = mapped_column(primary_key=True) author_id: Mapped[int] = mapped_column(ForeignKey("users.id")) - parent_post: Mapped[int] = mapped_column(ForeignKey("posts.id")) - wall_user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + parent_post: Mapped[Optional[int]] = mapped_column(ForeignKey("posts.id")) + wall_user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) created_utc: Mapped[int] edited_utc: Mapped[int] = mapped_column(default=0) is_banned: Mapped[bool] = mapped_column(default=False) ghost: Mapped[bool] = mapped_column(default=False) - bannedfor: Mapped[str] - chuddedfor: Mapped[str] + bannedfor: Mapped[Optional[str]] + chuddedfor: Mapped[Optional[str]] distinguished: Mapped[bool] = mapped_column(default=False) deleted_utc: Mapped[int] = mapped_column(default=0) - is_approved: Mapped[int] = mapped_column(ForeignKey("users.id")) + is_approved: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) level: Mapped[int] = mapped_column(default=1) - parent_comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id")) - top_comment_id: Mapped[int] + parent_comment_id: Mapped[Optional[int]] = mapped_column(ForeignKey("comments.id")) + top_comment_id: Mapped[Optional[int]] is_bot: Mapped[bool] = mapped_column(default=False) - stickied: Mapped[str] - stickied_utc: Mapped[int] + stickied: Mapped[Optional[str]] + stickied_utc: Mapped[Optional[int]] num_of_pinned_children: Mapped[int] = mapped_column(default=0) - sentto: Mapped[int] = mapped_column(ForeignKey("users.id")) - app_id: Mapped[int] = mapped_column(ForeignKey("oauth_apps.id")) + sentto: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + app_id: Mapped[Optional[int]] = mapped_column(ForeignKey("oauth_apps.id")) upvotes: Mapped[int] = mapped_column(default=1) downvotes: Mapped[int] = mapped_column(default=0) realupvotes: Mapped[int] = mapped_column(default=1) - body: Mapped[str] - body_html: Mapped[str] + body: Mapped[Optional[str]] + body_html: Mapped[Optional[str]] body_ts: Mapped[str] = mapped_column(TSVECTOR(), server_default=FetchedValue()) - ban_reason: Mapped[str] - treasure_amount: Mapped[str] - slots_result: Mapped[str] + ban_reason: Mapped[Optional[str]] + treasure_amount: Mapped[Optional[str]] + slots_result: Mapped[Optional[str]] ping_cost: Mapped[int] = mapped_column(default=0) - blackjack_result: Mapped[str] - casino_game_id: Mapped[int] = mapped_column(ForeignKey("casino_games.id")) + blackjack_result: Mapped[Optional[str]] + casino_game_id: Mapped[Optional[int]] = mapped_column(ForeignKey("casino_games.id")) chudded: Mapped[bool] = mapped_column(default=False) rainbowed: Mapped[bool] = mapped_column(default=False) queened: Mapped[bool] = mapped_column(default=False) diff --git a/files/classes/domains.py b/files/classes/domains.py index 36d27ef0a..9e728e98d 100644 --- a/files/classes/domains.py +++ b/files/classes/domains.py @@ -1,4 +1,5 @@ import time +from typing import Optional from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import * @@ -9,7 +10,7 @@ class BannedDomain(Base): __tablename__ = "banneddomains" domain: Mapped[str] = mapped_column(primary_key=True) reason: Mapped[str] - created_utc: Mapped[int] + created_utc: Mapped[Optional[int]] def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/emoji.py b/files/classes/emoji.py index 7b1c1a8db..bffe31260 100644 --- a/files/classes/emoji.py +++ b/files/classes/emoji.py @@ -1,4 +1,5 @@ import time +from typing import Optional from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column @@ -14,7 +15,7 @@ class Emoji(Base): author_id: Mapped[int] = mapped_column(ForeignKey("users.id")) tags: Mapped[str] count: Mapped[int] = mapped_column(default=0) - submitter_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + submitter_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) created_utc: Mapped[int] nsfw: Mapped[bool] = mapped_column(default=False) diff --git a/files/classes/group.py b/files/classes/group.py index 52c2e00a7..d3a2a4109 100644 --- a/files/classes/group.py +++ b/files/classes/group.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.types import Integer @@ -18,9 +18,9 @@ class Group(Base): __tablename__ = "groups" name: Mapped[str] = mapped_column(primary_key=True) created_utc: Mapped[int] - owner_id: Mapped[int] = mapped_column(ForeignKey("users.id")) - description: Mapped[str] - description_html: Mapped[str] + owner_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + description: Mapped[Optional[str]] + description_html: Mapped[Optional[str]] memberships: Mapped[list["GroupMembership"]] = relationship(primaryjoin="GroupMembership.group_name==Group.name", order_by="GroupMembership.approved_utc") owner: Mapped["User"] = relationship(primaryjoin="Group.owner_id==User.id") diff --git a/files/classes/group_membership.py b/files/classes/group_membership.py index 127ef7dce..b5153c974 100644 --- a/files/classes/group_membership.py +++ b/files/classes/group_membership.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -16,7 +16,7 @@ class GroupMembership(Base): user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) group_name: Mapped[str] = mapped_column(ForeignKey("groups.name"), primary_key=True) created_utc: Mapped[int] - approved_utc: Mapped[int] + approved_utc: Mapped[Optional[int]] is_mod: Mapped[bool] = mapped_column(default=False) user: Mapped["User"] = relationship(uselist=False) diff --git a/files/classes/hats.py b/files/classes/hats.py index 024c132da..0aef7d14d 100644 --- a/files/classes/hats.py +++ b/files/classes/hats.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -22,7 +22,7 @@ class HatDef(Base): description: Mapped[str] author_id: Mapped[int] = mapped_column(ForeignKey('users.id')) price: Mapped[int] - submitter_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + submitter_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) created_utc: Mapped[int] author: Mapped["User"] = relationship(primaryjoin="HatDef.author_id == User.id", back_populates="designed_hats") @@ -55,8 +55,8 @@ class Hat(Base): user_id: Mapped[int] = mapped_column(ForeignKey('users.id'), primary_key=True) hat_id: Mapped[int] = mapped_column(ForeignKey('hat_defs.id'), primary_key=True) - equipped: Mapped[bool] = mapped_column(default=False) - created_utc: Mapped[int] + equipped: Mapped[Optional[bool]] = mapped_column(default=False) + created_utc: Mapped[Optional[int]] hat_def: Mapped["HatDef"] = relationship() owners: Mapped[list["User"]] = relationship(back_populates="owned_hats") diff --git a/files/classes/hole.py b/files/classes/hole.py index b1a6d77e9..aade37b6b 100644 --- a/files/classes/hole.py +++ b/files/classes/hole.py @@ -1,6 +1,6 @@ import random import time -from typing import Annotated +from typing import Annotated, Optional from sqlalchemy.ext.mutable import MutableList from sqlalchemy.orm import DynamicMapped, Mapped, mapped_column, relationship @@ -15,19 +15,19 @@ from .hole_relationship import * class Hole(Base): __tablename__ = "holes" name: Mapped[str] = mapped_column(primary_key=True) - sidebar: Mapped[str] - sidebar_html: Mapped[str] + sidebar: Mapped[Optional[str]] + sidebar_html: Mapped[Optional[str]] sidebarurls: Mapped[list[str]] = mapped_column(MutableList.as_mutable(ARRAY(String)), default=MutableList([])) bannerurls: Mapped[list[str]] = mapped_column(MutableList.as_mutable(ARRAY(String)), default=MutableList([])) - marseyurl: Mapped[str] - css: Mapped[str] = mapped_column(deferred=True) - stealth: Mapped[bool] = mapped_column(default=False) + marseyurl: Mapped[Optional[str]] + css: Mapped[Optional[str]] = mapped_column(deferred=True) + stealth: Mapped[Optional[bool]] = mapped_column(default=False) public_use: Mapped[bool] = mapped_column(default=False) - created_utc: Mapped[int] + created_utc: Mapped[Optional[int]] if SITE_NAME == 'WPD': snappy_quotes = None else: - snappy_quotes: Mapped[Annotated[str, HOLE_SNAPPY_QUOTES_LENGTH]] = mapped_column(deferred=True) + snappy_quotes: Mapped[Optional[Annotated[str, HOLE_SNAPPY_QUOTES_LENGTH]]] = mapped_column(deferred=True) blocks: Mapped[list["HoleBlock"]] = relationship(primaryjoin="HoleBlock.hole==Hole.name") followers: Mapped[list["HoleFollow"]] = relationship(primaryjoin="HoleFollow.hole==Hole.name") diff --git a/files/classes/hole_logs.py b/files/classes/hole_logs.py index 1488c27bd..2c1398570 100644 --- a/files/classes/hole_logs.py +++ b/files/classes/hole_logs.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -20,12 +20,12 @@ class HoleAction(Base): __tablename__ = "hole_actions" id: Mapped[int] = mapped_column(primary_key=True) hole: Mapped[str] = mapped_column(ForeignKey("holes.name")) - user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) - kind: Mapped[str] - target_user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) - target_post_id: Mapped[int] = mapped_column(ForeignKey("posts.id")) - target_comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id")) - _note: Mapped[str] + user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + kind: Mapped[Optional[str]] + target_user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + target_post_id: Mapped[Optional[int]] = mapped_column(ForeignKey("posts.id")) + target_comment_id: Mapped[Optional[int]] = mapped_column(ForeignKey("comments.id")) + _note: Mapped[Optional[str]] created_utc: Mapped[int] user: Mapped["User"] = relationship(primaryjoin="User.id==HoleAction.user_id") diff --git a/files/classes/hole_relationship.py b/files/classes/hole_relationship.py index e581992c8..89a9b6971 100644 --- a/files/classes/hole_relationship.py +++ b/files/classes/hole_relationship.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, relationship, mapped_column @@ -17,7 +17,7 @@ class HoleRelationship(Base): user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) hole: Mapped[str] = mapped_column(ForeignKey("holes.name"), primary_key=True) - created_utc: Mapped[int] + created_utc: Mapped[Optional[int]] def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/lottery.py b/files/classes/lottery.py index 794ea7617..090ce49d4 100644 --- a/files/classes/lottery.py +++ b/files/classes/lottery.py @@ -1,4 +1,5 @@ import time +from typing import Optional from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column @@ -16,8 +17,8 @@ class Lottery(Base): ends_at: Mapped[int] prize: Mapped[int] = mapped_column(default=0) tickets_sold: Mapped[int] = mapped_column(default=0) - winner_id: Mapped[int] = mapped_column(ForeignKey("users.id")) - created_utc: Mapped[int] + winner_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + created_utc: Mapped[Optional[int]] def __init__(self, *args, **kwargs): if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) diff --git a/files/classes/mod_logs.py b/files/classes/mod_logs.py index f8c1f3725..41fba0839 100644 --- a/files/classes/mod_logs.py +++ b/files/classes/mod_logs.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -19,12 +19,12 @@ if TYPE_CHECKING: class ModAction(Base): __tablename__ = "modactions" id: Mapped[int] = mapped_column(primary_key=True) - user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) - kind: Mapped[str] - target_user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) - target_post_id: Mapped[int] = mapped_column(ForeignKey("posts.id")) - target_comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id")) - _note: Mapped[str] + user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + kind: Mapped[Optional[str]] + target_user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + target_post_id: Mapped[Optional[int]] = mapped_column(ForeignKey("posts.id")) + target_comment_id: Mapped[Optional[int]] = mapped_column(ForeignKey("comments.id")) + _note: Mapped[Optional[str]] created_utc: Mapped[int] user: Mapped["User"] = relationship(primaryjoin="User.id==ModAction.user_id") diff --git a/files/classes/orgy.py b/files/classes/orgy.py index 01708e643..819f73e31 100644 --- a/files/classes/orgy.py +++ b/files/classes/orgy.py @@ -1,6 +1,7 @@ import time from flask import g, abort import requests +from typing import Optional from sqlalchemy import or_ from sqlalchemy.orm import Mapped, mapped_column @@ -19,7 +20,7 @@ class Orgy(Base): data: Mapped[str] title: Mapped[str] start_utc: Mapped[int] - end_utc: Mapped[int] + end_utc: Mapped[Optional[int]] started: Mapped[bool] = mapped_column(default=False) def __init__(self, *args, **kwargs): diff --git a/files/classes/polls.py b/files/classes/polls.py index 847745f23..470765e0d 100644 --- a/files/classes/polls.py +++ b/files/classes/polls.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -19,7 +19,7 @@ class PostOption(Base): parent_id: Mapped[int] = mapped_column(ForeignKey("posts.id")) body_html: Mapped[str] = mapped_column(Text) exclusive: Mapped[int] - created_utc: Mapped[int] + created_utc: Mapped[Optional[int]] votes: Mapped[list["PostOptionVote"]] = relationship() parent: Mapped["Post"] = relationship(back_populates="options") @@ -48,7 +48,7 @@ class PostOptionVote(Base): option_id: Mapped[int] = mapped_column(ForeignKey("post_options.id"), primary_key=True) user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) created_utc: Mapped[int] - post_id: Mapped[int] = mapped_column(ForeignKey("posts.id")) + post_id: Mapped[Optional[int]] = mapped_column(ForeignKey("posts.id")) user: Mapped["User"] = relationship() @@ -68,7 +68,7 @@ class CommentOption(Base): parent_id: Mapped[int] = mapped_column(ForeignKey("comments.id")) body_html: Mapped[str] = mapped_column(Text) exclusive: Mapped[int] - created_utc: Mapped[int] + created_utc: Mapped[Optional[int]] votes: Mapped[list["CommentOptionVote"]] = relationship() parent: Mapped["Comment"] = relationship(back_populates="options") @@ -97,7 +97,7 @@ class CommentOptionVote(Base): option_id: Mapped[int] = mapped_column(ForeignKey("comment_options.id"), primary_key=True) user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) created_utc: Mapped[int] - comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id")) + comment_id: Mapped[Optional[int]] = mapped_column(ForeignKey("comments.id")) user: Mapped["User"] = relationship() diff --git a/files/classes/post.py b/files/classes/post.py index dfc596d47..17757da47 100644 --- a/files/classes/post.py +++ b/files/classes/post.py @@ -1,6 +1,6 @@ import random import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from urllib.parse import urlparse from flask import g @@ -34,38 +34,38 @@ class Post(Base): author_id: Mapped[int] = mapped_column(ForeignKey("users.id")) edited_utc: Mapped[int] = mapped_column(default=0) created_utc: Mapped[int] - thumburl: Mapped[str] - posterurl: Mapped[str] + thumburl: Mapped[Optional[str]] + posterurl: Mapped[Optional[str]] is_banned: Mapped[bool] = mapped_column(default=False) - bannedfor: Mapped[str] - chuddedfor: Mapped[str] + bannedfor: Mapped[Optional[str]] + chuddedfor: Mapped[Optional[str]] ghost: Mapped[bool] = mapped_column(default=False) effortpost: Mapped[bool] = mapped_column(default=False) views: Mapped[int] = mapped_column(default=0) deleted_utc: Mapped[int] = mapped_column(default=0) distinguished: Mapped[bool] = mapped_column(default=False) - stickied: Mapped[str] - stickied_utc: Mapped[int] - hole_pinned: Mapped[str] - hole: Mapped[str] = mapped_column(ForeignKey("holes.name")) + stickied: Mapped[Optional[str]] + stickied_utc: Mapped[Optional[int]] + hole_pinned: Mapped[Optional[str]] + hole: Mapped[Optional[str]] = mapped_column(ForeignKey("holes.name")) is_pinned: Mapped[bool] = mapped_column(default=False) private: Mapped[bool] = mapped_column(default=False) comment_count: Mapped[int] = mapped_column(default=0) - is_approved: Mapped[int] = mapped_column(ForeignKey("users.id")) + is_approved: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) is_bot: Mapped[bool] = mapped_column(default=False) upvotes: Mapped[int] = mapped_column(default=1) downvotes: Mapped[int] = mapped_column(default=0) - realupvotes: Mapped[int] = mapped_column(default=1) - app_id: Mapped[int] = mapped_column(ForeignKey("oauth_apps.id")) + realupvotes: Mapped[Optional[int]] = mapped_column(default=1) + app_id: Mapped[Optional[int]] = mapped_column(ForeignKey("oauth_apps.id")) title: Mapped[str] title_html: Mapped[str] - url: Mapped[str] - body: Mapped[str] - body_html: Mapped[str] - flair: Mapped[str] - ban_reason: Mapped[str] - embed: Mapped[str] - new: Mapped[bool] + url: Mapped[Optional[str]] + body: Mapped[Optional[str]] + body_html: Mapped[Optional[str]] + flair: Mapped[Optional[str]] + ban_reason: Mapped[Optional[str]] + embed: Mapped[Optional[str]] + new: Mapped[Optional[bool]] notify: Mapped[bool] chudded: Mapped[bool] = mapped_column(default=False) rainbowed: Mapped[bool] = mapped_column(default=False) diff --git a/files/classes/reports.py b/files/classes/reports.py index d1b512a40..900c6bc75 100644 --- a/files/classes/reports.py +++ b/files/classes/reports.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -18,7 +18,7 @@ class Report(Base): post_id: Mapped[int] = mapped_column(ForeignKey("posts.id"), primary_key=True) user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) - reason: Mapped[str] + reason: Mapped[Optional[str]] created_utc: Mapped[int] user: Mapped["User"] = relationship(primaryjoin = "Report.user_id == User.id", uselist = False) @@ -46,7 +46,7 @@ class CommentReport(Base): comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id"), primary_key=True) user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) - reason: Mapped[str] + reason: Mapped[Optional[str]] created_utc: Mapped[int] user: Mapped["User"] = relationship(primaryjoin = "CommentReport.user_id == User.id", uselist = False) diff --git a/files/classes/saves.py b/files/classes/saves.py index 2a072e5d3..00b28169f 100644 --- a/files/classes/saves.py +++ b/files/classes/saves.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -17,7 +17,7 @@ class SaveRelationship(Base): user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) post_id: Mapped[int] = mapped_column(ForeignKey("posts.id"), primary_key=True) - created_utc: Mapped[int] + created_utc: Mapped[Optional[int]] post: Mapped["Post"] = relationship(uselist=False) @@ -35,7 +35,7 @@ class CommentSaveRelationship(Base): user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id"), primary_key=True) - created_utc: Mapped[int] + created_utc: Mapped[Optional[int]] comment: Mapped["Comment"] = relationship(uselist=False) diff --git a/files/classes/subscriptions.py b/files/classes/subscriptions.py index 5c579d3d5..b3531231e 100644 --- a/files/classes/subscriptions.py +++ b/files/classes/subscriptions.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -15,7 +15,7 @@ class Subscription(Base): __tablename__ = "subscriptions" user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) post_id: Mapped[int] = mapped_column(ForeignKey("posts.id"), primary_key=True) - created_utc: Mapped[int] + created_utc: Mapped[Optional[int]] user: Mapped["User"] = relationship(uselist=False) post: Mapped["Post"] = relationship(uselist=False) diff --git a/files/classes/transactions.py b/files/classes/transactions.py index c18fa11df..9ae47620f 100644 --- a/files/classes/transactions.py +++ b/files/classes/transactions.py @@ -1,3 +1,5 @@ +from typing import Optional + from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import * @@ -10,7 +12,7 @@ class Transaction(Base): type: Mapped[str] amount: Mapped[int] email: Mapped[str] - claimed: Mapped[bool] + claimed: Mapped[Optional[bool]] def __repr__(self): return f"<{self.__class__.__name__}(id={self.id})>" diff --git a/files/classes/user.py b/files/classes/user.py index d64bac889..e3f63f44b 100644 --- a/files/classes/user.py +++ b/files/classes/user.py @@ -1,5 +1,6 @@ import random from operator import * +from typing import Optional import pyotp from sqlalchemy import ForeignKey, FetchedValue @@ -52,30 +53,30 @@ class User(Base): id: Mapped[int] = mapped_column(primary_key=True) username: Mapped[str] namecolor: Mapped[str] = mapped_column(default=DEFAULT_COLOR) - background: Mapped[str] - profile_background: Mapped[str] - flair: Mapped[str] = mapped_column(deferred=True) - flair_html: Mapped[str] + background: Mapped[Optional[str]] + profile_background: Mapped[Optional[str]] + flair: Mapped[Optional[str]] = mapped_column(deferred=True) + flair_html: Mapped[Optional[str]] flaircolor: Mapped[str] = mapped_column(default=DEFAULT_COLOR) theme: Mapped[str] = mapped_column(default=DEFAULT_THEME) themecolor: Mapped[str] = mapped_column(default=DEFAULT_COLOR) - song: Mapped[str] - highres: Mapped[str] - profileurl: Mapped[str] - bannerurl: Mapped[str] - house: Mapped[str] = mapped_column(default='') - old_house: Mapped[str] = mapped_column(default='') + song: Mapped[Optional[str]] + highres: Mapped[Optional[str]] + profileurl: Mapped[Optional[str]] + bannerurl: Mapped[Optional[str]] + house: Mapped[Optional[str]] = mapped_column(default='') + old_house: Mapped[Optional[str]] = mapped_column(default='') patron: Mapped[int] = mapped_column(default=0) patron_utc: Mapped[int] = mapped_column(default=0) - verified: Mapped[str] - verifiedcolor: Mapped[str] - hieroglyphs: Mapped[int] = mapped_column(default=0) - rehab: Mapped[int] = mapped_column(default=0) - longpost: Mapped[int] = mapped_column(default=0) - bird: Mapped[int] = mapped_column(default=0) - email: Mapped[str] = mapped_column(deferred=True) - css: Mapped[str] - profilecss: Mapped[str] = mapped_column(deferred=True) + verified: Mapped[Optional[str]] + verifiedcolor: Mapped[Optional[str]] + hieroglyphs: Mapped[Optional[int]] = mapped_column(default=0) + rehab: Mapped[Optional[int]] = mapped_column(default=0) + longpost: Mapped[Optional[int]] = mapped_column(default=0) + bird: Mapped[Optional[int]] = mapped_column(default=0) + email: Mapped[Optional[str]] = mapped_column(deferred=True) + css: Mapped[Optional[str]] + profilecss: Mapped[Optional[str]] = mapped_column(deferred=True) passhash: Mapped[str] = mapped_column(deferred=True) post_count: Mapped[int] = mapped_column(default=0) comment_count: Mapped[int] = mapped_column(default=0) @@ -87,49 +88,49 @@ class User(Base): coins_spent_on_hats: Mapped[int] = mapped_column(default=0) lootboxes_bought: Mapped[int] = mapped_column(default=0) chud: Mapped[int] = mapped_column(default=0) - queen: Mapped[int] = mapped_column(default=0) - chud_phrase: Mapped[str] + queen: Mapped[Optional[int]] = mapped_column(default=0) + chud_phrase: Mapped[Optional[str]] email_verified: Mapped[bool] = mapped_column(default=False) - shadowbanned: Mapped[int] = mapped_column(ForeignKey("users.id")) - chudded_by: Mapped[int] = mapped_column(ForeignKey("users.id")) + shadowbanned: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + chudded_by: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) slurreplacer: Mapped[int] = mapped_column(default=1) profanityreplacer: Mapped[int] = mapped_column(default=1) - flairchanged: Mapped[int] = mapped_column(default=0) - namechanged: Mapped[int] = mapped_column(default=0) + flairchanged: Mapped[Optional[int]] = mapped_column(default=0) + namechanged: Mapped[Optional[int]] = mapped_column(default=0) newtab: Mapped[bool] = mapped_column(default=False) newtabexternal: Mapped[bool] = mapped_column(default=True) frontsize: Mapped[int] = mapped_column(default=25) - bio: Mapped[str] = mapped_column(deferred=True) - bio_html: Mapped[str] - sig: Mapped[str] = mapped_column(deferred=True) - sig_html: Mapped[str] + bio: Mapped[Optional[str]] = mapped_column(deferred=True) + bio_html: Mapped[Optional[str]] + sig: Mapped[Optional[str]] = mapped_column(deferred=True) + sig_html: Mapped[Optional[str]] show_sigs: Mapped[bool] = mapped_column(default=True) - progressivestack: Mapped[int] = mapped_column(default=0) - deflector: Mapped[int] = mapped_column(default=0) - friends: Mapped[str] = mapped_column(deferred=True) - friends_html: Mapped[str] = mapped_column(deferred=True) - enemies: Mapped[str] = mapped_column(deferred=True) - enemies_html: Mapped[str] = mapped_column(deferred=True) - is_banned: Mapped[int] = mapped_column(ForeignKey("users.id")) - unban_utc: Mapped[int] - ban_reason: Mapped[str] = mapped_column(deferred=True) - shadowban_reason: Mapped[str] = mapped_column(deferred=True) + progressivestack: Mapped[Optional[int]] = mapped_column(default=0) + deflector: Mapped[Optional[int]] = mapped_column(default=0) + friends: Mapped[Optional[str]] = mapped_column(deferred=True) + friends_html: Mapped[Optional[str]] = mapped_column(deferred=True) + enemies: Mapped[Optional[str]] = mapped_column(deferred=True) + enemies_html: Mapped[Optional[str]] = mapped_column(deferred=True) + is_banned: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + unban_utc: Mapped[Optional[int]] + ban_reason: Mapped[Optional[str]] = mapped_column(deferred=True) + shadowban_reason: Mapped[Optional[str]] = mapped_column(deferred=True) is_muted: Mapped[bool] = mapped_column(default=False) login_nonce: Mapped[int] = mapped_column(default=0) coins: Mapped[int] = mapped_column(default=DEFAULT_COINS) truescore: Mapped[int] = mapped_column(default=0) marseybux: Mapped[int] = mapped_column(default=DEFAULT_MARSEYBUX) - mfa_secret: Mapped[str] = mapped_column(deferred=True) + mfa_secret: Mapped[Optional[str]] = mapped_column(deferred=True) is_private: Mapped[bool] = mapped_column(default=False) stored_subscriber_count: Mapped[int] = mapped_column(default=0) defaultsortingcomments: Mapped[str] = mapped_column(default="hot") defaultsorting: Mapped[str] = mapped_column(default="hot") defaulttime: Mapped[str] = mapped_column(default=DEFAULT_TIME_FILTER) - custom_filter_list: Mapped[str] - original_username: Mapped[str] - extra_username: Mapped[str] - prelock_username: Mapped[str] - referred_by: Mapped[int] = mapped_column(ForeignKey("users.id")) + custom_filter_list: Mapped[Optional[str]] + original_username: Mapped[Optional[str]] + extra_username: Mapped[Optional[str]] + prelock_username: Mapped[Optional[str]] + referred_by: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) currently_held_lottery_tickets: Mapped[int] = mapped_column(default=0) total_held_lottery_tickets: Mapped[int] = mapped_column(default=0) total_lottery_winnings: Mapped[int] = mapped_column(default=0) @@ -137,15 +138,15 @@ class User(Base): last_viewed_post_notifs: Mapped[int] = mapped_column(default=0) last_viewed_log_notifs: Mapped[int] = mapped_column(default=0) last_viewed_offsite_notifs: Mapped[int] = mapped_column(default=0) - bite: Mapped[int] = mapped_column(default=0) - owoify: Mapped[int] = mapped_column(default=0) - sharpen: Mapped[int] = mapped_column(default=0) - marsify: Mapped[int] = mapped_column(default=0) - rainbow: Mapped[int] = mapped_column(default=0) - spider: Mapped[int] = mapped_column(default=0) + bite: Mapped[Optional[int]] = mapped_column(default=0) + owoify: Mapped[Optional[int]] = mapped_column(default=0) + sharpen: Mapped[Optional[int]] = mapped_column(default=0) + marsify: Mapped[Optional[int]] = mapped_column(default=0) + rainbow: Mapped[Optional[int]] = mapped_column(default=0) + spider: Mapped[Optional[int]] = mapped_column(default=0) lifetimedonated: Mapped[int] = mapped_column(default=0) lifetimedonated_visible: Mapped[bool] = mapped_column(default=False) - blacklisted_by: Mapped[int] = mapped_column(ForeignKey("users.id")) + blacklisted_by: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) grinch: Mapped[bool] = mapped_column(default=SITE_NAME != 'rDrama') #don't put in an if condition, it will cause an error bc it has a not-null constraint group_creation_notifs: Mapped[bool] = mapped_column(default=False) effortpost_notifs: Mapped[bool] = mapped_column(default=False) @@ -166,7 +167,7 @@ class User(Base): controversial: Mapped[bool] = mapped_column(default=False) reddit: Mapped[str] = mapped_column(default='old.reddit.com') pronouns: Mapped[str] = mapped_column(default='they/them') - earlylife: Mapped[int] = mapped_column(default=0) + earlylife: Mapped[Optional[int]] = mapped_column(default=0) hole_creation_notifs: Mapped[bool] = mapped_column(default=True) hidevotedon = False hide_cw = False diff --git a/files/classes/userblock.py b/files/classes/userblock.py index 139e6c255..dbec17558 100644 --- a/files/classes/userblock.py +++ b/files/classes/userblock.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -15,7 +15,7 @@ class UserBlock(Base): __tablename__ = "userblocks" user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) target_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) - created_utc: Mapped[int] + created_utc: Mapped[Optional[int]] user: Mapped["User"] = relationship(primaryjoin="User.id==UserBlock.user_id", back_populates="blocking") target: Mapped["User"] = relationship(primaryjoin="User.id==UserBlock.target_id", back_populates="blocked") diff --git a/files/classes/usermute.py b/files/classes/usermute.py index 2a8da2b3e..bdec375cd 100644 --- a/files/classes/usermute.py +++ b/files/classes/usermute.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -15,7 +15,7 @@ class UserMute(Base): __tablename__ = "usermutes" user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) target_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) - created_utc: Mapped[int] + created_utc: Mapped[Optional[int]] user: Mapped["User"] = relationship(primaryjoin="User.id==UserMute.user_id") target: Mapped["User"] = relationship(primaryjoin="User.id==UserMute.target_id") diff --git a/files/classes/views.py b/files/classes/views.py index d914276a0..74940d901 100644 --- a/files/classes/views.py +++ b/files/classes/views.py @@ -1,5 +1,5 @@ import time -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -19,7 +19,7 @@ class ViewerRelationship(Base): user_id: Mapped[int] = mapped_column(ForeignKey('users.id'), primary_key=True) viewer_id: Mapped[int] = mapped_column(ForeignKey('users.id'), primary_key=True) last_view_utc: Mapped[int] - created_utc: Mapped[int] + created_utc: Mapped[Optional[int]] viewer: Mapped["User"] = relationship(primaryjoin="ViewerRelationship.viewer_id == User.id") -- 2.34.1 From 75666a021d2c14406eee31d4cdbabe3babea974c Mon Sep 17 00:00:00 2001 From: TriHard Date: Thu, 15 Feb 2024 14:50:18 -0700 Subject: [PATCH 6/7] Use type aliases for common columns --- files/classes/alts.py | 6 +++--- files/classes/award.py | 10 +++++----- files/classes/badges.py | 5 +++-- files/classes/casino_game.py | 6 +++--- files/classes/clients.py | 7 ++++--- files/classes/comment.py | 15 ++++++++------- files/classes/domains.py | 3 ++- files/classes/emoji.py | 8 ++++---- files/classes/follows.py | 6 +++--- files/classes/group.py | 8 ++++---- files/classes/group_membership.py | 4 ++-- files/classes/hats.py | 5 +++-- files/classes/hole_logs.py | 11 ++++++----- files/classes/ip_logs.py | 8 ++++---- files/classes/lottery.py | 6 +++--- files/classes/media.py | 10 +++++----- files/classes/mod_logs.py | 14 +++++++------- files/classes/notifications.py | 6 +++--- files/classes/orgy.py | 4 ++-- files/classes/polls.py | 17 +++++++++-------- files/classes/post.py | 9 +++++---- files/classes/push_subscriptions.py | 8 ++++---- files/classes/reports.py | 12 ++++++------ files/classes/saves.py | 12 ++++++------ files/classes/subscriptions.py | 8 ++++---- files/classes/transactions.py | 5 +++-- files/classes/user.py | 16 ++++++++-------- files/classes/userblock.py | 8 ++++---- files/classes/usermute.py | 8 ++++---- files/classes/views.py | 8 ++++---- files/classes/votes.py | 10 +++++----- files/helpers/types.py | 14 ++++++++++++++ 32 files changed, 150 insertions(+), 127 deletions(-) create mode 100644 files/helpers/types.py diff --git a/files/classes/alts.py b/files/classes/alts.py index cf4448c81..d70f76193 100644 --- a/files/classes/alts.py +++ b/files/classes/alts.py @@ -1,17 +1,17 @@ import time from typing import Optional -from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import * from files.classes import Base +from files.helpers.types import user_id_fk_pk class Alt(Base): __tablename__ = "alts" - user1: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) - user2: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + user1: Mapped[user_id_fk_pk] + user2: Mapped[user_id_fk_pk] is_manual: Mapped[bool] = mapped_column(default=False) created_utc: Mapped[Optional[int]] diff --git a/files/classes/award.py b/files/classes/award.py index 0a72ee9da..440c3a3b9 100644 --- a/files/classes/award.py +++ b/files/classes/award.py @@ -1,13 +1,13 @@ import time from typing import Optional, TYPE_CHECKING -from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base from files.helpers.config.awards import AWARDS, HOUSE_AWARDS from files.helpers.lazy import lazy +from files.helpers.types import comment_id_fk, int_pk, post_id_fk, user_id_fk if TYPE_CHECKING: from files.classes import Comment, Post, User @@ -16,10 +16,10 @@ if TYPE_CHECKING: class AwardRelationship(Base): __tablename__ = "award_relationships" - id: Mapped[int] = mapped_column(primary_key=True) - user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) - post_id: Mapped[Optional[int]] = mapped_column(ForeignKey("posts.id")) - comment_id: Mapped[Optional[int]] = mapped_column(ForeignKey("comments.id")) + id: Mapped[int_pk] + user_id: Mapped[user_id_fk] + post_id: Mapped[Optional[post_id_fk]] + comment_id: Mapped[Optional[comment_id_fk]] kind: Mapped[str] awarded_utc: Mapped[Optional[int]] created_utc: Mapped[Optional[int]] diff --git a/files/classes/badges.py b/files/classes/badges.py index 3ecbff807..a755421a3 100644 --- a/files/classes/badges.py +++ b/files/classes/badges.py @@ -8,6 +8,7 @@ from sqlalchemy.sql.sqltypes import * from files.classes import Base from files.helpers.config.const import * from files.helpers.lazy import lazy +from files.helpers.types import int_pk, user_id_fk_pk if TYPE_CHECKING: from files.classes import User @@ -16,7 +17,7 @@ if TYPE_CHECKING: class BadgeDef(Base): __tablename__ = "badge_defs" - id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) + id: Mapped[int_pk] = mapped_column(autoincrement=True) name: Mapped[str] description: Mapped[Optional[str]] created_utc: Mapped[int] @@ -37,7 +38,7 @@ class Badge(Base): __tablename__ = "badges" - user_id: Mapped[int] = mapped_column(ForeignKey('users.id'), primary_key=True) + user_id: Mapped[user_id_fk_pk] badge_id: Mapped[int] = mapped_column(ForeignKey('badge_defs.id'), primary_key=True) description: Mapped[Optional[str]] url: Mapped[Optional[str]] diff --git a/files/classes/casino_game.py b/files/classes/casino_game.py index fdf8a8d39..9d5233619 100644 --- a/files/classes/casino_game.py +++ b/files/classes/casino_game.py @@ -2,12 +2,12 @@ import json import time from typing import TYPE_CHECKING -from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base from files.helpers.lazy import lazy +from files.helpers.types import int_pk, user_id_fk if TYPE_CHECKING: from files.classes import User @@ -17,8 +17,8 @@ CASINO_GAME_KINDS = ['blackjack', 'slots', 'roulette'] class CasinoGame(Base): __tablename__ = "casino_games" - id: Mapped[int] = mapped_column(primary_key=True) - user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + id: Mapped[int_pk] + user_id: Mapped[user_id_fk] created_utc: Mapped[int] active: Mapped[bool] = mapped_column(default=True) currency: Mapped[str] diff --git a/files/classes/clients.py b/files/classes/clients.py index 1788a0867..a7ccac0f7 100644 --- a/files/classes/clients.py +++ b/files/classes/clients.py @@ -9,6 +9,7 @@ from sqlalchemy.sql.sqltypes import * from files.classes import Base from files.helpers.config.const import * from files.helpers.lazy import lazy +from files.helpers.types import int_pk, user_id_fk, user_id_fk_pk from .comment import Comment from .post import Post @@ -20,12 +21,12 @@ if TYPE_CHECKING: class OauthApp(Base): __tablename__ = "oauth_apps" - id: Mapped[int] = mapped_column(primary_key=True) + id: Mapped[int_pk] client_id: Mapped[Optional[Annotated[str, 64]]] app_name: Mapped[str] redirect_uri: Mapped[str] description: Mapped[str] - author_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + author_id: Mapped[user_id_fk] created_utc: Mapped[Optional[int]] author: Mapped["User"] = relationship(back_populates="apps") @@ -56,7 +57,7 @@ class OauthApp(Base): class ClientAuth(Base): __tablename__ = "client_auths" - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + user_id: Mapped[user_id_fk_pk] oauth_client: Mapped[int] = mapped_column(ForeignKey("oauth_apps.id"), primary_key=True) access_token: Mapped[str] created_utc: Mapped[Optional[int]] diff --git a/files/classes/comment.py b/files/classes/comment.py index 6ae808aa4..156d7fef2 100644 --- a/files/classes/comment.py +++ b/files/classes/comment.py @@ -18,6 +18,7 @@ from files.helpers.slurs_and_profanities import * from files.helpers.lazy import lazy from files.helpers.regex import * from files.helpers.sorting_and_time import * +from files.helpers.types import comment_id_fk, int_pk, post_id_fk, user_id_fk from files.helpers.bleach_body import * from .saves import CommentSaveRelationship @@ -176,10 +177,10 @@ def add_options(self, body, v): class Comment(Base): __tablename__ = "comments" - id: Mapped[int] = mapped_column(primary_key=True) - author_id: Mapped[int] = mapped_column(ForeignKey("users.id")) - parent_post: Mapped[Optional[int]] = mapped_column(ForeignKey("posts.id")) - wall_user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + id: Mapped[int_pk] + author_id: Mapped[user_id_fk] + parent_post: Mapped[Optional[post_id_fk]] + wall_user_id: Mapped[Optional[user_id_fk]] created_utc: Mapped[int] edited_utc: Mapped[int] = mapped_column(default=0) is_banned: Mapped[bool] = mapped_column(default=False) @@ -188,15 +189,15 @@ class Comment(Base): chuddedfor: Mapped[Optional[str]] distinguished: Mapped[bool] = mapped_column(default=False) deleted_utc: Mapped[int] = mapped_column(default=0) - is_approved: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + is_approved: Mapped[Optional[user_id_fk]] level: Mapped[int] = mapped_column(default=1) - parent_comment_id: Mapped[Optional[int]] = mapped_column(ForeignKey("comments.id")) + parent_comment_id: Mapped[Optional[comment_id_fk]] top_comment_id: Mapped[Optional[int]] is_bot: Mapped[bool] = mapped_column(default=False) stickied: Mapped[Optional[str]] stickied_utc: Mapped[Optional[int]] num_of_pinned_children: Mapped[int] = mapped_column(default=0) - sentto: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + sentto: Mapped[Optional[user_id_fk]] app_id: Mapped[Optional[int]] = mapped_column(ForeignKey("oauth_apps.id")) upvotes: Mapped[int] = mapped_column(default=1) downvotes: Mapped[int] = mapped_column(default=0) diff --git a/files/classes/domains.py b/files/classes/domains.py index 9e728e98d..af586a55d 100644 --- a/files/classes/domains.py +++ b/files/classes/domains.py @@ -5,10 +5,11 @@ from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import * from files.classes import Base +from files.helpers.types import str_pk class BannedDomain(Base): __tablename__ = "banneddomains" - domain: Mapped[str] = mapped_column(primary_key=True) + domain: Mapped[str_pk] reason: Mapped[str] created_utc: Mapped[Optional[int]] diff --git a/files/classes/emoji.py b/files/classes/emoji.py index bffe31260..04f95e40c 100644 --- a/files/classes/emoji.py +++ b/files/classes/emoji.py @@ -1,21 +1,21 @@ import time from typing import Optional -from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import * from files.classes import Base +from files.helpers.types import str_pk, user_id_fk class Emoji(Base): __tablename__ = "emojis" - name: Mapped[str] = mapped_column(primary_key=True) + name: Mapped[str_pk] kind: Mapped[str] - author_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + author_id: Mapped[user_id_fk] tags: Mapped[str] count: Mapped[int] = mapped_column(default=0) - submitter_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + submitter_id: Mapped[Optional[user_id_fk]] created_utc: Mapped[int] nsfw: Mapped[bool] = mapped_column(default=False) diff --git a/files/classes/follows.py b/files/classes/follows.py index 0a8e7cc7c..ba9b6169d 100644 --- a/files/classes/follows.py +++ b/files/classes/follows.py @@ -1,11 +1,11 @@ import time from typing import TYPE_CHECKING -from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base +from files.helpers.types import user_id_fk_pk if TYPE_CHECKING: from files.classes import User @@ -13,8 +13,8 @@ if TYPE_CHECKING: class Follow(Base): __tablename__ = "follows" - target_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + target_id: Mapped[user_id_fk_pk] + user_id: Mapped[user_id_fk_pk] created_utc: Mapped[int] user: Mapped["User"] = relationship(uselist=False, primaryjoin="User.id==Follow.user_id", back_populates="following") diff --git a/files/classes/group.py b/files/classes/group.py index d3a2a4109..a7ea4f3c3 100644 --- a/files/classes/group.py +++ b/files/classes/group.py @@ -1,12 +1,12 @@ import time from typing import Optional, TYPE_CHECKING -from sqlalchemy.orm import Mapped, mapped_column, relationship -from sqlalchemy.types import Integer +from sqlalchemy.orm import Mapped, relationship from files.classes import Base from files.helpers.lazy import lazy from files.helpers.config.const import * +from files.helpers.types import str_pk, user_id_fk from .group_membership import * @@ -16,9 +16,9 @@ if TYPE_CHECKING: class Group(Base): __tablename__ = "groups" - name: Mapped[str] = mapped_column(primary_key=True) + name: Mapped[str_pk] created_utc: Mapped[int] - owner_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + owner_id: Mapped[Optional[user_id_fk]] description: Mapped[Optional[str]] description_html: Mapped[Optional[str]] diff --git a/files/classes/group_membership.py b/files/classes/group_membership.py index b5153c974..c50b74eae 100644 --- a/files/classes/group_membership.py +++ b/files/classes/group_membership.py @@ -3,9 +3,9 @@ from typing import Optional, TYPE_CHECKING from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship -from sqlalchemy.types import Integer, String, Boolean from files.classes import Base +from files.helpers.types import user_id_fk_pk if TYPE_CHECKING: from files.classes.user import User @@ -13,7 +13,7 @@ if TYPE_CHECKING: class GroupMembership(Base): __tablename__ = "group_memberships" - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + user_id: Mapped[user_id_fk_pk] group_name: Mapped[str] = mapped_column(ForeignKey("groups.name"), primary_key=True) created_utc: Mapped[int] approved_utc: Mapped[Optional[int]] diff --git a/files/classes/hats.py b/files/classes/hats.py index 0aef7d14d..a24e3c556 100644 --- a/files/classes/hats.py +++ b/files/classes/hats.py @@ -9,6 +9,7 @@ from flask import g from files.classes import Base from files.helpers.lazy import lazy from files.helpers.slurs_and_profanities import censor_slurs_profanities +from files.helpers.types import int_pk, user_id_fk if TYPE_CHECKING: from files.classes import User @@ -17,12 +18,12 @@ if TYPE_CHECKING: class HatDef(Base): __tablename__ = "hat_defs" - id: Mapped[int] = mapped_column(primary_key=True) + id: Mapped[int_pk] name: Mapped[str] description: Mapped[str] author_id: Mapped[int] = mapped_column(ForeignKey('users.id')) price: Mapped[int] - submitter_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + submitter_id: Mapped[Optional[user_id_fk]] created_utc: Mapped[int] author: Mapped["User"] = relationship(primaryjoin="HatDef.author_id == User.id", back_populates="designed_hats") diff --git a/files/classes/hole_logs.py b/files/classes/hole_logs.py index 2c1398570..a2e6957ac 100644 --- a/files/classes/hole_logs.py +++ b/files/classes/hole_logs.py @@ -11,6 +11,7 @@ from files.helpers.config.const import * from files.helpers.lazy import lazy from files.helpers.slurs_and_profanities import censor_slurs_profanities from files.helpers.sorting_and_time import make_age_string +from files.helpers.types import comment_id_fk, int_pk, post_id_fk, user_id_fk if TYPE_CHECKING: from files.classes import Comment, Post, User @@ -18,13 +19,13 @@ if TYPE_CHECKING: class HoleAction(Base): __tablename__ = "hole_actions" - id: Mapped[int] = mapped_column(primary_key=True) + id: Mapped[int_pk] hole: Mapped[str] = mapped_column(ForeignKey("holes.name")) - user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + user_id: Mapped[Optional[user_id_fk]] kind: Mapped[Optional[str]] - target_user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) - target_post_id: Mapped[Optional[int]] = mapped_column(ForeignKey("posts.id")) - target_comment_id: Mapped[Optional[int]] = mapped_column(ForeignKey("comments.id")) + target_user_id: Mapped[Optional[user_id_fk]] + target_post_id: Mapped[Optional[post_id_fk]] + target_comment_id: Mapped[Optional[comment_id_fk]] _note: Mapped[Optional[str]] created_utc: Mapped[int] diff --git a/files/classes/ip_logs.py b/files/classes/ip_logs.py index 7fb965aff..a37af0018 100644 --- a/files/classes/ip_logs.py +++ b/files/classes/ip_logs.py @@ -1,11 +1,11 @@ import time from typing import TYPE_CHECKING -from sqlalchemy import ForeignKey -from sqlalchemy.orm import Mapped, mapped_column, relationship +from sqlalchemy.orm import Mapped, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base +from files.helpers.types import str_pk, user_id_fk_pk if TYPE_CHECKING: from files.classes import User @@ -13,8 +13,8 @@ if TYPE_CHECKING: class IPLog(Base): __tablename__ = "ip_logs" - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) - ip: Mapped[str] = mapped_column(primary_key=True) + user_id: Mapped[user_id_fk_pk] + ip: Mapped[str_pk] created_utc: Mapped[int] last_used: Mapped[int] diff --git a/files/classes/lottery.py b/files/classes/lottery.py index 090ce49d4..0e1850f9d 100644 --- a/files/classes/lottery.py +++ b/files/classes/lottery.py @@ -1,23 +1,23 @@ import time from typing import Optional -from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import * from files.classes import Base from files.helpers.config.const import * from files.helpers.lazy import lazy +from files.helpers.types import int_pk, user_id_fk class Lottery(Base): __tablename__ = "lotteries" - id: Mapped[int] = mapped_column(primary_key=True) + id: Mapped[int_pk] is_active: Mapped[bool] = mapped_column(default=False) ends_at: Mapped[int] prize: Mapped[int] = mapped_column(default=0) tickets_sold: Mapped[int] = mapped_column(default=0) - winner_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + winner_id: Mapped[Optional[user_id_fk]] created_utc: Mapped[Optional[int]] def __init__(self, *args, **kwargs): diff --git a/files/classes/media.py b/files/classes/media.py index 0e144ad4f..939a4a3b4 100644 --- a/files/classes/media.py +++ b/files/classes/media.py @@ -1,15 +1,15 @@ import time -from sqlalchemy import ForeignKey -from sqlalchemy.orm import Mapped, mapped_column +from sqlalchemy.orm import Mapped from sqlalchemy.sql.sqltypes import * from files.classes import Base +from files.helpers.types import str_pk, user_id_fk class Media(Base): __tablename__ = "media" - kind: Mapped[str] = mapped_column(primary_key=True) - filename: Mapped[str] = mapped_column(primary_key=True) - user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + kind: Mapped[str_pk] + filename: Mapped[str_pk] + user_id: Mapped[user_id_fk] created_utc: Mapped[int] size: Mapped[int] diff --git a/files/classes/mod_logs.py b/files/classes/mod_logs.py index 41fba0839..fefe904c3 100644 --- a/files/classes/mod_logs.py +++ b/files/classes/mod_logs.py @@ -1,8 +1,7 @@ import time from typing import Optional, TYPE_CHECKING -from sqlalchemy import ForeignKey -from sqlalchemy.orm import Mapped, mapped_column, relationship +from sqlalchemy.orm import Mapped, relationship from sqlalchemy.sql.sqltypes import * from flask import g @@ -11,6 +10,7 @@ from files.helpers.config.const import * from files.helpers.lazy import lazy from files.helpers.slurs_and_profanities import censor_slurs_profanities from files.helpers.sorting_and_time import make_age_string +from files.helpers.types import comment_id_fk, int_pk, post_id_fk, user_id_fk if TYPE_CHECKING: from files.classes import Comment, Post, User @@ -18,12 +18,12 @@ if TYPE_CHECKING: class ModAction(Base): __tablename__ = "modactions" - id: Mapped[int] = mapped_column(primary_key=True) - user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + id: Mapped[int_pk] + user_id: Mapped[Optional[user_id_fk]] kind: Mapped[Optional[str]] - target_user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) - target_post_id: Mapped[Optional[int]] = mapped_column(ForeignKey("posts.id")) - target_comment_id: Mapped[Optional[int]] = mapped_column(ForeignKey("comments.id")) + target_user_id: Mapped[Optional[user_id_fk]] + target_post_id: Mapped[Optional[post_id_fk]] + target_comment_id: Mapped[Optional[comment_id_fk]] _note: Mapped[Optional[str]] created_utc: Mapped[int] diff --git a/files/classes/notifications.py b/files/classes/notifications.py index c0a2ca651..5986b106a 100644 --- a/files/classes/notifications.py +++ b/files/classes/notifications.py @@ -1,11 +1,11 @@ import time from typing import TYPE_CHECKING -from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base +from files.helpers.types import comment_id_fk_pk, user_id_fk_pk if TYPE_CHECKING: from files.classes import Comment, User @@ -14,8 +14,8 @@ if TYPE_CHECKING: class Notification(Base): __tablename__ = "notifications" - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) - comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id"), primary_key=True) + user_id: Mapped[user_id_fk_pk] + comment_id: Mapped[comment_id_fk_pk] read: Mapped[bool] = mapped_column(default=False) created_utc: Mapped[int] diff --git a/files/classes/orgy.py b/files/classes/orgy.py index 819f73e31..6f6b795c5 100644 --- a/files/classes/orgy.py +++ b/files/classes/orgy.py @@ -3,11 +3,11 @@ from flask import g, abort import requests from typing import Optional -from sqlalchemy import or_ from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import * from files.classes import Base +from files.helpers.types import int_pk from files.helpers.lazy import lazy from files.helpers.config.const import * @@ -15,7 +15,7 @@ from files.helpers.config.const import * class Orgy(Base): __tablename__ = "orgies" - created_utc: Mapped[int] = mapped_column(primary_key=True) + created_utc: Mapped[int_pk] type: Mapped[str] data: Mapped[str] title: Mapped[str] diff --git a/files/classes/polls.py b/files/classes/polls.py index 470765e0d..a5636f3c5 100644 --- a/files/classes/polls.py +++ b/files/classes/polls.py @@ -7,6 +7,7 @@ from sqlalchemy.sql.sqltypes import * from files.classes import Base from files.helpers.lazy import lazy +from files.helpers.types import comment_id_fk, int_pk, post_id_fk, user_id_fk_pk if TYPE_CHECKING: from files.classes import Comment, Post, User @@ -15,8 +16,8 @@ if TYPE_CHECKING: class PostOption(Base): __tablename__ = "post_options" - id: Mapped[int] = mapped_column(primary_key=True) - parent_id: Mapped[int] = mapped_column(ForeignKey("posts.id")) + id: Mapped[int_pk] + parent_id: Mapped[post_id_fk] body_html: Mapped[str] = mapped_column(Text) exclusive: Mapped[int] created_utc: Mapped[Optional[int]] @@ -46,9 +47,9 @@ class PostOptionVote(Base): __tablename__ = "post_option_votes" option_id: Mapped[int] = mapped_column(ForeignKey("post_options.id"), primary_key=True) - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + user_id: Mapped[user_id_fk_pk] created_utc: Mapped[int] - post_id: Mapped[Optional[int]] = mapped_column(ForeignKey("posts.id")) + post_id: Mapped[Optional[post_id_fk]] user: Mapped["User"] = relationship() @@ -64,8 +65,8 @@ class CommentOption(Base): __tablename__ = "comment_options" - id: Mapped[int] = mapped_column(primary_key=True) - parent_id: Mapped[int] = mapped_column(ForeignKey("comments.id")) + id: Mapped[int_pk] + parent_id: Mapped[comment_id_fk] body_html: Mapped[str] = mapped_column(Text) exclusive: Mapped[int] created_utc: Mapped[Optional[int]] @@ -95,9 +96,9 @@ class CommentOptionVote(Base): __tablename__ = "comment_option_votes" option_id: Mapped[int] = mapped_column(ForeignKey("comment_options.id"), primary_key=True) - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + user_id: Mapped[user_id_fk_pk] created_utc: Mapped[int] - comment_id: Mapped[Optional[int]] = mapped_column(ForeignKey("comments.id")) + comment_id: Mapped[Optional[comment_id_fk]] user: Mapped["User"] = relationship() diff --git a/files/classes/post.py b/files/classes/post.py index 17757da47..dd09ed11b 100644 --- a/files/classes/post.py +++ b/files/classes/post.py @@ -4,7 +4,7 @@ from typing import Optional, TYPE_CHECKING from urllib.parse import urlparse from flask import g -from sqlalchemy import FetchedValue, ForeignKey +from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * @@ -15,6 +15,7 @@ from files.helpers.slurs_and_profanities import * from files.helpers.lazy import lazy from files.helpers.regex import * from files.helpers.sorting_and_time import make_age_string +from files.helpers.types import int_pk, user_id_fk from files.helpers.bleach_body import * from .comment import * @@ -30,8 +31,8 @@ if TYPE_CHECKING: class Post(Base): __tablename__ = "posts" - id: Mapped[int] = mapped_column(primary_key=True) - author_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + id: Mapped[int_pk] + author_id: Mapped[user_id_fk] edited_utc: Mapped[int] = mapped_column(default=0) created_utc: Mapped[int] thumburl: Mapped[Optional[str]] @@ -51,7 +52,7 @@ class Post(Base): is_pinned: Mapped[bool] = mapped_column(default=False) private: Mapped[bool] = mapped_column(default=False) comment_count: Mapped[int] = mapped_column(default=0) - is_approved: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + is_approved: Mapped[Optional[user_id_fk]] is_bot: Mapped[bool] = mapped_column(default=False) upvotes: Mapped[int] = mapped_column(default=1) downvotes: Mapped[int] = mapped_column(default=0) diff --git a/files/classes/push_subscriptions.py b/files/classes/push_subscriptions.py index ca1d91c54..24eda989f 100644 --- a/files/classes/push_subscriptions.py +++ b/files/classes/push_subscriptions.py @@ -1,15 +1,15 @@ import time -from sqlalchemy import ForeignKey -from sqlalchemy.orm import Mapped, mapped_column +from sqlalchemy.orm import Mapped from sqlalchemy.sql.sqltypes import * from files.classes import Base +from files.helpers.types import str_pk, user_id_fk_pk class PushSubscription(Base): __tablename__ = "push_subscriptions" - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) - subscription_json: Mapped[str] = mapped_column(primary_key=True) + user_id: Mapped[user_id_fk_pk] + subscription_json: Mapped[str_pk] created_utc: Mapped[int] def __init__(self, *args, **kwargs): diff --git a/files/classes/reports.py b/files/classes/reports.py index 900c6bc75..b99e8d5b1 100644 --- a/files/classes/reports.py +++ b/files/classes/reports.py @@ -1,13 +1,13 @@ import time from typing import Optional, TYPE_CHECKING -from sqlalchemy import ForeignKey -from sqlalchemy.orm import Mapped, mapped_column, relationship +from sqlalchemy.orm import Mapped, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base from files.helpers.lazy import lazy from files.helpers.slurs_and_profanities import censor_slurs_profanities +from files.helpers.types import comment_id_fk_pk, post_id_fk_pk, user_id_fk_pk if TYPE_CHECKING: from files.classes import User @@ -16,8 +16,8 @@ if TYPE_CHECKING: class Report(Base): __tablename__ = "reports" - post_id: Mapped[int] = mapped_column(ForeignKey("posts.id"), primary_key=True) - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + post_id: Mapped[post_id_fk_pk] + user_id: Mapped[user_id_fk_pk] reason: Mapped[Optional[str]] created_utc: Mapped[int] @@ -44,8 +44,8 @@ class Report(Base): class CommentReport(Base): __tablename__ = "commentreports" - comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id"), primary_key=True) - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + comment_id: Mapped[comment_id_fk_pk] + user_id: Mapped[user_id_fk_pk] reason: Mapped[Optional[str]] created_utc: Mapped[int] diff --git a/files/classes/saves.py b/files/classes/saves.py index 00b28169f..186f8bf4a 100644 --- a/files/classes/saves.py +++ b/files/classes/saves.py @@ -1,11 +1,11 @@ import time from typing import Optional, TYPE_CHECKING -from sqlalchemy import ForeignKey -from sqlalchemy.orm import Mapped, mapped_column, relationship +from sqlalchemy.orm import Mapped, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base +from files.helpers.types import comment_id_fk_pk, post_id_fk_pk, user_id_fk_pk if TYPE_CHECKING: from files.classes.comment import Comment @@ -15,8 +15,8 @@ if TYPE_CHECKING: class SaveRelationship(Base): __tablename__ = "save_relationship" - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) - post_id: Mapped[int] = mapped_column(ForeignKey("posts.id"), primary_key=True) + user_id: Mapped[user_id_fk_pk] + post_id: Mapped[post_id_fk_pk] created_utc: Mapped[Optional[int]] post: Mapped["Post"] = relationship(uselist=False) @@ -33,8 +33,8 @@ class CommentSaveRelationship(Base): __tablename__ = "comment_save_relationship" - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) - comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id"), primary_key=True) + user_id: Mapped[user_id_fk_pk] + comment_id: Mapped[comment_id_fk_pk] created_utc: Mapped[Optional[int]] comment: Mapped["Comment"] = relationship(uselist=False) diff --git a/files/classes/subscriptions.py b/files/classes/subscriptions.py index b3531231e..f1d581567 100644 --- a/files/classes/subscriptions.py +++ b/files/classes/subscriptions.py @@ -1,11 +1,11 @@ import time from typing import Optional, TYPE_CHECKING -from sqlalchemy import ForeignKey -from sqlalchemy.orm import Mapped, mapped_column, relationship +from sqlalchemy.orm import Mapped, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base +from files.helpers.types import post_id_fk_pk, user_id_fk_pk if TYPE_CHECKING: from files.classes import Post, User @@ -13,8 +13,8 @@ if TYPE_CHECKING: class Subscription(Base): __tablename__ = "subscriptions" - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) - post_id: Mapped[int] = mapped_column(ForeignKey("posts.id"), primary_key=True) + user_id: Mapped[user_id_fk_pk] + post_id: Mapped[post_id_fk_pk] created_utc: Mapped[Optional[int]] user: Mapped["User"] = relationship(uselist=False) diff --git a/files/classes/transactions.py b/files/classes/transactions.py index 9ae47620f..1cbed3108 100644 --- a/files/classes/transactions.py +++ b/files/classes/transactions.py @@ -1,13 +1,14 @@ from typing import Optional -from sqlalchemy.orm import Mapped, mapped_column +from sqlalchemy.orm import Mapped from sqlalchemy.sql.sqltypes import * from files.classes import Base +from files.helpers.types import str_pk class Transaction(Base): __tablename__ = "transactions" - id: Mapped[str] = mapped_column(primary_key=True) + id: Mapped[str_pk] created_utc: Mapped[int] type: Mapped[str] amount: Mapped[int] diff --git a/files/classes/user.py b/files/classes/user.py index e3f63f44b..e651f5723 100644 --- a/files/classes/user.py +++ b/files/classes/user.py @@ -3,8 +3,7 @@ from operator import * from typing import Optional import pyotp -from sqlalchemy import ForeignKey, FetchedValue -from sqlalchemy.orm import DynamicMapped, Mapped, Query, aliased, deferred, mapped_column +from sqlalchemy.orm import DynamicMapped, Mapped, aliased, mapped_column from sqlalchemy.sql import case, func, literal from sqlalchemy.sql.expression import not_, and_, or_ from sqlalchemy.sql.sqltypes import * @@ -21,6 +20,7 @@ from files.helpers.config.awards import AWARDS_ENABLED, HOUSE_AWARDS from files.helpers.media import * from files.helpers.security import * from files.helpers.sorting_and_time import * +from files.helpers.types import int_pk, user_id_fk from files.helpers.can_see import * from .alts import Alt @@ -50,7 +50,7 @@ else: class User(Base): __tablename__ = "users" - id: Mapped[int] = mapped_column(primary_key=True) + id: Mapped[int_pk] username: Mapped[str] namecolor: Mapped[str] = mapped_column(default=DEFAULT_COLOR) background: Mapped[Optional[str]] @@ -91,8 +91,8 @@ class User(Base): queen: Mapped[Optional[int]] = mapped_column(default=0) chud_phrase: Mapped[Optional[str]] email_verified: Mapped[bool] = mapped_column(default=False) - shadowbanned: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) - chudded_by: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + shadowbanned: Mapped[Optional[user_id_fk]] + chudded_by: Mapped[Optional[user_id_fk]] slurreplacer: Mapped[int] = mapped_column(default=1) profanityreplacer: Mapped[int] = mapped_column(default=1) flairchanged: Mapped[Optional[int]] = mapped_column(default=0) @@ -111,7 +111,7 @@ class User(Base): friends_html: Mapped[Optional[str]] = mapped_column(deferred=True) enemies: Mapped[Optional[str]] = mapped_column(deferred=True) enemies_html: Mapped[Optional[str]] = mapped_column(deferred=True) - is_banned: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + is_banned: Mapped[Optional[user_id_fk]] unban_utc: Mapped[Optional[int]] ban_reason: Mapped[Optional[str]] = mapped_column(deferred=True) shadowban_reason: Mapped[Optional[str]] = mapped_column(deferred=True) @@ -130,7 +130,7 @@ class User(Base): original_username: Mapped[Optional[str]] extra_username: Mapped[Optional[str]] prelock_username: Mapped[Optional[str]] - referred_by: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + referred_by: Mapped[Optional[user_id_fk]] currently_held_lottery_tickets: Mapped[int] = mapped_column(default=0) total_held_lottery_tickets: Mapped[int] = mapped_column(default=0) total_lottery_winnings: Mapped[int] = mapped_column(default=0) @@ -146,7 +146,7 @@ class User(Base): spider: Mapped[Optional[int]] = mapped_column(default=0) lifetimedonated: Mapped[int] = mapped_column(default=0) lifetimedonated_visible: Mapped[bool] = mapped_column(default=False) - blacklisted_by: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id")) + blacklisted_by: Mapped[Optional[user_id_fk]] grinch: Mapped[bool] = mapped_column(default=SITE_NAME != 'rDrama') #don't put in an if condition, it will cause an error bc it has a not-null constraint group_creation_notifs: Mapped[bool] = mapped_column(default=False) effortpost_notifs: Mapped[bool] = mapped_column(default=False) diff --git a/files/classes/userblock.py b/files/classes/userblock.py index dbec17558..e25694259 100644 --- a/files/classes/userblock.py +++ b/files/classes/userblock.py @@ -1,11 +1,11 @@ import time from typing import Optional, TYPE_CHECKING -from sqlalchemy import ForeignKey -from sqlalchemy.orm import Mapped, mapped_column, relationship +from sqlalchemy.orm import Mapped, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base +from files.helpers.types import user_id_fk_pk if TYPE_CHECKING: from files.classes import User @@ -13,8 +13,8 @@ if TYPE_CHECKING: class UserBlock(Base): __tablename__ = "userblocks" - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) - target_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + user_id: Mapped[user_id_fk_pk] + target_id: Mapped[user_id_fk_pk] created_utc: Mapped[Optional[int]] user: Mapped["User"] = relationship(primaryjoin="User.id==UserBlock.user_id", back_populates="blocking") diff --git a/files/classes/usermute.py b/files/classes/usermute.py index bdec375cd..af5ad1741 100644 --- a/files/classes/usermute.py +++ b/files/classes/usermute.py @@ -1,11 +1,11 @@ import time from typing import Optional, TYPE_CHECKING -from sqlalchemy import ForeignKey -from sqlalchemy.orm import Mapped, mapped_column, relationship +from sqlalchemy.orm import Mapped, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base +from files.helpers.types import user_id_fk_pk if TYPE_CHECKING: from files.classes import User @@ -13,8 +13,8 @@ if TYPE_CHECKING: class UserMute(Base): __tablename__ = "usermutes" - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) - target_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + user_id: Mapped[user_id_fk_pk] + target_id: Mapped[user_id_fk_pk] created_utc: Mapped[Optional[int]] user: Mapped["User"] = relationship(primaryjoin="User.id==UserMute.user_id") diff --git a/files/classes/views.py b/files/classes/views.py index 74940d901..725d64313 100644 --- a/files/classes/views.py +++ b/files/classes/views.py @@ -1,13 +1,13 @@ import time from typing import Optional, TYPE_CHECKING -from sqlalchemy import ForeignKey -from sqlalchemy.orm import Mapped, mapped_column, relationship +from sqlalchemy.orm import Mapped, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base from files.helpers.lazy import * from files.helpers.sorting_and_time import make_age_string +from files.helpers.types import user_id_fk_pk if TYPE_CHECKING: from files.classes import User @@ -16,8 +16,8 @@ if TYPE_CHECKING: class ViewerRelationship(Base): __tablename__ = "viewers" - user_id: Mapped[int] = mapped_column(ForeignKey('users.id'), primary_key=True) - viewer_id: Mapped[int] = mapped_column(ForeignKey('users.id'), primary_key=True) + user_id: Mapped[user_id_fk_pk] + viewer_id: Mapped[user_id_fk_pk] last_view_utc: Mapped[int] created_utc: Mapped[Optional[int]] diff --git a/files/classes/votes.py b/files/classes/votes.py index 4c8a079e4..6f987afdc 100644 --- a/files/classes/votes.py +++ b/files/classes/votes.py @@ -1,12 +1,12 @@ import time from typing import TYPE_CHECKING -from sqlalchemy import ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql.sqltypes import * from files.classes import Base from files.helpers.lazy import lazy +from files.helpers.types import comment_id_fk_pk, post_id_fk_pk, user_id_fk_pk if TYPE_CHECKING: from files.classes import User @@ -15,8 +15,8 @@ if TYPE_CHECKING: class Vote(Base): __tablename__ = "votes" - post_id: Mapped[int] = mapped_column(ForeignKey("posts.id"), primary_key=True) - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + post_id: Mapped[post_id_fk_pk] + user_id: Mapped[user_id_fk_pk] vote_type: Mapped[int] real: Mapped[bool] = mapped_column(default=True) coins: Mapped[int] = mapped_column(default=1) @@ -45,8 +45,8 @@ class CommentVote(Base): __tablename__ = "commentvotes" - comment_id: Mapped[int] = mapped_column(ForeignKey("comments.id"), primary_key=True) - user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) + comment_id: Mapped[comment_id_fk_pk] + user_id: Mapped[user_id_fk_pk] vote_type: Mapped[int] real: Mapped[bool] = mapped_column(default=True) coins: Mapped[int] = mapped_column(default=1) diff --git a/files/helpers/types.py b/files/helpers/types.py new file mode 100644 index 000000000..085070483 --- /dev/null +++ b/files/helpers/types.py @@ -0,0 +1,14 @@ +from typing import Annotated + +from sqlalchemy.sql.schema import ForeignKey +from sqlalchemy.orm import mapped_column + +int_pk = Annotated[int, mapped_column(primary_key=True)] +str_pk = Annotated[str, mapped_column(primary_key=True)] + +user_id_fk = Annotated[int, mapped_column(ForeignKey("users.id"))] +user_id_fk_pk = Annotated[int, mapped_column(ForeignKey("users.id"), primary_key=True)] +post_id_fk = Annotated[int, mapped_column(ForeignKey("posts.id"))] +post_id_fk_pk = Annotated[int, mapped_column(ForeignKey("posts.id"), primary_key=True)] +comment_id_fk = Annotated[int, mapped_column(ForeignKey("comments.id"))] +comment_id_fk_pk = Annotated[int, mapped_column(ForeignKey("comments.id"), primary_key=True)] \ No newline at end of file -- 2.34.1 From 0a8836b12d28033e593dbaf97142103a5df42f78 Mon Sep 17 00:00:00 2001 From: TriHard Date: Thu, 15 Feb 2024 16:14:30 -0700 Subject: [PATCH 7/7] Fix sqlalchemy.exc.ArgumentError --- files/classes/comment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/classes/comment.py b/files/classes/comment.py index 156d7fef2..ac2a7e785 100644 --- a/files/classes/comment.py +++ b/files/classes/comment.py @@ -225,7 +225,7 @@ class Comment(Base): post: Mapped["Post"] = relationship(back_populates="comments") author: Mapped["User"] = relationship(primaryjoin="User.id==Comment.author_id") senttouser: Mapped["User"] = relationship(primaryjoin="User.id==Comment.sentto") - parent_comment: Mapped["Comment"] = relationship(remote_side=[id]) + parent_comment: Mapped["Comment"] = relationship(remote_side="Comment.id") awards: Mapped[list["AwardRelationship"]] = relationship(order_by="AwardRelationship.awarded_utc.desc()", back_populates="comment") reports: Mapped[list["CommentReport"]] = relationship(order_by="CommentReport.created_utc") options: Mapped[list["CommentOption"]] = relationship(order_by="CommentOption.id") -- 2.34.1