Skip to content

Commit 168c3c1

Browse files
committed
Add type hints to src/palace/manager/api/admin/ code.
1 parent 83cf185 commit 168c3c1

9 files changed

Lines changed: 231 additions & 144 deletions

File tree

pyproject.toml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,6 @@ disallow_incomplete_defs = false
7575
disallow_untyped_decorators = false
7676
disallow_untyped_defs = false
7777
module = [
78-
"palace.manager.api.admin.admin_authentication_provider",
79-
"palace.manager.api.admin.model.custom_lists",
80-
"palace.manager.api.admin.password_admin_authentication_provider",
81-
"palace.manager.api.admin.routes",
82-
"palace.manager.api.admin.validator",
8378
"palace.manager.api.annotations",
8479
"palace.manager.api.app",
8580
"palace.manager.api.authentication.base",
Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1+
from __future__ import annotations
2+
3+
from typing import TYPE_CHECKING
4+
5+
if TYPE_CHECKING:
6+
from palace.manager.sqlalchemy.model.admin import Admin
7+
8+
19
class AdminAuthenticationProvider:
2-
def sign_in_template(self, redirect_url):
10+
def sign_in_template(self, redirect_url: str | None) -> str:
311
# Returns HTML to be rendered on the sign in page for
412
# this authentication provider.
513
raise NotImplementedError()
614

7-
def active_credentials(self, admin):
15+
def active_credentials(self, admin: Admin) -> bool:
816
# Returns True if the admin's credentials are not expired.
917
raise NotImplementedError()

src/palace/manager/api/admin/controller/collection_settings.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from palace.manager.api.admin.problem_details import (
1414
CANNOT_DELETE_COLLECTION_WITH_CHILDREN,
1515
MISSING_COLLECTION,
16+
MISSING_IDENTIFIER,
1617
MISSING_PARENT,
1718
MISSING_SERVICE,
1819
PROTOCOL_DOES_NOT_SUPPORT_PARENTS,
@@ -171,13 +172,17 @@ def process_deleted_libraries(
171172
reap_unassociated_loans.delay()
172173
reap_unassociated_holds.delay()
173174

174-
def process_delete(self, service_id: int) -> Response | ProblemDetail:
175+
def process_delete(self, service_id: int | str) -> Response | ProblemDetail:
175176
self.require_system_admin()
177+
try:
178+
sid = int(service_id) if isinstance(service_id, str) else service_id
179+
except ValueError:
180+
return MISSING_SERVICE
176181

177182
integration = get_one(
178183
self._db,
179184
IntegrationConfiguration,
180-
id=service_id,
185+
id=sid,
181186
goal=self.registry.goal,
182187
)
183188
if not integration:
@@ -196,8 +201,13 @@ def process_delete(self, service_id: int) -> Response | ProblemDetail:
196201
return Response("Deleted", 200)
197202

198203
def process_collection_self_tests(
199-
self, identifier: int | None
204+
self, identifier: int | str | None
200205
) -> Response | ProblemDetail:
206+
if identifier is not None and isinstance(identifier, str):
207+
try:
208+
identifier = int(identifier)
209+
except ValueError:
210+
return MISSING_IDENTIFIER
201211
return self.process_self_tests(identifier)
202212

203213
def run_self_tests(

src/palace/manager/api/admin/controller/dashboard.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from palace.manager.api.local_analytics_exporter import LocalAnalyticsExporter
1515
from palace.manager.api.util.flask import get_request_library
1616
from palace.manager.sqlalchemy.model.admin import Admin
17+
from palace.manager.util.problem_detail import ProblemDetail
1718

1819

1920
class DashboardController(CirculationManagerController):
@@ -25,7 +26,7 @@ def stats(
2526

2627
def bulk_circulation_events(
2728
self, analytics_exporter: LocalAnalyticsExporter | None = None
28-
) -> tuple[str, str, str, str | None]:
29+
) -> tuple[str | ProblemDetail, str, str, str | None]:
2930
date_format = "%Y-%m-%d"
3031

3132
def get_date(field: str) -> date:

src/palace/manager/api/admin/model/custom_lists.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import Any
2+
13
from pydantic import NonNegativeInt
24

35
from palace.manager.util.flask_util import CustomBaseModel
@@ -11,10 +13,10 @@ class CustomListSharePostResponse(CustomBaseModel):
1113
class CustomListPostRequest(CustomBaseModel):
1214
name: str
1315
id: NonNegativeInt | None = None
14-
entries: list[dict] = []
16+
entries: list[dict[str, Any]] = []
1517
collections: list[int] = []
16-
deletedEntries: list[dict] = []
18+
deletedEntries: list[dict[str, Any]] = []
1719
# For auto updating lists
1820
auto_update: bool = False
19-
auto_update_query: dict | None = None
20-
auto_update_facets: dict | None = None
21+
auto_update_query: dict[str, Any] | None = None
22+
auto_update_facets: dict[str, Any] | None = None

src/palace/manager/api/admin/password_admin_authentication_provider.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
from flask import render_template, url_for
1+
from flask import Response, render_template, url_for
22
from sqlalchemy.orm.session import Session
3+
from werkzeug.datastructures import ImmutableMultiDict
4+
from werkzeug.wrappers.response import Response as WerkzeugResponse
35

46
from palace.manager.api.admin.admin_authentication_provider import (
57
AdminAuthenticationProvider,
@@ -28,7 +30,7 @@ def __init__(self, send_email: SendEmailCallable):
2830
def get_secret_key(db: Session) -> str:
2931
return Key.get_key(db, KeyType.ADMIN_SECRET_KEY, raise_exception=True).value
3032

31-
def sign_in_template(self, redirect):
33+
def sign_in_template(self, redirect: str | None) -> str:
3234
password_sign_in_url = url_for("password_auth")
3335
forgot_password_url = url_for("admin_forgot_password")
3436
return render_template(
@@ -44,7 +46,9 @@ def sign_in_template(self, redirect):
4446
)
4547

4648
@staticmethod
47-
def forgot_password_template(redirect):
49+
def forgot_password_template(
50+
redirect: str | None | Response | WerkzeugResponse,
51+
) -> str:
4852
forgot_password_url = url_for("admin_forgot_password")
4953
return render_template(
5054
"admin/auth/forgot-password.html.jinja2",
@@ -56,7 +60,11 @@ def forgot_password_template(redirect):
5660
)
5761

5862
@staticmethod
59-
def reset_password_template(reset_password_token, admin_id, redirect):
63+
def reset_password_template(
64+
reset_password_token: str,
65+
admin_id: int,
66+
redirect: str | None | Response | WerkzeugResponse,
67+
) -> str:
6068
reset_password_url = url_for(
6169
"admin_reset_password",
6270
reset_password_token=reset_password_token,
@@ -71,7 +79,13 @@ def reset_password_template(reset_password_token, admin_id, redirect):
7179
button_style=button_style,
7280
)
7381

74-
def sign_in(self, _db, request={}):
82+
def sign_in(
83+
self,
84+
_db: Session,
85+
request: ImmutableMultiDict[str, str] | dict[str, str | None] | None = None,
86+
) -> tuple[dict[str, str], str | None] | tuple[ProblemDetail, None]:
87+
if request is None:
88+
request = {}
7589
email = request.get("email")
7690
password = request.get("password")
7791
redirect_url = request.get("redirect")
@@ -91,7 +105,7 @@ def sign_in(self, _db, request={}):
91105

92106
return INVALID_ADMIN_CREDENTIALS, None
93107

94-
def active_credentials(self, admin):
108+
def active_credentials(self, admin: Admin) -> bool:
95109
# Admins who have a password are always active.
96110
return True
97111

0 commit comments

Comments
 (0)