Skip to content

Commit 248c824

Browse files
refactor: modernize type hints across the package
Add `from __future__ import annotations` and switch to builtin generics and PEP 604 unions (dict/list/tuple/type, X | None) in hx_requests.py, hx_registry.py and templatetags/hx_tags.py; drop the now-unused typing imports. Also fixes the eager-evaluation TypeError from the dict[str, str] annotation on the Python floor. No runtime behavior change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent e2a4e07 commit 248c824

3 files changed

Lines changed: 27 additions & 25 deletions

File tree

hx_requests/hx_registry.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@
1313
That only becomes known at import time.
1414
"""
1515

16+
from __future__ import annotations
17+
1618
import ast
1719
import importlib
1820
import os
1921
import threading
20-
from typing import Dict, Optional, Tuple, Type, Union
2122

2223
from django.apps import apps
2324

@@ -26,7 +27,7 @@
2627

2728
class HxRequestRegistry:
2829
# name -> class OR (module_path, class_name)
29-
_registry: Dict[str, Union[Type[BaseHxRequest], Tuple[str, str]]] = {}
30+
_registry: dict[str, type[BaseHxRequest] | tuple[str, str]] = {}
3031
_initialized = False
3132
_lock = threading.Lock()
3233

@@ -103,7 +104,7 @@ def _parse_file(cls, file_path: str, module_name: str):
103104
return
104105

105106
@classmethod
106-
def _get_class_name_attribute(cls, class_node: ast.ClassDef) -> Optional[str]:
107+
def _get_class_name_attribute(cls, class_node: ast.ClassDef) -> str | None:
107108
"""
108109
Extract the `name` class attribute from a class definition.
109110
@@ -132,7 +133,7 @@ def _get_class_name_attribute(cls, class_node: ast.ClassDef) -> Optional[str]:
132133
return None
133134

134135
@classmethod
135-
def register_hx_request(cls, name: str, hx_request_class: Type[BaseHxRequest]):
136+
def register_hx_request(cls, name: str, hx_request_class: type[BaseHxRequest]):
136137
"""
137138
Manual registration
138139
"""

hx_requests/hx_requests.py

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
from __future__ import annotations
2+
13
import contextlib
24
import json
35
from functools import partial
4-
from typing import Dict, List, Optional, Union
56

67
from django.conf import settings
78
from django.contrib import messages
@@ -85,12 +86,12 @@ class BaseHxRequest:
8586

8687
name: str = ""
8788
hx_object_name: str = "hx_object"
88-
GET_template: Union[str, list] = ""
89-
POST_template: Union[str, list] = ""
90-
GET_block: Union[str, list] = ""
91-
POST_block: Union[str, list, dict[str, str]] = ""
89+
GET_template: str | list = ""
90+
POST_template: str | list = ""
91+
GET_block: str | list = ""
92+
POST_block: str | list | dict[str, str] = ""
9293
refresh_page: bool = False
93-
redirect: str = None
94+
redirect: str | None = None
9495
return_empty: bool = False
9596
no_swap = False
9697
show_messages: bool = True
@@ -118,7 +119,7 @@ def is_post_request(self):
118119
def use_messages(self):
119120
return getattr(settings, "HX_REQUESTS_USE_HX_MESSAGES", False) and self.show_messages
120121

121-
def get_context_data(self, **kwargs) -> Dict:
122+
def get_context_data(self, **kwargs) -> dict:
122123
"""
123124
Adds the context from the view and additionally adds:
124125
@@ -143,7 +144,7 @@ def get_context_data(self, **kwargs) -> Dict:
143144
# Turn into dict for template rendering which expects a dict
144145
return context.flatten()
145146

146-
def get_context_on_GET(self, **kwargs) -> Dict:
147+
def get_context_on_GET(self, **kwargs) -> dict:
147148
"""
148149
Adds extra context to the context data only on GET.
149150
"""
@@ -188,7 +189,7 @@ def _setup_hx_request(self, request, *args, **kwargs):
188189
def hx_object_to_str(self) -> str:
189190
return self.hx_object._meta.model.__name__.capitalize() if self.hx_object else ""
190191

191-
def get_headers(self, **kwargs) -> Dict:
192+
def get_headers(self, **kwargs) -> dict:
192193
"""
193194
Prepare the headers for the response.
194195
"""
@@ -204,7 +205,7 @@ def get_headers(self, **kwargs) -> Dict:
204205
headers.update(self.get_trigger_headers(**kwargs))
205206
return headers
206207

207-
def get_triggers(self, **kwargs) -> Union[List[Union[str, dict]], Dict[str, list]]:
208+
def get_triggers(self, **kwargs) -> list[str | dict] | dict[str, list]:
208209
"""
209210
Override to set the triggers for the response.
210211
@@ -232,7 +233,7 @@ def get_triggers(self, **kwargs) -> Union[List[Union[str, dict]], Dict[str, list
232233
"""
233234
return []
234235

235-
def get_trigger_headers(self, **kwargs) -> Dict[str, str]:
236+
def get_trigger_headers(self, **kwargs) -> dict[str, str]:
236237
"""
237238
Build the HTMX trigger response headers from :meth:`get_triggers`.
238239
@@ -266,7 +267,7 @@ def format_triggers(self, **kwargs) -> str:
266267
return self._format_trigger_value(triggers)
267268

268269
@staticmethod
269-
def _format_trigger_value(triggers: List[Union[str, dict]]) -> str:
270+
def _format_trigger_value(triggers: list[str | dict]) -> str:
270271
"""
271272
Format a single list of triggers into one header value.
272273
@@ -431,7 +432,7 @@ class FormHxRequest(BaseHxRequest):
431432
set_initial_from_kwargs: bool = False
432433
show_form_invalid_message: bool = True
433434

434-
def get_context_data(self, **kwargs) -> Dict:
435+
def get_context_data(self, **kwargs) -> dict:
435436
"""
436437
Additionally adds the form into the context.
437438
"""
@@ -460,7 +461,7 @@ def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
460461

461462
return response if response is not None else self._get_response(**kwargs)
462463

463-
def form_valid(self, **kwargs) -> Optional[HttpResponse]:
464+
def form_valid(self, **kwargs) -> HttpResponse | None:
464465
"""
465466
Saves the form and sets a success message.
466467
@@ -470,7 +471,7 @@ def form_valid(self, **kwargs) -> Optional[HttpResponse]:
470471
self.form.save()
471472
messages.success(self.request, self.get_success_message(**kwargs))
472473

473-
def form_invalid(self, **kwargs) -> Optional[HttpResponse]:
474+
def form_invalid(self, **kwargs) -> HttpResponse | None:
474475
"""
475476
Sets an error message unless ``show_form_invalid_message`` is False.
476477
@@ -573,7 +574,7 @@ def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
573574
response = self.delete(**kwargs)
574575
return response if response is not None else self._get_response(**kwargs)
575576

576-
def delete(self, **kwargs) -> Optional[HttpResponse]:
577+
def delete(self, **kwargs) -> HttpResponse | None:
577578
"""
578579
Deletes the hx_object and sets a success message.
579580
@@ -681,7 +682,7 @@ def get_triggers(self, **kwargs) -> list:
681682
triggers.append("closeHxModal")
682683
return triggers
683684

684-
def get_headers(self, **kwargs) -> Dict:
685+
def get_headers(self, **kwargs) -> dict:
685686
"""
686687
If the form is invalid, headers are set to retarget the innerHTML of the modal body.
687688
This is done to show the form errors.

hx_requests/templatetags/hx_tags.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Dict
1+
from __future__ import annotations
22

33
from django import template
44

@@ -8,7 +8,7 @@
88

99

1010
@register.simple_tag(takes_context=True)
11-
def hx_get(context: Dict, hx_request_name: str, object=None, use_full_path=False, **kwargs) -> str:
11+
def hx_get(context: dict, hx_request_name: str, object=None, use_full_path=False, **kwargs) -> str:
1212
"""
1313
Renders the proper HTML attributes for an HX GET request.
1414
And includes the hx_request_name, object, and any additional kwargs.
@@ -18,7 +18,7 @@ def hx_get(context: Dict, hx_request_name: str, object=None, use_full_path=False
1818

1919

2020
@register.simple_tag(takes_context=True)
21-
def hx_post(context: Dict, hx_request_name: str, object=None, use_full_path=False, **kwargs) -> str:
21+
def hx_post(context: dict, hx_request_name: str, object=None, use_full_path=False, **kwargs) -> str:
2222
"""
2323
Renders the proper HTML attributes for an HX POST request.
2424
And includes the hx_request_name, object, and any additional kwargs.
@@ -33,7 +33,7 @@ def hx_post(context: Dict, hx_request_name: str, object=None, use_full_path=Fals
3333

3434

3535
@register.simple_tag(takes_context=True)
36-
def hx_url(context: Dict, hx_request_name: str, object=None, use_full_path=False, **kwargs) -> str:
36+
def hx_url(context: dict, hx_request_name: str, object=None, use_full_path=False, **kwargs) -> str:
3737
"""
3838
Returns the URL for an HX request. Can be used when you need to manually set the URL in a template.
3939
Useful if the hx-get or hx-post tags are not flexible enough for your use case.

0 commit comments

Comments
 (0)