Skip to content

Commit af12acf

Browse files
refactor tags a bit (#49)
1 parent d35d517 commit af12acf

File tree

6 files changed

+57
-32
lines changed

6 files changed

+57
-32
lines changed

src/django_bird/_typing.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@
1010
)
1111

1212
override = typing_override
13+
14+
TagBits = list[str]
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
# pyright: reportAny=false
21
from __future__ import annotations
32

43
from django import template
54

6-
from .tags import do_bird
7-
from .tags import do_slot
5+
from .tags import bird
6+
from .tags import slot
87

98
register = template.Library()
109

1110

12-
register.tag("bird", do_bird)
13-
register.tag("bird:slot", do_slot)
11+
register.tag(bird.TAG, bird.do_bird)
12+
register.tag(slot.TAG, slot.do_slot)

src/django_bird/templatetags/tags/bird.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,48 @@
1212
from django.utils.safestring import SafeString
1313
from django.utils.safestring import mark_safe
1414

15+
from django_bird._typing import TagBits
1516
from django_bird._typing import override
1617
from django_bird.conf import app_settings
1718

1819
from .slot import SlotNode
1920

21+
TAG = "bird"
22+
END_TAG = "endbird"
23+
2024

2125
def do_bird(parser: Parser, token: Token) -> BirdNode:
2226
bits = token.split_contents()
27+
name = parse_bird_name(bits)
28+
attrs = parse_attrs(bits)
29+
nodelist = parse_nodelist(attrs, parser)
30+
return BirdNode(name, attrs, nodelist)
2331

24-
if len(bits) < 2:
25-
msg = f"{token.contents.split()[0]} tag requires at least one argument"
32+
33+
def parse_bird_name(bits: TagBits) -> str:
34+
if len(bits) == 1:
35+
msg = f"{TAG} tag requires at least one argument"
2636
raise template.TemplateSyntaxError(msg)
2737

2838
# {% bird name %}
2939
# {% bird 'name' %}
3040
# {% bird "name" %}
31-
name = bits[1].strip("'\"")
32-
attrs = bits[2:]
41+
return bits[1].strip("'\"")
42+
3343

44+
def parse_attrs(bits: TagBits) -> TagBits:
45+
return bits[2:]
46+
47+
48+
def parse_nodelist(attrs: TagBits, parser: Parser) -> NodeList | None:
3449
# self-closing tag
3550
# {% bird name / %}
3651
if len(attrs) > 0 and attrs[-1] == "/":
3752
nodelist = None
3853
else:
39-
nodelist = parser.parse(("endbird",))
54+
nodelist = parser.parse((END_TAG,))
4055
parser.delete_first_token()
41-
42-
return BirdNode(name, attrs, nodelist)
56+
return nodelist
4357

4458

4559
class BirdNode(template.Node):

src/django_bird/templatetags/tags/slot.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,39 @@
1111
from django.utils.safestring import SafeString
1212
from django.utils.safestring import mark_safe
1313

14+
from django_bird._typing import TagBits
1415
from django_bird._typing import override
1516

17+
TAG = "bird:slot"
18+
END_TAG = "endbird:slot"
19+
1620

1721
def do_slot(parser: Parser, token: Token) -> SlotNode:
1822
bits = token.split_contents()
1923
name = parse_slot_name(bits)
20-
nodelist = parser.parse(("endbird:slot",))
21-
parser.delete_first_token()
24+
nodelist = parse_nodelist(parser)
2225
return SlotNode(name, nodelist)
2326

2427

25-
def parse_slot_name(tag_args: list[str]) -> str:
26-
if len(tag_args) == 1:
28+
def parse_slot_name(bits: TagBits) -> str:
29+
if len(bits) == 1:
2730
return "default"
28-
elif len(tag_args) == 2:
29-
name = tag_args[1]
31+
elif len(bits) == 2:
32+
name = bits[1]
3033
if name.startswith("name="):
3134
name = name.split("=")[1]
3235
else:
3336
name = name
3437
return name.strip("'\"")
3538
else:
36-
raise template.TemplateSyntaxError(
37-
"slot tag requires either no arguments, one argument, or 'name=\"slot_name\"'"
38-
)
39+
msg = f"{TAG} tag requires either no arguments, one argument, or 'name=\"slot_name\"'"
40+
raise template.TemplateSyntaxError(msg)
41+
42+
43+
def parse_nodelist(parser: Parser) -> NodeList:
44+
nodelist = parser.parse((END_TAG,))
45+
parser.delete_first_token()
46+
return nodelist
3947

4048

4149
class SlotNode(template.Node):

tests/templatetags/test_bird.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,34 @@
1212
from django.template.exceptions import TemplateSyntaxError
1313
from django.test import override_settings
1414

15+
from django_bird.templatetags.tags.bird import END_TAG
16+
from django_bird.templatetags.tags.bird import TAG
1517
from django_bird.templatetags.tags.bird import BirdNode
1618
from django_bird.templatetags.tags.bird import do_bird
1719

1820

1921
class TestTemplateTag:
2022
@pytest.mark.parametrize(
21-
"name_arg,expected",
23+
"name,expected",
2224
[
2325
("button", "button"),
2426
("'button'", "button"),
2527
('"button"', "button"),
2628
("button.label", "button.label"),
2729
],
2830
)
29-
def test_node_name(self, name_arg, expected):
30-
token = Token(TokenType.BLOCK, f"bird {name_arg}")
31+
def test_node_name(self, name, expected):
32+
token = Token(TokenType.BLOCK, f"{TAG} {name}")
3133
parser = Parser(
32-
[Token(TokenType.BLOCK, "endbird")],
34+
[Token(TokenType.BLOCK, END_TAG)],
3335
)
3436
node = do_bird(parser, token)
3537
assert node.name == expected
3638

3739
def test_missing_argument(self):
38-
token = Token(TokenType.BLOCK, "bird")
40+
token = Token(TokenType.BLOCK, TAG)
3941
parser = Parser(
40-
[Token(TokenType.BLOCK, "endbird")],
42+
[Token(TokenType.BLOCK, END_TAG)],
4143
)
4244
with pytest.raises(TemplateSyntaxError):
4345
do_bird(parser, token)
@@ -51,9 +53,9 @@ def test_missing_argument(self):
5153
],
5254
)
5355
def test_node_attrs(self, attrs, expected_attrs):
54-
token = Token(TokenType.BLOCK, f"bird button {attrs}")
56+
token = Token(TokenType.BLOCK, f"{TAG} button {attrs}")
5557
parser = Parser(
56-
[Token(TokenType.BLOCK, "endbird")],
58+
[Token(TokenType.BLOCK, END_TAG)],
5759
)
5860
node = do_bird(parser, token)
5961
assert node.attrs == expected_attrs

tests/templatetags/test_slot.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010

1111
@pytest.mark.parametrize(
12-
"tag_args,expected",
12+
"bits,expected",
1313
[
1414
(["slot"], "default"),
1515
(["slot", "foo"], "foo"),
@@ -19,8 +19,8 @@
1919
(["slot", "name='foo'"], "foo"),
2020
],
2121
)
22-
def test_parse_slot_name(tag_args, expected):
23-
assert parse_slot_name(tag_args) == expected
22+
def test_parse_slot_name(bits, expected):
23+
assert parse_slot_name(bits) == expected
2424

2525

2626
def test_parse_slot_name_no_args():

0 commit comments

Comments
 (0)