def do_paginate(parser, token): """ Emits the pagination control for the most recent autopaginate list Syntax is: paginate [[using "TEMPLATE"] url_prefix] Where: - TEMPLATE is a quoted template name. If missing, the default template is used (paginate/pagination.html). - url_prefix is an optional variable containing the base url for pagination. If missing, it defaults to "". """ argv = token.split_contents() argc = len(argv) url_prefix = None if argc == 1: template = None elif argc == 3 and argv[1] == "using": template = unescape_string_literal(argv[2]) elif argc == 4 and argv[1] == "using": template = unescape_string_literal(argv[2]) url_prefix = argv[3] if url_prefix.startswith('"') or url_prefix.startswith("'"): url_prefix = unescape_string_literal(argv[3]) else: raise TemplateSyntaxError( "Invalid syntax. Proper usage of this tag is: " '{% paginate [[using "TEMPLATE"] url_prefix] %}' ) return PaginateNode(template, url_prefix)
def parse_placeholder(parser, token): """Parse the `PlaceholderNode` parameters. Return a tuple with the name and parameters.""" params = {} bits = token.split_contents() count = len(bits) error_string = '%r tag requires at least one argument' % bits[0] if count <= 1: raise TemplateSyntaxError(error_string) try: name = unescape_string_literal(bits[1]) except ValueError: name = bits[1] remaining = bits[2:] simple_options = ['parsed', 'inherited', 'untranslated', 'shared', 'block'] param_options = ['as', 'on', 'with', 'section'] all_options = simple_options + param_options while remaining: bit = remaining[0] if bit not in all_options: raise TemplateSyntaxError( "%r is not an correct option for a placeholder" % bit) if bit in param_options: if len(remaining) < 2: raise TemplateSyntaxError( "Placeholder option '%s' need a parameter" % bit) if bit == 'as': params['as_varname'] = remaining[1] if bit == 'with': params['widget'] = remaining[1] if bit == 'on': params['page'] = remaining[1] if bit == 'section': params['section'] = unescape_string_literal(remaining[1]) remaining = remaining[2:] elif bit == 'parsed': params['parsed'] = True remaining = remaining[1:] elif bit == 'inherited': params['inherited'] = True remaining = remaining[1:] elif bit == 'untranslated': params['untranslated'] = True remaining = remaining[1:] elif bit == 'shared': params['shared'] = True remaining = remaining[1:] elif bit == 'block': remaining = remaining[1:] nodelist = parser.parse(('endplaceholder',)) parser.delete_first_token() params['nodelist'] = nodelist return name, params
def test_unescape_string_literal(self): items = [ ('"abc"', 'abc'), ("'abc'", 'abc'), ('"a \"bc\""', 'a "bc"'), ("'\'ab\' c'", "'ab' c"), ] for value, output in items: self.assertEqual(text.unescape_string_literal(value), output) self.assertEqual(text.unescape_string_literal(lazystr(value)), output)
def parse_git_command(string): command, _, tail = string.lstrip().partition(' ') if command == 'help': return command, tail.split() try: parser = _parsers[command] except KeyError: raise Error('Command "%s" is not supported.' % command) args = [] for arg in smart_split(tail): try: arg = unescape_string_literal(arg) except ValueError: pass args.append(arg) namespace = parser.parse_args(args) if command in ('push', 'pull', 'fetch'): for url in namespace.pos: _check_url(url) elif command == 'remote': if namespace.pos and namespace.pos[0] == 'add': _check_url(namespace.pos[-1]) elif command == 'tag': if namespace.a and namespace.m is None: raise Error('The -m option is required if -a is used.') return command, args
def resolve_template_variable(context, name): try: return unescape_string_literal(name) except ValueError: return Variable(name).resolve(context) except TypeError: return name
def do_page_has_content(parser, token): """ Conditional tag that only renders its nodes if the page has content for a particular content type. By default the current page is used. Syntax:: {% page_has_content <content_type> [<page var name>] %} ... {%_end page_has_content %} Example use:: {% page_has_content 'header-image' %} <img src="{{ MEDIA_URL }}{% imageplaceholder 'header-image' %}"> {% end_page_has_content %} """ nodelist = parser.parse(('end_page_has_content',)) parser.delete_first_token() args = token.split_contents() try: content_type = unescape_string_literal(args[1]) except IndexError: raise template.TemplateSyntaxError( "%r tag requires the argument content_type" % args[0] ) if len(args) > 2: page = args[2] else: page = None return PageHasContentNode(page, content_type, nodelist)
def parse_inline_token(self, token): bits = token.split_contents() if len(bits) == 0: raise InlineSyntaxError(token.lineno, _(u'Empty inline found.')) args = [] kwargs = {} in_kwargs = False ibits = bits.pop(0).split(':') name, variant = ibits if len(ibits) == 2 else (ibits[0], None,) for arg in bits: match = KWARG_RE.match(arg) if match: k, v = match.groups() try: v = self.unescape_inline_argument( unescape_string_literal(v)) except ValueError: # Not a literal (i.e. doesn't start and end w\ ' or ") pass if k is None: if in_kwargs: raise InlineSyntaxError( token.lineno, _( u'Inline `%(inline_content)s`, ' u'non-keyword argument found after keyword ' u'argument.'), params={'inline_content': token.contents}) args.append(v) else: in_kwargs = True kwargs[k] = v return name, variant, args, kwargs
def do_searchbox(parser, token): try: tag, query = token.split_contents() except ValueError: raise template.TemplateSyntaxError("%r tag requires one argument" % token.contents.split()[0]) if not is_quoted(query): raise template.TemplateSyntaxError("%r tag's argument should be in quotes" % token.contents.split()[0]) return SearchBoxNode(query=unescape_string_literal(query))
def resolve_template_variable(context, name): try: return unescape_string_literal(name) except ValueError: #return Variable(name).resolve(context) #TODO: Research if should return always as a str return str(Variable(name).resolve(context)) except TypeError: return name
def do_link(parser, token): try: tag, href = token.split_contents() except ValueError: raise template.TemplateSyntaxError("%r tag requires one argument" % token.contents.split()[0]) if not is_quoted(href): raise template.TemplateSyntaxError("%r tag's argument should be in quotes" % token.contents.split()[0]) nodelist = parser.parse(("endlink",)) parser.delete_first_token() return LinkNode(unescape_string_literal(href), nodelist)
def __init__(self, view_name, *args, **kwargs): # Compatibility with Django 1.5 and later if hasattr(view_name, 'token'): try: unescape_string_literal(view_name.token) except ValueError: # If we cannot unescape the token then it is not quoted. # We have to cancel the variables's lookups and tell it # that it has a literal value. view_name.var.lookups = None view_name.var.literal = view_name.token super(EsiNode, self).__init__(view_name, *args, **kwargs) if '/' in str(self.view_name): # An actual URL has been passed instead of a view name. self.raw_url = unescape_string_literal(str(self.view_name)) self.view_name = None else: self.raw_url = None
def __init__(self, parser, token, *args, **kwargs): super(IncludeContentNode, self).__init__(*args, **kwargs) bits = token.split_contents() if len(bits) < 2: raise template.TemplateSyntaxError, ("%r tag requires at least one" " argument" % token.contents.split()[0]) self.args = [] for b in bits[1:]: if is_quoted(b): b = unescape_string_literal(b) self.args.append(b) self.name = self.args.pop(0)
def __init__(self, parser, token, *args, **kwargs): super(IncludePageNode, self).__init__(*args, **kwargs) bits = token.split_contents() if len(bits) < 2: raise template.TemplateSyntaxError, ('%r tag requires at least one' ' argument' % token.contents.split()[0]) page_name = bits[1] if is_quoted(page_name): page_name = unescape_string_literal(page_name) self.page_name = url_to_name(page_name) self.args = bits[2:]
def extract_terms(raw): """ Extraction based on spaces, understands double and single quotes. Returns a list of strings """ terms = list(smart_split(raw)) print terms for i, term in enumerate(terms): try: terms[i] = unescape_string_literal(terms) except ValueError: pass return terms
def Variable_init_with_underscores_allowed(original_function, self, var): from django.conf import settings # for security reasons, production deployments are not allowed to # render variable names containing underscores anyway. if not settings.DEBUG: return original_function(self, var) self.var = var self.literal = None self.lookups = None self.translate = False self.message_context = None try: # First try to treat this variable as a number. # # Note that this could cause an OverflowError here that we're not # catching. Since this should only happen at compile time, that's # probably OK. self.literal = float(var) # So it's a float... is it an int? If the original value contained a # dot or an "e" then it was a float, not an int. if '.' not in var and 'e' not in var.lower(): self.literal = int(self.literal) # "2." is invalid if var.endswith('.'): raise ValueError except ValueError: # A ValueError means that the variable isn't a number. if var.startswith('_(') and var.endswith(')'): # The result of the lookup should be translated at rendering # time. self.translate = True var = var[2:-1] # If it's wrapped with quotes (single or double), then # we're also dealing with a literal. try: from django.utils.text import unescape_string_literal self.literal = mark_safe(unescape_string_literal(var)) except ValueError: # Otherwise we'll set self.lookups so that resolve() knows we're # dealing with a bonafide variable """ if var.find(VARIABLE_ATTRIBUTE_SEPARATOR + '_') > -1 or var[0] == '_': raise TemplateSyntaxError("Variables and attributes may " "not begin with underscores: '%s'" % var) """ from django.template.base import VARIABLE_ATTRIBUTE_SEPARATOR self.lookups = tuple(var.split(VARIABLE_ATTRIBUTE_SEPARATOR))
def do_link(parser, token): try: tag, href = token.split_contents() except ValueError: raise template.TemplateSyntaxError("%r tag requires one argument" % token.contents.split()[0]) if is_quoted(href): href = unescape_string_literal(href) else: # It's probably a variable in this case. href = template.Variable(href) nodelist = parser.parse(('endlink',)) parser.delete_first_token() return LinkNode(href, nodelist)
def __init__(self, var): self.var = var self.literal = None self.lookups = None self.translate = False self.message_context = None if not isinstance(var, six.string_types): raise TypeError( "Variable must be a string or number, got %s" % type(var)) try: # First try to treat this variable as a number. # # Note that this could cause an OverflowError here that we're not # catching. Since this should only happen at compile time, that's # probably OK. self.literal = float(var) # So it's a float... is it an int? If the original value contained a # dot or an "e" then it was a float, not an int. if '.' not in var and 'e' not in var.lower(): self.literal = int(self.literal) # "2." is invalid if var.endswith('.'): raise ValueError except ValueError: # A ValueError means that the variable isn't a number. if var.startswith('_(') and var.endswith(')'): # The result of the lookup should be translated at rendering # time. self.translate = True var = var[2:-1] # If it's wrapped with quotes (single or double), then # we're also dealing with a literal. try: self.literal = mark_safe(unescape_string_literal(var)) except ValueError: # Otherwise we'll set self.lookups so that resolve() knows we're # dealing with a bonafide variable if var.find(VARIABLE_ATTRIBUTE_SEPARATOR + '_') > -1 or var[0] == '_': raise TemplateSyntaxError("Variables and attributes may " "not begin with underscores: '%s'" % var) self.lookups = tuple(var.split(VARIABLE_ATTRIBUTE_SEPARATOR))
def parse_placeholder(parser, token): """Parse the `PlaceholderNode` parameters. Return a tuple with the name and parameters.""" bits = token.split_contents() count = len(bits) error_string = '%r tag requires at least one argument' % bits[0] if count <= 1: raise TemplateSyntaxError(error_string) try: name = unescape_string_literal(bits[1]) except ValueError: name = bits[1] remaining = bits[2:] params = {} simple_options = ['parsed', 'inherited', 'untranslated'] param_options = ['as', 'on', 'with'] all_options = simple_options + param_options while remaining: bit = remaining[0] if bit not in all_options: raise TemplateSyntaxError( "%r is not an correct option for a placeholder" % bit) if bit in param_options: if len(remaining) < 2: raise TemplateSyntaxError( "Placeholder option '%s' need a parameter" % bit) if bit == 'as': params['as_varname'] = remaining[1] if bit == 'with': params['widget'] = remaining[1] if bit == 'on': params['page'] = remaining[1] remaining = remaining[2:] elif bit == 'parsed': params['parsed'] = True remaining = remaining[1:] elif bit == 'inherited': params['inherited'] = True remaining = remaining[1:] elif bit == 'untranslated': params['untranslated'] = True remaining = remaining[1:] return name, params
def __init__(self, var): self.var = var self.literal = None self.lookups = None self.translate = False try: # First try to treat this variable as a number. # # Note that this could cause an OverflowError here that we're not # catching. Since this should only happen at compile time, that's # probably OK. self.literal = float(var) # So it's a float... is it an int? If the original value contained a # dot or an "e" then it was a float, not an int. if '.' not in var and 'e' not in var.lower(): self.literal = int(self.literal) # "2." is invalid if var.endswith('.'): raise ValueError except ValueError: # A ValueError means that the variable isn't a number. if var.startswith('_(') and var.endswith(')'): # The result of the lookup should be translated at rendering # time. self.translate = True var = var[2:-1] # If it's wrapped with quotes (single or double), then # we're also dealing with a literal. try: self.literal = mark_safe(unescape_string_literal(var)) except ValueError: # Otherwise we'll set self.lookups so that resolve() knows we're # dealing with a bonafide variable if var.find(VARIABLE_ATTRIBUTE_SEPARATOR + '_') > -1 or var[0] == '_': raise TemplateSyntaxError( "Variables and attributes may not begin with underscores: '%s'" % var) self.lookups = tuple(var.split(VARIABLE_ATTRIBUTE_SEPARATOR))
def parse_placeholder(parser, token): """Parse the `PlaceholderNode` parameters. Return a tuple with the name and parameters.""" bits = token.split_contents() count = len(bits) error_string = "%r tag requires at least one argument" % bits[0] if count <= 1: raise TemplateSyntaxError(error_string) try: name = unescape_string_literal(bits[1]) except ValueError: name = bits[1] remaining = bits[2:] params = {} simple_options = ["parsed", "inherited", "untranslated"] param_options = ["as", "on", "with"] all_options = simple_options + param_options while remaining: bit = remaining[0] if bit not in all_options: raise TemplateSyntaxError("%r is not an correct option for a placeholder" % bit) if bit in param_options: if len(remaining) < 2: raise TemplateSyntaxError("Placeholder option '%s' need a parameter" % bit) if bit == "as": params["as_varname"] = remaining[1] if bit == "with": params["widget"] = remaining[1] if bit == "on": params["page"] = remaining[1] remaining = remaining[2:] elif bit == "parsed": params["parsed"] = True remaining = remaining[1:] elif bit == "inherited": params["inherited"] = True remaining = remaining[1:] elif bit == "untranslated": params["untranslated"] = True remaining = remaining[1:] return name, params
def do_paginate(parser, token): """ Emits the pagination control for the most recent autopaginate list Syntax is: paginate [using "TEMPLATE"] Where TEMPLATE is a quoted template name. If missing the default template is used (paginate/pagination.html). """ argv = token.split_contents() argc = len(argv) if argc == 1: template = None elif argc == 3 and argv[1] == 'using': template = unescape_string_literal(argv[2]) else: raise TemplateSyntaxError( "Invalid syntax. Proper usage of this tag is: " "{% paginate [using \"TEMPLATE\"] %}") return PaginateNode(template)
def get_search_results(self, request, queryset, search_term): """ Returns a tuple containing a queryset to implement the search, and a boolean indicating if the results may contain duplicates. """ # Apply keyword searches. def construct_search(field_name): if field_name.startswith('^'): return "%s__istartswith" % field_name[1:] elif field_name.startswith('='): return "%s__iexact" % field_name[1:] elif field_name.startswith('@'): return "%s__search" % field_name[1:] else: return "%s__icontains" % field_name use_distinct = False search_fields = self.get_search_fields(request) if search_fields and search_term: orm_lookups = [ construct_search(str(search_field)) for search_field in search_fields ] for bit in smart_split(search_term): if bit.startswith(('"', "'")): bit = unescape_string_literal(bit) or_queries = [ models.Q(**{orm_lookup: bit}) for orm_lookup in orm_lookups ] queryset = queryset.filter(reduce(operator.or_, or_queries)) if not use_distinct: for search_spec in orm_lookups: if lookup_needs_distinct(self.opts, search_spec): use_distinct = True break return queryset, use_distinct
def parse_inline_token(self, token): bits = token.split_contents() if len(bits) == 0: raise InlineSyntaxError(token.lineno, _(u'Empty inline found.')) args = [] kwargs = {} in_kwargs = False ibits = bits.pop(0).split(':') name, variant = ibits if len(ibits) == 2 else ( ibits[0], None, ) for arg in bits: match = KWARG_RE.match(arg) if match: k, v = match.groups() try: v = unescape_string_literal(v) except ValueError: # Not a literal (i.e. doesn't start and end w\ ' or ") pass if k is None: if in_kwargs: raise InlineSyntaxError( token.lineno, _(u'Inline `%(inline_content)s`, ' u'non-keyword argument found after keyword ' u'argument.'), params={'inline_content': token.contents}) args.append(v) else: in_kwargs = True kwargs[k] = v return name, variant, args, kwargs
def parse_placeholder(parser, token): """Parse the `PlaceholderNode` parameters. Return a tuple with the name and parameters.""" params = {} # try to parse to an endblock parser_copy = copy.deepcopy( parser) # do a deep copy to avoid to change the state of the parser try: nodelist = parser_copy.parse(('endplaceholder', )) except: pass else: nodelist = parser.parse(('endplaceholder', )) parser.delete_first_token() params['nodelist'] = nodelist bits = token.split_contents() count = len(bits) error_string = '%r tag requires at least one argument' % bits[0] if count <= 1: raise TemplateSyntaxError(error_string) try: name = unescape_string_literal(bits[1]) except ValueError: name = bits[1] remaining = bits[2:] simple_options = ['parsed', 'inherited', 'untranslated', 'shared'] param_options = ['as', 'on', 'with', 'section'] all_options = simple_options + param_options while remaining: bit = remaining[0] if bit not in all_options: raise TemplateSyntaxError( "%r is not an correct option for a placeholder" % bit) if bit in param_options: if len(remaining) < 2: raise TemplateSyntaxError( "Placeholder option '%s' need a parameter" % bit) if bit == 'as': params['as_varname'] = remaining[1] if bit == 'with': params['widget'] = remaining[1] if bit == 'on': params['page'] = remaining[1] if bit == 'section': params['section'] = unescape_string_literal(remaining[1]) remaining = remaining[2:] elif bit == 'parsed': params['parsed'] = True remaining = remaining[1:] elif bit == 'inherited': params['inherited'] = True remaining = remaining[1:] elif bit == 'untranslated': params['untranslated'] = True remaining = remaining[1:] elif bit == 'shared': params['shared'] = True remaining = remaining[1:] return name, params
def __init__(self, var): """ :param var: 变量模板字符串,注意:必须是字符串类型 执行过程: 1. 先判断传入的字符串是否是数值类型 1.1 如果包含'.'、'e'字符,有可能是浮点类型,float() 1.1.2 字符串以'.'结尾,不是有效的数值,例如:2. 1.2 否则可能是整形 int() 1.3 如果异常则进入2 2. 是需要翻译的内容,以'_('开头,')'结尾 2.1 设置变量对象的translate属性为True 3. 如果以'"包围,例如:"123"或者'123',则转换为字符串,去掉'"符号 4. 拆分为变量、对象 处理结果: 1. 如果是数值类型或者字符串,放到literal属性中 1.1 如果是需要翻译的字符串,设置translate = True 2. 如果是变量类型,以'.'分解后,放到lookups中,是一个tuple """ # 保存传入的模板字符串 self.var = var # 模板解析结果(文本、数值),保存 self.literal = None # 模板解析结果(对象、变量),保存 self.lookups = None # 模板解析结果为需要翻译的文本,保存为True self.translate = False # 模板中包含%,可以使用message_content,组合后输出 self.message_context = None # 传入的var变量必须是一个字符串类型 if not isinstance(var, str): raise TypeError( "Variable must be a string or number, got %s" % type(var)) try: # First try to treat this variable as a number. # # Note that this could cause an OverflowError here that we're not # catching. Since this should only happen at compile time, that's # probably OK. # Try to interpret values containing a period or an 'e'/'E' # (possibly scientific notation) as a float; otherwise, try int. # 先判断是否数值类型 # 如果包含'.'或'e',有可能是浮点数 if '.' in var or 'e' in var.lower(): self.literal = float(var) # "2." is invalid # 结尾不能是'.' if var.endswith('.'): raise ValueError else: # 不是浮点,有可能是整形 self.literal = int(var) except ValueError: # 如果不是数值类型,转换触发异常 # A ValueError means that the variable isn't a number. # 如果是一个需要翻译的数据 if var.startswith('_(') and var.endswith(')'): # The result of the lookup should be translated at rendering # time. # 设置需要翻译标志,在渲染时再处理 self.translate = True # 去掉翻译的前后标志'_('和')' var = var[2:-1] # If it's wrapped with quotes (single or double), then # we're also dealing with a literal. try: # unescape_string_literal() 去掉字符串头尾的'或",并对字符串中的\"和\\进行反向转义 # 如果没有'",则触发ValueError异常,也就是说该数据应该是一个变量或对象 # make_safe() 将字符串转换为SafeText对象实例 self.literal = mark_safe(unescape_string_literal(var)) except ValueError: # Otherwise we'll set self.lookups so that resolve() knows we're # dealing with a bonafide variable # 只能是变量或者对象了 # 变量或对象的属性,都不可以'_'开头 if var.find(VARIABLE_ATTRIBUTE_SEPARATOR + '_') > -1 or var[0] == '_': raise TemplateSyntaxError("Variables and attributes may " "not begin with underscores: '%s'" % var) # 将变量以'.'拆分为多个变量,保存到lookups中 self.lookups = tuple(var.split(VARIABLE_ATTRIBUTE_SEPARATOR))
"""
def test_unescape_string_literal(inp): try: text.unescape_string_literal(inp) except ValueError as e: if "Not a string literal: " not in str(e): raise
def _process_arg(arg): try: return unescape_string_literal(arg) except ValueError: return Variable(arg)
def test_unescape_string_literal_invalid_value(self): items = ['', 'abc', "'abc\""] for item in items: msg = f'Not a string literal: {item!r}' with self.assertRaisesMessage(ValueError, msg): text.unescape_string_literal(item)
def unescape_string_literal_if_possible(bit): try: return unescape_string_literal(bit) except ValueError: return bit
def safe_unescape_string_literal(value): """Safe version of the `django.utils.text#unescape_string_literal` function.""" try: return unescape_string_literal(value) except (ValueError, IndexError): return value