implement /packages/{name} as its own route

A few things added with this commit:

- aurweb.packages.util
    - A module providing package and pkgbase helpers.
- aurweb.template.register_filter
    - A decorator that can be used to register a filter:
      @register_filter("some_filter") def f(): pass

Additionally, template partials have been split off a bit
differently. Changes:

- /packages/{name} is defined in packages/show.html.
- partials/packages/package_actions.html is now
  partials/packages/actions.html.
- partials/packages/details.html has been added.
- partials/packages/comments.html has been added.
- partials/packages/comment.html has been added.
- models.dependency_type additions: name and id constants.
- models.relation_type additions: name and id constants.
- models.official_provider additions: base official url constant.

Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
Kevin Morris 2021-07-15 22:48:26 -07:00
parent 2d3d03e01e
commit ae3d302c47
22 changed files with 1166 additions and 254 deletions

View file

@ -1,39 +1,98 @@
from http import HTTPStatus
from typing import Any, Dict
from fastapi import APIRouter, HTTPException, Request
from fastapi import APIRouter, Request, Response
from fastapi.responses import RedirectResponse
from sqlalchemy import and_
import aurweb.models.package
import aurweb.models.package_comment
import aurweb.models.package_keyword
import aurweb.packages.util
from aurweb import db
from aurweb.models.license import License
from aurweb.models.package import Package
from aurweb.models.package_base import PackageBase
from aurweb.models.package_dependency import PackageDependency
from aurweb.models.package_license import PackageLicense
from aurweb.models.package_notification import PackageNotification
from aurweb.models.package_relation import PackageRelation
from aurweb.models.package_source import PackageSource
from aurweb.models.package_vote import PackageVote
from aurweb.models.relation_type import CONFLICTS_ID, RelationType
from aurweb.packages.util import get_pkgbase
from aurweb.templates import make_variable_context, render_template
router = APIRouter()
@router.get("/packages/{package}")
async def package_base(request: Request, package: str):
package = db.query(PackageBase).filter(PackageBase.Name == package).first()
if not package:
raise HTTPException(status_code=int(HTTPStatus.NOT_FOUND))
async def make_single_context(request: Request,
pkgbase: PackageBase) -> Dict[str, Any]:
""" Make a basic context for package or pkgbase.
context = await make_variable_context(request, package.Name)
context["git_clone_uri_anon"] = aurweb.config.get("options", "git_clone_uri_anon")
context["git_clone_uri_priv"] = aurweb.config.get("options", "git_clone_uri_priv")
context["pkgbase"] = package
context["packages"] = package.packages.all()
context["packages_count"] = package.packages.count()
context["keywords"] = package.keywords.all()
context["comments"] = package.comments.all()
context["is_maintainer"] = request.user.is_authenticated() \
and request.user.Username == package.Maintainer.Username
:param request: FastAPI request
:param pkgbase: PackageBase instance
:return: A pkgbase context without specific differences
"""
context = await make_variable_context(request, pkgbase.Name)
context["git_clone_uri_anon"] = aurweb.config.get("options",
"git_clone_uri_anon")
context["git_clone_uri_priv"] = aurweb.config.get("options",
"git_clone_uri_priv")
context["pkgbase"] = pkgbase
context["packages_count"] = pkgbase.packages.count()
context["keywords"] = pkgbase.keywords
context["comments"] = pkgbase.comments
context["is_maintainer"] = (request.user.is_authenticated()
and request.user == pkgbase.Maintainer)
context["notified"] = db.query(
PackageNotification).join(PackageBase).filter(
and_(PackageBase.ID == pkgbase.ID,
PackageNotification.UserID == request.user.ID)).count() > 0
return render_template(request, "pkgbase.html", context)
context["out_of_date"] = bool(pkgbase.OutOfDateTS)
context["voted"] = pkgbase.package_votes.filter(
PackageVote.UsersID == request.user.ID).count() > 0
context["notifications_enabled"] = db.query(
PackageNotification).join(PackageBase).filter(
PackageBase.ID == pkgbase.ID).count() > 0
return context
@router.get("/pkgbase/{package}")
async def package_base_redirect(request: Request, package: str):
return RedirectResponse(f"/packages/{package}")
@router.get("/packages/{name}")
async def package(request: Request, name: str) -> Response:
# Get the PackageBase.
pkgbase = get_pkgbase(name)
# Add our base information.
context = await make_single_context(request, pkgbase)
# Package sources.
sources = db.query(PackageSource).join(Package).filter(
Package.PackageBaseID == pkgbase.ID)
context["sources"] = sources
# Package dependencies.
dependencies = db.query(PackageDependency).join(Package).filter(
Package.PackageBaseID == pkgbase.ID)
context["dependencies"] = dependencies
# Package requirements (other packages depend on this one).
required_by = db.query(PackageDependency).join(Package).filter(
PackageDependency.DepName == pkgbase.Name).order_by(
Package.Name.asc())
context["required_by"] = required_by
licenses = db.query(License).join(PackageLicense).join(Package).filter(
PackageLicense.PackageID == pkgbase.packages.first().ID)
context["licenses"] = licenses
conflicts = db.query(PackageRelation).join(RelationType).join(Package).join(PackageBase).filter(
and_(RelationType.ID == CONFLICTS_ID,
PackageBase.ID == pkgbase.ID))
context["conflicts"] = conflicts
return render_template(request, "packages/show.html", context)