Skip to content
Browse files

Added test for mark_descendants

  • Loading branch information...
1 parent b546ef4 commit 035cb5392af2f1caaeeff4d23c574b3cbfa5bf9f Jonas Obrist committed Dec 31, 2010
Showing with 86 additions and 65 deletions.
  1. +3 −2 cms/models/pluginmodel.py
  2. +7 −0 cms/templatetags/cms_tags.py
  3. +20 −5 cms/tests/menu.py
  4. +55 −57 menus/menu_pool.py
  5. +1 −1 menus/utils.py
View
5 cms/models/pluginmodel.py
@@ -257,9 +257,10 @@ def delete_with_public(self):
"""
position = self.position
slot = self.placeholder.slot
- if self.page and getattr(self.page, 'publisher_public'):
+ page = get_page_from_placeholder_if_exists(self.placeholder)
+ if page and getattr(page, 'publisher_public'):
try:
- placeholder = Placeholder.objects.get(page=self.page.publisher_public, slot=slot)
+ placeholder = Placeholder.objects.get(page=page.publisher_public, slot=slot)
except Placeholder.DoesNotExist:
pass
else:
View
7 cms/templatetags/cms_tags.py
@@ -16,6 +16,7 @@
from django.utils.translation import ugettext_lazy as _
from itertools import chain
import operator
+import re
register = template.Library()
@@ -35,11 +36,17 @@ def has_permission(page, request):
return page.has_change_permission(request)
register.filter(has_permission)
+CLEAN_KEY_PATTERN = re.compile(r'[^a-zA-Z0-9_-]')
+
+def _clean_key(key):
+ return CLEAN_KEY_PATTERN.sub('-', key)
+
def _get_cache_key(name, page_lookup, lang, site_id):
if isinstance(page_lookup, Page):
page_key = str(page_lookup.pk)
else:
page_key = str(page_lookup)
+ page_key = _clean_key(page_key)
return name+'__page_lookup:'+page_key+'_site:'+str(site_id)+'_lang:'+str(lang)
def _get_page_by_untyped_arg(page_lookup, request, site_id):
View
25 cms/tests/menu.py
@@ -6,9 +6,20 @@
from django.contrib.auth.models import User
from django.template import Template
from menus.base import NavigationNode
-from menus.menu_pool import menu_pool
+from menus.menu_pool import menu_pool, _build_nodes_inner_for_one_menu
+from menus.utils import mark_descendants
class MenusTestCase(CMSTestCase):
+
+ def _get_nodes(self):
+ node1 = NavigationNode('1', '/1/', 1)
+ node2 = NavigationNode('2', '/2/', 2, 1)
+ node3 = NavigationNode('3', '/3/', 3, 2)
+ node4 = NavigationNode('4', '/4/', 4, 2)
+ node5 = NavigationNode('5', '/5/', 5)
+ nodes = [node1, node2, node3, node4, node5]
+ tree = _build_nodes_inner_for_one_menu(nodes, "test")
+ return tree, nodes
def setUp(self):
settings.CMS_MODERATOR = False
@@ -404,8 +415,7 @@ def test_20_build_nodes_inner_for_worst_case_menu(self):
nodes = [node1,node2,node3,node4,node5,]
len_nodes = len(nodes)
- final_list = menu_pool._build_nodes_inner_for_one_menu(nodes,
- menu_class_name)
+ final_list = _build_nodes_inner_for_one_menu(nodes, menu_class_name)
self.assertEqual(len(final_list), len_nodes)
self.assertEqual(node1.parent, node2)
@@ -450,8 +460,7 @@ def test_22_build_nodes_inner_for_broken_menu(self):
menu_class_name = 'Test'
nodes = [node1,node2,node3,node4,node5,]
- final_list = menu_pool._build_nodes_inner_for_one_menu(nodes,
- menu_class_name)
+ final_list = _build_nodes_inner_for_one_menu(nodes, menu_class_name)
self.assertEqual(len(final_list), 3)
self.assertFalse(node1 in final_list)
self.assertFalse(node2 in final_list)
@@ -467,3 +476,9 @@ def test_22_build_nodes_inner_for_broken_menu(self):
self.assertEqual(node3.children, [])
self.assertEqual(node4.children, [node3])
self.assertEqual(node5.children, [node4])
+
+ def test_23_utils_mark_descendants(self):
+ tree_nodes, flat_nodes = self._get_nodes()
+ mark_descendants(tree_nodes)
+ for node in flat_nodes:
+ self.assertTrue(node.descendant, node)
View
112 menus/menu_pool.py
@@ -13,6 +13,60 @@ def lex_cache_key(key):
"""
return key.rsplit('_', 2)[1:]
+def _build_nodes_inner_for_one_menu(nodes, menu_class_name):
+ '''
+ This is an easier to test "inner loop" building the menu tree structure
+ for one menu (one language, one site)
+ '''
+ done_nodes = {} # Dict of node.id:Node
+ final_nodes = []
+
+ # This is to prevent infinite loops - we need to compare the number of
+ # times we see a specific node to "something", and for the time being,
+ # it's the total number of nodes
+ list_total_length = len(nodes)
+
+ while nodes:
+ # For when the node has a parent_id but we haven't seen it yet.
+ # We must not append it to the final list in this case!
+ should_add_to_final_list = True
+
+ node = nodes.pop(0)
+
+ # Increment the "seen" counter for this specific node.
+ node._counter = getattr(node,'_counter',0) + 1
+
+ # Implicit namespacing by menu.__name__
+ if not node.namespace:
+ node.namespace = menu_class_name
+ if node.namespace not in done_nodes:
+ # We need to create the namespace dict to avoid KeyErrors
+ done_nodes[node.namespace] = {}
+
+ # If we have seen the parent_id already...
+ if node.parent_id in done_nodes[node.namespace] :
+ # Implicit parent namespace by menu.__name__
+ if not node.parent_namespace:
+ node.parent_namespace = menu_class_name
+ parent = done_nodes[node.namespace][node.parent_id]
+ parent.children.append(node)
+ node.parent = parent
+ # If it has a parent_id but we haven't seen it yet...
+ elif node.parent_id:
+ # We check for infinite loops here, by comparing the number of
+ # times we "saw" this node to the number of nodes in the list
+ if node._counter < list_total_length:
+ nodes.append(node)
+ # Never add this node to the final list until it has a real
+ # parent (node.parent)
+ should_add_to_final_list = False
+
+ if should_add_to_final_list:
+ final_nodes.append(node)
+ # add it to the "seen" list
+ done_nodes[node.namespace][node.id] = node
+ return final_nodes
+
class MenuPool(object):
def __init__(self):
self.menus = {}
@@ -83,8 +137,7 @@ def _build_nodes(self, request, site_id):
for menu_class_name in self.menus:
nodes = self.menus[menu_class_name].get_nodes(request)
# nodes is a list of navigation nodes (page tree in cms + others)
- final_nodes += self._build_nodes_inner_for_one_menu(nodes,
- menu_class_name)
+ final_nodes += _build_nodes_inner_for_one_menu(nodes, menu_class_name)
duration = getattr(settings, "MENU_CACHE_DURATION", 60*60)
cache.set(key, final_nodes, duration)
# We need to have a list of the cache keys for languages and sites that
@@ -95,68 +148,13 @@ def _build_nodes(self, request, site_id):
CacheKey.objects.create(key=key, language=lang, site=site_id)
return final_nodes
- def _build_nodes_inner_for_one_menu(self, nodes, menu_class_name):
- '''
- This is an easier to test "inner loop" building the menu tree structure
- for one menu (one language, one site)
- '''
- done_nodes = {} # Dict of node.id:Node
- final_nodes = []
-
- # This is to prevent infinite loops - we need to compare the number of
- # times we see a specific node to "something", and for the time being,
- # it's the total number of nodes
- list_total_length = len(nodes)
-
- while nodes:
- # For when the node has a parent_id but we haven't seen it yet.
- # We must not append it to the final list in this case!
- should_add_to_final_list = True
-
- node = nodes.pop(0)
-
- # Increment the "seen" counter for this specific node.
- node._counter = getattr(node,'_counter',0) + 1
-
- # Implicit namespacing by menu.__name__
- if not node.namespace:
- node.namespace = menu_class_name
- if node.namespace not in done_nodes:
- # We need to create the namespace dict to avoid KeyErrors
- done_nodes[node.namespace] = {}
-
- # If we have seen the parent_id already...
- if node.parent_id in done_nodes[node.namespace] :
- # Implicit parent namespace by menu.__name__
- if not node.parent_namespace:
- node.parent_namespace = menu_class_name
- parent = done_nodes[node.namespace][node.parent_id]
- parent.children.append(node)
- node.parent = parent
- # If it has a parent_id but we haven't seen it yet...
- elif node.parent_id:
- # We check for infinite loops here, by comparing the number of
- # times we "saw" this node to the number of nodes in the list
- if node._counter < list_total_length:
- nodes.append(node)
- # Never add this node to the final list until it has a real
- # parent (node.parent)
- should_add_to_final_list = False
-
- if should_add_to_final_list:
- final_nodes.append(node)
- # add it to the "seen" list
- done_nodes[node.namespace][node.id] = node
- return final_nodes
-
def apply_modifiers(self, nodes, request, namespace=None, root_id=None, post_cut=False, breadcrumb=False):
if not post_cut:
nodes = self._mark_selected(request, nodes)
for cls in self.modifiers:
inst = cls()
nodes = inst.modify(request, nodes, namespace, root_id, post_cut, breadcrumb)
return nodes
-
def get_nodes(self, request, namespace=None, root_id=None, site_id=None, breadcrumb=False):
self.discover_menus()
View
2 menus/utils.py
@@ -5,7 +5,7 @@
def mark_descendants(nodes):
for node in nodes:
node.descendant = True
- mark_descendants(node.childrens)
+ mark_descendants(node.children)
def make_tree(request, items, levels, url, ancestors, descendants=False, current_level=0, to_levels=100, active_levels=0):
from cms.models import Page

0 comments on commit 035cb53

Please sign in to comment.
Something went wrong with that request. Please try again.