From 51320ab22a244af16bbbed587a61bb6955ff19ba Mon Sep 17 00:00:00 2001 From: Kevin Morris Date: Sat, 16 Oct 2021 16:16:44 -0700 Subject: [PATCH] change(fastapi): unify all model relationship behavior Now, we allow the direct relationships and their foreign keys to be set in all of our models. Previously, we constrained this to direct relationships, and this forced users to perform a query in most situations to satisfy that requirement. Now, IDs can be passed directly. Additionally, this change removes the need for extraneous imports when users which to use relationships. We now import and use models directly instead of passing string-references to them. Signed-off-by: Kevin Morris --- aurweb/models/accepted_term.py | 26 +++++++--------- aurweb/models/api_rate_limit.py | 9 ++---- aurweb/models/group.py | 6 ++-- aurweb/models/license.py | 5 ++-- aurweb/models/official_provider.py | 11 +++---- aurweb/models/package.py | 25 +++++----------- aurweb/models/package_base.py | 43 +++++++++++---------------- aurweb/models/package_blacklist.py | 5 ++-- aurweb/models/package_comaintainer.py | 23 ++++++-------- aurweb/models/package_comment.py | 26 +++++++--------- aurweb/models/package_dependency.py | 35 ++++++++-------------- aurweb/models/package_group.py | 21 ++++++------- aurweb/models/package_keyword.py | 17 ++++------- aurweb/models/package_license.py | 21 ++++++------- aurweb/models/package_notification.py | 22 ++++++-------- aurweb/models/package_relation.py | 30 +++++++------------ aurweb/models/package_request.py | 36 +++++++--------------- aurweb/models/package_source.py | 14 ++++----- aurweb/models/package_vote.py | 23 ++++++-------- aurweb/models/session.py | 18 ++++++----- aurweb/models/term.py | 10 ++----- aurweb/models/tu_vote.py | 21 ++++++------- aurweb/models/tu_voteinfo.py | 28 ++++++----------- aurweb/models/user.py | 3 +- 24 files changed, 181 insertions(+), 297 deletions(-) diff --git a/aurweb/models/accepted_term.py b/aurweb/models/accepted_term.py index b46d086b..b4dbb410 100644 --- a/aurweb/models/accepted_term.py +++ b/aurweb/models/accepted_term.py @@ -2,10 +2,9 @@ from sqlalchemy import Column, ForeignKey, Integer from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.models.term -import aurweb.models.user - from aurweb.models.declarative import Base +from aurweb.models.term import Term as _Term +from aurweb.models.user import User as _User class AcceptedTerm(Base): @@ -14,33 +13,28 @@ class AcceptedTerm(Base): UsersID = Column(Integer, ForeignKey("Users.ID", ondelete="CASCADE"), nullable=False) User = relationship( - "User", backref=backref("accepted_terms", lazy="dynamic"), + _User, backref=backref("accepted_terms", lazy="dynamic"), foreign_keys=[UsersID]) TermsID = Column(Integer, ForeignKey("Terms.ID", ondelete="CASCADE"), nullable=False) Term = relationship( - "Term", backref=backref("accepted_terms", lazy="dynamic"), + _Term, backref=backref("accepted_terms", lazy="dynamic"), foreign_keys=[TermsID]) __mapper_args__ = {"primary_key": [TermsID]} - def __init__(self, - User: aurweb.models.user.User = None, - Term: aurweb.models.term.Term = None, - Revision: int = None): - self.User = User - if not self.User: + def __init__(self, **kwargs): + super().__init__(**kwargs) + + if not self.User and not self.UsersID: raise IntegrityError( - statement="Foreign key UserID cannot be null.", + statement="Foreign key UsersID cannot be null.", orig="AcceptedTerms.UserID", params=("NULL")) - self.Term = Term - if not self.Term: + if not self.Term and not self.TermsID: raise IntegrityError( statement="Foreign key TermID cannot be null.", orig="AcceptedTerms.TermID", params=("NULL")) - - self.Revision = Revision diff --git a/aurweb/models/api_rate_limit.py b/aurweb/models/api_rate_limit.py index f4590553..f8641896 100644 --- a/aurweb/models/api_rate_limit.py +++ b/aurweb/models/api_rate_limit.py @@ -11,20 +11,15 @@ class ApiRateLimit(Base): __mapper_args__ = {"primary_key": [IP]} - def __init__(self, - IP: str = None, - Requests: int = None, - WindowStart: int = None): - self.IP = IP + def __init__(self, **kwargs): + super().__init__(**kwargs) - self.Requests = Requests if self.Requests is None: raise IntegrityError( statement="Column Requests cannot be null.", orig="ApiRateLimit.Requests", params=("NULL")) - self.WindowStart = WindowStart if self.WindowStart is None: raise IntegrityError( statement="Column WindowStart cannot be null.", diff --git a/aurweb/models/group.py b/aurweb/models/group.py index 1bd3a402..5493bb7f 100644 --- a/aurweb/models/group.py +++ b/aurweb/models/group.py @@ -11,9 +11,9 @@ class Group(Base): __mapper_args__ = {"primary_key": [ID]} - def __init__(self, Name: str = None): - self.Name = Name - if not self.Name: + def __init__(self, **kwargs): + super().__init__(**kwargs) + if self.Name is None: raise IntegrityError( statement="Column Name cannot be null.", orig="Groups.Name", diff --git a/aurweb/models/license.py b/aurweb/models/license.py index aef6a619..fa863379 100644 --- a/aurweb/models/license.py +++ b/aurweb/models/license.py @@ -11,8 +11,9 @@ class License(Base): __mapper_args__ = {"primary_key": [ID]} - def __init__(self, Name: str = None): - self.Name = Name + def __init__(self, **kwargs): + super().__init__(**kwargs) + if not self.Name: raise IntegrityError( statement="Column Name cannot be null.", diff --git a/aurweb/models/official_provider.py b/aurweb/models/official_provider.py index e53556b9..a273dd06 100644 --- a/aurweb/models/official_provider.py +++ b/aurweb/models/official_provider.py @@ -3,6 +3,7 @@ from sqlalchemy.exc import IntegrityError from aurweb.models.declarative import Base +# TODO: Fix this! Official packages aren't from aur.archlinux.org... OFFICIAL_BASE = "https://aur.archlinux.org" @@ -13,25 +14,21 @@ class OfficialProvider(Base): __mapper_args__ = {"primary_key": [ID]} - def __init__(self, - Name: str = None, - Repo: str = None, - Provides: str = None): - self.Name = Name + def __init__(self, **kwargs): + super().__init__(**kwargs) + if not self.Name: raise IntegrityError( statement="Column Name cannot be null.", orig="OfficialProviders.Name", params=("NULL")) - self.Repo = Repo if not self.Repo: raise IntegrityError( statement="Column Repo cannot be null.", orig="OfficialProviders.Repo", params=("NULL")) - self.Provides = Provides if not self.Provides: raise IntegrityError( statement="Column Provides cannot be null.", diff --git a/aurweb/models/package.py b/aurweb/models/package.py index e8159d85..ef119f3c 100644 --- a/aurweb/models/package.py +++ b/aurweb/models/package.py @@ -2,10 +2,8 @@ from sqlalchemy import Column, ForeignKey, Integer from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.db -import aurweb.models.package_base - from aurweb.models.declarative import Base +from aurweb.models.package_base import PackageBase as _PackageBase class Package(Base): @@ -17,31 +15,22 @@ class Package(Base): Integer, ForeignKey("PackageBases.ID", ondelete="CASCADE"), nullable=False) PackageBase = relationship( - "PackageBase", backref=backref("packages", lazy="dynamic"), + _PackageBase, backref=backref("packages", lazy="dynamic"), foreign_keys=[PackageBaseID]) __mapper_args__ = {"primary_key": [ID]} - def __init__(self, - PackageBase: aurweb.models.package_base.PackageBase = None, - Name: str = None, - Version: str = None, - Description: str = None, - URL: str = None): - self.PackageBase = PackageBase - if not self.PackageBase: + def __init__(self, **kwargs): + super().__init__(**kwargs) + + if not self.PackageBase and not self.PackageBaseID: raise IntegrityError( statement="Foreign key PackageBaseID cannot be null.", orig="Packages.PackageBaseID", params=("NULL")) - self.Name = Name - if not self.Name: + if self.Name is None: raise IntegrityError( statement="Column Name cannot be null.", orig="Packages.Name", params=("NULL")) - - self.Version = Version - self.Description = Description - self.URL = URL diff --git a/aurweb/models/package_base.py b/aurweb/models/package_base.py index 9177c422..e6f28050 100644 --- a/aurweb/models/package_base.py +++ b/aurweb/models/package_base.py @@ -4,9 +4,8 @@ from sqlalchemy import Column, ForeignKey, Integer from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.models.user - from aurweb.models.declarative import Base +from aurweb.models.user import User as _User class PackageBase(Base): @@ -15,56 +14,48 @@ class PackageBase(Base): FlaggerUID = Column(Integer, ForeignKey("Users.ID", ondelete="SET NULL")) Flagger = relationship( - "User", backref=backref("flagged_bases", lazy="dynamic"), + _User, backref=backref("flagged_bases", lazy="dynamic"), foreign_keys=[FlaggerUID]) SubmitterUID = Column(Integer, ForeignKey("Users.ID", ondelete="SET NULL")) Submitter = relationship( - "User", backref=backref("submitted_bases", lazy="dynamic"), + _User, backref=backref("submitted_bases", lazy="dynamic"), foreign_keys=[SubmitterUID]) MaintainerUID = Column(Integer, ForeignKey("Users.ID", ondelete="SET NULL")) Maintainer = relationship( - "User", backref=backref("maintained_bases", lazy="dynamic"), + _User, backref=backref("maintained_bases", lazy="dynamic"), foreign_keys=[MaintainerUID]) PackagerUID = Column(Integer, ForeignKey("Users.ID", ondelete="SET NULL")) Packager = relationship( - "User", backref=backref("package_bases", lazy="dynamic"), + _User, backref=backref("package_bases", lazy="dynamic"), foreign_keys=[PackagerUID]) # A set used to check for floatable values. TO_FLOAT = {"Popularity"} - def __init__(self, Name: str = None, - Flagger: aurweb.models.user.User = None, - Maintainer: aurweb.models.user.User = None, - Submitter: aurweb.models.user.User = None, - Packager: aurweb.models.user.User = None, - **kwargs): + def __init__(self, **kwargs): super().__init__(**kwargs) - self.Name = Name - if not self.Name: + + if self.Name is None: raise IntegrityError( statement="Column Name cannot be null.", orig="PackageBases.Name", params=("NULL")) - self.Flagger = Flagger - self.Maintainer = Maintainer - self.Submitter = Submitter - self.Packager = Packager + # If no SubmittedTS/ModifiedTS is provided on creation, set them + # here to the current utc timestamp. + now = datetime.utcnow().timestamp() + if not self.SubmittedTS: + self.SubmittedTS = now + if not self.ModifiedTS: + self.ModifiedTS = now - self.NumVotes = kwargs.get("NumVotes") - self.Popularity = kwargs.get("Popularity") - self.OutOfDateTS = kwargs.get("OutOfDateTS") - self.FlaggerComment = kwargs.get("FlaggerComment", str()) - self.SubmittedTS = kwargs.get("SubmittedTS", - datetime.utcnow().timestamp()) - self.ModifiedTS = kwargs.get("ModifiedTS", - datetime.utcnow().timestamp()) + if not self.FlaggerComment: + self.FlaggerComment = str() def __getattribute__(self, key: str): attr = super().__getattribute__(key) diff --git a/aurweb/models/package_blacklist.py b/aurweb/models/package_blacklist.py index 7702c877..4ba3f308 100644 --- a/aurweb/models/package_blacklist.py +++ b/aurweb/models/package_blacklist.py @@ -11,8 +11,9 @@ class PackageBlacklist(Base): __mapper_args__ = {"primary_key": [ID]} - def __init__(self, Name: str = None): - self.Name = Name + def __init__(self, **kwargs): + super().__init__(**kwargs) + if not self.Name: raise IntegrityError( statement="Column Name cannot be null.", diff --git a/aurweb/models/package_comaintainer.py b/aurweb/models/package_comaintainer.py index 88fd58ae..2f77782c 100644 --- a/aurweb/models/package_comaintainer.py +++ b/aurweb/models/package_comaintainer.py @@ -2,10 +2,9 @@ from sqlalchemy import Column, ForeignKey, Integer from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.models.package_base -import aurweb.models.user - from aurweb.models.declarative import Base +from aurweb.models.package_base import PackageBase as _PackageBase +from aurweb.models.user import User as _User class PackageComaintainer(Base): @@ -15,37 +14,33 @@ class PackageComaintainer(Base): Integer, ForeignKey("Users.ID", ondelete="CASCADE"), nullable=False) User = relationship( - "User", backref=backref("comaintained", lazy="dynamic"), + _User, backref=backref("comaintained", lazy="dynamic"), foreign_keys=[UsersID]) PackageBaseID = Column( Integer, ForeignKey("PackageBases.ID", ondelete="CASCADE"), nullable=False) PackageBase = relationship( - "PackageBase", backref=backref("comaintainers", lazy="dynamic"), + _PackageBase, backref=backref("comaintainers", lazy="dynamic"), foreign_keys=[PackageBaseID]) __mapper_args__ = {"primary_key": [UsersID, PackageBaseID]} - def __init__(self, - User: aurweb.models.user.User = None, - PackageBase: aurweb.models.package_base.PackageBase = None, - Priority: int = None): - self.User = User - if not self.User: + def __init__(self, **kwargs): + super().__init__(**kwargs) + + if not self.User and not self.UsersID: raise IntegrityError( statement="Foreign key UsersID cannot be null.", orig="PackageComaintainers.UsersID", params=("NULL")) - self.PackageBase = PackageBase - if not self.PackageBase: + if not self.PackageBase and not self.PackageBaseID: raise IntegrityError( statement="Foreign key PackageBaseID cannot be null.", orig="PackageComaintainers.PackageBaseID", params=("NULL")) - self.Priority = Priority if not self.Priority: raise IntegrityError( statement="Column Priority cannot be null.", diff --git a/aurweb/models/package_comment.py b/aurweb/models/package_comment.py index 92ae8911..ffe1300b 100644 --- a/aurweb/models/package_comment.py +++ b/aurweb/models/package_comment.py @@ -2,10 +2,9 @@ from sqlalchemy import Column, ForeignKey, Integer from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.models.package_base -import aurweb.models.user - from aurweb.models.declarative import Base +from aurweb.models.package_base import PackageBase as _PackageBase +from aurweb.models.user import User as _User class PackageComment(Base): @@ -17,44 +16,39 @@ class PackageComment(Base): Integer, ForeignKey("PackageBases.ID", ondelete="CASCADE"), nullable=False) PackageBase = relationship( - "PackageBase", backref=backref("comments", lazy="dynamic", - cascade="all,delete"), + _PackageBase, backref=backref("comments", lazy="dynamic", + cascade="all,delete"), foreign_keys=[PackageBaseID]) UsersID = Column(Integer, ForeignKey("Users.ID", ondelete="SET NULL")) User = relationship( - "User", backref=backref("package_comments", lazy="dynamic"), + _User, backref=backref("package_comments", lazy="dynamic"), foreign_keys=[UsersID]) EditedUsersID = Column( Integer, ForeignKey("Users.ID", ondelete="SET NULL")) Editor = relationship( - "User", backref=backref("edited_comments", lazy="dynamic"), + _User, backref=backref("edited_comments", lazy="dynamic"), foreign_keys=[EditedUsersID]) DelUsersID = Column( Integer, ForeignKey("Users.ID", ondelete="SET NULL")) Deleter = relationship( - "User", backref=backref("deleted_comments", lazy="dynamic"), + _User, backref=backref("deleted_comments", lazy="dynamic"), foreign_keys=[DelUsersID]) __mapper_args__ = {"primary_key": [ID]} - def __init__(self, - PackageBase: aurweb.models.package_base.PackageBase = None, - User: aurweb.models.user.User = None, - **kwargs): + def __init__(self, **kwargs): super().__init__(**kwargs) - self.PackageBase = PackageBase - if not self.PackageBase: + if not self.PackageBase and not self.PackageBaseID: raise IntegrityError( statement="Foreign key PackageBaseID cannot be null.", orig="PackageComments.PackageBaseID", params=("NULL")) - self.User = User - if not self.User: + if not self.User and not self.UsersID: raise IntegrityError( statement="Foreign key UsersID cannot be null.", orig="PackageComments.UsersID", diff --git a/aurweb/models/package_dependency.py b/aurweb/models/package_dependency.py index fb66c6f2..df6cc6cf 100644 --- a/aurweb/models/package_dependency.py +++ b/aurweb/models/package_dependency.py @@ -2,10 +2,9 @@ from sqlalchemy import Column, ForeignKey, Integer, String from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.models.package - -from aurweb.models import dependency_type from aurweb.models.declarative import Base +from aurweb.models.dependency_type import DependencyType as _DependencyType +from aurweb.models.package import Package as _Package class PackageDependency(Base): @@ -15,15 +14,15 @@ class PackageDependency(Base): Integer, ForeignKey("Packages.ID", ondelete="CASCADE"), nullable=False) Package = relationship( - "Package", backref=backref("package_dependencies", lazy="dynamic", - cascade="all,delete"), + _Package, backref=backref("package_dependencies", lazy="dynamic", + cascade="all,delete"), foreign_keys=[PackageID]) DepTypeID = Column( Integer, ForeignKey("DependencyTypes.ID", ondelete="NO ACTION"), nullable=False) DependencyType = relationship( - "DependencyType", + _DependencyType, backref=backref("package_dependencies", lazy="dynamic"), foreign_keys=[DepTypeID]) @@ -31,39 +30,29 @@ class PackageDependency(Base): __mapper_args__ = {"primary_key": [PackageID, DepName]} - def __init__(self, - Package: aurweb.models.package.Package = None, - DependencyType: dependency_type.DependencyType = None, - DepName: str = None, - DepDesc: str = None, - DepCondition: str = None, - DepArch: str = None): - self.Package = Package - if not self.Package: + def __init__(self, **kwargs): + super().__init__(**kwargs) + + if not self.Package and not self.PackageID: raise IntegrityError( statement="Foreign key PackageID cannot be null.", orig="PackageDependencies.PackageID", params=("NULL")) - self.DependencyType = DependencyType - if not self.DependencyType: + if not self.DependencyType and not self.DepTypeID: raise IntegrityError( statement="Foreign key DepTypeID cannot be null.", orig="PackageDependencies.DepTypeID", params=("NULL")) - self.DepName = DepName - if not self.DepName: + if self.DepName is None: raise IntegrityError( statement="Column DepName cannot be null.", orig="PackageDependencies.DepName", params=("NULL")) - self.DepDesc = DepDesc - self.DepCondition = DepCondition - self.DepArch = DepArch - def is_package(self) -> bool: + # TODO: Improve the speed of this query if possible. from aurweb import db from aurweb.models.official_provider import OfficialProvider from aurweb.models.package import Package diff --git a/aurweb/models/package_group.py b/aurweb/models/package_group.py index a8031e0d..c1d1e4f8 100644 --- a/aurweb/models/package_group.py +++ b/aurweb/models/package_group.py @@ -2,10 +2,9 @@ from sqlalchemy import Column, ForeignKey, Integer from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.models.group -import aurweb.models.package - from aurweb.models.declarative import Base +from aurweb.models.group import Group as _Group +from aurweb.models.package import Package as _Package class PackageGroup(Base): @@ -14,29 +13,27 @@ class PackageGroup(Base): PackageID = Column(Integer, ForeignKey("Packages.ID", ondelete="CASCADE"), primary_key=True, nullable=True) Package = relationship( - "Package", backref=backref("package_groups", lazy="dynamic"), + _Package, backref=backref("package_groups", lazy="dynamic"), foreign_keys=[PackageID]) GroupID = Column(Integer, ForeignKey("Groups.ID", ondelete="CASCADE"), primary_key=True, nullable=True) Group = relationship( - "Group", backref=backref("package_groups", lazy="dynamic"), + _Group, backref=backref("package_groups", lazy="dynamic"), foreign_keys=[GroupID]) __mapper_args__ = {"primary_key": [PackageID, GroupID]} - def __init__(self, - Package: aurweb.models.package.Package = None, - Group: aurweb.models.group.Group = None): - self.Package = Package - if not self.Package: + def __init__(self, **kwargs): + super().__init__(**kwargs) + + if not self.Package and not self.PackageID: raise IntegrityError( statement="Primary key PackageID cannot be null.", orig="PackageGroups.PackageID", params=("NULL")) - self.Group = Group - if not self.Group: + if not self.Group and not self.GroupID: raise IntegrityError( statement="Primary key GroupID cannot be null.", orig="PackageGroups.GroupID", diff --git a/aurweb/models/package_keyword.py b/aurweb/models/package_keyword.py index 803e6bca..6c18ac5d 100644 --- a/aurweb/models/package_keyword.py +++ b/aurweb/models/package_keyword.py @@ -2,10 +2,8 @@ from sqlalchemy import Column, ForeignKey, Integer, String, text from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.db -import aurweb.models.package_base - from aurweb.models.declarative import Base +from aurweb.models.package_base import PackageBase as _PackageBase class PackageKeyword(Base): @@ -15,7 +13,7 @@ class PackageKeyword(Base): Integer, ForeignKey("PackageBases.ID", ondelete="CASCADE"), primary_key=True, nullable=True) PackageBase = relationship( - "PackageBase", backref=backref("keywords", lazy="dynamic"), + _PackageBase, backref=backref("keywords", lazy="dynamic"), foreign_keys=[PackageBaseID]) Keyword = Column( @@ -24,14 +22,11 @@ class PackageKeyword(Base): __mapper_args__ = {"primary_key": [PackageBaseID, Keyword]} - def __init__(self, - PackageBase: aurweb.models.package_base.PackageBase = None, - Keyword: str = None): - self.PackageBase = PackageBase - if not self.PackageBase: + def __init__(self, **kwargs): + super().__init__(**kwargs) + + if not self.PackageBase and not self.PackageBaseID: raise IntegrityError( statement="Primary key PackageBaseID cannot be null.", orig="PackageKeywords.PackageBaseID", params=("NULL")) - - self.Keyword = Keyword diff --git a/aurweb/models/package_license.py b/aurweb/models/package_license.py index 0689562f..ab429fc6 100644 --- a/aurweb/models/package_license.py +++ b/aurweb/models/package_license.py @@ -2,10 +2,9 @@ from sqlalchemy import Column, ForeignKey, Integer from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.models.license -import aurweb.models.package - from aurweb.models.declarative import Base +from aurweb.models.license import License as _License +from aurweb.models.package import Package as _Package class PackageLicense(Base): @@ -15,30 +14,28 @@ class PackageLicense(Base): Integer, ForeignKey("Packages.ID", ondelete="CASCADE"), primary_key=True, nullable=True) Package = relationship( - "Package", backref=backref("package_license", uselist=False), + _Package, backref=backref("package_license", uselist=False), foreign_keys=[PackageID]) LicenseID = Column( Integer, ForeignKey("Licenses.ID", ondelete="CASCADE"), primary_key=True, nullable=True) License = relationship( - "License", backref=backref("package_license", uselist=False), + _License, backref=backref("package_license", uselist=False), foreign_keys=[LicenseID]) __mapper_args__ = {"primary_key": [PackageID, LicenseID]} - def __init__(self, - Package: aurweb.models.package.Package = None, - License: aurweb.models.license.License = None): - self.Package = Package - if not self.Package: + def __init__(self, **kwargs): + super().__init__(**kwargs) + + if not self.Package and not self.PackageID: raise IntegrityError( statement="Primary key PackageID cannot be null.", orig="PackageLicenses.PackageID", params=("NULL")) - self.License = License - if not self.License: + if not self.License and not self.LicenseID: raise IntegrityError( statement="Primary key LicenseID cannot be null.", orig="PackageLicenses.LicenseID", diff --git a/aurweb/models/package_notification.py b/aurweb/models/package_notification.py index 803c0496..221067e1 100644 --- a/aurweb/models/package_notification.py +++ b/aurweb/models/package_notification.py @@ -2,10 +2,9 @@ from sqlalchemy import Column, ForeignKey, Integer from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.models.package_base -import aurweb.models.user - from aurweb.models.declarative import Base +from aurweb.models.package_base import PackageBase as _PackageBase +from aurweb.models.user import User as _User class PackageNotification(Base): @@ -15,32 +14,29 @@ class PackageNotification(Base): Integer, ForeignKey("Users.ID", ondelete="CASCADE"), nullable=False) User = relationship( - "User", backref=backref("notifications", lazy="dynamic"), + _User, backref=backref("notifications", lazy="dynamic"), foreign_keys=[UserID]) PackageBaseID = Column( Integer, ForeignKey("PackageBases.ID", ondelete="CASCADE"), nullable=False) PackageBase = relationship( - "PackageBase", + _PackageBase, backref=backref("notifications", lazy="dynamic"), foreign_keys=[PackageBaseID]) __mapper_args__ = {"primary_key": [UserID, PackageBaseID]} - def __init__(self, - User: aurweb.models.user.User = None, - PackageBase: aurweb.models.package_base.PackageBase = None, - NotificationTS: int = None): - self.User = User - if not self.User: + def __init__(self, **kwargs): + super().__init__(**kwargs) + + if not self.User and not self.UserID: raise IntegrityError( statement="Foreign key UserID cannot be null.", orig="PackageNotifications.UserID", params=("NULL")) - self.PackageBase = PackageBase - if not self.PackageBase: + if not self.PackageBase and not self.PackageBaseID: raise IntegrityError( statement="Foreign key PackageBaseID cannot be null.", orig="PackageNotifications.PackageBaseID", diff --git a/aurweb/models/package_relation.py b/aurweb/models/package_relation.py index d4921859..a8b495e2 100644 --- a/aurweb/models/package_relation.py +++ b/aurweb/models/package_relation.py @@ -2,11 +2,9 @@ from sqlalchemy import Column, ForeignKey, Integer, String from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.db -import aurweb.models.package -import aurweb.models.relation_type - from aurweb.models.declarative import Base +from aurweb.models.package import Package as _Package +from aurweb.models.relation_type import RelationType as _RelationType class PackageRelation(Base): @@ -16,46 +14,38 @@ class PackageRelation(Base): Integer, ForeignKey("Packages.ID", ondelete="CASCADE"), nullable=False) Package = relationship( - "Package", backref=backref("package_relations", lazy="dynamic", - cascade="all,delete"), + _Package, backref=backref("package_relations", lazy="dynamic", + cascade="all,delete"), foreign_keys=[PackageID]) RelTypeID = Column( Integer, ForeignKey("RelationTypes.ID", ondelete="CASCADE"), nullable=False) RelationType = relationship( - "RelationType", backref=backref("package_relations", lazy="dynamic"), + _RelationType, backref=backref("package_relations", lazy="dynamic"), foreign_keys=[RelTypeID]) RelName = Column(String(255), unique=True) __mapper_args__ = {"primary_key": [PackageID, RelName]} - def __init__(self, - Package: aurweb.models.package.Package = None, - RelationType: aurweb.models.relation_type.RelationType = None, - RelName: str = None, RelCondition: str = None, - RelArch: str = None): - self.Package = Package - if not self.Package: + def __init__(self, **kwargs): + super().__init__(**kwargs) + + if not self.Package and not self.PackageID: raise IntegrityError( statement="Foreign key PackageID cannot be null.", orig="PackageRelations.PackageID", params=("NULL")) - self.RelationType = RelationType - if not self.RelationType: + if not self.RelationType and not self.RelTypeID: raise IntegrityError( statement="Foreign key RelTypeID cannot be null.", orig="PackageRelations.RelTypeID", params=("NULL")) - self.RelName = RelName # nullable=False if not self.RelName: raise IntegrityError( statement="Column RelName cannot be null.", orig="PackageRelations.RelName", params=("NULL")) - - self.RelCondition = RelCondition - self.RelArch = RelArch diff --git a/aurweb/models/package_request.py b/aurweb/models/package_request.py index a5125cee..ae0a5b48 100644 --- a/aurweb/models/package_request.py +++ b/aurweb/models/package_request.py @@ -2,11 +2,10 @@ from sqlalchemy import Column, ForeignKey, Integer from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.models.package_base -import aurweb.models.request_type -import aurweb.models.user - from aurweb.models.declarative import Base +from aurweb.models.package_base import PackageBase as _PackageBase +from aurweb.models.request_type import RequestType as _RequestType +from aurweb.models.user import User as _User PENDING = "Pending" CLOSED = "Closed" @@ -29,24 +28,24 @@ class PackageRequest(Base): Integer, ForeignKey("RequestTypes.ID", ondelete="NO ACTION"), nullable=False) RequestType = relationship( - "RequestType", backref=backref("package_requests", lazy="dynamic"), + _RequestType, backref=backref("package_requests", lazy="dynamic"), foreign_keys=[ReqTypeID]) UsersID = Column(Integer, ForeignKey("Users.ID", ondelete="SET NULL")) User = relationship( - "User", backref=backref("package_requests", lazy="dynamic"), + _User, backref=backref("package_requests", lazy="dynamic"), foreign_keys=[UsersID]) PackageBaseID = Column( Integer, ForeignKey("PackageBases.ID", ondelete="SET NULL"), nullable=False) PackageBase = relationship( - "PackageBase", backref=backref("requests", lazy="dynamic"), + _PackageBase, backref=backref("requests", lazy="dynamic"), foreign_keys=[PackageBaseID]) ClosedUID = Column(Integer, ForeignKey("Users.ID", ondelete="SET NULL")) Closer = relationship( - "User", backref=backref("closed_requests", lazy="dynamic"), + _User, backref=backref("closed_requests", lazy="dynamic"), foreign_keys=[ClosedUID]) __mapper_args__ = {"primary_key": [ID]} @@ -58,52 +57,39 @@ class PackageRequest(Base): REJECTED_ID: REJECTED } - def __init__(self, - RequestType: aurweb.models.request_type.RequestType = None, - PackageBase: aurweb.models.package_base.PackageBase = None, - PackageBaseName: str = None, - User: aurweb.models.user.User = None, - Comments: str = None, - ClosureComment: str = None, - **kwargs): + def __init__(self, **kwargs): super().__init__(**kwargs) - self.RequestType = RequestType - if not self.RequestType: + if not self.RequestType and not self.ReqTypeID: raise IntegrityError( statement="Foreign key ReqTypeID cannot be null.", orig="PackageRequests.ReqTypeID", params=("NULL")) - self.PackageBase = PackageBase - if not self.PackageBase: + if not self.PackageBase and not self.PackageBaseID: raise IntegrityError( statement="Foreign key PackageBaseID cannot be null.", orig="PackageRequests.PackageBaseID", params=("NULL")) - self.PackageBaseName = PackageBaseName if not self.PackageBaseName: raise IntegrityError( statement="Column PackageBaseName cannot be null.", orig="PackageRequests.PackageBaseName", params=("NULL")) - self.User = User - if not self.User: + if not self.User and not self.UsersID: raise IntegrityError( statement="Foreign key UsersID cannot be null.", orig="PackageRequests.UsersID", params=("NULL")) - self.Comments = Comments if self.Comments is None: raise IntegrityError( statement="Column Comments cannot be null.", orig="PackageRequests.Comments", params=("NULL")) - self.ClosureComment = ClosureComment if self.ClosureComment is None: raise IntegrityError( statement="Column ClosureComment cannot be null.", diff --git a/aurweb/models/package_source.py b/aurweb/models/package_source.py index f016bee0..edb54f63 100644 --- a/aurweb/models/package_source.py +++ b/aurweb/models/package_source.py @@ -2,9 +2,8 @@ from sqlalchemy import Column, ForeignKey, Integer from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.models.package - from aurweb.models.declarative import Base +from aurweb.models.package import Package as _Package class PackageSource(Base): @@ -13,19 +12,16 @@ class PackageSource(Base): PackageID = Column(Integer, ForeignKey("Packages.ID", ondelete="CASCADE"), nullable=False) Package = relationship( - "Package", backref=backref("package_sources", lazy="dynamic", - cascade="all,delete"), + _Package, backref=backref("package_sources", lazy="dynamic", + cascade="all,delete"), foreign_keys=[PackageID]) __mapper_args__ = {"primary_key": [PackageID]} - def __init__(self, - Package: aurweb.models.package.Package = None, - **kwargs): + def __init__(self, **kwargs): super().__init__(**kwargs) - self.Package = Package - if not self.Package: + if not self.Package and not self.PackageID: raise IntegrityError( statement="Foreign key PackageID cannot be null.", orig="PackageSources.PackageID", diff --git a/aurweb/models/package_vote.py b/aurweb/models/package_vote.py index 55a9ecbb..2d70be16 100644 --- a/aurweb/models/package_vote.py +++ b/aurweb/models/package_vote.py @@ -2,10 +2,9 @@ from sqlalchemy import Column, ForeignKey, Integer from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.models.package_base -import aurweb.models.user - from aurweb.models.declarative import Base +from aurweb.models.package_base import PackageBase as _PackageBase +from aurweb.models.user import User as _User class PackageVote(Base): @@ -15,37 +14,33 @@ class PackageVote(Base): Integer, ForeignKey("Users.ID", ondelete="CASCADE"), nullable=False) User = relationship( - "User", backref=backref("package_votes", lazy="dynamic"), + _User, backref=backref("package_votes", lazy="dynamic"), foreign_keys=[UsersID]) PackageBaseID = Column( Integer, ForeignKey("PackageBases.ID", ondelete="CASCADE"), nullable=False) PackageBase = relationship( - "PackageBase", backref=backref("package_votes", lazy="dynamic"), + _PackageBase, backref=backref("package_votes", lazy="dynamic"), foreign_keys=[PackageBaseID]) __mapper_args__ = {"primary_key": [UsersID, PackageBaseID]} - def __init__(self, - User: aurweb.models.user.User = None, - PackageBase: aurweb.models.package_base.PackageBase = None, - VoteTS: int = None): - self.User = User - if not self.User: + def __init__(self, **kwargs): + super().__init__(**kwargs) + + if not self.User and not self.UsersID: raise IntegrityError( statement="Foreign key UsersID cannot be null.", orig="PackageVotes.UsersID", params=("NULL")) - self.PackageBase = PackageBase - if not self.PackageBase: + if not self.PackageBase and not self.PackageBaseID: raise IntegrityError( statement="Foreign key PackageBaseID cannot be null.", orig="PackageVotes.PackageBaseID", params=("NULL")) - self.VoteTS = VoteTS if not self.VoteTS: raise IntegrityError( statement="Column VoteTS cannot be null.", diff --git a/aurweb/models/session.py b/aurweb/models/session.py index 9154178e..a4034678 100644 --- a/aurweb/models/session.py +++ b/aurweb/models/session.py @@ -4,7 +4,7 @@ from sqlalchemy.orm import backref, relationship from aurweb.db import make_random_value, query from aurweb.models.declarative import Base -from aurweb.models.user import User +from aurweb.models.user import User as _User class Session(Base): @@ -14,22 +14,24 @@ class Session(Base): Integer, ForeignKey("Users.ID", ondelete="CASCADE"), nullable=False) User = relationship( - "User", backref=backref("session", uselist=False), + _User, backref=backref("session", uselist=False), foreign_keys=[UsersID]) __mapper_args__ = {"primary_key": [UsersID]} def __init__(self, **kwargs): - self.UsersID = kwargs.get("UsersID") - if not query(User, User.ID == self.UsersID).first(): + super().__init__(**kwargs) + + user_exists = query( + query(_User).filter(_User.ID == self.UsersID).exists() + ).scalar() + if not user_exists: raise IntegrityError( - statement="Foreign key UsersID cannot be null.", + statement=("Foreign key UsersID cannot be null and " + "must be a valid user's ID."), orig="Sessions.UsersID", params=("NULL")) - self.SessionID = kwargs.get("SessionID") - self.LastUpdateTS = kwargs.get("LastUpdateTS") - def generate_unique_sid(): return make_random_value(Session, Session.SessionID) diff --git a/aurweb/models/term.py b/aurweb/models/term.py index b0da71f7..0985cd76 100644 --- a/aurweb/models/term.py +++ b/aurweb/models/term.py @@ -11,21 +11,17 @@ class Term(Base): __mapper_args__ = {"primary_key": [ID]} - def __init__(self, - Description: str = None, URL: str = None, - Revision: int = None): - self.Description = Description + def __init__(self, **kwargs): + super().__init__(**kwargs) + if not self.Description: raise IntegrityError( statement="Column Description cannot be null.", orig="Terms.Description", params=("NULL")) - self.URL = URL if not self.URL: raise IntegrityError( statement="Column URL cannot be null.", orig="Terms.URL", params=("NULL")) - - self.Revision = Revision diff --git a/aurweb/models/tu_vote.py b/aurweb/models/tu_vote.py index 2b7bf2d0..634c041e 100644 --- a/aurweb/models/tu_vote.py +++ b/aurweb/models/tu_vote.py @@ -2,10 +2,9 @@ from sqlalchemy import Column, ForeignKey, Integer from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.models.tu_voteinfo -import aurweb.models.user - from aurweb.models.declarative import Base +from aurweb.models.tu_voteinfo import TUVoteInfo as _TUVoteInfo +from aurweb.models.user import User as _User class TUVote(Base): @@ -14,29 +13,27 @@ class TUVote(Base): VoteID = Column(Integer, ForeignKey("TU_VoteInfo.ID", ondelete="CASCADE"), nullable=False) VoteInfo = relationship( - "TUVoteInfo", backref=backref("tu_votes", lazy="dynamic"), + _TUVoteInfo, backref=backref("tu_votes", lazy="dynamic"), foreign_keys=[VoteID]) UserID = Column(Integer, ForeignKey("Users.ID", ondelete="CASCADE"), nullable=False) User = relationship( - "User", backref=backref("tu_votes", lazy="dynamic"), + _User, backref=backref("tu_votes", lazy="dynamic"), foreign_keys=[UserID]) __mapper_args__ = {"primary_key": [VoteID, UserID]} - def __init__(self, - VoteInfo: aurweb.models.tu_voteinfo.TUVoteInfo = None, - User: aurweb.models.user.User = None): - self.VoteInfo = VoteInfo - if self.VoteInfo is None: + def __init__(self, **kwargs): + super().__init__(**kwargs) + + if not self.VoteInfo and not self.VoteID: raise IntegrityError( statement="Foreign key VoteID cannot be null.", orig="TU_Votes.VoteID", params=("NULL")) - self.User = User - if self.User is None: + if not self.User and not self.UserID: raise IntegrityError( statement="Foreign key UserID cannot be null.", orig="TU_Votes.UserID", diff --git a/aurweb/models/tu_voteinfo.py b/aurweb/models/tu_voteinfo.py index b80073f4..da43b097 100644 --- a/aurweb/models/tu_voteinfo.py +++ b/aurweb/models/tu_voteinfo.py @@ -6,9 +6,8 @@ from sqlalchemy import Column, ForeignKey, Integer from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship -import aurweb.models.user - from aurweb.models.declarative import Base +from aurweb.models.user import User as _User class TUVoteInfo(Base): @@ -20,57 +19,44 @@ class TUVoteInfo(Base): Integer, ForeignKey("Users.ID", ondelete="CASCADE"), nullable=False) Submitter = relationship( - "User", backref=backref("tu_voteinfo_set", lazy="dynamic"), + _User, backref=backref("tu_voteinfo_set", lazy="dynamic"), foreign_keys=[SubmitterID]) __mapper_args__ = {"primary_key": [ID]} - def __init__(self, - Agenda: str = None, - User: str = None, - Submitted: int = None, - End: int = None, - Quorum: float = None, - Submitter: aurweb.models.user.User = None, - **kwargs): + def __init__(self, **kwargs): super().__init__(**kwargs) - self.Agenda = Agenda if self.Agenda is None: raise IntegrityError( statement="Column Agenda cannot be null.", orig="TU_VoteInfo.Agenda", params=("NULL")) - self.User = User if self.User is None: raise IntegrityError( statement="Column User cannot be null.", orig="TU_VoteInfo.User", params=("NULL")) - self.Submitted = Submitted if self.Submitted is None: raise IntegrityError( statement="Column Submitted cannot be null.", orig="TU_VoteInfo.Submitted", params=("NULL")) - self.End = End if self.End is None: raise IntegrityError( statement="Column End cannot be null.", orig="TU_VoteInfo.End", params=("NULL")) - if Quorum is None: + if self.Quorum is None: raise IntegrityError( statement="Column Quorum cannot be null.", orig="TU_VoteInfo.Quorum", params=("NULL")) - self.Quorum = Quorum - self.Submitter = Submitter if not self.Submitter: raise IntegrityError( statement="Foreign key SubmitterID cannot be null.", @@ -86,7 +72,11 @@ class TUVoteInfo(Base): def __getattribute__(self, key: str): """ Customize getattr to floatify any fetched Quorum values. """ attr = super().__getattribute__(key) - return float(attr) if key == "Quorum" else attr + if attr is None: + return attr + elif key == "Quorum": + return float(attr) + return attr def is_running(self): return self.End > int(datetime.utcnow().timestamp()) diff --git a/aurweb/models/user.py b/aurweb/models/user.py index 5f848304..5b0da4ce 100644 --- a/aurweb/models/user.py +++ b/aurweb/models/user.py @@ -13,6 +13,7 @@ import aurweb.models.account_type import aurweb.schema from aurweb import db +from aurweb.models.account_type import AccountType as _AccountType from aurweb.models.ban import is_banned from aurweb.models.declarative import Base @@ -29,7 +30,7 @@ class User(Base): Integer, ForeignKey("AccountTypes.ID", ondelete="NO ACTION"), nullable=False, server_default=text("1")) AccountType = relationship( - "AccountType", + _AccountType, backref=backref("users", lazy="dynamic"), foreign_keys=[AccountTypeID], uselist=False)