Skip to content

Commit d31c755

Browse files
committed
feat: Add django support
1 parent 9ef8326 commit d31c755

File tree

12 files changed

+104
-4
lines changed

12 files changed

+104
-4
lines changed

Diff for: .github/workflows/test.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ jobs:
4949
- name: Install dependencies
5050
run: |
5151
python -m pip install --upgrade pip setuptools setuptools_scm
52-
python -m pip install .[full,test]
52+
python -m pip install .[full,test,django]
5353
5454
- name: Test with pytest
5555
run: |

Diff for: .pre-commit-config.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ repos:
3939
additional_dependencies:
4040
- types-cachetools
4141
- typeguard
42+
- django
4243

4344
- repo: https://github.com/compilerla/conventional-pre-commit
4445
rev: v3.2.0

Diff for: ludic/base.py

+3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ def __init__(self, *children: Any, **attrs: Any) -> None:
2424
def __str__(self) -> str:
2525
return self.to_html()
2626

27+
def __bytes__(self) -> bytes:
28+
return self.to_html().encode("utf-8")
29+
2730
def __format__(self, _: str) -> str:
2831
return self.formatter.append(self)
2932

Diff for: ludic/catalog/messages.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,10 @@ def render(self) -> div:
4545
return div(
4646
self.children[0],
4747
div(*self.children[1:], classes=["content"]),
48+
**self.attrs,
4849
)
4950
else:
50-
return div(div(*self.children, classes=["content"]))
51+
return div(div(*self.children, classes=["content"]), **self.attrs)
5152

5253

5354
class MessageSuccess(Message):

Diff for: ludic/contrib/__init__.py

Whitespace-only changes.

Diff for: ludic/contrib/django/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from .middlewares import LudicMiddleware as LudicMiddleware
2+
from .responses import LudicResponse as LudicResponse

Diff for: ludic/contrib/django/middlewares.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from collections.abc import Callable
2+
3+
from django.http import HttpRequest, HttpResponse
4+
5+
from ludic.base import BaseElement
6+
7+
8+
class LudicMiddleware:
9+
"""Ludic middleware for Django to clean up the cache for f-strings.
10+
11+
Usage:
12+
13+
# somewhere in django settings.py
14+
15+
MIDDLEWARES = [
16+
"...",
17+
"ludic.contrib.django.LudicMiddleware",
18+
]
19+
"""
20+
21+
def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]) -> None:
22+
self.get_response = get_response
23+
24+
def __call__(self, request: HttpRequest) -> HttpResponse:
25+
with BaseElement.formatter:
26+
response: HttpResponse = self.get_response(request)
27+
28+
return response

Diff for: ludic/contrib/django/responses.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from typing import Any
2+
3+
from django.http import HttpResponse
4+
5+
from ludic.types import AnyChildren
6+
7+
8+
class LudicResponse(HttpResponse):
9+
"""Class representing Ludic response for Django View.
10+
11+
Usage:
12+
13+
from django.http import HttpRequest
14+
15+
from ludic.html import p
16+
from ludic.contrib.django import LudicResponse
17+
18+
def index(request: HttpRequest) -> LudicResponse:
19+
return LudicResponse(p("Hello, World!"))
20+
21+
"""
22+
23+
def __init__(self, content: AnyChildren = "", *args: Any, **kwargs: Any) -> None:
24+
super().__init__(str(content), *args, **kwargs)

Diff for: pyproject.toml

+4
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,13 @@ full = [
3434
"typeguard>=4.1.5",
3535
"pygments",
3636
]
37+
django = [
38+
"django",
39+
]
3740
dev = [
3841
"mypy",
3942
"types-pygments",
43+
"django-stubs",
4044
]
4145
test = [
4246
"pytest",

Diff for: tests/contrib/__init__.py

Whitespace-only changes.

Diff for: tests/contrib/test_django.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import os
2+
3+
from django.http import HttpRequest
4+
5+
from ludic.base import BaseElement
6+
from ludic.contrib.django import LudicMiddleware, LudicResponse
7+
from ludic.html import p
8+
9+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tests.contrib")
10+
11+
12+
def test_django_response() -> None:
13+
assert LudicResponse(p("test")).content == b"<p>test</p>"
14+
15+
16+
def test_django_middleware() -> None:
17+
get_response_called = False
18+
19+
def get_response(_: HttpRequest) -> LudicResponse:
20+
nonlocal get_response_called
21+
get_response_called = True
22+
23+
assert len(BaseElement.formatter.get()) == 0
24+
response = LudicResponse(f"{p("does not clean up cache")}")
25+
assert len(BaseElement.formatter.get()) == 1
26+
return response
27+
28+
middleware = LudicMiddleware(get_response)
29+
middleware(HttpRequest())
30+
31+
assert get_response_called
32+
assert len(BaseElement.formatter.get()) == 0

Diff for: tests/test_elements.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
from ludic.styles import CSSProperties
33

44

5+
def test_str_and_bytes() -> None:
6+
assert str(html.a("str")) == "<a>str</a>"
7+
assert bytes(html.p("str")) == b"<p>str</p>"
8+
9+
510
def test_empty_element() -> None:
611
dom = html.div()
712
assert dom.to_html() == "<div></div>"
@@ -155,7 +160,7 @@ def test_repr_and_str_and_to_string() -> None:
155160

156161

157162
def test_data_attributes() -> None:
158-
dom = html.div("content", data_foo="1", data_bar="test") # type: ignore
163+
dom = html.div("content", data_foo="1", data_bar="test") # type: ignore[call-arg]
159164

160165
assert dom.attrs == {"data_foo": "1", "data_bar": "test"}
161166
assert dom.to_html() == '<div data-foo="1" data-bar="test">content</div>'
@@ -165,7 +170,7 @@ def test_htmx_attributes() -> None:
165170
assert html.button(
166171
"Get Info!",
167172
hx_get="/info", hx_on__before_request="alert('Making a request!')",
168-
).to_html() == ( # type: ignore
173+
).to_html() == ( # type: ignore[call-arg]
169174
'<button hx-get="/info" hx-on--before-request="alert(\'Making a request!\')">'
170175
"Get Info!"
171176
"</button>"

0 commit comments

Comments
 (0)