Skip to content

Commit

Permalink
change(fastapi): refactor database ORM model definitions
Browse files Browse the repository at this point in the history
We don't want to depend on the database to load up data
about the models we define. We now leverage the existing
`aurweb.schema` module for table definitions and set
__table_args__["autoload"] to False.

Signed-off-by: Kevin Morris <kevr@0cost.org>
  • Loading branch information
kevr committed Nov 8, 2021
1 parent e4a5b7f commit 446a082
Show file tree
Hide file tree
Showing 31 changed files with 210 additions and 354 deletions.
16 changes: 6 additions & 10 deletions aurweb/models/accepted_term.py
@@ -1,28 +1,24 @@
from sqlalchemy import Column, ForeignKey, Integer
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import backref, relationship

from aurweb import schema
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):
__tablename__ = "AcceptedTerms"
__table__ = schema.AcceptedTerms
__tablename__ = __table__.name
__mapper_args__ = {"primary_key": [__table__.c.TermsID]}

UsersID = Column(Integer, ForeignKey("Users.ID", ondelete="CASCADE"),
nullable=False)
User = relationship(
_User, backref=backref("accepted_terms", lazy="dynamic"),
foreign_keys=[UsersID])
foreign_keys=[__table__.c.UsersID])

TermsID = Column(Integer, ForeignKey("Terms.ID", ondelete="CASCADE"),
nullable=False)
Term = relationship(
_Term, backref=backref("accepted_terms", lazy="dynamic"),
foreign_keys=[TermsID])

__mapper_args__ = {"primary_key": [TermsID]}
foreign_keys=[__table__.c.TermsID])

def __init__(self, **kwargs):
super().__init__(**kwargs)
Expand Down
52 changes: 20 additions & 32 deletions aurweb/models/account_type.py
@@ -1,21 +1,33 @@
from sqlalchemy import Column, Integer

from aurweb import db
from aurweb import schema
from aurweb.models.declarative import Base

USER = "User"
TRUSTED_USER = "Trusted User"
DEVELOPER = "Developer"
TRUSTED_USER_AND_DEV = "Trusted User & Developer"

USER_ID = 1
TRUSTED_USER_ID = 2
DEVELOPER_ID = 3
TRUSTED_USER_AND_DEV_ID = 4

class AccountType(Base):
""" An ORM model of a single AccountTypes record. """
__tablename__ = "AccountTypes"
# Map string constants to integer constants.
ACCOUNT_TYPE_ID = {
USER: USER_ID,
TRUSTED_USER: TRUSTED_USER_ID,
DEVELOPER: DEVELOPER_ID,
TRUSTED_USER_AND_DEV: TRUSTED_USER_AND_DEV_ID
}

# Reversed ACCOUNT_TYPE_ID mapping.
ACCOUNT_TYPE_NAME = {v: k for k, v in ACCOUNT_TYPE_ID.items()}

ID = Column(Integer, primary_key=True)

__mapper_args__ = {"primary_key": [ID]}
class AccountType(Base):
""" An ORM model of a single AccountTypes record. """
__table__ = schema.AccountTypes
__tablename__ = __table__.name
__mapper_args__ = {"primary_key": [__table__.c.ID]}

def __init__(self, **kwargs):
self.AccountType = kwargs.pop("AccountType")
Expand All @@ -26,27 +38,3 @@ def __str__(self):
def __repr__(self):
return "<AccountType(ID='%s', AccountType='%s')>" % (
self.ID, str(self))


# Fetch account type IDs from the database for constants.
_account_types = db.query(AccountType)
USER_ID = _account_types.filter(
AccountType.AccountType == USER).first().ID
TRUSTED_USER_ID = _account_types.filter(
AccountType.AccountType == TRUSTED_USER).first().ID
DEVELOPER_ID = _account_types.filter(
AccountType.AccountType == DEVELOPER).first().ID
TRUSTED_USER_AND_DEV_ID = _account_types.filter(
AccountType.AccountType == TRUSTED_USER_AND_DEV).first().ID
_account_types = None # Get rid of the query handle.

# Map string constants to integer constants.
ACCOUNT_TYPE_ID = {
USER: USER_ID,
TRUSTED_USER: TRUSTED_USER_ID,
DEVELOPER: DEVELOPER_ID,
TRUSTED_USER_AND_DEV: TRUSTED_USER_AND_DEV_ID
}

# Reversed ACCOUNT_TYPE_ID mapping.
ACCOUNT_TYPE_NAME = {v: k for k, v in ACCOUNT_TYPE_ID.items()}
10 changes: 4 additions & 6 deletions aurweb/models/api_rate_limit.py
@@ -1,15 +1,13 @@
from sqlalchemy import Column, String
from sqlalchemy.exc import IntegrityError

from aurweb import schema
from aurweb.models.declarative import Base


class ApiRateLimit(Base):
__tablename__ = "ApiRateLimit"

IP = Column(String(45), primary_key=True, unique=True, default=str())

__mapper_args__ = {"primary_key": [IP]}
__table__ = schema.ApiRateLimit
__tablename__ = __table__.name
__mapper_args__ = {"primary_key": [__table__.c.IP]}

def __init__(self, **kwargs):
super().__init__(**kwargs)
Expand Down
10 changes: 4 additions & 6 deletions aurweb/models/ban.py
@@ -1,15 +1,13 @@
from fastapi import Request
from sqlalchemy import Column, String

from aurweb import schema
from aurweb.models.declarative import Base


class Ban(Base):
__tablename__ = "Bans"

IPAddress = Column(String(45), primary_key=True)

__mapper_args__ = {"primary_key": [IPAddress]}
__table__ = schema.Bans
__tablename__ = __table__.name
__mapper_args__ = {"primary_key": [__table__.c.IPAddress]}

def __init__(self, **kwargs):
self.IPAddress = kwargs.get("IPAddress")
Expand Down
6 changes: 1 addition & 5 deletions aurweb/models/declarative.py
Expand Up @@ -2,8 +2,6 @@

from sqlalchemy.ext.declarative import declarative_base

import aurweb.db

from aurweb import util


Expand All @@ -25,12 +23,10 @@ def to_json(model, indent: int = None):

# Setup __table_args__ applicable to every table.
Base.__table_args__ = {
"autoload": True,
"autoload_with": aurweb.db.get_engine(),
"autoload": False,
"extend_existing": True
}


# Setup Base.as_dict and Base.json.
#
# With this, declarative models can use .as_dict() or .json()
Expand Down
27 changes: 9 additions & 18 deletions aurweb/models/dependency_type.py
@@ -1,30 +1,21 @@
from sqlalchemy import Column, Integer

from aurweb import db
from aurweb import schema
from aurweb.models.declarative import Base

DEPENDS = "depends"
MAKEDEPENDS = "makedepends"
CHECKDEPENDS = "checkdepends"
OPTDEPENDS = "optdepends"

DEPENDS_ID = 1
MAKEDEPENDS_ID = 2
CHECKDEPENDS_ID = 3
OPTDEPENDS_ID = 4

class DependencyType(Base):
__tablename__ = "DependencyTypes"

ID = Column(Integer, primary_key=True)

__mapper_args__ = {"primary_key": [ID]}
class DependencyType(Base):
__table__ = schema.DependencyTypes
__tablename__ = __table__.name
__mapper_args__ = {"primary_key": [__table__.c.ID]}

def __init__(self, Name: str = None):
self.Name = Name


DEPENDS_ID = db.query(DependencyType).filter(
DependencyType.Name == DEPENDS).first().ID
MAKEDEPENDS_ID = db.query(DependencyType).filter(
DependencyType.Name == MAKEDEPENDS).first().ID
CHECKDEPENDS_ID = db.query(DependencyType).filter(
DependencyType.Name == CHECKDEPENDS).first().ID
OPTDEPENDS_ID = db.query(DependencyType).filter(
DependencyType.Name == OPTDEPENDS).first().ID
10 changes: 4 additions & 6 deletions aurweb/models/group.py
@@ -1,15 +1,13 @@
from sqlalchemy import Column, Integer
from sqlalchemy.exc import IntegrityError

from aurweb import schema
from aurweb.models.declarative import Base


class Group(Base):
__tablename__ = "Groups"

ID = Column(Integer, primary_key=True)

__mapper_args__ = {"primary_key": [ID]}
__table__ = schema.Groups
__tablename__ = __table__.name
__mapper_args__ = {"primary_key": [__table__.c.ID]}

def __init__(self, **kwargs):
super().__init__(**kwargs)
Expand Down
10 changes: 4 additions & 6 deletions aurweb/models/license.py
@@ -1,15 +1,13 @@
from sqlalchemy import Column, Integer
from sqlalchemy.exc import IntegrityError

from aurweb import schema
from aurweb.models.declarative import Base


class License(Base):
__tablename__ = "Licenses"

ID = Column(Integer, primary_key=True)

__mapper_args__ = {"primary_key": [ID]}
__table__ = schema.Licenses
__tablename__ = __table__.name
__mapper_args__ = {"primary_key": [__table__.c.ID]}

def __init__(self, **kwargs):
super().__init__(**kwargs)
Expand Down
10 changes: 4 additions & 6 deletions aurweb/models/official_provider.py
@@ -1,18 +1,16 @@
from sqlalchemy import Column, Integer
from sqlalchemy.exc import IntegrityError

from aurweb import schema
from aurweb.models.declarative import Base

# TODO: Fix this! Official packages aren't from aur.archlinux.org...
OFFICIAL_BASE = "https://aur.archlinux.org"


class OfficialProvider(Base):
__tablename__ = "OfficialProviders"

ID = Column(Integer, primary_key=True)

__mapper_args__ = {"primary_key": [ID]}
__table__ = schema.OfficialProviders
__tablename__ = __table__.name
__mapper_args__ = {"primary_key": [__table__.c.ID]}

def __init__(self, **kwargs):
super().__init__(**kwargs)
Expand Down
15 changes: 5 additions & 10 deletions aurweb/models/package.py
@@ -1,24 +1,19 @@
from sqlalchemy import Column, ForeignKey, Integer
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import backref, relationship

from aurweb import schema
from aurweb.models.declarative import Base
from aurweb.models.package_base import PackageBase as _PackageBase


class Package(Base):
__tablename__ = "Packages"
__table__ = schema.Packages
__tablename__ = __table__.name
__mapper_args__ = {"primary_key": [__table__.c.ID]}

ID = Column(Integer, primary_key=True)

PackageBaseID = Column(
Integer, ForeignKey("PackageBases.ID", ondelete="CASCADE"),
nullable=False)
PackageBase = relationship(
_PackageBase, backref=backref("packages", lazy="dynamic"),
foreign_keys=[PackageBaseID])

__mapper_args__ = {"primary_key": [ID]}
foreign_keys=[__table__.c.PackageBaseID])

def __init__(self, **kwargs):
super().__init__(**kwargs)
Expand Down
21 changes: 8 additions & 13 deletions aurweb/models/package_base.py
@@ -1,38 +1,33 @@
from datetime import datetime

from sqlalchemy import Column, ForeignKey, Integer
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import backref, relationship

from aurweb import schema
from aurweb.models.declarative import Base
from aurweb.models.user import User as _User


class PackageBase(Base):
__tablename__ = "PackageBases"
__table__ = schema.PackageBases
__tablename__ = __table__.name
__mapper_args__ = {"primary_key": [__table__.c.ID]}

FlaggerUID = Column(Integer,
ForeignKey("Users.ID", ondelete="SET NULL"))
Flagger = relationship(
_User, backref=backref("flagged_bases", lazy="dynamic"),
foreign_keys=[FlaggerUID])
foreign_keys=[__table__.c.FlaggerUID])

SubmitterUID = Column(Integer,
ForeignKey("Users.ID", ondelete="SET NULL"))
Submitter = relationship(
_User, backref=backref("submitted_bases", lazy="dynamic"),
foreign_keys=[SubmitterUID])
foreign_keys=[__table__.c.SubmitterUID])

MaintainerUID = Column(Integer,
ForeignKey("Users.ID", ondelete="SET NULL"))
Maintainer = relationship(
_User, backref=backref("maintained_bases", lazy="dynamic"),
foreign_keys=[MaintainerUID])
foreign_keys=[__table__.c.MaintainerUID])

PackagerUID = Column(Integer, ForeignKey("Users.ID", ondelete="SET NULL"))
Packager = relationship(
_User, backref=backref("package_bases", lazy="dynamic"),
foreign_keys=[PackagerUID])
foreign_keys=[__table__.c.PackagerUID])

# A set used to check for floatable values.
TO_FLOAT = {"Popularity"}
Expand Down
10 changes: 4 additions & 6 deletions aurweb/models/package_blacklist.py
@@ -1,15 +1,13 @@
from sqlalchemy import Column, Integer
from sqlalchemy.exc import IntegrityError

from aurweb import schema
from aurweb.models.declarative import Base


class PackageBlacklist(Base):
__tablename__ = "PackageBlacklist"

ID = Column(Integer, primary_key=True)

__mapper_args__ = {"primary_key": [ID]}
__table__ = schema.PackageBlacklist
__tablename__ = __table__.name
__mapper_args__ = {"primary_key": [__table__.c.ID]}

def __init__(self, **kwargs):
super().__init__(**kwargs)
Expand Down

0 comments on commit 446a082

Please sign in to comment.