mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
feat(rpc): add search type handler
This commit introduces a PackageSearch-derivative class: `RPCSearch`. This derivative modifies callback behavior of PackageSearch to suit RPC searches, including [make|check|opt]depends `by` types. Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
parent
ece25e0499
commit
af2f3694e7
5 changed files with 245 additions and 37 deletions
|
@ -1,6 +1,7 @@
|
|||
from sqlalchemy import and_, case, or_, orm
|
||||
|
||||
from aurweb import config, db, models
|
||||
from aurweb import config, db, models, util
|
||||
from aurweb.models.dependency_type import CHECKDEPENDS_ID, DEPENDS_ID, MAKEDEPENDS_ID, OPTDEPENDS_ID
|
||||
|
||||
DEFAULT_MAX_RESULTS = 2500
|
||||
|
||||
|
@ -11,24 +12,25 @@ class PackageSearch:
|
|||
# A constant mapping of short to full name sort orderings.
|
||||
FULL_SORT_ORDER = {"d": "desc", "a": "asc"}
|
||||
|
||||
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.
|
||||
"""
|
||||
def __init__(self, user: models.User = None):
|
||||
self.user = user
|
||||
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(
|
||||
models.PackageNotification,
|
||||
and_(models.PackageNotification.PackageBaseID == models.PackageBase.ID,
|
||||
models.PackageNotification.UserID == self.user.ID),
|
||||
isouter=True
|
||||
)
|
||||
self.query = db.query(models.Package).join(models.PackageBase)
|
||||
|
||||
if self.user:
|
||||
PackageVote = models.PackageVote
|
||||
join_vote_on = and_(
|
||||
PackageVote.PackageBaseID == models.PackageBase.ID,
|
||||
PackageVote.UsersID == self.user.ID)
|
||||
|
||||
PackageNotification = models.PackageNotification
|
||||
join_notif_on = and_(
|
||||
PackageNotification.PackageBaseID == models.PackageBase.ID,
|
||||
PackageNotification.UserID == self.user.ID)
|
||||
|
||||
self.query = self.query.join(
|
||||
models.PackageVote, join_vote_on, isouter=True
|
||||
).join(models.PackageNotification, join_notif_on, isouter=True)
|
||||
|
||||
self.ordering = "d"
|
||||
|
||||
# Setup SeB (Search By) callbacks.
|
||||
|
@ -198,3 +200,83 @@ class PackageSearch:
|
|||
|
||||
# Return the query to the user.
|
||||
return self.query
|
||||
|
||||
|
||||
class RPCSearch(PackageSearch):
|
||||
""" A PackageSearch-derived RPC package search query builder.
|
||||
|
||||
With RPC search, we need a subset of PackageSearch's handlers,
|
||||
with a few additional handlers added. So, within the RPCSearch
|
||||
constructor, we pop unneeded keys out of inherited self.search_by_cb
|
||||
and add a few more keys to it, namely: depends, makedepends,
|
||||
optdepends and checkdepends.
|
||||
|
||||
Additionally, some logic within the inherited PackageSearch.search_by
|
||||
method is not needed, so it is overridden in this class without
|
||||
sanitization done for the PackageSearch `by` argument.
|
||||
"""
|
||||
|
||||
keys_removed = ("b", "N", "B", "k", "c", "M", "s")
|
||||
|
||||
def __init__(self) -> "RPCSearch":
|
||||
super().__init__()
|
||||
|
||||
# Fix-up inherited search_by_cb to reflect RPC-specific by params.
|
||||
# We keep: "nd", "n" and "m". We also overlay four new by params
|
||||
# on top: "depends", "makedepends", "optdepends" and "checkdepends".
|
||||
util.apply_all(RPCSearch.keys_removed,
|
||||
lambda k: self.search_by_cb.pop(k))
|
||||
self.search_by_cb.update({
|
||||
"depends": self._search_by_depends,
|
||||
"makedepends": self._search_by_makedepends,
|
||||
"optdepends": self._search_by_optdepends,
|
||||
"checkdepends": self._search_by_checkdepends
|
||||
})
|
||||
|
||||
def _join_depends(self, dep_type_id: int) -> orm.Query:
|
||||
""" Join Package with PackageDependency and filter results
|
||||
based on `dep_type_id`.
|
||||
|
||||
:param dep_type_id: DependencyType ID
|
||||
:returns: PackageDependency-joined orm.Query
|
||||
"""
|
||||
self.query = self.query.join(models.PackageDependency).filter(
|
||||
models.PackageDependency.DepTypeID == dep_type_id)
|
||||
return self.query
|
||||
|
||||
def _search_by_depends(self, keywords: str) -> "RPCSearch":
|
||||
self.query = self._join_depends(DEPENDS_ID).filter(
|
||||
models.PackageDependency.DepName == keywords)
|
||||
return self
|
||||
|
||||
def _search_by_makedepends(self, keywords: str) -> "RPCSearch":
|
||||
self.query = self._join_depends(MAKEDEPENDS_ID).filter(
|
||||
models.PackageDependency.DepName == keywords)
|
||||
return self
|
||||
|
||||
def _search_by_optdepends(self, keywords: str) -> "RPCSearch":
|
||||
self.query = self._join_depends(OPTDEPENDS_ID).filter(
|
||||
models.PackageDependency.DepName == keywords)
|
||||
return self
|
||||
|
||||
def _search_by_checkdepends(self, keywords: str) -> "RPCSearch":
|
||||
self.query = self._join_depends(CHECKDEPENDS_ID).filter(
|
||||
models.PackageDependency.DepName == keywords)
|
||||
return self
|
||||
|
||||
def search_by(self, by: str, keywords: str) -> "RPCSearch":
|
||||
""" Override inherited search_by. In this override, we reduce the
|
||||
scope of what we handle within this function. We do not set `by`
|
||||
to a default of "nd" in the RPC, as the RPC returns an error when
|
||||
incorrect `by` fields are specified.
|
||||
|
||||
:param by: RPC `by` argument
|
||||
:param keywords: RPC `arg` argument
|
||||
:returns: self
|
||||
"""
|
||||
callback = self.search_by_cb.get(by)
|
||||
result = callback(keywords)
|
||||
return result
|
||||
|
||||
def results(self) -> orm.Query:
|
||||
return self.query
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue