def do_filter(value, filter): try: p = template.Parser("") fe = template.FilterExpression("value|" + filter, p) return fe.resolve({'value': value}) except: return value
def parse_titles(self, items, context=None): """Walks through the list of items, and resolves any variable found in a title of an item. We deliberately strip down template tokens that are not text or variable. There is definitely no need nor purpose in blocks or comments in a title. Why to think otherwise, if only you're a villain. Joke here. Returns the list with resolved titles. """ if context is None: context = self.global_context for item in items: if item.title.find(template.VARIABLE_TAG_START) != -1: my_lexer = template.Lexer(item.title, template.UNKNOWN_SOURCE) my_tokens = my_lexer.tokenize() for my_token in my_tokens: if my_token.token_type not in (template.TOKEN_TEXT, template.TOKEN_VAR): my_tokens.remove(my_token) my_parser = template.Parser(my_tokens) item.title_resolved = my_parser.parse().render(context) return items
def test_node_can_have_no_args_with_default_value(self): parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, 'tag_name "a"') node = MyEasyNodeWithoutDefaults.parse(parser, token) self.assertEquals(u'a', node.args[0].var)
def compile_template_with_filters(template_string, filters): """Compile a Django template, using additional filters. This is like Template(template_string) except that additional filters to be made available to the template may be specified. Normally, one would define filters as documented in [1], but this requires the INSTALLED_APPS settings to be set, which is not the case in NAV[2]. This function is just a hack to get around that limitation. The code is based on django.template.compile_string[3]. filters should be a dictionary mapping filter names to functions. [1]: http://docs.djangoproject.com/en/dev/howto/custom-template-tags/ [2]: https://nav.uninett.no/wiki/devel:django_introduction#settings [3]: http://code.djangoproject.com/browser/django/trunk/django/template/__init__.py """ lib = template.Library() for name in filters.keys(): lib.filter(name, filters[name]) lexer = template.Lexer(template_string, None) parser = template.Parser(lexer.tokenize()) parser.add_library(lib) return parser.parse()
def my_compile_string(self, template_string, origin, libraries=[]): "Compiles template_string into NodeList ready for rendering" lexer = template.Lexer(template_string, origin) parser = template.Parser(lexer.tokenize()) for lib in libraries: parser.add_library(lib) return parser.parse()
def test_node_parse_returns_node_instance(self): parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, 'tag_name arg1 kwarg1="a=1"') node = MyEasyNode.parse(parser, token) self.assertTrue(isinstance(node, MyEasyNode)) self.assertEquals(u'arg1', node.args[0].token) self.assertEquals(u'"a=1"', node.kwargs['kwarg1'].token)
def __unicode__(self): my_lexer = template.Lexer(self.title, template.UNKNOWN_SOURCE) my_tokens = my_lexer.tokenize() # Deliberately strip off template tokens that are not text or variable. for my_token in my_tokens: if my_token.token_type not in (template.TOKEN_TEXT, template.TOKEN_VAR): my_tokens.remove(my_token) my_parser = template.Parser(my_tokens) return my_parser.parse().render(SiteTree.get_global_context())
def test_node_verifies_if_required_kwarg_is_specified_when_code_can_receive_kwargs( self): parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, 'tag_name arg2="2"') MyEasyNode = type( 'MyEasyNode', (EasyNode, ), { 'render_context': lambda self, context, arg1, **kwargs: True }) self.assertRaises(TemplateSyntaxError, MyEasyNode.parse, parser, token)
def test_node_verifies_if_required_arg_is_specified_two_times(self): parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, 'tag_name "required" arg1="3"') MyEasyNode = type('MyEasyNode', (EasyNode, ), { 'render_context': lambda self, context, arg1, *args, **kwargs: True }) self.assertRaises(TemplateSyntaxError, MyEasyNode.parse, parser, token)
def test_parse_tag_with_equals_in_arg_value(self): parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, 'tag_name "a=1"') args_kwargs = EasyNode.parse_to_args_kwargs(parser, token) args_kwargs_str = { 'args': tuple([x.token for x in args_kwargs['args']]), 'kwargs': dict((key, value.token) for key, value in args_kwargs['kwargs'].iteritems()) } self.assertEquals({'args': ('"a=1"', ), 'kwargs': {}}, args_kwargs_str)
def _build_choices(self): """Build choices list runtime using 'sitetree_tree' tag""" tree_token = u'sitetree_tree from "%s" template "%s"' % (self.tree, self.template) choices_str = sitetree_tree(template.Parser(None), template.Token(token_type=template.TOKEN_BLOCK, contents=tree_token)).render(template.Context(current_app='admin')) tree_choices = [('', self.root_title)] for line in choices_str.splitlines(): if line.strip(): splitted = line.split(':::') tree_choices.append((splitted[0], mark_safe(splitted[1]))) return tree_choices
def test_node_applies_filters_to_variable_in_kwargs(self): parser = template.Parser([]) context = Context({'variable': "string1 string2"}) token = template.Token(template.TOKEN_BLOCK, 'tag_name arg1=variable|slugify|upper') args_kwargs = EasyNode.parse_to_args_kwargs(parser, token) node = MyEasyNode(args_kwargs) self.assertEquals( u'STRING1-STRING2', node.render(context), )
def test_easy_library_register_easy_node_with_parameters(self): def test_tag(context, arg1): return arg1 register = EasyLibrary() register.easytag(test_tag) parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, 'test_tag "my arg"') test_node = register.tags['test_tag'](parser, token) context = template.Context({}) self.assertEquals(u'my arg', test_node.render(context))
def test_as_node_can_be_used_without_as_parameter(self): parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, u'tag_name "value"') MyEasyAsNode = type( 'MyEasyAsNode', (EasyAsNode, ), { 'render_context': lambda self, context, arg1, **kwargs: arg1 }) node = MyEasyAsNode.parse(parser, token) context = Context() self.assertEqual('value', node.render(context))
def test_node_can_receive_kwargs(self): parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, 'tag_name arg1="bla" arg2="ble"') MyEasyNode = type('MyEasyNode', (EasyNode,), { 'render_context': lambda self, context, **kwargs:\ reduce(lambda x,y: u'%s%s' % (x, y), ['%s=%s' % (key, value) for key, value in kwargs.items()]) }) node = MyEasyNode.parse(parser, token) self.assertEquals(u'arg1=blaarg2=ble', node.render(Context({})))
def test_node_can_receive_infinite_args(self): parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, 'tag_name "a" "b" "c" "d"') MyEasyNode = type( 'MyEasyNodeWithArgs', (EasyNode, ), { 'render_context': lambda self, context, *args: reduce(lambda x, y: x + y, args) }) node = MyEasyNode.parse(parser, token) self.assertEquals(u'abcd', node.render(Context({})))
def test_if_node_can_receive_args_and_kwargs(self): parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, 'tag_name "1" arg2="2"') MyEasyNode = type( 'MyEasyNode', (EasyNode, ), { 'render_context': lambda self, context, *args, **kwargs: args[0] + kwargs.items( )[0][0] + u'=' + kwargs.items()[0][1] }) node = MyEasyNode.parse(parser, token) self.assertEquals(u'1arg2=2', node.render(Context({})))
def test_as_node_receives_as_parameter(self): parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, u'tag_name as varname') MyEasyAsNode = type( 'MyEasyAsNode', (EasyAsNode, ), { 'render_context': lambda self, context, **kwargs: 'value' }) node = MyEasyAsNode.parse(parser, token) context = Context() self.assertEqual('', node.render(context)) self.assertEqual('value', context['varname'])
def test_parse_tag_special_symbol_in_kwarg_value(self): parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, u'tag_name kwarg1="será?"') args_kwargs = EasyNode.parse_to_args_kwargs(parser, token) args_kwargs_str = { 'args': tuple([x.token for x in args_kwargs['args']]), 'kwargs': dict((key, value.token) for key, value in args_kwargs['kwargs'].iteritems()) } self.assertEquals({ 'args': (), 'kwargs': { 'kwarg1': u'"será?"' } }, args_kwargs_str)
def test_parse_tag_with_args(self): """ Tests if the parser recognizes one tag and parses its args """ parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, 'tag_name "arg1" "arg2"') args_kwargs = EasyNode.parse_to_args_kwargs(parser, token) args_kwargs_str = { 'args': tuple([x.token for x in args_kwargs['args']]), 'kwargs': dict((key, value.token) for key, value in args_kwargs['kwargs'].iteritems()) } self.assertEquals({ 'args': ('"arg1"', '"arg2"'), 'kwargs': {} }, args_kwargs_str)
def test_easy_library_register_easy_node(self): def test_tag(context): return u'my return' register = EasyLibrary() register.easytag(test_tag) parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, 'test_tag') self.assertTrue('test_tag' in register.tags) test_node = register.tags['test_tag'](parser, token) self.assertTrue(isinstance(test_node, EasyNode)) context = template.Context({}) self.assertEquals(u'my return', test_node.render(context))
def testResolveValue(self): from request_utils.templatetags.request_utils import resolve_value parser = template.Parser([]) context = template.Context({}) filter_expr = parser.compile_filter('"foo"') resolved = resolve_value(filter_expr, context) self.assertEquals('foo', resolved) filter_expr = parser.compile_filter('foo') self.assertRaises(template.VariableDoesNotExist, resolve_value, filter_expr, context) filter_expr = parser.compile_filter('foo') resolved = resolve_value(filter_expr, template.Context({'foo': 'bar'})) self.assertEquals('bar', resolved) var = template.Variable('foo') self.assertRaises(template.VariableDoesNotExist, resolve_value, var, context) literal = 'foo' resolved = resolve_value(literal, context) self.assertEquals('foo', resolved)
def get_form(self, request, obj=None, **kwargs): """Returns modified form for TreeItem model. 'Parent' field choices are built by sitetree itself. """ class TreeItemChoiceField(ChoiceField): """We use custom ChoiceField as to have a chance to resolve TreeItem by ID from dropdown. """ def clean(self, value): if value == '': return None return TreeItem.objects.get(pk=value) # We build choices dropdown using 'sitetree_tree' tag tree_token = u'sitetree_tree from "%s" template "admin/sitetree/tree/tree_combo.html"' % self.tree.alias my_context = template.RequestContext(request, current_app='admin') choices_str = sitetree_tree(template.Parser(None), template.Token(token_type=template.TOKEN_BLOCK, contents=tree_token)).render(my_context) tree_choices = [('', '---------')] for line in choices_str.splitlines(): if line.strip() != '': splitted = line.split(':::') tree_choices.append((splitted[0], mark_safe(splitted[1]))) if obj is not None and obj.parent is not None: self.previous_parent = obj.parent previous_parent_id = self.previous_parent.id else: previous_parent_id = None my_choice_field = TreeItemChoiceField(choices=tree_choices, initial=previous_parent_id) form = super(TreeItemAdmin, self).get_form(request, obj, **kwargs) my_choice_field.label = form.base_fields['parent'].label my_choice_field.help_text = form.base_fields['parent'].help_text # Replace 'parent' TreeItem field with new appropriate one form.base_fields['parent'] = my_choice_field return form
def test_node_parse_verifies_if_required_arg_is_specified(self): parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, 'tag_name kwarg1="a"') self.assertRaises(TemplateSyntaxError, MyEasyNode.parse, parser, token)
def url(self, sitetree_item, tag_arguments=None, context=None): """Resolves item's URL. 'sitetree_item' points to TreeItem object, 'url' property of which is processed as URL pattern or simple URL. 'tag_arguments' is a list of additional arguments passed to 'sitetree_url' in template. """ if tag_arguments is None: tag_arguments = [] else: # TODO Remove tag_arguments in 1.0. warnings.warn( 'Use of sitetree_url tag additional arguments is deprecated. Feature support will be completely removed in 1.0.', DeprecationWarning) if context is None: context = self._global_context if not isinstance(sitetree_item, TreeItem): sitetree_item = self.resolve_var(sitetree_item, context) # Resolve only if item's URL is marked as pattern. if sitetree_item.urlaspattern: resolved_var = self.resolve_var(sitetree_item.url, context) # Check whether a template variable is used instead of a URL pattern. if resolved_var != sitetree_item.url: if not isinstance( resolved_var, six.string_types ): # Variable contains what we're not expecting, revert to original URL. resolved_var = sitetree_item.url # TODO Remove template var resolution in 1.0. warnings.warn( 'Use of a template variable in URL field is deprecated. Feature support will be completely removed in 1.0.', DeprecationWarning) view_path = resolved_var all_arguments = copy(tag_arguments) if ' ' in resolved_var: view_path = resolved_var.split(' ') # We should try to resolve URL parameters from site tree item. for view_argument in view_path[1:]: resolved = self.resolve_var(view_argument) # In case of non-ascii data we leave variable unresolved. if isinstance(resolved, six.text_type): if resolved.encode( 'ascii', 'ignore').decode('ascii') != resolved: resolved = view_argument # URL parameters from site tree item should be concatenated with those from template. all_arguments.append( '"%s"' % str(resolved) ) # We enclose arg in double quotes as already resolved. view_path = view_path[0].strip('"\' ') if DJANGO_VERSION_INT >= 150: # "new-style" url tag - consider sitetree named urls literals. view_path = "'%s'" % view_path url_pattern = u'%s %s' % (view_path, ' '.join(all_arguments)) else: url_pattern = str(sitetree_item.url) tree_alias = sitetree_item.tree.alias entry_from_cache = self.get_cache_entry('urls', tree_alias) if not entry_from_cache: # Create 'cache_urls' for this tree. entry_from_cache = {} self.set_cache_entry('urls', tree_alias, {}) if url_pattern in entry_from_cache: resolved_url = entry_from_cache[url_pattern][0] else: if sitetree_item.urlaspattern: # Form token to pass to Django 'url' tag. url_token = u'url %s as item.url_resolved' % url_pattern url_tag( template.Parser(None), template.Token(token_type=template.TOKEN_BLOCK, contents=url_token)).render(context) # We make an anchor link from an unresolved URL as a reminder. if not context['item.url_resolved']: resolved_url = u'#unresolved' else: resolved_url = context['item.url_resolved'] else: resolved_url = url_pattern self.update_cache_entry_value( 'urls', tree_alias, {url_pattern: (resolved_url, sitetree_item)}) return resolved_url
def test_node_parse_verifies_kwarg_already_satisfied_by_arg(self): parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, 'tag_name arg1 arg1="a=1"') self.assertRaises(TemplateSyntaxError, MyEasyNode.parse, parser, token)
def test_node_parse_verifies_if_there_are_less_args_kwargs_then_method_requires( self): parser = template.Parser([]) token = template.Token(template.TOKEN_BLOCK, 'tag_name') self.assertRaises(TemplateSyntaxError, MyEasyNode.parse, parser, token)
def url(self, sitetree_item, tag_arguments=[], context=None): """Resolves item's URL. 'sitetree_item' points to TreeItem object, 'url' property of which is processed as URL pattern or simple URL. 'tag_arguments' is a list of additional arguments passed to 'sitetree_url' in template. """ if context is None: context = self.global_context if not isinstance(sitetree_item, TreeItem): sitetree_item = self.resolve_var(sitetree_item, context) # Resolve only if item's URL is marked as pattern. if sitetree_item.urlaspattern: resolved_var = self.resolve_var(sitetree_item.url, context) if isinstance(resolved_var, list): raise SiteTreeError( 'Named URL for "%s" sitetree item clashes with template variable name. Please change either name.' % sitetree_item.title) view_path = resolved_var.split(' ') # We should try to resolve URL parameters from site tree item. view_arguments = [] for view_argument in view_path[1:]: resolved = self.resolve_var(view_argument) # In case of non-ascii data we leave variable unresolved. if isinstance(resolved, unicode): if resolved.encode('ascii', 'ignore').decode('ascii') != resolved: resolved = view_argument view_arguments.append(resolved) # URL parameters from site tree item should be concatenated with # those from template. arguments_couled = tag_arguments + view_arguments view_arguments = [] for argument in arguments_couled: argument = str(argument) # To be able to process slug-like strings (strings with "-"'s and "_"'s) # we enclose those in double quotes. if '-' in argument or '_': argument = '"%s"' % argument view_arguments.append(argument) view_arguments = ' '.join(view_arguments).strip() view_path = view_path[0] url_pattern = u'%s %s' % (view_path, view_arguments) else: url_pattern = u'%s' % sitetree_item.url url_pattern = url_pattern.strip() # Create 'cache_urls' for this tree. tree_alias = sitetree_item.tree.alias entry_from_cache = self.get_cache_entry('urls', tree_alias) if not entry_from_cache: entry_from_cache = {} self.set_cache_entry('urls', tree_alias, {}) if url_pattern in entry_from_cache: resolved_url = entry_from_cache[url_pattern][0] else: if sitetree_item.urlaspattern: # Form token to pass to Django 'url' tag. url_token = u'url %s as item.url_resolved' % url_pattern url_tag( template.Parser(None), template.Token(token_type=template.TOKEN_BLOCK, contents=url_token)).render(context) # We make an anchor link from an unresolved URL as a reminder. if context['item.url_resolved'] == '': resolved_url = u'#unresolved' else: resolved_url = context['item.url_resolved'] else: resolved_url = url_pattern self.update_cache_entry_value( 'urls', tree_alias, {url_pattern: (resolved_url, sitetree_item)}) return resolved_url
def parse_template(content): lexer = template.Lexer(content, '') parser = template.Parser(lexer.tokenize()) token = parser.next_token() return parser, token
def url(self, sitetree_item, context=None): """Resolves item's URL. 'sitetree_item' points to TreeItem object, 'url' property of which is processed as URL pattern or simple URL. """ if context is None: context = self._global_context if not isinstance(sitetree_item, MODEL_TREE_ITEM_CLASS): sitetree_item = self.resolve_var(sitetree_item, context) # Resolve only if item's URL is marked as pattern. if sitetree_item.urlaspattern: url = sitetree_item.url view_path = url all_arguments = [] if ' ' in url: view_path = url.split(' ') # We should try to resolve URL parameters from site tree item. for view_argument in view_path[1:]: resolved = self.resolve_var(view_argument) # In case of non-ascii data we leave variable unresolved. if isinstance(resolved, six.text_type): if resolved.encode('ascii', 'ignore').decode('ascii') != resolved: resolved = view_argument # URL parameters from site tree item should be concatenated with those from template. all_arguments.append('"%s"' % str(resolved)) # We enclose arg in double quotes as already resolved. view_path = view_path[0].strip('"\' ') if VERSION >= (1, 5, 0): # "new-style" url tag - consider sitetree named urls literals. view_path = "'%s'" % view_path url_pattern = u'%s %s' % (view_path, ' '.join(all_arguments)) else: url_pattern = str(sitetree_item.url) tree_alias = sitetree_item.tree.alias entry_from_cache = self.get_cache_entry('urls', tree_alias) if not entry_from_cache: # Create 'cache_urls' for this tree. entry_from_cache = {} self.set_cache_entry('urls', tree_alias, {}) if url_pattern in entry_from_cache: resolved_url = entry_from_cache[url_pattern][0] else: if sitetree_item.urlaspattern: # Form token to pass to Django 'url' tag. url_token = u'url %s as item.url_resolved' % url_pattern url_tag(template.Parser(None), template.Token(token_type=template.TOKEN_BLOCK, contents=url_token)).render(context) # We make an anchor link from an unresolved URL as a reminder. if not context['item.url_resolved']: resolved_url = UNRESOLVED_ITEM_MARKER else: resolved_url = context['item.url_resolved'] else: resolved_url = url_pattern self.update_cache_entry_value('urls', tree_alias, {url_pattern: (resolved_url, sitetree_item)}) return resolved_url