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
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)")

View file

@ -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(

View file

@ -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)

View file

@ -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()

View file

@ -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`.

View file

@ -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)
]

View file

@ -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`.

View file

@ -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."])

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_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

View file

@ -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.

View file

@ -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)):

View file

@ -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)

View file

@ -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)

View file

@ -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.

View file

@ -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,

View file

@ -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.

View file

@ -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`.

View file

@ -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,

View file

@ -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')

View file

@ -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

View file

@ -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.

View file

@ -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()]

View file

@ -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()

View file

@ -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()

View file

@ -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."

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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)

View file

@ -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.

View file

@ -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.",