From a509e4047483763316d3b06a4dfe3c2004455aff Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sun, 31 Jul 2022 20:58:39 +0200 Subject: [PATCH] fix(python): use standard dict/list type annotation Since Python 3.9 list/dict can be used as type hint. --- aurweb/filters.py | 20 +++++----- aurweb/models/package_dependency.py | 4 +- aurweb/models/user.py | 4 +- aurweb/packages/requests.py | 10 ++--- aurweb/packages/util.py | 18 ++++----- aurweb/pkgbase/actions.py | 4 +- aurweb/pkgbase/util.py | 10 ++--- aurweb/pkgbase/validate.py | 4 +- aurweb/prometheus.py | 4 +- aurweb/routers/accounts.py | 4 +- aurweb/routers/packages.py | 24 ++++++------ aurweb/routers/rpc.py | 8 ++-- aurweb/routers/trusted_user.py | 4 +- aurweb/rpc.py | 44 ++++++++++----------- aurweb/scripts/mkpkglists.py | 4 +- aurweb/scripts/popupdate.py | 4 +- aurweb/spawn.py | 10 ++--- aurweb/testing/alpm.py | 4 +- aurweb/testing/html.py | 5 +-- aurweb/testing/requests.py | 6 +-- aurweb/users/update.py | 8 ++-- aurweb/util.py | 4 +- test/test_adduser.py | 3 +- test/test_mkpkglists.py | 7 ++-- test/test_notify.py | 35 +++++++++-------- test/test_packages_routes.py | 31 ++++++++------- test/test_pkgbase_routes.py | 5 +-- test/test_pkgmaint.py | 8 ++-- test/test_requests.py | 11 +++--- test/test_rpc.py | 59 ++++++++++++++--------------- test/test_templates.py | 4 +- 31 files changed, 175 insertions(+), 195 deletions(-) diff --git a/aurweb/filters.py b/aurweb/filters.py index 45cb6d83..22f65024 100644 --- a/aurweb/filters.py +++ b/aurweb/filters.py @@ -2,7 +2,7 @@ import copy import math from datetime import datetime -from typing import Any, Dict, Union +from typing import Any, Union from urllib.parse import quote_plus, urlencode from zoneinfo import ZoneInfo @@ -19,7 +19,7 @@ from aurweb.templates import register_filter, register_function @register_filter("pager_nav") @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(page) # Make sure this is an int. @@ -71,7 +71,7 @@ def do_round(f: float) -> int: @register_filter("tr") @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") }}. """ _ = l10n.get_translator_for_request(context.get("request")) return _(value) @@ -79,7 +79,7 @@ def tr(context: Dict[str, Any], value: str): @register_filter("tn") @pass_context -def tn(context: Dict[str, Any], count: int, +def tn(context: dict[str, Any], count: int, singular: str, plural: str) -> str: """ A singular and plural translation filter. @@ -107,7 +107,7 @@ def as_timezone(dt: datetime, timezone: str): @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. """ q = copy.copy(query) for k, v in list(additions): @@ -116,7 +116,7 @@ def extend_query(query: Dict[str, Any], *additions) -> Dict[str, Any]: @register_filter("urlencode") -def to_qs(query: Dict[str, Any]) -> str: +def to_qs(query: dict[str, Any]) -> str: return urlencode(query, doseq=True) @@ -134,7 +134,7 @@ def number_format(value: float, places: int): @register_filter("account_url") @pass_context -def account_url(context: Dict[str, Any], +def account_url(context: dict[str, Any], user: "aurweb.models.user.User") -> str: base = aurweb.config.get("options", "aur_location") return f"{base}/account/{user.Username}" @@ -152,7 +152,7 @@ def ceil(*args, **kwargs) -> int: @register_function("date_strftime") @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: if isinstance(dt, int): 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") @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)") @register_function("datetime_display") @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)") diff --git a/aurweb/models/package_dependency.py b/aurweb/models/package_dependency.py index 2fd87f2a..67a7717f 100644 --- a/aurweb/models/package_dependency.py +++ b/aurweb/models/package_dependency.py @@ -1,5 +1,3 @@ -from typing import List - from sqlalchemy import and_, literal from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import backref, relationship @@ -60,7 +58,7 @@ class PackageDependency(Base): _OfficialProvider.Name == self.DepName).exists() 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 rels = db.query(PackageRelation).join(_Package).filter( diff --git a/aurweb/models/user.py b/aurweb/models/user.py index c375fcbc..3fa72a85 100644 --- a/aurweb/models/user.py +++ b/aurweb/models/user.py @@ -1,6 +1,6 @@ import hashlib -from typing import List, Set +from typing import Set import bcrypt @@ -149,7 +149,7 @@ class User(Base): return self.session.SessionID def has_credential(self, credential: Set[int], - approved: List["User"] = list()): + approved: list["User"] = list()): from aurweb.auth.creds import has_credential return has_credential(self, credential, approved) diff --git a/aurweb/packages/requests.py b/aurweb/packages/requests.py index 6aaa59ab..42026a33 100644 --- a/aurweb/packages/requests.py +++ b/aurweb/packages/requests.py @@ -1,4 +1,4 @@ -from typing import List, Optional, Set +from typing import Optional, Set from fastapi import Request from sqlalchemy import and_, orm @@ -139,7 +139,7 @@ def close_pkgreq(pkgreq: PackageRequest, closer: User, def handle_request(request: Request, reqtype_id: int, pkgbase: PackageBase, - target: PackageBase = None) -> List[notify.Notification]: + target: PackageBase = None) -> list[notify.Notification]: """ 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 target: Optional target to merge into """ - notifs: List[notify.Notification] = [] + notifs: list[notify.Notification] = [] # If it's an orphan request, perform further verification # regarding existing requests. @@ -187,13 +187,13 @@ def handle_request(request: Request, reqtype_id: int, PackageRequest.MergeBaseName == target.Name) # 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) # Build a reject list out of `query` filtered by IDs not found # in `to_accept`. That is, unmatched records of the same base # query properties. - to_reject: List[PackageRequest] = query.filter( + to_reject: list[PackageRequest] = query.filter( ~PackageRequest.ID.in_(accepted_ids) ).all() diff --git a/aurweb/packages/util.py b/aurweb/packages/util.py index 5085ddf4..bd173065 100644 --- a/aurweb/packages/util.py +++ b/aurweb/packages/util.py @@ -1,6 +1,6 @@ from collections import defaultdict from http import HTTPStatus -from typing import Dict, List, Tuple, Union +from typing import Tuple, Union import orjson @@ -15,7 +15,7 @@ from aurweb.models.package_relation import PackageRelation from aurweb.redis import redis_connection 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: @@ -123,7 +123,7 @@ def out_of_date(packages: orm.Query) -> orm.Query: 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 ModifiedTS column in descending order from cache, after setting the cache when no key yet exists. @@ -168,8 +168,8 @@ def updated_packages(limit: int = 0, return packages -def query_voted(query: List[models.Package], - user: models.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. @@ -191,8 +191,8 @@ def query_voted(query: List[models.Package], return output -def query_notified(query: List[models.Package], - user: models.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. @@ -214,8 +214,8 @@ def query_notified(query: List[models.Package], return output -def pkg_required(pkgname: str, provides: List[str]) \ - -> List[PackageDependency]: +def pkg_required(pkgname: str, provides: list[str]) \ + -> list[PackageDependency]: """ Get dependencies that match a string in `[pkgname] + provides`. diff --git a/aurweb/pkgbase/actions.py b/aurweb/pkgbase/actions.py index 6fd55497..46609f89 100644 --- a/aurweb/pkgbase/actions.py +++ b/aurweb/pkgbase/actions.py @@ -1,5 +1,3 @@ -from typing import List - from fastapi import Request 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, comments: str = str()) \ - -> List[notify.Notification]: + -> list[notify.Notification]: notifs = handle_request(request, DELETION_ID, pkgbase) + [ notify.DeleteNotification(request.user.ID, pkgbase.ID) ] diff --git a/aurweb/pkgbase/util.py b/aurweb/pkgbase/util.py index 55dbb022..5a7d952a 100644 --- a/aurweb/pkgbase/util.py +++ b/aurweb/pkgbase/util.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List +from typing import Any from fastapi import Request 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) \ - -> Dict[str, Any]: + -> dict[str, Any]: ctx = await _make_variable_context(request, pkgbase.Name) return make_context(request, pkgbase, ctx) 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. :param request: FastAPI request @@ -89,7 +89,7 @@ def remove_comaintainer(comaint: PackageComaintainer) \ return notif -def remove_comaintainers(pkgbase: PackageBase, usernames: List[str]) -> None: +def remove_comaintainers(pkgbase: PackageBase, usernames: list[str]) -> None: """ Remove comaintainers from `pkgbase`. @@ -163,7 +163,7 @@ def add_comaintainer(pkgbase: PackageBase, comaintainer: User) \ def add_comaintainers(request: Request, pkgbase: PackageBase, - usernames: List[str]) -> None: + usernames: list[str]) -> None: """ Add comaintainers to `pkgbase`. diff --git a/aurweb/pkgbase/validate.py b/aurweb/pkgbase/validate.py index 8d05a3d7..baefc415 100644 --- a/aurweb/pkgbase/validate.py +++ b/aurweb/pkgbase/validate.py @@ -1,4 +1,4 @@ -from typing import Any, Dict +from typing import Any from aurweb import db from aurweb.exceptions import ValidationError @@ -7,7 +7,7 @@ from aurweb.models import PackageBase def request(pkgbase: PackageBase, type: str, comments: str, merge_into: str, - context: Dict[str, Any]) -> None: + context: dict[str, Any]) -> None: if not comments: raise ValidationError(["The comment field must not be empty."]) diff --git a/aurweb/prometheus.py b/aurweb/prometheus.py index 272ee023..227d46ed 100644 --- a/aurweb/prometheus.py +++ b/aurweb/prometheus.py @@ -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_fastapi_instrumentator import Instrumentator @@ -19,7 +19,7 @@ def instrumentator(): # Their license is included in LICENSES/starlette_exporter. # The code has been modified to remove child route checks # (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: """ Find a matching route and return its original path string diff --git a/aurweb/routers/accounts.py b/aurweb/routers/accounts.py index b603d22a..dcac72b0 100644 --- a/aurweb/routers/accounts.py +++ b/aurweb/routers/accounts.py @@ -2,7 +2,7 @@ import copy import typing from http import HTTPStatus -from typing import Any, Dict +from typing import Any from fastapi import APIRouter, Form, Request 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, - args: Dict[str, Any]): + args: dict[str, Any]): """ Process an account form. All fields are optional and only checks requirements in the case they are present. diff --git a/aurweb/routers/packages.py b/aurweb/routers/packages.py index f14b0ad8..7bf4e3d4 100644 --- a/aurweb/routers/packages.py +++ b/aurweb/routers/packages.py @@ -1,6 +1,6 @@ from collections import defaultdict from http import HTTPStatus -from typing import Any, Dict, List +from typing import Any from fastapi import APIRouter, Form, Query, Request, Response @@ -21,7 +21,7 @@ logger = logging.get_logger(__name__) 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): # Query parameters used in this request. 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) -async def packages_unflag(request: Request, package_ids: List[int] = [], +async def packages_unflag(request: Request, package_ids: list[int] = [], **kwargs): if not package_ids: 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."]) -async def packages_notify(request: Request, package_ids: List[int] = [], +async def packages_notify(request: Request, package_ids: list[int] = [], **kwargs): # In cases where we encounter errors with the request, we'll # 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."]) -async def packages_unnotify(request: Request, package_ids: List[int] = [], +async def packages_unnotify(request: Request, package_ids: list[int] = [], **kwargs): if not package_ids: # 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."]) -async def packages_adopt(request: Request, package_ids: List[int] = [], +async def packages_adopt(request: Request, package_ids: list[int] = [], confirm: bool = False, **kwargs): if not package_ids: 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."]) -def disown_all(request: Request, pkgbases: List[models.PackageBase]) \ - -> List[str]: +def disown_all(request: Request, pkgbases: list[models.PackageBase]) \ + -> list[str]: errors = [] for pkgbase in pkgbases: try: @@ -356,7 +356,7 @@ def disown_all(request: Request, pkgbases: List[models.PackageBase]) \ 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): if not package_ids: 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."]) -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(), **kwargs): 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 # `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 = { "unflag": packages_unflag, "notify": packages_notify, @@ -445,7 +445,7 @@ PACKAGE_ACTIONS = { @handle_form_exceptions @requires_auth async def packages_post(request: Request, - IDs: List[int] = Form(default=[]), + IDs: list[int] = Form(default=[]), action: str = Form(default=str()), confirm: bool = Form(default=False)): diff --git a/aurweb/routers/rpc.py b/aurweb/routers/rpc.py index 49e98f8c..ff58063f 100644 --- a/aurweb/routers/rpc.py +++ b/aurweb/routers/rpc.py @@ -2,7 +2,7 @@ import hashlib import re from http import HTTPStatus -from typing import List, Optional +from typing import Optional from urllib.parse import unquote import orjson @@ -71,7 +71,7 @@ async def rpc_request(request: Request, type: Optional[str] = None, by: Optional[str] = defaults.RPC_SEARCH_BY, arg: Optional[str] = None, - args: Optional[List[str]] = [], + args: Optional[list[str]] = [], callback: Optional[str] = None): # Create a handle to our RPC class. @@ -140,7 +140,7 @@ async def rpc(request: Request, type: Optional[str] = Query(default=None), by: Optional[str] = Query(default=defaults.RPC_SEARCH_BY), 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)): if not request.url.query: return documentation() @@ -157,6 +157,6 @@ async def rpc_post(request: Request, type: Optional[str] = Form(default=None), by: Optional[str] = Form(default=defaults.RPC_SEARCH_BY), 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)): return await rpc_request(request, v, type, by, arg, args, callback) diff --git a/aurweb/routers/trusted_user.py b/aurweb/routers/trusted_user.py index 3f0eb836..e1267409 100644 --- a/aurweb/routers/trusted_user.py +++ b/aurweb/routers/trusted_user.py @@ -2,7 +2,7 @@ import html import typing from http import HTTPStatus -from typing import Any, Dict +from typing import Any from fastapi import APIRouter, Form, HTTPException, Request 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( or_(User.AccountTypeID == TRUSTED_USER_ID, User.AccountTypeID == TRUSTED_USER_AND_DEV_ID) diff --git a/aurweb/rpc.py b/aurweb/rpc.py index 5bc6b80d..f04de7d6 100644 --- a/aurweb/rpc.py +++ b/aurweb/rpc.py @@ -1,7 +1,7 @@ import os 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 sqlalchemy import and_, literal, orm @@ -24,7 +24,7 @@ TYPE_MAPPING = { } DataGenerator = NewType("DataGenerator", - Callable[[models.Package], Dict[str, Any]]) + Callable[[models.Package], dict[str, Any]]) def documentation(): @@ -86,7 +86,7 @@ class RPC: self.version = version 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 { "version": self.version, "results": [], @@ -95,7 +95,7 @@ class RPC: "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: raise RPCError("Please specify an API version.") @@ -111,11 +111,11 @@ class RPC: if self.type not in RPC.EXPOSED_TYPES: 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: 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. :param package: Package instance @@ -146,7 +146,7 @@ class RPC: "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) # All info results have _at least_ an empty list of @@ -163,9 +163,9 @@ class RPC: return data - def _assemble_json_data(self, packages: List[models.Package], + def _assemble_json_data(self, packages: list[models.Package], data_generator: DataGenerator) \ - -> List[Dict[str, Any]]: + -> list[dict[str, Any]]: """ Assemble JSON data out of a list of packages. @@ -192,8 +192,8 @@ class RPC: models.User.Username.label("Maintainer"), ).group_by(models.Package.ID) - def _handle_multiinfo_type(self, args: List[str] = [], **kwargs) \ - -> List[Dict[str, Any]]: + def _handle_multiinfo_type(self, args: list[str] = [], **kwargs) \ + -> list[dict[str, Any]]: self._enforce_args(args) args = set(args) @@ -296,7 +296,7 @@ class RPC: return self._assemble_json_data(packages, self._get_info_json_data) 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. # In maintainer's case, return all orphans if there are no args, # 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) - def _handle_msearch_type(self, args: List[str] = [], **kwargs)\ - -> List[Dict[str, Any]]: + def _handle_msearch_type(self, args: list[str] = [], **kwargs)\ + -> list[dict[str, Any]]: return self._handle_search_type(by="m", args=args) - def _handle_suggest_type(self, args: List[str] = [], **kwargs)\ - -> List[str]: + def _handle_suggest_type(self, args: list[str] = [], **kwargs)\ + -> list[str]: if not args: return [] @@ -336,8 +336,8 @@ class RPC: ).order_by(models.Package.Name.asc()).limit(20) return [pkg.Name for pkg in packages] - def _handle_suggest_pkgbase_type(self, args: List[str] = [], **kwargs)\ - -> List[str]: + def _handle_suggest_pkgbase_type(self, args: list[str] = [], **kwargs)\ + -> list[str]: if not args: return [] @@ -351,16 +351,16 @@ class RPC: def _is_suggestion(self) -> bool: return self.type.startswith("suggest") - def _handle_callback(self, by: str, args: List[str])\ - -> Union[List[Dict[str, Any]], List[str]]: + def _handle_callback(self, by: str, args: list[str])\ + -> Union[list[dict[str, Any]], list[str]]: # Get a handle to our callback and trap an RPCError with # an empty list of results based on callback's execution. callback = getattr(self, f"_handle_{self.type.replace('-', '_')}_type") results = callback(by=by, args=args) return results - def handle(self, by: str = defaults.RPC_SEARCH_BY, args: List[str] = [])\ - -> Union[List[Dict[str, Any]], Dict[str, Any]]: + def handle(self, by: str = defaults.RPC_SEARCH_BY, args: list[str] = [])\ + -> Union[list[dict[str, Any]], dict[str, Any]]: """ Request entrypoint. A router should pass v, type and args to this function and expect an output dictionary to be returned. diff --git a/aurweb/scripts/mkpkglists.py b/aurweb/scripts/mkpkglists.py index 00096d74..888e346c 100755 --- a/aurweb/scripts/mkpkglists.py +++ b/aurweb/scripts/mkpkglists.py @@ -27,7 +27,7 @@ import sys import tempfile from collections import defaultdict -from typing import Any, Dict +from typing import Any 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 { "ID": package.ID, "Name": package.Name, diff --git a/aurweb/scripts/popupdate.py b/aurweb/scripts/popupdate.py index a2a796fd..637173eb 100755 --- a/aurweb/scripts/popupdate.py +++ b/aurweb/scripts/popupdate.py @@ -1,7 +1,5 @@ #!/usr/bin/env python3 -from typing import List - from sqlalchemy import and_, func from sqlalchemy.sql.functions import coalesce from sqlalchemy.sql.functions import sum as _sum @@ -10,7 +8,7 @@ from aurweb import db, time 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. diff --git a/aurweb/spawn.py b/aurweb/spawn.py index 46f2f021..c7d54c4e 100644 --- a/aurweb/spawn.py +++ b/aurweb/spawn.py @@ -17,7 +17,7 @@ import sys import tempfile import time -from typing import Iterable, List +from typing import Iterable import aurweb.config import aurweb.schema @@ -204,8 +204,8 @@ def start(): """) -def _kill_children(children: Iterable, exceptions: List[Exception] = []) \ - -> List[Exception]: +def _kill_children(children: Iterable, exceptions: list[Exception] = []) \ + -> list[Exception]: """ Kill each process found in `children`. @@ -223,8 +223,8 @@ def _kill_children(children: Iterable, exceptions: List[Exception] = []) \ return exceptions -def _wait_for_children(children: Iterable, exceptions: List[Exception] = []) \ - -> List[Exception]: +def _wait_for_children(children: Iterable, exceptions: list[Exception] = []) \ + -> list[Exception]: """ Wait for each process to end found in `children`. diff --git a/aurweb/testing/alpm.py b/aurweb/testing/alpm.py index 6015d859..ce30d042 100644 --- a/aurweb/testing/alpm.py +++ b/aurweb/testing/alpm.py @@ -4,8 +4,6 @@ import re import shutil import subprocess -from typing import List - from aurweb import logging, util from aurweb.templates import base_template @@ -38,7 +36,7 @@ class AlpmDatabase: return pkgdir def add(self, pkgname: str, pkgver: str, arch: str, - provides: List[str] = []) -> None: + provides: list[str] = []) -> None: context = { "pkgname": pkgname, "pkgver": pkgver, diff --git a/aurweb/testing/html.py b/aurweb/testing/html.py index f01aaf3d..8c923438 100644 --- a/aurweb/testing/html.py +++ b/aurweb/testing/html.py @@ -1,5 +1,4 @@ from io import StringIO -from typing import List from lxml import etree @@ -15,11 +14,11 @@ def parse_root(html: str) -> etree.Element: 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) 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) return root.xpath('//ul[@class="success"]/li') diff --git a/aurweb/testing/requests.py b/aurweb/testing/requests.py index be13ab77..c97d1532 100644 --- a/aurweb/testing/requests.py +++ b/aurweb/testing/requests.py @@ -1,5 +1,3 @@ -from typing import Dict - import aurweb.config @@ -35,8 +33,8 @@ class Request: user: User = User(), authenticated: bool = False, method: str = "GET", - headers: Dict[str, str] = dict(), - cookies: Dict[str, str] = dict()) -> "Request": + headers: dict[str, str] = dict(), + cookies: dict[str, str] = dict()) -> "Request": self.user = user self.user.authenticated = authenticated diff --git a/aurweb/users/update.py b/aurweb/users/update.py index 5a32fd01..ffea1f2f 100644 --- a/aurweb/users/update.py +++ b/aurweb/users/update.py @@ -1,4 +1,4 @@ -from typing import Any, Dict +from typing import Any from fastapi import Request @@ -34,7 +34,7 @@ def simple(U: str = str(), E: str = str(), H: bool = False, def language(L: str = str(), request: Request = None, user: models.User = None, - context: Dict[str, Any] = {}, + context: dict[str, Any] = {}, **kwargs) -> None: if L and L != user.LangPreference: with db.begin(): @@ -45,7 +45,7 @@ def language(L: str = str(), def timezone(TZ: str = str(), request: Request = None, user: models.User = None, - context: Dict[str, Any] = {}, + context: dict[str, Any] = {}, **kwargs) -> None: if TZ and TZ != user.Timezone: with db.begin(): @@ -95,7 +95,7 @@ def account_type(T: int = None, def password(P: str = str(), request: Request = None, user: models.User = None, - context: Dict[str, Any] = {}, + context: dict[str, Any] = {}, **kwargs) -> None: if P and not user.valid_password(P): # Remove the fields we consumed for passwords. diff --git a/aurweb/util.py b/aurweb/util.py index 5138f7da..8291b578 100644 --- a/aurweb/util.py +++ b/aurweb/util.py @@ -6,7 +6,7 @@ import string from datetime import datetime from http import HTTPStatus 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 import fastapi @@ -194,6 +194,6 @@ def parse_ssh_key(string: str) -> Tuple[str, str]: 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. """ return [parse_ssh_key(e) for e in string.splitlines()] diff --git a/test/test_adduser.py b/test/test_adduser.py index c6210e74..65968d40 100644 --- a/test/test_adduser.py +++ b/test/test_adduser.py @@ -1,4 +1,3 @@ -from typing import List from unittest import mock import pytest @@ -21,7 +20,7 @@ def setup(db_test): return -def run_main(args: List[str] = []): +def run_main(args: list[str] = []): with mock.patch("sys.argv", ["aurweb-adduser"] + args): adduser.main() diff --git a/test/test_mkpkglists.py b/test/test_mkpkglists.py index 7b538e02..9bc1073b 100644 --- a/test/test_mkpkglists.py +++ b/test/test_mkpkglists.py @@ -2,7 +2,6 @@ import gzip import json import os -from typing import List from unittest import mock import py @@ -47,7 +46,7 @@ def user() -> User: @pytest.fixture -def packages(user: User) -> List[Package]: +def packages(user: User) -> list[Package]: output = [] with db.begin(): lic = db.create(License, Name="GPL") @@ -89,7 +88,7 @@ def config_mock(tmpdir: py.path.local) -> None: 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 mkpkglists.main() @@ -168,7 +167,7 @@ def test_mkpkglists_extended_empty(config_mock: None): @mock.patch("sys.argv", ["mkpkglists", "--extended"]) def test_mkpkglists_extended(config_mock: None, user: User, - packages: List[Package]): + packages: list[Package]): from aurweb.scripts import mkpkglists mkpkglists.main() diff --git a/test/test_notify.py b/test/test_notify.py index fdec5ed7..bbcc6b5a 100644 --- a/test/test_notify.py +++ b/test/test_notify.py @@ -1,5 +1,4 @@ from logging import ERROR -from typing import List from unittest import mock import pytest @@ -46,7 +45,7 @@ def user2() -> User: @pytest.fixture -def pkgbases(user: User) -> List[PackageBase]: +def pkgbases(user: User) -> list[PackageBase]: now = time.utcnow() output = [] @@ -62,7 +61,7 @@ def pkgbases(user: User) -> List[PackageBase]: @pytest.fixture -def pkgreq(user2: User, pkgbases: List[PackageBase]): +def pkgreq(user2: User, pkgbases: list[PackageBase]): pkgbase = pkgbases[0] with db.begin(): pkgreq_ = db.create(PackageRequest, PackageBase=pkgbase, @@ -74,7 +73,7 @@ def pkgreq(user2: User, pkgbases: List[PackageBase]): @pytest.fixture -def packages(pkgbases: List[PackageBase]) -> List[Package]: +def packages(pkgbases: list[PackageBase]) -> list[Package]: output = [] with db.begin(): 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, - pkgbases: List[PackageBase]): + pkgbases: list[PackageBase]): pkgbase = pkgbases[0] # Create two comaintainers. We'll pass the maintainer uid to # 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 -def test_comment(user: User, user2: User, pkgbases: List[PackageBase]): +def test_comment(user: User, user2: User, pkgbases: list[PackageBase]): pkgbase = pkgbases[0] with db.begin(): @@ -194,7 +193,7 @@ please go to the package page [2] and select "Disable notifications". 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] with db.begin(): user.UpdateNotify = 1 @@ -221,7 +220,7 @@ please go to the package page [2] and select "Disable notifications". 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] notif = notify.AdoptNotification(user2.ID, pkgbase.ID) notif.send() @@ -241,7 +240,7 @@ The package {pkgbase.Name} [1] was adopted by {user2.Username} [2]. 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] notif = notify.DisownNotification(user2.ID, pkgbase.ID) notif.send() @@ -261,7 +260,7 @@ The package {pkgbase.Name} [1] was disowned by {user2.Username} [2]. 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] notif = notify.ComaintainerAddNotification(user.ID, pkgbase.ID) notif.send() @@ -280,7 +279,7 @@ You were added to the co-maintainer list of {pkgbase.Name} [1]. 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] notif = notify.ComaintainerRemoveNotification(user.ID, pkgbase.ID) notif.send() @@ -299,7 +298,7 @@ You were removed from the co-maintainer list of {pkgbase.Name} [1]. 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(): user.Suspended = 1 @@ -314,7 +313,7 @@ def test_suspended_ownership_change(user: User, pkgbases: List[PackageBase]): 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] notif = notify.DeleteNotification(user2.ID, pkgbase.ID) notif.send() @@ -336,7 +335,7 @@ You will no longer receive notifications about this package. 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] notif = notify.DeleteNotification(user2.ID, source.ID, target.ID) notif.send() @@ -361,7 +360,7 @@ please go to [3] and click "Disable notifications". assert email.body == expected -def set_tu(users: List[User]) -> User: +def set_tu(users: list[User]) -> User: with db.begin(): for user in users: 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, pkgreq: PackageRequest, - pkgbases: List[PackageBase]): + pkgbases: list[PackageBase]): set_tu([user]) 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, pkgreq: PackageRequest, - pkgbases: List[PackageBase]): + pkgbases: list[PackageBase]): pkgbase = pkgbases[0] with db.begin(): 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, pkgreq: PackageRequest, - pkgbases: List[PackageBase]): + pkgbases: list[PackageBase]): pkgbase = pkgbases[0] with db.begin(): pkgreq.ClosureComment = "This is a test closure comment." diff --git a/test/test_packages_routes.py b/test/test_packages_routes.py index e4c992af..62f89e23 100644 --- a/test/test_packages_routes.py +++ b/test/test_packages_routes.py @@ -1,7 +1,6 @@ import re from http import HTTPStatus -from typing import List from unittest import mock import pytest @@ -177,7 +176,7 @@ def comment(user: User, package: Package) -> PackageComment: @pytest.fixture -def packages(maintainer: User) -> List[Package]: +def packages(maintainer: User) -> list[Package]: """ Yield 55 packages named pkg_0 .. pkg_54. """ packages_ = [] now = time.utcnow() @@ -521,7 +520,7 @@ def test_package_dependencies(client: TestClient, maintainer: User, 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: response = request.get("/packages", params={ "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 -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: response = request.get("/packages", params={ "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, - packages: List[Package]): + packages: list[Package]): with client as request: response = request.get("/packages", params={ "SeB": "N", @@ -594,7 +593,7 @@ def test_packages_search_by_exact_name(client: TestClient, def test_packages_search_by_pkgbase(client: TestClient, - packages: List[Package]): + packages: list[Package]): with client as request: response = request.get("/packages", params={ "SeB": "b", @@ -609,7 +608,7 @@ def test_packages_search_by_pkgbase(client: TestClient, def test_packages_search_by_exact_pkgbase(client: TestClient, - packages: List[Package]): + packages: list[Package]): with client as request: response = request.get("/packages", params={ "SeB": "B", @@ -634,7 +633,7 @@ def test_packages_search_by_exact_pkgbase(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. with client as request: response = request.get("/packages", params={ @@ -791,7 +790,7 @@ def test_packages_search_by_submitter(client: TestClient, 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: response = request.get("/packages", params={ "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, maintainer: User, - packages: List[Package]): + packages: list[Package]): # Set the first package's NumVotes to 1. with db.begin(): 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, maintainer: User, - packages: List[Package]): + packages: list[Package]): # Set the first package's Popularity to 0.50. with db.begin(): 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, maintainer: User, - packages: List[Package]): + packages: list[Package]): now = time.utcnow() with db.begin(): 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, maintainer: User, - packages: List[Package]): + packages: list[Package]): db.create(PackageNotification, PackageBase=packages[0].PackageBase, User=maintainer) @@ -970,7 +969,7 @@ def test_packages_sort_by_maintainer(client: TestClient, def test_packages_sort_by_last_modified(client: TestClient, - packages: List[Package]): + packages: list[Package]): now = time.utcnow() # Set the first package's ModifiedTS to be 1000 seconds before now. package = packages[0] @@ -996,7 +995,7 @@ def test_packages_sort_by_last_modified(client: TestClient, def test_packages_flagged(client: TestClient, maintainer: User, - packages: List[Package]): + packages: list[Package]): package = packages[0] now = time.utcnow() @@ -1029,7 +1028,7 @@ def test_packages_flagged(client: TestClient, maintainer: User, 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] with db.begin(): package.PackageBase.Maintainer = None diff --git a/test/test_pkgbase_routes.py b/test/test_pkgbase_routes.py index 5edae592..3468656e 100644 --- a/test/test_pkgbase_routes.py +++ b/test/test_pkgbase_routes.py @@ -1,7 +1,6 @@ import re from http import HTTPStatus -from typing import List from unittest import mock import pytest @@ -176,7 +175,7 @@ def comment(user: User, package: Package) -> PackageComment: @pytest.fixture -def packages(maintainer: User) -> List[Package]: +def packages(maintainer: User) -> list[Package]: """ Yield 55 packages named pkg_0 .. pkg_54. """ packages_ = [] now = time.utcnow() @@ -197,7 +196,7 @@ def packages(maintainer: User) -> List[Package]: @pytest.fixture -def requests(user: User, packages: List[Package]) -> List[PackageRequest]: +def requests(user: User, packages: list[Package]) -> list[PackageRequest]: pkgreqs = [] deletion_type = db.query(RequestType).filter( RequestType.ID == DELETION_ID diff --git a/test/test_pkgmaint.py b/test/test_pkgmaint.py index 5d6a56de..da758c22 100644 --- a/test/test_pkgmaint.py +++ b/test/test_pkgmaint.py @@ -1,5 +1,3 @@ -from typing import List - import pytest from aurweb import db, time @@ -22,7 +20,7 @@ def user() -> User: @pytest.fixture -def packages(user: User) -> List[Package]: +def packages(user: User) -> list[Package]: output = [] now = time.utcnow() @@ -37,14 +35,14 @@ def packages(user: User) -> List[Package]: yield output -def test_pkgmaint_noop(packages: List[Package]): +def test_pkgmaint_noop(packages: list[Package]): assert len(packages) == 5 pkgmaint.main() packages = db.query(Package).all() assert len(packages) == 5 -def test_pkgmaint(packages: List[Package]): +def test_pkgmaint(packages: list[Package]): assert len(packages) == 5 # Modify the first package so it's out of date and gets deleted. diff --git a/test/test_requests.py b/test/test_requests.py index 5ac558e0..b7ab3835 100644 --- a/test/test_requests.py +++ b/test/test_requests.py @@ -2,7 +2,6 @@ import re from http import HTTPStatus from logging import DEBUG -from typing import List import pytest @@ -91,7 +90,7 @@ def maintainer() -> User: @pytest.fixture -def packages(maintainer: User) -> List[Package]: +def packages(maintainer: User) -> list[Package]: """ Yield 55 packages named pkg_0 .. pkg_54. """ packages_ = [] now = time.utcnow() @@ -112,7 +111,7 @@ def packages(maintainer: User) -> List[Package]: @pytest.fixture -def requests(user: User, packages: List[Package]) -> List[PackageRequest]: +def requests(user: User, packages: list[Package]) -> list[PackageRequest]: pkgreqs = [] with db.begin(): for i in range(55): @@ -660,8 +659,8 @@ def test_requests_unauthorized(client: TestClient): def test_requests(client: TestClient, tu_user: User, - packages: List[Package], - requests: List[PackageRequest]): + packages: list[Package], + requests: list[PackageRequest]): cookies = {"AURSID": tu_user.login(Request(), "testPassword")} with client as request: resp = request.get("/requests", params={ @@ -697,7 +696,7 @@ def test_requests(client: TestClient, def test_requests_selfmade(client: TestClient, user: User, - requests: List[PackageRequest]): + requests: list[PackageRequest]): cookies = {"AURSID": user.login(Request(), "testPassword")} with client as request: resp = request.get("/requests", cookies=cookies) diff --git a/test/test_rpc.py b/test/test_rpc.py index 2f7f7860..0e24467a 100644 --- a/test/test_rpc.py +++ b/test/test_rpc.py @@ -1,7 +1,6 @@ import re from http import HTTPStatus -from typing import List from unittest import mock import orjson @@ -62,7 +61,7 @@ def user3() -> User: @pytest.fixture -def packages(user: User, user2: User, user3: User) -> List[Package]: +def packages(user: User, user2: User, user3: User) -> list[Package]: output = [] # Create package records used in our tests. @@ -123,7 +122,7 @@ def packages(user: User, user2: User, user3: User) -> List[Package]: @pytest.fixture -def depends(packages: List[Package]) -> List[PackageDependency]: +def depends(packages: list[Package]) -> list[PackageDependency]: output = [] with db.begin(): @@ -162,7 +161,7 @@ def depends(packages: List[Package]) -> List[PackageDependency]: @pytest.fixture -def relations(user: User, packages: List[Package]) -> List[PackageRelation]: +def relations(user: User, packages: list[Package]) -> list[PackageRelation]: output = [] with db.begin(): @@ -241,9 +240,9 @@ def test_rpc_documentation_missing(): def test_rpc_singular_info(client: TestClient, user: User, - packages: List[Package], - depends: List[PackageDependency], - relations: List[PackageRelation]): + packages: list[Package], + depends: list[PackageDependency], + relations: list[PackageRelation]): # Define expected response. pkg = packages[0] expected_data = { @@ -310,7 +309,7 @@ def test_rpc_nonexistent_package(client: TestClient): 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. request_packages = ["big-chungus", "chungy-chungus"] with client as request: @@ -328,7 +327,7 @@ def test_rpc_multiinfo(client: TestClient, packages: List[Package]): assert request_packages == [] -def test_rpc_mixedargs(client: TestClient, packages: List[Package]): +def test_rpc_mixedargs(client: TestClient, packages: list[Package]): # Make dummy request. response1_packages = ["gluggly-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, - packages: List[Package], - depends: List[PackageDependency], - relations: List[PackageRelation]): + packages: list[Package], + depends: list[PackageDependency], + relations: list[PackageRelation]): """ This makes sure things like 'MakeDepends' get removed from JSON strings when they don't have set values. @@ -517,7 +516,7 @@ def test_rpc_no_args(client: TestClient): 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. with client as request: 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 -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"} with client as request: response = request.get("/rpc", params=params) @@ -560,7 +559,7 @@ def test_rpc_suggest_pkgbase(client: TestClient, packages: List[Package]): 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"} with client as request: 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) 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"} 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) -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"} 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." -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"} with client as request: 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." -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} with client as request: 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" -def test_rpc_search_depends(client: TestClient, packages: List[Package], - depends: List[PackageDependency]): +def test_rpc_search_depends(client: TestClient, packages: list[Package], + depends: list[PackageDependency]): params = { "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 -def test_rpc_search_makedepends(client: TestClient, packages: List[Package], - depends: List[PackageDependency]): +def test_rpc_search_makedepends(client: TestClient, packages: list[Package], + depends: list[PackageDependency]): params = { "v": 5, "type": "search", @@ -738,8 +737,8 @@ def test_rpc_search_makedepends(client: TestClient, packages: List[Package], assert result.get("Name") == packages[0].Name -def test_rpc_search_optdepends(client: TestClient, packages: List[Package], - depends: List[PackageDependency]): +def test_rpc_search_optdepends(client: TestClient, packages: list[Package], + depends: list[PackageDependency]): params = { "v": 5, "type": "search", @@ -754,8 +753,8 @@ def test_rpc_search_optdepends(client: TestClient, packages: List[Package], assert result.get("Name") == packages[0].Name -def test_rpc_search_checkdepends(client: TestClient, packages: List[Package], - depends: List[PackageDependency]): +def test_rpc_search_checkdepends(client: TestClient, packages: list[Package], + depends: list[PackageDependency]): params = { "v": 5, "type": "search", @@ -802,7 +801,7 @@ def test_rpc_jsonp_callback(client: TestClient): 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 = { "v": 5, "type": "info", @@ -816,7 +815,7 @@ def test_rpc_post(client: TestClient, packages: List[Package]): def test_rpc_too_many_search_results(client: TestClient, - packages: List[Package]): + packages: list[Package]): config_getint = config.getint 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." -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. # This way, we can test to see that the exceeded limit stays true # regardless of the number of related records. diff --git a/test/test_templates.py b/test/test_templates.py index 7d6b585c..e4888127 100644 --- a/test/test_templates.py +++ b/test/test_templates.py @@ -1,6 +1,6 @@ import re -from typing import Any, Dict +from typing import Any import pytest @@ -126,7 +126,7 @@ def test_commit_hash(): 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 { "request": Request(), "singular": "%d package found.",