fix(python): use standard dict/list type annotation

Since Python 3.9 list/dict can be used as type hint.
This commit is contained in:
Jelle van der Waa 2022-07-31 20:58:39 +02:00 committed by Jelle van der Waa
parent 28970ccc91
commit a509e40474
31 changed files with 175 additions and 195 deletions

View file

@ -2,7 +2,7 @@ import copy
import math import math
from datetime import datetime from datetime import datetime
from typing import Any, Dict, Union from typing import Any, Union
from urllib.parse import quote_plus, urlencode from urllib.parse import quote_plus, urlencode
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
@ -19,7 +19,7 @@ from aurweb.templates import register_filter, register_function
@register_filter("pager_nav") @register_filter("pager_nav")
@pass_context @pass_context
def pager_nav(context: Dict[str, Any], def pager_nav(context: dict[str, Any],
page: int, total: int, prefix: str) -> str: page: int, total: int, prefix: str) -> str:
page = int(page) # Make sure this is an int. page = int(page) # Make sure this is an int.
@ -71,7 +71,7 @@ def do_round(f: float) -> int:
@register_filter("tr") @register_filter("tr")
@pass_context @pass_context
def tr(context: Dict[str, Any], value: str): def tr(context: dict[str, Any], value: str):
""" A translation filter; example: {{ "Hello" | tr("de") }}. """ """ A translation filter; example: {{ "Hello" | tr("de") }}. """
_ = l10n.get_translator_for_request(context.get("request")) _ = l10n.get_translator_for_request(context.get("request"))
return _(value) return _(value)
@ -79,7 +79,7 @@ def tr(context: Dict[str, Any], value: str):
@register_filter("tn") @register_filter("tn")
@pass_context @pass_context
def tn(context: Dict[str, Any], count: int, def tn(context: dict[str, Any], count: int,
singular: str, plural: str) -> str: singular: str, plural: str) -> str:
""" A singular and plural translation filter. """ A singular and plural translation filter.
@ -107,7 +107,7 @@ def as_timezone(dt: datetime, timezone: str):
@register_filter("extend_query") @register_filter("extend_query")
def extend_query(query: Dict[str, Any], *additions) -> Dict[str, Any]: def extend_query(query: dict[str, Any], *additions) -> dict[str, Any]:
""" Add additional key value pairs to query. """ """ Add additional key value pairs to query. """
q = copy.copy(query) q = copy.copy(query)
for k, v in list(additions): for k, v in list(additions):
@ -116,7 +116,7 @@ def extend_query(query: Dict[str, Any], *additions) -> Dict[str, Any]:
@register_filter("urlencode") @register_filter("urlencode")
def to_qs(query: Dict[str, Any]) -> str: def to_qs(query: dict[str, Any]) -> str:
return urlencode(query, doseq=True) return urlencode(query, doseq=True)
@ -134,7 +134,7 @@ def number_format(value: float, places: int):
@register_filter("account_url") @register_filter("account_url")
@pass_context @pass_context
def account_url(context: Dict[str, Any], def account_url(context: dict[str, Any],
user: "aurweb.models.user.User") -> str: user: "aurweb.models.user.User") -> str:
base = aurweb.config.get("options", "aur_location") base = aurweb.config.get("options", "aur_location")
return f"{base}/account/{user.Username}" return f"{base}/account/{user.Username}"
@ -152,7 +152,7 @@ def ceil(*args, **kwargs) -> int:
@register_function("date_strftime") @register_function("date_strftime")
@pass_context @pass_context
def date_strftime(context: Dict[str, Any], dt: Union[int, datetime], fmt: str) \ def date_strftime(context: dict[str, Any], dt: Union[int, datetime], fmt: str) \
-> str: -> str:
if isinstance(dt, int): if isinstance(dt, int):
dt = timestamp_to_datetime(dt) dt = timestamp_to_datetime(dt)
@ -162,11 +162,11 @@ def date_strftime(context: Dict[str, Any], dt: Union[int, datetime], fmt: str) \
@register_function("date_display") @register_function("date_display")
@pass_context @pass_context
def date_display(context: Dict[str, Any], dt: Union[int, datetime]) -> str: def date_display(context: dict[str, Any], dt: Union[int, datetime]) -> str:
return date_strftime(context, dt, "%Y-%m-%d (%Z)") return date_strftime(context, dt, "%Y-%m-%d (%Z)")
@register_function("datetime_display") @register_function("datetime_display")
@pass_context @pass_context
def datetime_display(context: Dict[str, Any], dt: Union[int, datetime]) -> str: def datetime_display(context: dict[str, Any], dt: Union[int, datetime]) -> str:
return date_strftime(context, dt, "%Y-%m-%d %H:%M (%Z)") return date_strftime(context, dt, "%Y-%m-%d %H:%M (%Z)")

View file

@ -1,5 +1,3 @@
from typing import List
from sqlalchemy import and_, literal from sqlalchemy import and_, literal
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import backref, relationship from sqlalchemy.orm import backref, relationship
@ -60,7 +58,7 @@ class PackageDependency(Base):
_OfficialProvider.Name == self.DepName).exists() _OfficialProvider.Name == self.DepName).exists()
return db.query(pkg).scalar() or db.query(official).scalar() return db.query(pkg).scalar() or db.query(official).scalar()
def provides(self) -> List[PackageRelation]: def provides(self) -> list[PackageRelation]:
from aurweb.models.relation_type import PROVIDES_ID from aurweb.models.relation_type import PROVIDES_ID
rels = db.query(PackageRelation).join(_Package).filter( rels = db.query(PackageRelation).join(_Package).filter(

View file

@ -1,6 +1,6 @@
import hashlib import hashlib
from typing import List, Set from typing import Set
import bcrypt import bcrypt
@ -149,7 +149,7 @@ class User(Base):
return self.session.SessionID return self.session.SessionID
def has_credential(self, credential: Set[int], def has_credential(self, credential: Set[int],
approved: List["User"] = list()): approved: list["User"] = list()):
from aurweb.auth.creds import has_credential from aurweb.auth.creds import has_credential
return has_credential(self, credential, approved) return has_credential(self, credential, approved)

View file

@ -1,4 +1,4 @@
from typing import List, Optional, Set from typing import Optional, Set
from fastapi import Request from fastapi import Request
from sqlalchemy import and_, orm from sqlalchemy import and_, orm
@ -139,7 +139,7 @@ def close_pkgreq(pkgreq: PackageRequest, closer: User,
def handle_request(request: Request, reqtype_id: int, def handle_request(request: Request, reqtype_id: int,
pkgbase: PackageBase, pkgbase: PackageBase,
target: PackageBase = None) -> List[notify.Notification]: target: PackageBase = None) -> list[notify.Notification]:
""" """
Handle package requests before performing an action. Handle package requests before performing an action.
@ -158,7 +158,7 @@ def handle_request(request: Request, reqtype_id: int,
:param pkgbase: PackageBase which the request is about :param pkgbase: PackageBase which the request is about
:param target: Optional target to merge into :param target: Optional target to merge into
""" """
notifs: List[notify.Notification] = [] notifs: list[notify.Notification] = []
# If it's an orphan request, perform further verification # If it's an orphan request, perform further verification
# regarding existing requests. # regarding existing requests.
@ -187,13 +187,13 @@ def handle_request(request: Request, reqtype_id: int,
PackageRequest.MergeBaseName == target.Name) PackageRequest.MergeBaseName == target.Name)
# Build an accept list out of `accept_query`. # Build an accept list out of `accept_query`.
to_accept: List[PackageRequest] = accept_query.all() to_accept: list[PackageRequest] = accept_query.all()
accepted_ids: Set[int] = set(p.ID for p in to_accept) accepted_ids: Set[int] = set(p.ID for p in to_accept)
# Build a reject list out of `query` filtered by IDs not found # Build a reject list out of `query` filtered by IDs not found
# in `to_accept`. That is, unmatched records of the same base # in `to_accept`. That is, unmatched records of the same base
# query properties. # query properties.
to_reject: List[PackageRequest] = query.filter( to_reject: list[PackageRequest] = query.filter(
~PackageRequest.ID.in_(accepted_ids) ~PackageRequest.ID.in_(accepted_ids)
).all() ).all()

View file

@ -1,6 +1,6 @@
from collections import defaultdict from collections import defaultdict
from http import HTTPStatus from http import HTTPStatus
from typing import Dict, List, Tuple, Union from typing import Tuple, Union
import orjson import orjson
@ -15,7 +15,7 @@ from aurweb.models.package_relation import PackageRelation
from aurweb.redis import redis_connection from aurweb.redis import redis_connection
from aurweb.templates import register_filter from aurweb.templates import register_filter
Providers = List[Union[PackageRelation, OfficialProvider]] Providers = list[Union[PackageRelation, OfficialProvider]]
def dep_extra_with_arch(dep: models.PackageDependency, annotation: str) -> str: def dep_extra_with_arch(dep: models.PackageDependency, annotation: str) -> str:
@ -123,7 +123,7 @@ def out_of_date(packages: orm.Query) -> orm.Query:
def updated_packages(limit: int = 0, def updated_packages(limit: int = 0,
cache_ttl: int = 600) -> List[models.Package]: cache_ttl: int = 600) -> list[models.Package]:
""" Return a list of valid Package objects ordered by their """ Return a list of valid Package objects ordered by their
ModifiedTS column in descending order from cache, after setting ModifiedTS column in descending order from cache, after setting
the cache when no key yet exists. the cache when no key yet exists.
@ -168,8 +168,8 @@ def updated_packages(limit: int = 0,
return packages return packages
def query_voted(query: List[models.Package], def query_voted(query: list[models.Package],
user: models.User) -> Dict[int, bool]: user: models.User) -> dict[int, bool]:
""" Produce a dictionary of package base ID keys to boolean values, """ Produce a dictionary of package base ID keys to boolean values,
which indicate whether or not the package base has a vote record which indicate whether or not the package base has a vote record
related to user. related to user.
@ -191,8 +191,8 @@ def query_voted(query: List[models.Package],
return output return output
def query_notified(query: List[models.Package], def query_notified(query: list[models.Package],
user: models.User) -> Dict[int, bool]: user: models.User) -> dict[int, bool]:
""" Produce a dictionary of package base ID keys to boolean values, """ Produce a dictionary of package base ID keys to boolean values,
which indicate whether or not the package base has a notification which indicate whether or not the package base has a notification
record related to user. record related to user.
@ -214,8 +214,8 @@ def query_notified(query: List[models.Package],
return output return output
def pkg_required(pkgname: str, provides: List[str]) \ def pkg_required(pkgname: str, provides: list[str]) \
-> List[PackageDependency]: -> list[PackageDependency]:
""" """
Get dependencies that match a string in `[pkgname] + provides`. Get dependencies that match a string in `[pkgname] + provides`.

View file

@ -1,5 +1,3 @@
from typing import List
from fastapi import Request from fastapi import Request
from aurweb import db, logging, util from aurweb import db, logging, util
@ -86,7 +84,7 @@ def pkgbase_adopt_instance(request: Request, pkgbase: PackageBase) -> None:
def pkgbase_delete_instance(request: Request, pkgbase: PackageBase, def pkgbase_delete_instance(request: Request, pkgbase: PackageBase,
comments: str = str()) \ comments: str = str()) \
-> List[notify.Notification]: -> list[notify.Notification]:
notifs = handle_request(request, DELETION_ID, pkgbase) + [ notifs = handle_request(request, DELETION_ID, pkgbase) + [
notify.DeleteNotification(request.user.ID, pkgbase.ID) notify.DeleteNotification(request.user.ID, pkgbase.ID)
] ]

View file

@ -1,4 +1,4 @@
from typing import Any, Dict, List from typing import Any
from fastapi import Request from fastapi import Request
from sqlalchemy import and_ from sqlalchemy import and_
@ -15,13 +15,13 @@ from aurweb.templates import make_variable_context as _make_variable_context
async def make_variable_context(request: Request, pkgbase: PackageBase) \ async def make_variable_context(request: Request, pkgbase: PackageBase) \
-> Dict[str, Any]: -> dict[str, Any]:
ctx = await _make_variable_context(request, pkgbase.Name) ctx = await _make_variable_context(request, pkgbase.Name)
return make_context(request, pkgbase, ctx) return make_context(request, pkgbase, ctx)
def make_context(request: Request, pkgbase: PackageBase, def make_context(request: Request, pkgbase: PackageBase,
context: Dict[str, Any] = None) -> Dict[str, Any]: context: dict[str, Any] = None) -> dict[str, Any]:
""" Make a basic context for package or pkgbase. """ Make a basic context for package or pkgbase.
:param request: FastAPI request :param request: FastAPI request
@ -89,7 +89,7 @@ def remove_comaintainer(comaint: PackageComaintainer) \
return notif return notif
def remove_comaintainers(pkgbase: PackageBase, usernames: List[str]) -> None: def remove_comaintainers(pkgbase: PackageBase, usernames: list[str]) -> None:
""" """
Remove comaintainers from `pkgbase`. Remove comaintainers from `pkgbase`.
@ -163,7 +163,7 @@ def add_comaintainer(pkgbase: PackageBase, comaintainer: User) \
def add_comaintainers(request: Request, pkgbase: PackageBase, def add_comaintainers(request: Request, pkgbase: PackageBase,
usernames: List[str]) -> None: usernames: list[str]) -> None:
""" """
Add comaintainers to `pkgbase`. Add comaintainers to `pkgbase`.

View file

@ -1,4 +1,4 @@
from typing import Any, Dict from typing import Any
from aurweb import db from aurweb import db
from aurweb.exceptions import ValidationError from aurweb.exceptions import ValidationError
@ -7,7 +7,7 @@ from aurweb.models import PackageBase
def request(pkgbase: PackageBase, def request(pkgbase: PackageBase,
type: str, comments: str, merge_into: str, type: str, comments: str, merge_into: str,
context: Dict[str, Any]) -> None: context: dict[str, Any]) -> None:
if not comments: if not comments:
raise ValidationError(["The comment field must not be empty."]) raise ValidationError(["The comment field must not be empty."])

View file

@ -1,4 +1,4 @@
from typing import Any, Callable, Dict, List, Optional from typing import Any, Callable, Optional
from prometheus_client import Counter from prometheus_client import Counter
from prometheus_fastapi_instrumentator import Instrumentator from prometheus_fastapi_instrumentator import Instrumentator
@ -19,7 +19,7 @@ def instrumentator():
# Their license is included in LICENSES/starlette_exporter. # Their license is included in LICENSES/starlette_exporter.
# The code has been modified to remove child route checks # The code has been modified to remove child route checks
# (since we don't have any) and to stay within an 80-width limit. # (since we don't have any) and to stay within an 80-width limit.
def get_matching_route_path(scope: Dict[Any, Any], routes: List[Route], def get_matching_route_path(scope: dict[Any, Any], routes: list[Route],
route_name: Optional[str] = None) -> str: route_name: Optional[str] = None) -> str:
""" """
Find a matching route and return its original path string Find a matching route and return its original path string

View file

@ -2,7 +2,7 @@ import copy
import typing import typing
from http import HTTPStatus from http import HTTPStatus
from typing import Any, Dict from typing import Any
from fastapi import APIRouter, Form, Request from fastapi import APIRouter, Form, Request
from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.responses import HTMLResponse, RedirectResponse
@ -108,7 +108,7 @@ async def passreset_post(request: Request,
def process_account_form(request: Request, user: models.User, def process_account_form(request: Request, user: models.User,
args: Dict[str, Any]): args: dict[str, Any]):
""" Process an account form. All fields are optional and only checks """ Process an account form. All fields are optional and only checks
requirements in the case they are present. requirements in the case they are present.

View file

@ -1,6 +1,6 @@
from collections import defaultdict from collections import defaultdict
from http import HTTPStatus from http import HTTPStatus
from typing import Any, Dict, List from typing import Any
from fastapi import APIRouter, Form, Query, Request, Response from fastapi import APIRouter, Form, Query, Request, Response
@ -21,7 +21,7 @@ logger = logging.get_logger(__name__)
router = APIRouter() router = APIRouter()
async def packages_get(request: Request, context: Dict[str, Any], async def packages_get(request: Request, context: dict[str, Any],
status_code: HTTPStatus = HTTPStatus.OK): status_code: HTTPStatus = HTTPStatus.OK):
# Query parameters used in this request. # Query parameters used in this request.
context["q"] = dict(request.query_params) context["q"] = dict(request.query_params)
@ -210,7 +210,7 @@ async def package(request: Request, name: str,
return render_template(request, "packages/show.html", context) return render_template(request, "packages/show.html", context)
async def packages_unflag(request: Request, package_ids: List[int] = [], async def packages_unflag(request: Request, package_ids: list[int] = [],
**kwargs): **kwargs):
if not package_ids: if not package_ids:
return (False, ["You did not select any packages to unflag."]) return (False, ["You did not select any packages to unflag."])
@ -236,7 +236,7 @@ async def packages_unflag(request: Request, package_ids: List[int] = [],
return (True, ["The selected packages have been unflagged."]) return (True, ["The selected packages have been unflagged."])
async def packages_notify(request: Request, package_ids: List[int] = [], async def packages_notify(request: Request, package_ids: list[int] = [],
**kwargs): **kwargs):
# In cases where we encounter errors with the request, we'll # In cases where we encounter errors with the request, we'll
# use this error tuple as a return value. # use this error tuple as a return value.
@ -275,7 +275,7 @@ async def packages_notify(request: Request, package_ids: List[int] = [],
return (True, ["The selected packages' notifications have been enabled."]) return (True, ["The selected packages' notifications have been enabled."])
async def packages_unnotify(request: Request, package_ids: List[int] = [], async def packages_unnotify(request: Request, package_ids: list[int] = [],
**kwargs): **kwargs):
if not package_ids: if not package_ids:
# TODO: This error does not yet have a translation. # TODO: This error does not yet have a translation.
@ -312,7 +312,7 @@ async def packages_unnotify(request: Request, package_ids: List[int] = [],
return (True, ["The selected packages' notifications have been removed."]) return (True, ["The selected packages' notifications have been removed."])
async def packages_adopt(request: Request, package_ids: List[int] = [], async def packages_adopt(request: Request, package_ids: list[int] = [],
confirm: bool = False, **kwargs): confirm: bool = False, **kwargs):
if not package_ids: if not package_ids:
return (False, ["You did not select any packages to adopt."]) return (False, ["You did not select any packages to adopt."])
@ -345,8 +345,8 @@ async def packages_adopt(request: Request, package_ids: List[int] = [],
return (True, ["The selected packages have been adopted."]) return (True, ["The selected packages have been adopted."])
def disown_all(request: Request, pkgbases: List[models.PackageBase]) \ def disown_all(request: Request, pkgbases: list[models.PackageBase]) \
-> List[str]: -> list[str]:
errors = [] errors = []
for pkgbase in pkgbases: for pkgbase in pkgbases:
try: try:
@ -356,7 +356,7 @@ def disown_all(request: Request, pkgbases: List[models.PackageBase]) \
return errors return errors
async def packages_disown(request: Request, package_ids: List[int] = [], async def packages_disown(request: Request, package_ids: list[int] = [],
confirm: bool = False, **kwargs): confirm: bool = False, **kwargs):
if not package_ids: if not package_ids:
return (False, ["You did not select any packages to disown."]) return (False, ["You did not select any packages to disown."])
@ -390,7 +390,7 @@ async def packages_disown(request: Request, package_ids: List[int] = [],
return (True, ["The selected packages have been disowned."]) return (True, ["The selected packages have been disowned."])
async def packages_delete(request: Request, package_ids: List[int] = [], async def packages_delete(request: Request, package_ids: list[int] = [],
confirm: bool = False, merge_into: str = str(), confirm: bool = False, merge_into: str = str(),
**kwargs): **kwargs):
if not package_ids: if not package_ids:
@ -430,7 +430,7 @@ async def packages_delete(request: Request, package_ids: List[int] = [],
# A mapping of action string -> callback functions used within the # A mapping of action string -> callback functions used within the
# `packages_post` route below. We expect any action callback to # `packages_post` route below. We expect any action callback to
# return a tuple in the format: (succeeded: bool, message: List[str]). # return a tuple in the format: (succeeded: bool, message: list[str]).
PACKAGE_ACTIONS = { PACKAGE_ACTIONS = {
"unflag": packages_unflag, "unflag": packages_unflag,
"notify": packages_notify, "notify": packages_notify,
@ -445,7 +445,7 @@ PACKAGE_ACTIONS = {
@handle_form_exceptions @handle_form_exceptions
@requires_auth @requires_auth
async def packages_post(request: Request, async def packages_post(request: Request,
IDs: List[int] = Form(default=[]), IDs: list[int] = Form(default=[]),
action: str = Form(default=str()), action: str = Form(default=str()),
confirm: bool = Form(default=False)): confirm: bool = Form(default=False)):

View file

@ -2,7 +2,7 @@ import hashlib
import re import re
from http import HTTPStatus from http import HTTPStatus
from typing import List, Optional from typing import Optional
from urllib.parse import unquote from urllib.parse import unquote
import orjson import orjson
@ -71,7 +71,7 @@ async def rpc_request(request: Request,
type: Optional[str] = None, type: Optional[str] = None,
by: Optional[str] = defaults.RPC_SEARCH_BY, by: Optional[str] = defaults.RPC_SEARCH_BY,
arg: Optional[str] = None, arg: Optional[str] = None,
args: Optional[List[str]] = [], args: Optional[list[str]] = [],
callback: Optional[str] = None): callback: Optional[str] = None):
# Create a handle to our RPC class. # Create a handle to our RPC class.
@ -140,7 +140,7 @@ async def rpc(request: Request,
type: Optional[str] = Query(default=None), type: Optional[str] = Query(default=None),
by: Optional[str] = Query(default=defaults.RPC_SEARCH_BY), by: Optional[str] = Query(default=defaults.RPC_SEARCH_BY),
arg: Optional[str] = Query(default=None), arg: Optional[str] = Query(default=None),
args: Optional[List[str]] = Query(default=[], alias="arg[]"), args: Optional[list[str]] = Query(default=[], alias="arg[]"),
callback: Optional[str] = Query(default=None)): callback: Optional[str] = Query(default=None)):
if not request.url.query: if not request.url.query:
return documentation() return documentation()
@ -157,6 +157,6 @@ async def rpc_post(request: Request,
type: Optional[str] = Form(default=None), type: Optional[str] = Form(default=None),
by: Optional[str] = Form(default=defaults.RPC_SEARCH_BY), by: Optional[str] = Form(default=defaults.RPC_SEARCH_BY),
arg: Optional[str] = Form(default=None), arg: Optional[str] = Form(default=None),
args: Optional[List[str]] = Form(default=[], alias="arg[]"), args: Optional[list[str]] = Form(default=[], alias="arg[]"),
callback: Optional[str] = Form(default=None)): callback: Optional[str] = Form(default=None)):
return await rpc_request(request, v, type, by, arg, args, callback) return await rpc_request(request, v, type, by, arg, args, callback)

View file

@ -2,7 +2,7 @@ import html
import typing import typing
from http import HTTPStatus from http import HTTPStatus
from typing import Any, Dict from typing import Any
from fastapi import APIRouter, Form, HTTPException, Request from fastapi import APIRouter, Form, HTTPException, Request
from fastapi.responses import RedirectResponse, Response from fastapi.responses import RedirectResponse, Response
@ -34,7 +34,7 @@ ADDVOTE_SPECIFICS = {
} }
def populate_trusted_user_counts(context: Dict[str, Any]) -> None: def populate_trusted_user_counts(context: dict[str, Any]) -> None:
tu_query = db.query(User).filter( tu_query = db.query(User).filter(
or_(User.AccountTypeID == TRUSTED_USER_ID, or_(User.AccountTypeID == TRUSTED_USER_ID,
User.AccountTypeID == TRUSTED_USER_AND_DEV_ID) User.AccountTypeID == TRUSTED_USER_AND_DEV_ID)

View file

@ -1,7 +1,7 @@
import os import os
from collections import defaultdict from collections import defaultdict
from typing import Any, Callable, Dict, List, NewType, Union from typing import Any, Callable, NewType, Union
from fastapi.responses import HTMLResponse from fastapi.responses import HTMLResponse
from sqlalchemy import and_, literal, orm from sqlalchemy import and_, literal, orm
@ -24,7 +24,7 @@ TYPE_MAPPING = {
} }
DataGenerator = NewType("DataGenerator", DataGenerator = NewType("DataGenerator",
Callable[[models.Package], Dict[str, Any]]) Callable[[models.Package], dict[str, Any]])
def documentation(): def documentation():
@ -86,7 +86,7 @@ class RPC:
self.version = version self.version = version
self.type = RPC.TYPE_ALIASES.get(type, type) self.type = RPC.TYPE_ALIASES.get(type, type)
def error(self, message: str) -> Dict[str, Any]: def error(self, message: str) -> dict[str, Any]:
return { return {
"version": self.version, "version": self.version,
"results": [], "results": [],
@ -95,7 +95,7 @@ class RPC:
"error": message "error": message
} }
def _verify_inputs(self, by: str = [], args: List[str] = []) -> None: def _verify_inputs(self, by: str = [], args: list[str] = []) -> None:
if self.version is None: if self.version is None:
raise RPCError("Please specify an API version.") raise RPCError("Please specify an API version.")
@ -111,11 +111,11 @@ class RPC:
if self.type not in RPC.EXPOSED_TYPES: if self.type not in RPC.EXPOSED_TYPES:
raise RPCError("Incorrect request type specified.") raise RPCError("Incorrect request type specified.")
def _enforce_args(self, args: List[str]) -> None: def _enforce_args(self, args: list[str]) -> None:
if not args: if not args:
raise RPCError("No request type/data specified.") raise RPCError("No request type/data specified.")
def _get_json_data(self, package: models.Package) -> Dict[str, Any]: def _get_json_data(self, package: models.Package) -> dict[str, Any]:
""" Produce dictionary data of one Package that can be JSON-serialized. """ Produce dictionary data of one Package that can be JSON-serialized.
:param package: Package instance :param package: Package instance
@ -146,7 +146,7 @@ class RPC:
"LastModified": package.ModifiedTS "LastModified": package.ModifiedTS
} }
def _get_info_json_data(self, package: models.Package) -> Dict[str, Any]: def _get_info_json_data(self, package: models.Package) -> dict[str, Any]:
data = self._get_json_data(package) data = self._get_json_data(package)
# All info results have _at least_ an empty list of # All info results have _at least_ an empty list of
@ -163,9 +163,9 @@ class RPC:
return data return data
def _assemble_json_data(self, packages: List[models.Package], def _assemble_json_data(self, packages: list[models.Package],
data_generator: DataGenerator) \ data_generator: DataGenerator) \
-> List[Dict[str, Any]]: -> list[dict[str, Any]]:
""" """
Assemble JSON data out of a list of packages. Assemble JSON data out of a list of packages.
@ -192,8 +192,8 @@ class RPC:
models.User.Username.label("Maintainer"), models.User.Username.label("Maintainer"),
).group_by(models.Package.ID) ).group_by(models.Package.ID)
def _handle_multiinfo_type(self, args: List[str] = [], **kwargs) \ def _handle_multiinfo_type(self, args: list[str] = [], **kwargs) \
-> List[Dict[str, Any]]: -> list[dict[str, Any]]:
self._enforce_args(args) self._enforce_args(args)
args = set(args) args = set(args)
@ -296,7 +296,7 @@ class RPC:
return self._assemble_json_data(packages, self._get_info_json_data) return self._assemble_json_data(packages, self._get_info_json_data)
def _handle_search_type(self, by: str = defaults.RPC_SEARCH_BY, def _handle_search_type(self, by: str = defaults.RPC_SEARCH_BY,
args: List[str] = []) -> List[Dict[str, Any]]: args: list[str] = []) -> list[dict[str, Any]]:
# If `by` isn't maintainer and we don't have any args, raise an error. # If `by` isn't maintainer and we don't have any args, raise an error.
# In maintainer's case, return all orphans if there are no args, # In maintainer's case, return all orphans if there are no args,
# so we need args to pass through to the handler without errors. # so we need args to pass through to the handler without errors.
@ -318,12 +318,12 @@ class RPC:
return self._assemble_json_data(results, self._get_json_data) return self._assemble_json_data(results, self._get_json_data)
def _handle_msearch_type(self, args: List[str] = [], **kwargs)\ def _handle_msearch_type(self, args: list[str] = [], **kwargs)\
-> List[Dict[str, Any]]: -> list[dict[str, Any]]:
return self._handle_search_type(by="m", args=args) return self._handle_search_type(by="m", args=args)
def _handle_suggest_type(self, args: List[str] = [], **kwargs)\ def _handle_suggest_type(self, args: list[str] = [], **kwargs)\
-> List[str]: -> list[str]:
if not args: if not args:
return [] return []
@ -336,8 +336,8 @@ class RPC:
).order_by(models.Package.Name.asc()).limit(20) ).order_by(models.Package.Name.asc()).limit(20)
return [pkg.Name for pkg in packages] return [pkg.Name for pkg in packages]
def _handle_suggest_pkgbase_type(self, args: List[str] = [], **kwargs)\ def _handle_suggest_pkgbase_type(self, args: list[str] = [], **kwargs)\
-> List[str]: -> list[str]:
if not args: if not args:
return [] return []
@ -351,16 +351,16 @@ class RPC:
def _is_suggestion(self) -> bool: def _is_suggestion(self) -> bool:
return self.type.startswith("suggest") return self.type.startswith("suggest")
def _handle_callback(self, by: str, args: List[str])\ def _handle_callback(self, by: str, args: list[str])\
-> Union[List[Dict[str, Any]], List[str]]: -> Union[list[dict[str, Any]], list[str]]:
# Get a handle to our callback and trap an RPCError with # Get a handle to our callback and trap an RPCError with
# an empty list of results based on callback's execution. # an empty list of results based on callback's execution.
callback = getattr(self, f"_handle_{self.type.replace('-', '_')}_type") callback = getattr(self, f"_handle_{self.type.replace('-', '_')}_type")
results = callback(by=by, args=args) results = callback(by=by, args=args)
return results return results
def handle(self, by: str = defaults.RPC_SEARCH_BY, args: List[str] = [])\ def handle(self, by: str = defaults.RPC_SEARCH_BY, args: list[str] = [])\
-> Union[List[Dict[str, Any]], Dict[str, Any]]: -> Union[list[dict[str, Any]], dict[str, Any]]:
""" Request entrypoint. A router should pass v, type and args """ Request entrypoint. A router should pass v, type and args
to this function and expect an output dictionary to be returned. to this function and expect an output dictionary to be returned.

View file

@ -27,7 +27,7 @@ import sys
import tempfile import tempfile
from collections import defaultdict from collections import defaultdict
from typing import Any, Dict from typing import Any
import orjson import orjson
@ -151,7 +151,7 @@ EXTENDED_FIELD_HANDLERS = {
} }
def as_dict(package: Package) -> Dict[str, Any]: def as_dict(package: Package) -> dict[str, Any]:
return { return {
"ID": package.ID, "ID": package.ID,
"Name": package.Name, "Name": package.Name,

View file

@ -1,7 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from typing import List
from sqlalchemy import and_, func from sqlalchemy import and_, func
from sqlalchemy.sql.functions import coalesce from sqlalchemy.sql.functions import coalesce
from sqlalchemy.sql.functions import sum as _sum from sqlalchemy.sql.functions import sum as _sum
@ -10,7 +8,7 @@ from aurweb import db, time
from aurweb.models import PackageBase, PackageVote from aurweb.models import PackageBase, PackageVote
def run_variable(pkgbases: List[PackageBase] = []) -> None: def run_variable(pkgbases: list[PackageBase] = []) -> None:
""" """
Update popularity on a list of PackageBases. Update popularity on a list of PackageBases.

View file

@ -17,7 +17,7 @@ import sys
import tempfile import tempfile
import time import time
from typing import Iterable, List from typing import Iterable
import aurweb.config import aurweb.config
import aurweb.schema import aurweb.schema
@ -204,8 +204,8 @@ def start():
""") """)
def _kill_children(children: Iterable, exceptions: List[Exception] = []) \ def _kill_children(children: Iterable, exceptions: list[Exception] = []) \
-> List[Exception]: -> list[Exception]:
""" """
Kill each process found in `children`. Kill each process found in `children`.
@ -223,8 +223,8 @@ def _kill_children(children: Iterable, exceptions: List[Exception] = []) \
return exceptions return exceptions
def _wait_for_children(children: Iterable, exceptions: List[Exception] = []) \ def _wait_for_children(children: Iterable, exceptions: list[Exception] = []) \
-> List[Exception]: -> list[Exception]:
""" """
Wait for each process to end found in `children`. Wait for each process to end found in `children`.

View file

@ -4,8 +4,6 @@ import re
import shutil import shutil
import subprocess import subprocess
from typing import List
from aurweb import logging, util from aurweb import logging, util
from aurweb.templates import base_template from aurweb.templates import base_template
@ -38,7 +36,7 @@ class AlpmDatabase:
return pkgdir return pkgdir
def add(self, pkgname: str, pkgver: str, arch: str, def add(self, pkgname: str, pkgver: str, arch: str,
provides: List[str] = []) -> None: provides: list[str] = []) -> None:
context = { context = {
"pkgname": pkgname, "pkgname": pkgname,
"pkgver": pkgver, "pkgver": pkgver,

View file

@ -1,5 +1,4 @@
from io import StringIO from io import StringIO
from typing import List
from lxml import etree from lxml import etree
@ -15,11 +14,11 @@ def parse_root(html: str) -> etree.Element:
return etree.parse(StringIO(html), parser) return etree.parse(StringIO(html), parser)
def get_errors(content: str) -> List[etree._Element]: def get_errors(content: str) -> list[etree._Element]:
root = parse_root(content) root = parse_root(content)
return root.xpath('//ul[@class="errorlist"]/li') return root.xpath('//ul[@class="errorlist"]/li')
def get_successes(content: str) -> List[etree._Element]: def get_successes(content: str) -> list[etree._Element]:
root = parse_root(content) root = parse_root(content)
return root.xpath('//ul[@class="success"]/li') return root.xpath('//ul[@class="success"]/li')

View file

@ -1,5 +1,3 @@
from typing import Dict
import aurweb.config import aurweb.config
@ -35,8 +33,8 @@ class Request:
user: User = User(), user: User = User(),
authenticated: bool = False, authenticated: bool = False,
method: str = "GET", method: str = "GET",
headers: Dict[str, str] = dict(), headers: dict[str, str] = dict(),
cookies: Dict[str, str] = dict()) -> "Request": cookies: dict[str, str] = dict()) -> "Request":
self.user = user self.user = user
self.user.authenticated = authenticated self.user.authenticated = authenticated

View file

@ -1,4 +1,4 @@
from typing import Any, Dict from typing import Any
from fastapi import Request from fastapi import Request
@ -34,7 +34,7 @@ def simple(U: str = str(), E: str = str(), H: bool = False,
def language(L: str = str(), def language(L: str = str(),
request: Request = None, request: Request = None,
user: models.User = None, user: models.User = None,
context: Dict[str, Any] = {}, context: dict[str, Any] = {},
**kwargs) -> None: **kwargs) -> None:
if L and L != user.LangPreference: if L and L != user.LangPreference:
with db.begin(): with db.begin():
@ -45,7 +45,7 @@ def language(L: str = str(),
def timezone(TZ: str = str(), def timezone(TZ: str = str(),
request: Request = None, request: Request = None,
user: models.User = None, user: models.User = None,
context: Dict[str, Any] = {}, context: dict[str, Any] = {},
**kwargs) -> None: **kwargs) -> None:
if TZ and TZ != user.Timezone: if TZ and TZ != user.Timezone:
with db.begin(): with db.begin():
@ -95,7 +95,7 @@ def account_type(T: int = None,
def password(P: str = str(), def password(P: str = str(),
request: Request = None, request: Request = None,
user: models.User = None, user: models.User = None,
context: Dict[str, Any] = {}, context: dict[str, Any] = {},
**kwargs) -> None: **kwargs) -> None:
if P and not user.valid_password(P): if P and not user.valid_password(P):
# Remove the fields we consumed for passwords. # Remove the fields we consumed for passwords.

View file

@ -6,7 +6,7 @@ import string
from datetime import datetime from datetime import datetime
from http import HTTPStatus from http import HTTPStatus
from subprocess import PIPE, Popen from subprocess import PIPE, Popen
from typing import Callable, Iterable, List, Tuple, Union from typing import Callable, Iterable, Tuple, Union
from urllib.parse import urlparse from urllib.parse import urlparse
import fastapi import fastapi
@ -194,6 +194,6 @@ def parse_ssh_key(string: str) -> Tuple[str, str]:
return (prefix, key) return (prefix, key)
def parse_ssh_keys(string: str) -> List[Tuple[str, str]]: def parse_ssh_keys(string: str) -> list[Tuple[str, str]]:
""" Parse a list of SSH public keys. """ """ Parse a list of SSH public keys. """
return [parse_ssh_key(e) for e in string.splitlines()] return [parse_ssh_key(e) for e in string.splitlines()]

View file

@ -1,4 +1,3 @@
from typing import List
from unittest import mock from unittest import mock
import pytest import pytest
@ -21,7 +20,7 @@ def setup(db_test):
return return
def run_main(args: List[str] = []): def run_main(args: list[str] = []):
with mock.patch("sys.argv", ["aurweb-adduser"] + args): with mock.patch("sys.argv", ["aurweb-adduser"] + args):
adduser.main() adduser.main()

View file

@ -2,7 +2,6 @@ import gzip
import json import json
import os import os
from typing import List
from unittest import mock from unittest import mock
import py import py
@ -47,7 +46,7 @@ def user() -> User:
@pytest.fixture @pytest.fixture
def packages(user: User) -> List[Package]: def packages(user: User) -> list[Package]:
output = [] output = []
with db.begin(): with db.begin():
lic = db.create(License, Name="GPL") lic = db.create(License, Name="GPL")
@ -89,7 +88,7 @@ def config_mock(tmpdir: py.path.local) -> None:
config.rehash() config.rehash()
def test_mkpkglists(tmpdir: py.path.local, config_mock: None, user: User, packages: List[Package]): def test_mkpkglists(tmpdir: py.path.local, config_mock: None, user: User, packages: list[Package]):
from aurweb.scripts import mkpkglists from aurweb.scripts import mkpkglists
mkpkglists.main() mkpkglists.main()
@ -168,7 +167,7 @@ def test_mkpkglists_extended_empty(config_mock: None):
@mock.patch("sys.argv", ["mkpkglists", "--extended"]) @mock.patch("sys.argv", ["mkpkglists", "--extended"])
def test_mkpkglists_extended(config_mock: None, user: User, def test_mkpkglists_extended(config_mock: None, user: User,
packages: List[Package]): packages: list[Package]):
from aurweb.scripts import mkpkglists from aurweb.scripts import mkpkglists
mkpkglists.main() mkpkglists.main()

View file

@ -1,5 +1,4 @@
from logging import ERROR from logging import ERROR
from typing import List
from unittest import mock from unittest import mock
import pytest import pytest
@ -46,7 +45,7 @@ def user2() -> User:
@pytest.fixture @pytest.fixture
def pkgbases(user: User) -> List[PackageBase]: def pkgbases(user: User) -> list[PackageBase]:
now = time.utcnow() now = time.utcnow()
output = [] output = []
@ -62,7 +61,7 @@ def pkgbases(user: User) -> List[PackageBase]:
@pytest.fixture @pytest.fixture
def pkgreq(user2: User, pkgbases: List[PackageBase]): def pkgreq(user2: User, pkgbases: list[PackageBase]):
pkgbase = pkgbases[0] pkgbase = pkgbases[0]
with db.begin(): with db.begin():
pkgreq_ = db.create(PackageRequest, PackageBase=pkgbase, pkgreq_ = db.create(PackageRequest, PackageBase=pkgbase,
@ -74,7 +73,7 @@ def pkgreq(user2: User, pkgbases: List[PackageBase]):
@pytest.fixture @pytest.fixture
def packages(pkgbases: List[PackageBase]) -> List[Package]: def packages(pkgbases: list[PackageBase]) -> list[Package]:
output = [] output = []
with db.begin(): with db.begin():
for i, pkgbase in enumerate(pkgbases): for i, pkgbase in enumerate(pkgbases):
@ -85,7 +84,7 @@ def packages(pkgbases: List[PackageBase]) -> List[Package]:
def test_out_of_date(user: User, user1: User, user2: User, def test_out_of_date(user: User, user1: User, user2: User,
pkgbases: List[PackageBase]): pkgbases: list[PackageBase]):
pkgbase = pkgbases[0] pkgbase = pkgbases[0]
# Create two comaintainers. We'll pass the maintainer uid to # Create two comaintainers. We'll pass the maintainer uid to
# FlagNotification, so we should expect to get two emails. # FlagNotification, so we should expect to get two emails.
@ -162,7 +161,7 @@ link does not work, try copying and pasting it into your browser.
assert email.body == expected assert email.body == expected
def test_comment(user: User, user2: User, pkgbases: List[PackageBase]): def test_comment(user: User, user2: User, pkgbases: list[PackageBase]):
pkgbase = pkgbases[0] pkgbase = pkgbases[0]
with db.begin(): with db.begin():
@ -194,7 +193,7 @@ please go to the package page [2] and select "Disable notifications".
assert expected == email.body assert expected == email.body
def test_update(user: User, user2: User, pkgbases: List[PackageBase]): def test_update(user: User, user2: User, pkgbases: list[PackageBase]):
pkgbase = pkgbases[0] pkgbase = pkgbases[0]
with db.begin(): with db.begin():
user.UpdateNotify = 1 user.UpdateNotify = 1
@ -221,7 +220,7 @@ please go to the package page [2] and select "Disable notifications".
assert expected == email.body assert expected == email.body
def test_adopt(user: User, user2: User, pkgbases: List[PackageBase]): def test_adopt(user: User, user2: User, pkgbases: list[PackageBase]):
pkgbase = pkgbases[0] pkgbase = pkgbases[0]
notif = notify.AdoptNotification(user2.ID, pkgbase.ID) notif = notify.AdoptNotification(user2.ID, pkgbase.ID)
notif.send() notif.send()
@ -241,7 +240,7 @@ The package {pkgbase.Name} [1] was adopted by {user2.Username} [2].
assert email.body == expected assert email.body == expected
def test_disown(user: User, user2: User, pkgbases: List[PackageBase]): def test_disown(user: User, user2: User, pkgbases: list[PackageBase]):
pkgbase = pkgbases[0] pkgbase = pkgbases[0]
notif = notify.DisownNotification(user2.ID, pkgbase.ID) notif = notify.DisownNotification(user2.ID, pkgbase.ID)
notif.send() notif.send()
@ -261,7 +260,7 @@ The package {pkgbase.Name} [1] was disowned by {user2.Username} [2].
assert email.body == expected assert email.body == expected
def test_comaintainer_addition(user: User, pkgbases: List[PackageBase]): def test_comaintainer_addition(user: User, pkgbases: list[PackageBase]):
pkgbase = pkgbases[0] pkgbase = pkgbases[0]
notif = notify.ComaintainerAddNotification(user.ID, pkgbase.ID) notif = notify.ComaintainerAddNotification(user.ID, pkgbase.ID)
notif.send() notif.send()
@ -280,7 +279,7 @@ You were added to the co-maintainer list of {pkgbase.Name} [1].
assert email.body == expected assert email.body == expected
def test_comaintainer_removal(user: User, pkgbases: List[PackageBase]): def test_comaintainer_removal(user: User, pkgbases: list[PackageBase]):
pkgbase = pkgbases[0] pkgbase = pkgbases[0]
notif = notify.ComaintainerRemoveNotification(user.ID, pkgbase.ID) notif = notify.ComaintainerRemoveNotification(user.ID, pkgbase.ID)
notif.send() notif.send()
@ -299,7 +298,7 @@ You were removed from the co-maintainer list of {pkgbase.Name} [1].
assert email.body == expected assert email.body == expected
def test_suspended_ownership_change(user: User, pkgbases: List[PackageBase]): def test_suspended_ownership_change(user: User, pkgbases: list[PackageBase]):
with db.begin(): with db.begin():
user.Suspended = 1 user.Suspended = 1
@ -314,7 +313,7 @@ def test_suspended_ownership_change(user: User, pkgbases: List[PackageBase]):
assert Email.count() == 1 assert Email.count() == 1
def test_delete(user: User, user2: User, pkgbases: List[PackageBase]): def test_delete(user: User, user2: User, pkgbases: list[PackageBase]):
pkgbase = pkgbases[0] pkgbase = pkgbases[0]
notif = notify.DeleteNotification(user2.ID, pkgbase.ID) notif = notify.DeleteNotification(user2.ID, pkgbase.ID)
notif.send() notif.send()
@ -336,7 +335,7 @@ You will no longer receive notifications about this package.
assert email.body == expected assert email.body == expected
def test_merge(user: User, user2: User, pkgbases: List[PackageBase]): def test_merge(user: User, user2: User, pkgbases: list[PackageBase]):
source, target = pkgbases[:2] source, target = pkgbases[:2]
notif = notify.DeleteNotification(user2.ID, source.ID, target.ID) notif = notify.DeleteNotification(user2.ID, source.ID, target.ID)
notif.send() notif.send()
@ -361,7 +360,7 @@ please go to [3] and click "Disable notifications".
assert email.body == expected assert email.body == expected
def set_tu(users: List[User]) -> User: def set_tu(users: list[User]) -> User:
with db.begin(): with db.begin():
for user in users: for user in users:
user.AccountTypeID = TRUSTED_USER_ID user.AccountTypeID = TRUSTED_USER_ID
@ -369,7 +368,7 @@ def set_tu(users: List[User]) -> User:
def test_open_close_request(user: User, user2: User, def test_open_close_request(user: User, user2: User,
pkgreq: PackageRequest, pkgreq: PackageRequest,
pkgbases: List[PackageBase]): pkgbases: list[PackageBase]):
set_tu([user]) set_tu([user])
pkgbase = pkgbases[0] pkgbase = pkgbases[0]
@ -432,7 +431,7 @@ Request #{pkgreq.ID} has been rejected by {user2.Username} [1].
def test_close_request_comaintainer_cc(user: User, user2: User, def test_close_request_comaintainer_cc(user: User, user2: User,
pkgreq: PackageRequest, pkgreq: PackageRequest,
pkgbases: List[PackageBase]): pkgbases: list[PackageBase]):
pkgbase = pkgbases[0] pkgbase = pkgbases[0]
with db.begin(): with db.begin():
db.create(models.PackageComaintainer, PackageBase=pkgbase, db.create(models.PackageComaintainer, PackageBase=pkgbase,
@ -449,7 +448,7 @@ def test_close_request_comaintainer_cc(user: User, user2: User,
def test_close_request_closure_comment(user: User, user2: User, def test_close_request_closure_comment(user: User, user2: User,
pkgreq: PackageRequest, pkgreq: PackageRequest,
pkgbases: List[PackageBase]): pkgbases: list[PackageBase]):
pkgbase = pkgbases[0] pkgbase = pkgbases[0]
with db.begin(): with db.begin():
pkgreq.ClosureComment = "This is a test closure comment." pkgreq.ClosureComment = "This is a test closure comment."

View file

@ -1,7 +1,6 @@
import re import re
from http import HTTPStatus from http import HTTPStatus
from typing import List
from unittest import mock from unittest import mock
import pytest import pytest
@ -177,7 +176,7 @@ def comment(user: User, package: Package) -> PackageComment:
@pytest.fixture @pytest.fixture
def packages(maintainer: User) -> List[Package]: def packages(maintainer: User) -> list[Package]:
""" Yield 55 packages named pkg_0 .. pkg_54. """ """ Yield 55 packages named pkg_0 .. pkg_54. """
packages_ = [] packages_ = []
now = time.utcnow() now = time.utcnow()
@ -521,7 +520,7 @@ def test_package_dependencies(client: TestClient, maintainer: User,
assert broken_node.text.strip() == broken_dep.DepName assert broken_node.text.strip() == broken_dep.DepName
def test_packages(client: TestClient, packages: List[Package]): def test_packages(client: TestClient, packages: list[Package]):
with client as request: with client as request:
response = request.get("/packages", params={ response = request.get("/packages", params={
"SeB": "X", # "X" isn't valid, defaults to "nd" "SeB": "X", # "X" isn't valid, defaults to "nd"
@ -550,7 +549,7 @@ def test_packages_empty(client: TestClient):
assert results[0].text.strip() == expected assert results[0].text.strip() == expected
def test_packages_search_by_name(client: TestClient, packages: List[Package]): def test_packages_search_by_name(client: TestClient, packages: list[Package]):
with client as request: with client as request:
response = request.get("/packages", params={ response = request.get("/packages", params={
"SeB": "n", "SeB": "n",
@ -565,7 +564,7 @@ def test_packages_search_by_name(client: TestClient, packages: List[Package]):
def test_packages_search_by_exact_name(client: TestClient, def test_packages_search_by_exact_name(client: TestClient,
packages: List[Package]): packages: list[Package]):
with client as request: with client as request:
response = request.get("/packages", params={ response = request.get("/packages", params={
"SeB": "N", "SeB": "N",
@ -594,7 +593,7 @@ def test_packages_search_by_exact_name(client: TestClient,
def test_packages_search_by_pkgbase(client: TestClient, def test_packages_search_by_pkgbase(client: TestClient,
packages: List[Package]): packages: list[Package]):
with client as request: with client as request:
response = request.get("/packages", params={ response = request.get("/packages", params={
"SeB": "b", "SeB": "b",
@ -609,7 +608,7 @@ def test_packages_search_by_pkgbase(client: TestClient,
def test_packages_search_by_exact_pkgbase(client: TestClient, def test_packages_search_by_exact_pkgbase(client: TestClient,
packages: List[Package]): packages: list[Package]):
with client as request: with client as request:
response = request.get("/packages", params={ response = request.get("/packages", params={
"SeB": "B", "SeB": "B",
@ -634,7 +633,7 @@ def test_packages_search_by_exact_pkgbase(client: TestClient,
def test_packages_search_by_keywords(client: TestClient, def test_packages_search_by_keywords(client: TestClient,
packages: List[Package]): packages: list[Package]):
# None of our packages have keywords, so this query should return nothing. # None of our packages have keywords, so this query should return nothing.
with client as request: with client as request:
response = request.get("/packages", params={ response = request.get("/packages", params={
@ -791,7 +790,7 @@ def test_packages_search_by_submitter(client: TestClient,
assert len(rows) == 1 assert len(rows) == 1
def test_packages_sort_by_name(client: TestClient, packages: List[Package]): def test_packages_sort_by_name(client: TestClient, packages: list[Package]):
with client as request: with client as request:
response = request.get("/packages", params={ response = request.get("/packages", params={
"SB": "n", # Name "SB": "n", # Name
@ -820,7 +819,7 @@ def test_packages_sort_by_name(client: TestClient, packages: List[Package]):
def test_packages_sort_by_votes(client: TestClient, def test_packages_sort_by_votes(client: TestClient,
maintainer: User, maintainer: User,
packages: List[Package]): packages: list[Package]):
# Set the first package's NumVotes to 1. # Set the first package's NumVotes to 1.
with db.begin(): with db.begin():
packages[0].PackageBase.NumVotes = 1 packages[0].PackageBase.NumVotes = 1
@ -855,7 +854,7 @@ def test_packages_sort_by_votes(client: TestClient,
def test_packages_sort_by_popularity(client: TestClient, def test_packages_sort_by_popularity(client: TestClient,
maintainer: User, maintainer: User,
packages: List[Package]): packages: list[Package]):
# Set the first package's Popularity to 0.50. # Set the first package's Popularity to 0.50.
with db.begin(): with db.begin():
packages[0].PackageBase.Popularity = "0.50" packages[0].PackageBase.Popularity = "0.50"
@ -875,7 +874,7 @@ def test_packages_sort_by_popularity(client: TestClient,
def test_packages_sort_by_voted(client: TestClient, def test_packages_sort_by_voted(client: TestClient,
maintainer: User, maintainer: User,
packages: List[Package]): packages: list[Package]):
now = time.utcnow() now = time.utcnow()
with db.begin(): with db.begin():
db.create(PackageVote, PackageBase=packages[0].PackageBase, db.create(PackageVote, PackageBase=packages[0].PackageBase,
@ -902,7 +901,7 @@ def test_packages_sort_by_voted(client: TestClient,
def test_packages_sort_by_notify(client: TestClient, def test_packages_sort_by_notify(client: TestClient,
maintainer: User, maintainer: User,
packages: List[Package]): packages: list[Package]):
db.create(PackageNotification, db.create(PackageNotification,
PackageBase=packages[0].PackageBase, PackageBase=packages[0].PackageBase,
User=maintainer) User=maintainer)
@ -970,7 +969,7 @@ def test_packages_sort_by_maintainer(client: TestClient,
def test_packages_sort_by_last_modified(client: TestClient, def test_packages_sort_by_last_modified(client: TestClient,
packages: List[Package]): packages: list[Package]):
now = time.utcnow() now = time.utcnow()
# Set the first package's ModifiedTS to be 1000 seconds before now. # Set the first package's ModifiedTS to be 1000 seconds before now.
package = packages[0] package = packages[0]
@ -996,7 +995,7 @@ def test_packages_sort_by_last_modified(client: TestClient,
def test_packages_flagged(client: TestClient, maintainer: User, def test_packages_flagged(client: TestClient, maintainer: User,
packages: List[Package]): packages: list[Package]):
package = packages[0] package = packages[0]
now = time.utcnow() now = time.utcnow()
@ -1029,7 +1028,7 @@ def test_packages_flagged(client: TestClient, maintainer: User,
assert len(rows) == 50 assert len(rows) == 50
def test_packages_orphans(client: TestClient, packages: List[Package]): def test_packages_orphans(client: TestClient, packages: list[Package]):
package = packages[0] package = packages[0]
with db.begin(): with db.begin():
package.PackageBase.Maintainer = None package.PackageBase.Maintainer = None

View file

@ -1,7 +1,6 @@
import re import re
from http import HTTPStatus from http import HTTPStatus
from typing import List
from unittest import mock from unittest import mock
import pytest import pytest
@ -176,7 +175,7 @@ def comment(user: User, package: Package) -> PackageComment:
@pytest.fixture @pytest.fixture
def packages(maintainer: User) -> List[Package]: def packages(maintainer: User) -> list[Package]:
""" Yield 55 packages named pkg_0 .. pkg_54. """ """ Yield 55 packages named pkg_0 .. pkg_54. """
packages_ = [] packages_ = []
now = time.utcnow() now = time.utcnow()
@ -197,7 +196,7 @@ def packages(maintainer: User) -> List[Package]:
@pytest.fixture @pytest.fixture
def requests(user: User, packages: List[Package]) -> List[PackageRequest]: def requests(user: User, packages: list[Package]) -> list[PackageRequest]:
pkgreqs = [] pkgreqs = []
deletion_type = db.query(RequestType).filter( deletion_type = db.query(RequestType).filter(
RequestType.ID == DELETION_ID RequestType.ID == DELETION_ID

View file

@ -1,5 +1,3 @@
from typing import List
import pytest import pytest
from aurweb import db, time from aurweb import db, time
@ -22,7 +20,7 @@ def user() -> User:
@pytest.fixture @pytest.fixture
def packages(user: User) -> List[Package]: def packages(user: User) -> list[Package]:
output = [] output = []
now = time.utcnow() now = time.utcnow()
@ -37,14 +35,14 @@ def packages(user: User) -> List[Package]:
yield output yield output
def test_pkgmaint_noop(packages: List[Package]): def test_pkgmaint_noop(packages: list[Package]):
assert len(packages) == 5 assert len(packages) == 5
pkgmaint.main() pkgmaint.main()
packages = db.query(Package).all() packages = db.query(Package).all()
assert len(packages) == 5 assert len(packages) == 5
def test_pkgmaint(packages: List[Package]): def test_pkgmaint(packages: list[Package]):
assert len(packages) == 5 assert len(packages) == 5
# Modify the first package so it's out of date and gets deleted. # Modify the first package so it's out of date and gets deleted.

View file

@ -2,7 +2,6 @@ import re
from http import HTTPStatus from http import HTTPStatus
from logging import DEBUG from logging import DEBUG
from typing import List
import pytest import pytest
@ -91,7 +90,7 @@ def maintainer() -> User:
@pytest.fixture @pytest.fixture
def packages(maintainer: User) -> List[Package]: def packages(maintainer: User) -> list[Package]:
""" Yield 55 packages named pkg_0 .. pkg_54. """ """ Yield 55 packages named pkg_0 .. pkg_54. """
packages_ = [] packages_ = []
now = time.utcnow() now = time.utcnow()
@ -112,7 +111,7 @@ def packages(maintainer: User) -> List[Package]:
@pytest.fixture @pytest.fixture
def requests(user: User, packages: List[Package]) -> List[PackageRequest]: def requests(user: User, packages: list[Package]) -> list[PackageRequest]:
pkgreqs = [] pkgreqs = []
with db.begin(): with db.begin():
for i in range(55): for i in range(55):
@ -660,8 +659,8 @@ def test_requests_unauthorized(client: TestClient):
def test_requests(client: TestClient, def test_requests(client: TestClient,
tu_user: User, tu_user: User,
packages: List[Package], packages: list[Package],
requests: List[PackageRequest]): requests: list[PackageRequest]):
cookies = {"AURSID": tu_user.login(Request(), "testPassword")} cookies = {"AURSID": tu_user.login(Request(), "testPassword")}
with client as request: with client as request:
resp = request.get("/requests", params={ resp = request.get("/requests", params={
@ -697,7 +696,7 @@ def test_requests(client: TestClient,
def test_requests_selfmade(client: TestClient, user: User, def test_requests_selfmade(client: TestClient, user: User,
requests: List[PackageRequest]): requests: list[PackageRequest]):
cookies = {"AURSID": user.login(Request(), "testPassword")} cookies = {"AURSID": user.login(Request(), "testPassword")}
with client as request: with client as request:
resp = request.get("/requests", cookies=cookies) resp = request.get("/requests", cookies=cookies)

View file

@ -1,7 +1,6 @@
import re import re
from http import HTTPStatus from http import HTTPStatus
from typing import List
from unittest import mock from unittest import mock
import orjson import orjson
@ -62,7 +61,7 @@ def user3() -> User:
@pytest.fixture @pytest.fixture
def packages(user: User, user2: User, user3: User) -> List[Package]: def packages(user: User, user2: User, user3: User) -> list[Package]:
output = [] output = []
# Create package records used in our tests. # Create package records used in our tests.
@ -123,7 +122,7 @@ def packages(user: User, user2: User, user3: User) -> List[Package]:
@pytest.fixture @pytest.fixture
def depends(packages: List[Package]) -> List[PackageDependency]: def depends(packages: list[Package]) -> list[PackageDependency]:
output = [] output = []
with db.begin(): with db.begin():
@ -162,7 +161,7 @@ def depends(packages: List[Package]) -> List[PackageDependency]:
@pytest.fixture @pytest.fixture
def relations(user: User, packages: List[Package]) -> List[PackageRelation]: def relations(user: User, packages: list[Package]) -> list[PackageRelation]:
output = [] output = []
with db.begin(): with db.begin():
@ -241,9 +240,9 @@ def test_rpc_documentation_missing():
def test_rpc_singular_info(client: TestClient, def test_rpc_singular_info(client: TestClient,
user: User, user: User,
packages: List[Package], packages: list[Package],
depends: List[PackageDependency], depends: list[PackageDependency],
relations: List[PackageRelation]): relations: list[PackageRelation]):
# Define expected response. # Define expected response.
pkg = packages[0] pkg = packages[0]
expected_data = { expected_data = {
@ -310,7 +309,7 @@ def test_rpc_nonexistent_package(client: TestClient):
assert response_data["resultcount"] == 0 assert response_data["resultcount"] == 0
def test_rpc_multiinfo(client: TestClient, packages: List[Package]): def test_rpc_multiinfo(client: TestClient, packages: list[Package]):
# Make dummy request. # Make dummy request.
request_packages = ["big-chungus", "chungy-chungus"] request_packages = ["big-chungus", "chungy-chungus"]
with client as request: with client as request:
@ -328,7 +327,7 @@ def test_rpc_multiinfo(client: TestClient, packages: List[Package]):
assert request_packages == [] assert request_packages == []
def test_rpc_mixedargs(client: TestClient, packages: List[Package]): def test_rpc_mixedargs(client: TestClient, packages: list[Package]):
# Make dummy request. # Make dummy request.
response1_packages = ["gluggly-chungus"] response1_packages = ["gluggly-chungus"]
response2_packages = ["gluggly-chungus", "chungy-chungus"] response2_packages = ["gluggly-chungus", "chungy-chungus"]
@ -361,9 +360,9 @@ def test_rpc_mixedargs(client: TestClient, packages: List[Package]):
def test_rpc_no_dependencies_omits_key(client: TestClient, user: User, def test_rpc_no_dependencies_omits_key(client: TestClient, user: User,
packages: List[Package], packages: list[Package],
depends: List[PackageDependency], depends: list[PackageDependency],
relations: List[PackageRelation]): relations: list[PackageRelation]):
""" """
This makes sure things like 'MakeDepends' get removed from JSON strings This makes sure things like 'MakeDepends' get removed from JSON strings
when they don't have set values. when they don't have set values.
@ -517,7 +516,7 @@ def test_rpc_no_args(client: TestClient):
assert expected_data == response_data assert expected_data == response_data
def test_rpc_no_maintainer(client: TestClient, packages: List[Package]): def test_rpc_no_maintainer(client: TestClient, packages: list[Package]):
# Make dummy request. # Make dummy request.
with client as request: with client as request:
response = request.get("/rpc", params={ response = request.get("/rpc", params={
@ -531,7 +530,7 @@ def test_rpc_no_maintainer(client: TestClient, packages: List[Package]):
assert response_data["results"][0]["Maintainer"] is None assert response_data["results"][0]["Maintainer"] is None
def test_rpc_suggest_pkgbase(client: TestClient, packages: List[Package]): def test_rpc_suggest_pkgbase(client: TestClient, packages: list[Package]):
params = {"v": 5, "type": "suggest-pkgbase", "arg": "big"} params = {"v": 5, "type": "suggest-pkgbase", "arg": "big"}
with client as request: with client as request:
response = request.get("/rpc", params=params) response = request.get("/rpc", params=params)
@ -560,7 +559,7 @@ def test_rpc_suggest_pkgbase(client: TestClient, packages: List[Package]):
assert data == [] assert data == []
def test_rpc_suggest(client: TestClient, packages: List[Package]): def test_rpc_suggest(client: TestClient, packages: list[Package]):
params = {"v": 5, "type": "suggest", "arg": "other"} params = {"v": 5, "type": "suggest", "arg": "other"}
with client as request: with client as request:
response = request.get("/rpc", params=params) response = request.get("/rpc", params=params)
@ -600,7 +599,7 @@ def mock_config_getint(section: str, key: str):
@mock.patch("aurweb.config.getint", side_effect=mock_config_getint) @mock.patch("aurweb.config.getint", side_effect=mock_config_getint)
def test_rpc_ratelimit(getint: mock.MagicMock, client: TestClient, def test_rpc_ratelimit(getint: mock.MagicMock, client: TestClient,
pipeline: Pipeline, packages: List[Package]): pipeline: Pipeline, packages: list[Package]):
params = {"v": 5, "type": "suggest-pkgbase", "arg": "big"} params = {"v": 5, "type": "suggest-pkgbase", "arg": "big"}
for i in range(4): for i in range(4):
@ -626,7 +625,7 @@ def test_rpc_ratelimit(getint: mock.MagicMock, client: TestClient,
assert response.status_code == int(HTTPStatus.OK) assert response.status_code == int(HTTPStatus.OK)
def test_rpc_etag(client: TestClient, packages: List[Package]): def test_rpc_etag(client: TestClient, packages: list[Package]):
params = {"v": 5, "type": "suggest-pkgbase", "arg": "big"} params = {"v": 5, "type": "suggest-pkgbase", "arg": "big"}
with client as request: with client as request:
@ -647,7 +646,7 @@ def test_rpc_search_arg_too_small(client: TestClient):
assert response.json().get("error") == "Query arg too small." assert response.json().get("error") == "Query arg too small."
def test_rpc_search(client: TestClient, packages: List[Package]): def test_rpc_search(client: TestClient, packages: list[Package]):
params = {"v": 5, "type": "search", "arg": "big"} params = {"v": 5, "type": "search", "arg": "big"}
with client as request: with client as request:
response = request.get("/rpc", params=params) response = request.get("/rpc", params=params)
@ -673,7 +672,7 @@ def test_rpc_search(client: TestClient, packages: List[Package]):
assert response.json().get("error") == "No request type/data specified." assert response.json().get("error") == "No request type/data specified."
def test_rpc_msearch(client: TestClient, user: User, packages: List[Package]): def test_rpc_msearch(client: TestClient, user: User, packages: list[Package]):
params = {"v": 5, "type": "msearch", "arg": user.Username} params = {"v": 5, "type": "msearch", "arg": user.Username}
with client as request: with client as request:
response = request.get("/rpc", params=params) response = request.get("/rpc", params=params)
@ -709,8 +708,8 @@ def test_rpc_msearch(client: TestClient, user: User, packages: List[Package]):
assert result.get("Name") == "big-chungus" assert result.get("Name") == "big-chungus"
def test_rpc_search_depends(client: TestClient, packages: List[Package], def test_rpc_search_depends(client: TestClient, packages: list[Package],
depends: List[PackageDependency]): depends: list[PackageDependency]):
params = { params = {
"v": 5, "type": "search", "by": "depends", "arg": "chungus-depends" "v": 5, "type": "search", "by": "depends", "arg": "chungus-depends"
} }
@ -722,8 +721,8 @@ def test_rpc_search_depends(client: TestClient, packages: List[Package],
assert result.get("Name") == packages[0].Name assert result.get("Name") == packages[0].Name
def test_rpc_search_makedepends(client: TestClient, packages: List[Package], def test_rpc_search_makedepends(client: TestClient, packages: list[Package],
depends: List[PackageDependency]): depends: list[PackageDependency]):
params = { params = {
"v": 5, "v": 5,
"type": "search", "type": "search",
@ -738,8 +737,8 @@ def test_rpc_search_makedepends(client: TestClient, packages: List[Package],
assert result.get("Name") == packages[0].Name assert result.get("Name") == packages[0].Name
def test_rpc_search_optdepends(client: TestClient, packages: List[Package], def test_rpc_search_optdepends(client: TestClient, packages: list[Package],
depends: List[PackageDependency]): depends: list[PackageDependency]):
params = { params = {
"v": 5, "v": 5,
"type": "search", "type": "search",
@ -754,8 +753,8 @@ def test_rpc_search_optdepends(client: TestClient, packages: List[Package],
assert result.get("Name") == packages[0].Name assert result.get("Name") == packages[0].Name
def test_rpc_search_checkdepends(client: TestClient, packages: List[Package], def test_rpc_search_checkdepends(client: TestClient, packages: list[Package],
depends: List[PackageDependency]): depends: list[PackageDependency]):
params = { params = {
"v": 5, "v": 5,
"type": "search", "type": "search",
@ -802,7 +801,7 @@ def test_rpc_jsonp_callback(client: TestClient):
assert response.json().get("error") == "Invalid callback name." assert response.json().get("error") == "Invalid callback name."
def test_rpc_post(client: TestClient, packages: List[Package]): def test_rpc_post(client: TestClient, packages: list[Package]):
data = { data = {
"v": 5, "v": 5,
"type": "info", "type": "info",
@ -816,7 +815,7 @@ def test_rpc_post(client: TestClient, packages: List[Package]):
def test_rpc_too_many_search_results(client: TestClient, def test_rpc_too_many_search_results(client: TestClient,
packages: List[Package]): packages: list[Package]):
config_getint = config.getint config_getint = config.getint
def mock_config(section: str, key: str): def mock_config(section: str, key: str):
@ -831,7 +830,7 @@ def test_rpc_too_many_search_results(client: TestClient,
assert resp.json().get("error") == "Too many package results." assert resp.json().get("error") == "Too many package results."
def test_rpc_too_many_info_results(client: TestClient, packages: List[Package]): def test_rpc_too_many_info_results(client: TestClient, packages: list[Package]):
# Make many of these packages depend and rely on each other. # Make many of these packages depend and rely on each other.
# This way, we can test to see that the exceeded limit stays true # This way, we can test to see that the exceeded limit stays true
# regardless of the number of related records. # regardless of the number of related records.

View file

@ -1,6 +1,6 @@
import re import re
from typing import Any, Dict from typing import Any
import pytest import pytest
@ -126,7 +126,7 @@ def test_commit_hash():
assert commit_hash not in render assert commit_hash not in render
def pager_context(num_packages: int) -> Dict[str, Any]: def pager_context(num_packages: int) -> dict[str, Any]:
return { return {
"request": Request(), "request": Request(),
"singular": "%d package found.", "singular": "%d package found.",