mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
change(fastapi): simplify model imports across code-base
Closes: #133 Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
parent
bfdc85d7d6
commit
28c4e9697b
12 changed files with 341 additions and 343 deletions
|
@ -1,13 +1,6 @@
|
|||
from sqlalchemy import and_, case, or_, orm
|
||||
|
||||
from aurweb import config, db
|
||||
from aurweb.models.package import Package
|
||||
from aurweb.models.package_base import PackageBase
|
||||
from aurweb.models.package_comaintainer import PackageComaintainer
|
||||
from aurweb.models.package_keyword import PackageKeyword
|
||||
from aurweb.models.package_notification import PackageNotification
|
||||
from aurweb.models.package_vote import PackageVote
|
||||
from aurweb.models.user import User
|
||||
from aurweb import config, db, models
|
||||
|
||||
DEFAULT_MAX_RESULTS = 2500
|
||||
|
||||
|
@ -18,22 +11,22 @@ class PackageSearch:
|
|||
# A constant mapping of short to full name sort orderings.
|
||||
FULL_SORT_ORDER = {"d": "desc", "a": "asc"}
|
||||
|
||||
def __init__(self, user: User):
|
||||
def __init__(self, user: models.User):
|
||||
""" Construct an instance of PackageSearch.
|
||||
|
||||
This constructors performs several steps during initialization:
|
||||
1. Setup self.query: an ORM query of Package joined by PackageBase.
|
||||
"""
|
||||
self.user = user
|
||||
self.query = db.query(Package).join(PackageBase).join(
|
||||
PackageVote,
|
||||
and_(PackageVote.PackageBaseID == PackageBase.ID,
|
||||
PackageVote.UsersID == self.user.ID),
|
||||
self.query = db.query(models.Package).join(models.PackageBase).join(
|
||||
models.PackageVote,
|
||||
and_(models.PackageVote.PackageBaseID == models.PackageBase.ID,
|
||||
models.PackageVote.UsersID == self.user.ID),
|
||||
isouter=True
|
||||
).join(
|
||||
PackageNotification,
|
||||
and_(PackageNotification.PackageBaseID == PackageBase.ID,
|
||||
PackageNotification.UserID == self.user.ID),
|
||||
models.PackageNotification,
|
||||
and_(models.PackageNotification.PackageBaseID == models.PackageBase.ID,
|
||||
models.PackageNotification.UserID == self.user.ID),
|
||||
isouter=True
|
||||
)
|
||||
self.ordering = "d"
|
||||
|
@ -65,59 +58,64 @@ class PackageSearch:
|
|||
|
||||
def _search_by_namedesc(self, keywords: str) -> orm.Query:
|
||||
self.query = self.query.filter(
|
||||
or_(Package.Name.like(f"%{keywords}%"),
|
||||
Package.Description.like(f"%{keywords}%"))
|
||||
or_(models.Package.Name.like(f"%{keywords}%"),
|
||||
models.Package.Description.like(f"%{keywords}%"))
|
||||
)
|
||||
return self
|
||||
|
||||
def _search_by_name(self, keywords: str) -> orm.Query:
|
||||
self.query = self.query.filter(Package.Name.like(f"%{keywords}%"))
|
||||
self.query = self.query.filter(
|
||||
models.Package.Name.like(f"%{keywords}%"))
|
||||
return self
|
||||
|
||||
def _search_by_exact_name(self, keywords: str) -> orm.Query:
|
||||
self.query = self.query.filter(Package.Name == keywords)
|
||||
self.query = self.query.filter(
|
||||
models.Package.Name == keywords)
|
||||
return self
|
||||
|
||||
def _search_by_pkgbase(self, keywords: str) -> orm.Query:
|
||||
self.query = self.query.filter(PackageBase.Name.like(f"%{keywords}%"))
|
||||
self.query = self.query.filter(
|
||||
models.PackageBase.Name.like(f"%{keywords}%"))
|
||||
return self
|
||||
|
||||
def _search_by_exact_pkgbase(self, keywords: str) -> orm.Query:
|
||||
self.query = self.query.filter(PackageBase.Name == keywords)
|
||||
self.query = self.query.filter(
|
||||
models.PackageBase.Name == keywords)
|
||||
return self
|
||||
|
||||
def _search_by_keywords(self, keywords: str) -> orm.Query:
|
||||
self.query = self.query.join(PackageKeyword).filter(
|
||||
PackageKeyword.Keyword == keywords
|
||||
self.query = self.query.join(models.PackageKeyword).filter(
|
||||
models.PackageKeyword.Keyword == keywords
|
||||
)
|
||||
return self
|
||||
|
||||
def _search_by_maintainer(self, keywords: str) -> orm.Query:
|
||||
self.query = self.query.join(
|
||||
User, User.ID == PackageBase.MaintainerUID
|
||||
).filter(User.Username == keywords)
|
||||
models.User, models.User.ID == models.PackageBase.MaintainerUID
|
||||
).filter(models.User.Username == keywords)
|
||||
return self
|
||||
|
||||
def _search_by_comaintainer(self, keywords: str) -> orm.Query:
|
||||
self.query = self.query.join(PackageComaintainer).join(
|
||||
User, User.ID == PackageComaintainer.UsersID
|
||||
).filter(User.Username == keywords)
|
||||
self.query = self.query.join(models.PackageComaintainer).join(
|
||||
models.User, models.User.ID == models.PackageComaintainer.UsersID
|
||||
).filter(models.User.Username == keywords)
|
||||
return self
|
||||
|
||||
def _search_by_co_or_maintainer(self, keywords: str) -> orm.Query:
|
||||
self.query = self.query.join(
|
||||
PackageComaintainer,
|
||||
models.PackageComaintainer,
|
||||
isouter=True
|
||||
).join(
|
||||
User, or_(User.ID == PackageBase.MaintainerUID,
|
||||
User.ID == PackageComaintainer.UsersID)
|
||||
).filter(User.Username == keywords)
|
||||
models.User,
|
||||
or_(models.User.ID == models.PackageBase.MaintainerUID,
|
||||
models.User.ID == models.PackageComaintainer.UsersID)
|
||||
).filter(models.User.Username == keywords)
|
||||
return self
|
||||
|
||||
def _search_by_submitter(self, keywords: str) -> orm.Query:
|
||||
self.query = self.query.join(
|
||||
User, User.ID == PackageBase.SubmitterUID
|
||||
).filter(User.Username == keywords)
|
||||
models.User, models.User.ID == models.PackageBase.SubmitterUID
|
||||
).filter(models.User.Username == keywords)
|
||||
return self
|
||||
|
||||
def search_by(self, search_by: str, keywords: str) -> orm.Query:
|
||||
|
@ -128,17 +126,17 @@ class PackageSearch:
|
|||
return result
|
||||
|
||||
def _sort_by_name(self, order: str):
|
||||
column = getattr(Package.Name, order)
|
||||
column = getattr(models.Package.Name, order)
|
||||
self.query = self.query.order_by(column())
|
||||
return self
|
||||
|
||||
def _sort_by_votes(self, order: str):
|
||||
column = getattr(PackageBase.NumVotes, order)
|
||||
column = getattr(models.PackageBase.NumVotes, order)
|
||||
self.query = self.query.order_by(column())
|
||||
return self
|
||||
|
||||
def _sort_by_popularity(self, order: str):
|
||||
column = getattr(PackageBase.Popularity, order)
|
||||
column = getattr(models.PackageBase.Popularity, order)
|
||||
self.query = self.query.order_by(column())
|
||||
return self
|
||||
|
||||
|
@ -147,10 +145,10 @@ class PackageSearch:
|
|||
# in terms of performance. We should improve this; there's no
|
||||
# reason it should take _longer_.
|
||||
column = getattr(
|
||||
case([(PackageVote.UsersID == self.user.ID, 1)], else_=0),
|
||||
case([(models.PackageVote.UsersID == self.user.ID, 1)], else_=0),
|
||||
order
|
||||
)
|
||||
self.query = self.query.order_by(column(), Package.Name.desc())
|
||||
self.query = self.query.order_by(column(), models.Package.Name.desc())
|
||||
return self
|
||||
|
||||
def _sort_by_notify(self, order: str):
|
||||
|
@ -158,21 +156,24 @@ class PackageSearch:
|
|||
# in terms of performance. We should improve this; there's no
|
||||
# reason it should take _longer_.
|
||||
column = getattr(
|
||||
case([(PackageNotification.UserID == self.user.ID, 1)], else_=0),
|
||||
case([(models.PackageNotification.UserID == self.user.ID, 1)],
|
||||
else_=0),
|
||||
order
|
||||
)
|
||||
self.query = self.query.order_by(column(), Package.Name.desc())
|
||||
self.query = self.query.order_by(column(), models.Package.Name.desc())
|
||||
return self
|
||||
|
||||
def _sort_by_maintainer(self, order: str):
|
||||
column = getattr(User.Username, order)
|
||||
column = getattr(models.User.Username, order)
|
||||
self.query = self.query.join(
|
||||
User, User.ID == PackageBase.MaintainerUID, isouter=True
|
||||
models.User,
|
||||
models.User.ID == models.PackageBase.MaintainerUID,
|
||||
isouter=True
|
||||
).order_by(column())
|
||||
return self
|
||||
|
||||
def _sort_by_last_modified(self, order: str):
|
||||
column = getattr(PackageBase.ModifiedTS, order)
|
||||
column = getattr(models.PackageBase.ModifiedTS, order)
|
||||
self.query = self.query.order_by(column())
|
||||
return self
|
||||
|
||||
|
|
|
@ -7,43 +7,35 @@ import orjson
|
|||
from fastapi import HTTPException
|
||||
from sqlalchemy import and_, orm
|
||||
|
||||
from aurweb import db
|
||||
from aurweb.models.official_provider import OFFICIAL_BASE, OfficialProvider
|
||||
from aurweb.models.package import Package
|
||||
from aurweb.models.package_base import PackageBase
|
||||
from aurweb.models.package_comment import PackageComment
|
||||
from aurweb.models.package_dependency import PackageDependency
|
||||
from aurweb.models.package_notification import PackageNotification
|
||||
from aurweb.models.package_relation import PackageRelation
|
||||
from aurweb.models.package_vote import PackageVote
|
||||
from aurweb.models.relation_type import PROVIDES_ID, RelationType
|
||||
from aurweb.models.user import User
|
||||
from aurweb import db, models
|
||||
from aurweb.models.official_provider import OFFICIAL_BASE
|
||||
from aurweb.models.relation_type import PROVIDES_ID
|
||||
from aurweb.redis import redis_connection
|
||||
from aurweb.templates import register_filter
|
||||
|
||||
|
||||
def dep_depends_extra(dep: PackageDependency) -> str:
|
||||
def dep_depends_extra(dep: models.PackageDependency) -> str:
|
||||
""" A function used to produce extra text for dependency display. """
|
||||
return str()
|
||||
|
||||
|
||||
def dep_makedepends_extra(dep: PackageDependency) -> str:
|
||||
def dep_makedepends_extra(dep: models.PackageDependency) -> str:
|
||||
""" A function used to produce extra text for dependency display. """
|
||||
return "(make)"
|
||||
|
||||
|
||||
def dep_checkdepends_extra(dep: PackageDependency) -> str:
|
||||
def dep_checkdepends_extra(dep: models.PackageDependency) -> str:
|
||||
""" A function used to produce extra text for dependency display. """
|
||||
return "(check)"
|
||||
|
||||
|
||||
def dep_optdepends_extra(dep: PackageDependency) -> str:
|
||||
def dep_optdepends_extra(dep: models.PackageDependency) -> str:
|
||||
""" A function used to produce extra text for dependency display. """
|
||||
return "(optional)"
|
||||
|
||||
|
||||
@register_filter("dep_extra")
|
||||
def dep_extra(dep: PackageDependency) -> str:
|
||||
def dep_extra(dep: models.PackageDependency) -> str:
|
||||
""" Some dependency types have extra text added to their
|
||||
display. This function provides that output. However, it
|
||||
**assumes** that the dep passed is bound to a valid one
|
||||
|
@ -53,7 +45,7 @@ def dep_extra(dep: PackageDependency) -> str:
|
|||
|
||||
|
||||
@register_filter("dep_extra_desc")
|
||||
def dep_extra_desc(dep: PackageDependency) -> str:
|
||||
def dep_extra_desc(dep: models.PackageDependency) -> str:
|
||||
extra = dep_extra(dep)
|
||||
if not dep.DepDesc:
|
||||
return extra
|
||||
|
@ -63,30 +55,30 @@ def dep_extra_desc(dep: PackageDependency) -> str:
|
|||
@register_filter("pkgname_link")
|
||||
def pkgname_link(pkgname: str) -> str:
|
||||
base = "/".join([OFFICIAL_BASE, "packages"])
|
||||
official = db.query(OfficialProvider).filter(
|
||||
OfficialProvider.Name == pkgname)
|
||||
official = db.query(models.OfficialProvider).filter(
|
||||
models.OfficialProvider.Name == pkgname)
|
||||
if official.scalar():
|
||||
return f"{base}/?q={pkgname}"
|
||||
return f"/packages/{pkgname}"
|
||||
|
||||
|
||||
@register_filter("package_link")
|
||||
def package_link(package: Package) -> str:
|
||||
def package_link(package: models.Package) -> str:
|
||||
base = "/".join([OFFICIAL_BASE, "packages"])
|
||||
official = db.query(OfficialProvider).filter(
|
||||
OfficialProvider.Name == package.Name)
|
||||
official = db.query(models.OfficialProvider).filter(
|
||||
models.OfficialProvider.Name == package.Name)
|
||||
if official.scalar():
|
||||
return f"{base}/?q={package.Name}"
|
||||
return f"/packages/{package.Name}"
|
||||
|
||||
|
||||
@register_filter("provides_list")
|
||||
def provides_list(package: Package, depname: str) -> list:
|
||||
providers = db.query(Package).join(
|
||||
PackageRelation).join(RelationType).filter(
|
||||
def provides_list(package: models.Package, depname: str) -> list:
|
||||
providers = db.query(models.Package).join(
|
||||
models.PackageRelation).join(models.RelationType).filter(
|
||||
and_(
|
||||
PackageRelation.RelName == depname,
|
||||
RelationType.ID == PROVIDES_ID
|
||||
models.PackageRelation.RelName == depname,
|
||||
models.RelationType.ID == PROVIDES_ID
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -102,7 +94,9 @@ def provides_list(package: Package, depname: str) -> list:
|
|||
return string
|
||||
|
||||
|
||||
def get_pkg_or_base(name: str, cls: Union[Package, PackageBase] = PackageBase):
|
||||
def get_pkg_or_base(
|
||||
name: str,
|
||||
cls: Union[models.Package, models.PackageBase] = models.PackageBase):
|
||||
""" Get a PackageBase instance by its name or raise a 404 if
|
||||
it can't be found in the database.
|
||||
|
||||
|
@ -110,20 +104,21 @@ def get_pkg_or_base(name: str, cls: Union[Package, PackageBase] = PackageBase):
|
|||
:raises HTTPException: With status code 404 if record doesn't exist
|
||||
:return: {Package,PackageBase} instance
|
||||
"""
|
||||
provider = db.query(OfficialProvider).filter(
|
||||
OfficialProvider.Name == name).first()
|
||||
provider = db.query(models.OfficialProvider).filter(
|
||||
models.OfficialProvider.Name == name).first()
|
||||
if provider:
|
||||
raise HTTPException(status_code=HTTPStatus.NOT_FOUND)
|
||||
|
||||
instance = db.query(cls).filter(cls.Name == name).first()
|
||||
if cls == PackageBase and not instance:
|
||||
if cls == models.PackageBase and not instance:
|
||||
raise HTTPException(status_code=HTTPStatus.NOT_FOUND)
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
def get_pkgbase_comment(pkgbase: PackageBase, id: int) -> PackageComment:
|
||||
comment = pkgbase.comments.filter(PackageComment.ID == id).first()
|
||||
def get_pkgbase_comment(
|
||||
pkgbase: models.PackageBase, id: int) -> models.PackageComment:
|
||||
comment = pkgbase.comments.filter(models.PackageComment.ID == id).first()
|
||||
if not comment:
|
||||
raise HTTPException(status_code=HTTPStatus.NOT_FOUND)
|
||||
return comment
|
||||
|
@ -131,10 +126,11 @@ def get_pkgbase_comment(pkgbase: PackageBase, id: int) -> PackageComment:
|
|||
|
||||
@register_filter("out_of_date")
|
||||
def out_of_date(packages: orm.Query) -> orm.Query:
|
||||
return packages.filter(PackageBase.OutOfDateTS.isnot(None))
|
||||
return packages.filter(models.PackageBase.OutOfDateTS.isnot(None))
|
||||
|
||||
|
||||
def updated_packages(limit: int = 0, cache_ttl: int = 600) -> List[Package]:
|
||||
def updated_packages(limit: int = 0,
|
||||
cache_ttl: int = 600) -> List[models.Package]:
|
||||
""" Return a list of valid Package objects ordered by their
|
||||
ModifiedTS column in descending order from cache, after setting
|
||||
the cache when no key yet exists.
|
||||
|
@ -149,10 +145,10 @@ def updated_packages(limit: int = 0, cache_ttl: int = 600) -> List[Package]:
|
|||
# If we already have a cache, deserialize it and return.
|
||||
return orjson.loads(packages)
|
||||
|
||||
query = db.query(Package).join(PackageBase).filter(
|
||||
PackageBase.PackagerUID.isnot(None)
|
||||
query = db.query(models.Package).join(models.PackageBase).filter(
|
||||
models.PackageBase.PackagerUID.isnot(None)
|
||||
).order_by(
|
||||
PackageBase.ModifiedTS.desc()
|
||||
models.PackageBase.ModifiedTS.desc()
|
||||
)
|
||||
|
||||
if limit:
|
||||
|
@ -178,7 +174,8 @@ def updated_packages(limit: int = 0, cache_ttl: int = 600) -> List[Package]:
|
|||
return packages
|
||||
|
||||
|
||||
def query_voted(query: List[Package], user: User) -> Dict[int, bool]:
|
||||
def query_voted(query: List[models.Package],
|
||||
user: models.User) -> Dict[int, bool]:
|
||||
""" Produce a dictionary of package base ID keys to boolean values,
|
||||
which indicate whether or not the package base has a vote record
|
||||
related to user.
|
||||
|
@ -189,18 +186,19 @@ def query_voted(query: List[Package], user: User) -> Dict[int, bool]:
|
|||
"""
|
||||
output = defaultdict(bool)
|
||||
query_set = {pkg.PackageBase.ID for pkg in query}
|
||||
voted = db.query(PackageVote).join(
|
||||
PackageBase,
|
||||
PackageBase.ID.in_(query_set)
|
||||
voted = db.query(models.PackageVote).join(
|
||||
models.PackageBase,
|
||||
models.PackageBase.ID.in_(query_set)
|
||||
).filter(
|
||||
PackageVote.UsersID == user.ID
|
||||
models.PackageVote.UsersID == user.ID
|
||||
)
|
||||
for vote in voted:
|
||||
output[vote.PackageBase.ID] = True
|
||||
return output
|
||||
|
||||
|
||||
def query_notified(query: List[Package], user: User) -> Dict[int, bool]:
|
||||
def query_notified(query: List[models.Package],
|
||||
user: models.User) -> Dict[int, bool]:
|
||||
""" Produce a dictionary of package base ID keys to boolean values,
|
||||
which indicate whether or not the package base has a notification
|
||||
record related to user.
|
||||
|
@ -211,11 +209,11 @@ def query_notified(query: List[Package], user: User) -> Dict[int, bool]:
|
|||
"""
|
||||
output = defaultdict(bool)
|
||||
query_set = {pkg.PackageBase.ID for pkg in query}
|
||||
notified = db.query(PackageNotification).join(
|
||||
PackageBase,
|
||||
PackageBase.ID.in_(query_set)
|
||||
notified = db.query(models.PackageNotification).join(
|
||||
models.PackageBase,
|
||||
models.PackageBase.ID.in_(query_set)
|
||||
).filter(
|
||||
PackageNotification.UserID == user.ID
|
||||
models.PackageNotification.UserID == user.ID
|
||||
)
|
||||
for notify in notified:
|
||||
output[notify.PackageBase.ID] = True
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue