Skip to content

Commit 3a8b09f

Browse files
author
Evan Borgstrom
committed
Improve children handling and improve tests
Fixes #38
1 parent a9cdaec commit 3a8b09f

File tree

2 files changed

+62
-20
lines changed

2 files changed

+62
-20
lines changed

menu/menu.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ def __init__(self, title, url, children=[], weight=1, check=None,
179179
self._title = None
180180
self.visible = visible
181181
self.children = children
182+
self._children = None
182183
self.weight = weight
183184
self.check = check
184185
self.slug = slug
@@ -210,7 +211,7 @@ def process(self, request):
210211
# evaluate children
211212
visible_children = []
212213
self.check_children(request)
213-
self.children.sort(key=lambda child: child.weight)
214+
214215
for child in self.children:
215216
child.process(request)
216217
if child.visible:
@@ -245,17 +246,28 @@ def match_url(self, request):
245246
return matched
246247

247248
def check_children(self, request):
248-
if hasattr(self, '_children'):
249-
self.children = self._children(request)
250-
if callable(self.children):
251-
kids = self.children(request)
249+
"""
250+
Check children against the given request
251+
"""
252+
if callable(self._children):
253+
children = self._children(request)
254+
elif callable(self.children):
255+
children = self.children(request)
252256
self._children = self.children
253-
self.children = kids
257+
else:
258+
children = self.children
254259

255-
for kid in self.children:
256-
kid.parent = self
260+
children = [child for child in children]
261+
children.sort(key=lambda child: child.weight)
262+
for child in children:
263+
child.parent = self
264+
265+
self.children = children
257266

258267
def check_check(self, request):
268+
"""
269+
Set our visibility based on our check against the given request
270+
"""
259271
if callable(self.check):
260272
self.visible = self.check(request)
261273

menu/tests/test_menu.py

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,37 +7,63 @@
77

88
from menu import Menu, MenuItem
99

10+
# XXX TODO: test MENU_HIDE_EMPTY
11+
# XXX TODO: test check_children
12+
1013
class MenuTests(TestCase):
14+
"""
15+
Tests for Menu
16+
"""
17+
1118
def setUp(self):
12-
# allow the title of kids3-2 to be changed
19+
"""
20+
Build some menus for our tests
21+
"""
1322
self.kids3_2_desired_title = None
1423
def kids3_2_title(request):
24+
"Allow the title of kids3-2 to be changed"
1525
if self.kids3_2_desired_title is not None:
1626
return "-".join([request.path, self.kids3_2_desired_title])
1727
return 'kids3-2'
1828

19-
# hide kids2-2 whenever the request path ends with /hidden
2029
def kids2_2_check(request):
30+
"Hide kids2-2 whenever the request path ends with /hidden"
2131
if request.path.endswith('/hidden'):
2232
return False
2333
return True
2434

25-
kids2 = [
26-
MenuItem("kids2-1", "/parent2/kids2-1", weight=999),
27-
MenuItem("kids2-2", "/kids2-2", check=kids2_2_check)
28-
]
29-
kids3 = [
30-
MenuItem("kids3-1", "/parent3/kids3-1", children=[
31-
MenuItem("kids3-1-1", "/parent3/kids3-1/kid1", exact_url=True)
32-
]),
35+
# Ensure we can pass children as tuples (or other iterables, like generators)
36+
# Following the implementation of sorted children there was a bug reported due to children
37+
# being passed as a tuple, which has no .sort method
38+
# See: https://github.com/borgstrom/django-simple-menu/issues/38
39+
def kids2():
40+
"Generator for kids2"
41+
class RepeatIterator(object):
42+
"We need this to be reusable -- http://stackoverflow.com/a/1985733"
43+
def __iter__(self):
44+
yield MenuItem("kids2-1", "/parent2/kids2-1", weight=999)
45+
yield MenuItem("kids2-2", "/kids2-2", check=kids2_2_check)
46+
return RepeatIterator()
47+
48+
def kids3_1(request):
49+
"Callable for kids3-1"
50+
return [
51+
MenuItem("kids3-1-1", "/parent3/kids3-1/kid1", exact_url=True),
52+
]
53+
54+
kids3 = (
55+
MenuItem("kids3-1", "/parent3/kids3-1", children=kids3_1),
3356
MenuItem(kids3_2_title, "/parent3/kids3-2")
34-
]
57+
)
3558

3659
Menu.items = {}
3760
Menu.sorted = {}
3861
Menu.loaded = False
62+
63+
# add our items. because we set weight to 999 for parent 1 it will become the last child
64+
# even though it's added first
3965
Menu.add_item("test", MenuItem("Parent 1", "/parent1", weight=999))
40-
Menu.add_item("test", MenuItem("Parent 2", "/parent2", children=kids2))
66+
Menu.add_item("test", MenuItem("Parent 2", "/parent2", children=kids2()))
4167
Menu.add_item("test", MenuItem("Parent 3", "/parent3", children=kids3))
4268

4369
self.factory = RequestFactory()
@@ -152,6 +178,10 @@ def test_template_tag_missing_attribute(self):
152178
self.assertEqual(out, "Parent 2,Parent 3,Parent 1,")
153179

154180
class MenuItemTests(TestCase):
181+
"""
182+
Tests for MenuItem
183+
"""
184+
155185
def test_kwargs(self):
156186
"""
157187
MenuItems should accept arbitrary keyword args

0 commit comments

Comments
 (0)