Exemple #1
0
    def get_template(self, template, def_name=None):
        '''Retrieve a *Django* API template object for the given template name, using the app_path and template_subdir
           settings in this object.  This method still uses the corresponding Mako template and engine, but it
           gives a Django API wrapper around it so you can use it the same as any Django template.

           If def_name is provided, template rendering will be limited to the named def/block (see Mako docs).

           This method corresponds to the Django templating system API.
           A Django exception is raised if the template is not found or cannot compile.
        '''
        try:
            # wrap the mako template in an adapter that gives the Django template API
            return MakoTemplateAdapter(self.get_mako_template(template), def_name)

        except (TopLevelLookupException, TemplateLookupException) as e: # Mako exception raised
            tdne = TemplateDoesNotExist('Template "%s" not found in search path: %s.' % (template, self.template_search_dirs))
            if settings.DEBUG:
                tdne.template_debug = get_template_debug(template, e)
            raise tdne from e

        except (CompileException, SyntaxException) as e: # Mako exception raised
            tse = TemplateSyntaxError('Template "%s" raised an error: %s' % (template, e))
            if settings.DEBUG:
                tse.template_debug = get_template_debug(template, e)
            raise tse from e
Exemple #2
0
 def get_template(self, template_name):
     try:
         return Template(self.env.get_template(template_name))
     except jinja2.TemplateNotFound as exc:
         six.reraise(TemplateDoesNotExist, TemplateDoesNotExist(exc.name, backend=self), sys.exc_info()[2])
     except jinja2.TemplateSyntaxError as exc:
         new = TemplateSyntaxError(exc.args)
         new.template_debug = get_exception_info(exc)
         six.reraise(TemplateSyntaxError, new, sys.exc_info()[2])
Exemple #3
0
 def get_template(self, template_name):
     try:
         return Template(self.env.get_template(template_name), self)
     except jinja2.TemplateNotFound as exc:
         raise TemplateDoesNotExist(exc.name, backend=self) from exc
     except jinja2.TemplateSyntaxError as exc:
         new = TemplateSyntaxError(exc.args)
         new.template_debug = get_exception_info(exc)
         raise new from exc
Exemple #4
0
 def render_node(self, node, context):
     try:
         result = node.render(context)
     except TemplateSyntaxError as e:
         if not hasattr(e, 'source'):
             e.source = node.source
         raise
     except Exception as e:
         from sys import exc_info
         wrapped = TemplateSyntaxError('Caught an exception while rendering: %s' % force_unicode(e, errors='replace'))
         wrapped.source = node.source
         wrapped.exc_info = exc_info()
         raise wrapped
     return result
    def get_template(self, template_name):
        if not self.match_template(template_name):
            message = "Template {} does not exists".format(template_name)
            raise TemplateDoesNotExist(message)

        try:
            return Template(self.env.get_template(template_name), self)
        except jinja2.TemplateNotFound as exc:
            six.reraise(
                TemplateDoesNotExist,
                TemplateDoesNotExist(exc.name, backend=self),
                sys.exc_info()[2],
            )
        except jinja2.TemplateSyntaxError as exc:
            new = TemplateSyntaxError(exc.args)
            new.template_debug = get_exception_info(exc)
            six.reraise(TemplateSyntaxError, new, sys.exc_info()[2])
Exemple #6
0
        if current.value in self.exclude:
            raise InvalidArgument(self, current.value, self.tagname)

        try:
            if self.resolve:
                return self.expr_parser.parse(stream, parser)
            else:
                result = StaticValue(current.value)
                next(stream)
                return result
        except TemplateSyntaxError, e:
            raise
        except Warning, w:
            raise
        except Exception, e:
            raise TemplateSyntaxError(
                "Argument unable to process token '%s'." % current.value)

    def get_value(self, parser, stream, nextargs=None):
        name, value = self.name, self.clean_token(parser, stream)
        return name, self.value_class(value)

    def set_value(self, name, value, container):
        if name is not None:
            if name in container.tag_kwargs:
                raise KeywordInUse(name, self.tagname)

            container.tag_kwargs[str(name)] = value

        elif isinstance(value, (list, tuple)):
            [args.append(item) for item in value]
Exemple #7
0
def media_map2gis(parser, token):
    bits = token.split_contents()
    if len(bits) != 1:
        raise TemplateSyntaxError(_("Error token tag \"media_map2gis\""))
    return MediaMap2GisNode()
def regroup(parser, token):
    """
    Regroups a list of alike objects by a common attribute.

    This complex tag is best illustrated by use of an example:  say that
    ``people`` is a list of ``Person`` objects that have ``first_name``,
    ``last_name``, and ``gender`` attributes, and you'd like to display a list
    that looks like:

        * Male:
            * George Bush
            * Bill Clinton
        * Female:
            * Margaret Thatcher
            * Colendeeza Rice
        * Unknown:
            * Pat Smith

    The following snippet of template code would accomplish this dubious task::

        {% regroup people by gender as grouped %}
        <ul>
        {% for group in grouped %}
            <li>{{ group.grouper }}
            <ul>
                {% for item in group.list %}
                <li>{{ item }}</li>
                {% endfor %}
            </ul>
        {% endfor %}
        </ul>

    As you can see, ``{% regroup %}`` populates a variable with a list of
    objects with ``grouper`` and ``list`` attributes.  ``grouper`` contains the
    item that was grouped by; ``list`` contains the list of objects that share
    that ``grouper``.  In this case, ``grouper`` would be ``Male``, ``Female``
    and ``Unknown``, and ``list`` is the list of people with those genders.

    Note that `{% regroup %}`` does not work when the list to be grouped is not
    sorted by the key you are grouping by!  This means that if your list of
    people was not sorted by gender, you'd need to make sure it is sorted
    before using it, i.e.::

        {% regroup people|dictsort:"gender" by gender as grouped %}

    """
    firstbits = token.contents.split(None, 3)
    if len(firstbits) != 4:
        raise TemplateSyntaxError, "'regroup' tag takes five arguments"
    target = parser.compile_filter(firstbits[1])
    if firstbits[2] != 'by':
        raise TemplateSyntaxError("second argument to 'regroup' tag must be 'by'")
    lastbits_reversed = firstbits[3][::-1].split(None, 2)
    if lastbits_reversed[1][::-1] != 'as':
        raise TemplateSyntaxError("next-to-last argument to 'regroup' tag must"
                                  " be 'as'")

    expression = parser.compile_filter(lastbits_reversed[2][::-1])

    var_name = lastbits_reversed[0][::-1]
    return RegroupNode(target, expression, var_name)
def cycle(parser, token):
    """
    Cycles among the given strings each time this tag is encountered.

    Within a loop, cycles among the given strings each time through
    the loop::

        {% for o in some_list %}
            <tr class="{% cycle 'row1' 'row2' %}">
                ...
            </tr>
        {% endfor %}

    Outside of a loop, give the values a unique name the first time you call
    it, then use that name each sucessive time through::

            <tr class="{% cycle 'row1' 'row2' 'row3' as rowcolors %}">...</tr>
            <tr class="{% cycle rowcolors %}">...</tr>
            <tr class="{% cycle rowcolors %}">...</tr>

    You can use any number of values, seperated by spaces. Commas can also
    be used to separate values; if a comma is used, the cycle values are
    interpreted as literal strings.
    """

    # Note: This returns the exact same node on each {% cycle name %} call;
    # that is, the node object returned from {% cycle a b c as name %} and the
    # one returned from {% cycle name %} are the exact same object.  This
    # shouldn't cause problems (heh), but if it does, now you know.
    #
    # Ugly hack warning: this stuffs the named template dict into parser so
    # that names are only unique within each template (as opposed to using
    # a global variable, which would make cycle names have to be unique across
    # *all* templates.

    args = token.split_contents()

    if len(args) < 2:
        raise TemplateSyntaxError("'cycle' tag requires at least two arguments")

    if ',' in args[1]:
        # Backwards compatibility: {% cycle a,b %} or {% cycle a,b as foo %}
        # case.
        args[1:2] = ['"%s"' % arg for arg in args[1].split(",")]

    if len(args) == 2:
        # {% cycle foo %} case.
        name = args[1]
        if not hasattr(parser, '_namedCycleNodes'):
            raise TemplateSyntaxError("No named cycles in template."
                                      " '%s' is not defined" % name)
        if not name in parser._namedCycleNodes:
            raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)
        return parser._namedCycleNodes[name]

    if len(args) > 4 and args[-2] == 'as':
        name = args[-1]
        node = CycleNode(args[1:-2], name)
        if not hasattr(parser, '_namedCycleNodes'):
            parser._namedCycleNodes = {}
        parser._namedCycleNodes[name] = node
    else:
        node = CycleNode(args[1:])
    return node
def get_imgix(image_url, alias=None, wh=None, **kwargs):

    try:
        domains = settings.IMGIX_DOMAINS
    except:
        raise ImproperlyConfigured(
            "IMGIX_DOMAINS not set in settings.py"
        )

    ### Build arguments
    args = {}

    # Get arguments from settings
    shard_strategy, sign_key, use_https, aliases,\
        format_detect, web_proxy = get_settings_variables()

    args['use_https'] = use_https

    if sign_key:
        args['sign_key'] = sign_key

    if shard_strategy:
        args['shard_strategy'] = shard_strategy

    # Imgix by default appends ?ixlib=python-<version_number> to the end
    # of the URL, but we don't want that.
    args['sign_with_library_version'] = False

    # Get builder instance
    builder = imgix.UrlBuilder(
        domains,
        **args
    )

    # Has the wh argument been passed? If yes,
    # set w and h arguments accordingly
    if wh:
        size = wh
        if isinstance(size, six.string_types):
            m = WH_PATTERN.match(size)
            if m:
                w = int(m.group(1))
                h = int(m.group(2))
                if w > 0:
                    kwargs['w'] = int(m.group(1))
                if h > 0:
                    kwargs['h'] = int(m.group(2))
            else:
                raise TemplateSyntaxError(
                    "%r is not a valid size." % size
                )

    # Is format detection on? If yes, use the appropriate image format.

    arguments = get_kwargs(alias, aliases, kwargs)

    if format_detect and 'fm' not in arguments:
        fm = get_fm(image_url)
        if fm:
            arguments['fm'] = fm

    # Take only the relative path of the URL if the source is not a Web Proxy Source
    if not web_proxy:
        image_url = urlparse(image_url).path

    # URLs should append an 'ixlib=django-<version_number>' parameter
    arguments['ixlib'] = "django-" + __version__

    # Build the imgix URL
    url = builder.create_url(image_url, arguments)
    return mark_safe(url)
Exemple #11
0
def thumbnail(parser, token):
    """
    Creates a thumbnail of for an ImageField.

    To just output the absolute url to the thumbnail::

        {% thumbnail image 80x80 %}

    After the image path and dimensions, you can put any options::

        {% thumbnail image 80x80 quality=95 crop %}

    To put the DjangoThumbnail class on the context instead of just rendering
    the absolute url, finish the tag with ``as [context_var_name]``::

        {% thumbnail image 80x80 as thumb %}
        {{ thumb.width }} x {{ thumb.height }}
    """
    args = token.split_contents()
    tag = args[0]
    # Check to see if we're setting to a context variable.
    if len(args) > 4 and args[-2] == 'as':
        context_name = args[-1]
        args = args[:-2]
    else:
        context_name = None

    if len(args) < 3:
        raise TemplateSyntaxError("Invalid syntax. Expected "
            "'{%% %s source size [option1 option2 ...] %%}' or "
            "'{%% %s source size [option1 option2 ...] as variable %%}'" %
            (tag, tag))

    # Get the source image path and requested size.
    source_var = parser.compile_filter(args[1])
    # If the size argument was a correct static format, wrap it in quotes so
    # that it is compiled correctly.
    m = size_pat.match(args[2])
    if m:
        args[2] = '"%s"' % args[2]
    size_var = parser.compile_filter(args[2])

    # Get the options.
    args_list = split_args(args[3:]).items()

    # Check the options.
    opts = {}
    kwargs = {} # key,values here override settings and defaults

    for arg, value in args_list:
        value = value and parser.compile_filter(value)
        if arg in TAG_SETTINGS and value is not None:
            kwargs[str(arg)] = value
            continue
        if arg in VALID_OPTIONS:
            opts[arg] = value
        else:
            raise TemplateSyntaxError("'%s' tag received a bad argument: "
                                      "'%s'" % (tag, arg))
    return ThumbnailNode(source_var, size_var, opts=opts,
                         context_name=context_name, **kwargs)
Exemple #12
0
def do_block_translate(parser, token):
    """
    This will translate a block of text with parameters.

    Usage::

        {% blocktrans with bar=foo|filter boo=baz|filter %}
        This is {{ bar }} and {{ boo }}.
        {% endblocktrans %}

    Additionally, this supports pluralization::

        {% blocktrans count count=var|length %}
        There is {{ count }} object.
        {% plural %}
        There are {{ count }} objects.
        {% endblocktrans %}

    This is much like ngettext, only in template syntax.

    The "var as value" legacy format is still supported::

        {% blocktrans with foo|filter as bar and baz|filter as boo %}
        {% blocktrans count var|length as count %}

    Contextual translations are supported::

        {% blocktrans with bar=foo|filter context "greeting" %}
            This is {{ bar }}.
        {% endblocktrans %}

    This is equivalent to calling pgettext/npgettext instead of
    (u)gettext/(u)ngettext.
    """
    bits = token.split_contents()

    options = {}
    remaining_bits = bits[1:]
    while remaining_bits:
        option = remaining_bits.pop(0)
        if option in options:
            raise TemplateSyntaxError('The %r option was specified more '
                                      'than once.' % option)
        if option == 'with':
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if not value:
                raise TemplateSyntaxError('"with" in %r tag needs at least '
                                          'one keyword argument.' % bits[0])
        elif option == 'count':
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if len(value) != 1:
                raise TemplateSyntaxError('"count" in %r tag expected exactly '
                                          'one keyword argument.' % bits[0])
        elif option == "context":
            try:
                value = remaining_bits.pop(0)
                value = parser.compile_filter(value)
            except Exception:
                msg = (
                    '"context" in %r tag expected '
                    'exactly one argument.') % bits[0]
                six.reraise(TemplateSyntaxError, TemplateSyntaxError(msg), sys.exc_info()[2])
        else:
            raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
                                      (bits[0], option))
        options[option] = value

    if 'count' in options:
        countervar, counter = list(six.iteritems(options['count']))[0]
    else:
        countervar, counter = None, None
    if 'context' in options:
        message_context = options['context']
    else:
        message_context = None
    extra_context = options.get('with', {})

    singular = []
    plural = []
    while parser.tokens:
        token = parser.next_token()
        if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
            singular.append(token)
        else:
            break
    if countervar and counter:
        if token.contents.strip() != 'plural':
            raise TemplateSyntaxError("'blocktrans' doesn't allow other block tags inside it")
        while parser.tokens:
            token = parser.next_token()
            if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
                plural.append(token)
            else:
                break
    if token.contents.strip() != 'endblocktrans':
        raise TemplateSyntaxError("'blocktrans' doesn't allow other block tags (seen %r) inside it" % token.contents)

    return BlockTranslateNode(extra_context, singular, plural, countervar,
            counter, message_context)
    def render(self, context):
        try:
            # This evaluates to a ImageWithThumbsField, as long as the
            # user specified a valid model field.
            relative_source = Variable(self.source_var).resolve(context)
        except VariableDoesNotExist:
            if settings.TEMPLATE_DEBUG:
                raise VariableDoesNotExist("Variable '%s' does not exist." %
                                           self.source_var)
            else:
                relative_source = None

        try:
            requested_name = Variable(self.thumb_name_var).resolve(context)
        except VariableDoesNotExist:
            if settings.TEMPLATE_DEBUG:
                raise TemplateSyntaxError(
                    "Name argument '%s' is not a valid thumbnail." %
                    self.thumb_name_var)
            else:
                requested_name = None

        if relative_source is None or requested_name is None:
            # Couldn't resolve the given template variable. Fail silently.
            thumbnail = ''
        else:
            # Spaces at the end of sizes is just not OK.
            requested_name = requested_name.strip()
            # This is typically a athumb.fields.ImageWithThumbsFieldFile object.
            try:
                # Allow the user to override the protocol in the tag.
                force_ssl = self.kwargs.get('force_ssl', False)
                # Try to detect SSL mode in the request context. Front-facing
                # server or proxy must be passing the correct headers for
                # this to work. Also, factor in force_ssl.
                ssl_mode = self.is_secure(context) or force_ssl
                # Get the URL for the thumbnail from the
                # ImageWithThumbsFieldFile object.
                try:
                    thumbnail = relative_source.generate_url(requested_name,
                                                             ssl_mode=ssl_mode)
                except:
                    #import traceback
                    #traceback.print_stack()
                    print(
                        "ERROR: Using {% thumbnail %} tag with "
                        "a regular ImageField instead of ImageWithThumbsField:",
                        self.source_var)
                    return ''
            except ValueError:
                # This file object doesn't actually have a file. Probably
                # model field with a None value.
                thumbnail = ''

        # Return the thumbnail class, or put it on the context
        if self.context_name is None:
            return thumbnail

        # We need to get here so we don't have old values in the context
        # variable.
        context[self.context_name] = thumbnail

        return ''
Exemple #14
0
 def source_error(self, source, msg):
     e = TemplateSyntaxError(msg)
     e.source = source
     return e
Exemple #15
0
 def get_setting(*args):
     try:
         return getattr(settings, args[0])
     except AttributeError as e:
         raise TemplateSyntaxError(str(e))
Exemple #16
0
def get_rss(parser, token):
    """
    Take an RSS feed so you can iterate through the entries.

    Usage::

        {% get_rss [rss_feed_url] as [variable] cache=600 %}

    Options include:

        ``cache``
           The length of time to cache the feed in seconds. **Default: 300**

    Example 1::

        {% get_rss "http://www.freesound.org/blog/?feed=rss2" as rss %}
        {% for entry in rss.entries %}
            <h1>{{entry.title}}</h1>
            <p>
                {{entry.summary|safe}}
            </p>
            <p>
                <a href="{{entry.link}}">read more...</a>
            </p>
        {% endfor %}


    Example 2::

        {% get_rss "http://rss.nytimes.com/services/xml/rss/nyt/PersonalTech.xml" as rss %}
        {% if rss.feed.image %}
            <img src="{{ rss.feed.image.href }}" alt="" />
        {% endif %}
        {% for entry in rss.entries %}
        <div class="row entry-item">

             <div class="col-xs-4 col-md-3">
             {# media image #}
              {% if entry.media_content %}
                  {% for media in entry.media_content %}
                      {% if media.medium == 'image' %}
                      <img src="{{ media.url }}" width="{{ media.width }}" height="{{ media.height }}" alt="" />
                      {% endif %}
                  {% endfor %}
              {% endif %}
               </div>

              <div class="col-xs-8 col-md-9">
                  {# title #}
                  <h4 class="entry-title"><a href="{{ entry.link }}">{{entry.title}}</a></h4>

                  {# pubdate #}
                  <div class="small">Published on: {{entry.published}}</div>

                  {# authors #}
                  {% if entry.authors %}
                      <div class="small">Author{{ entry.authors|pluralize }}:
                      {% for author in entry.authors %}
                          {{ author.name }}
                    {% endfor %}
                      </div>
                {% endif %}

                {# categories #}
                {% if entry.tags %}
                      <div class="small">Categories:
                      {% for tag in entry.tags %}
                          {% if tag.scheme  %}
                          <a href="{{ tag.scheme }}">{{ tag.term }}</a>
                          {% else  %}
                          {{ tag.term }}
                          {% endif %}
                    {% endfor %}
                      </div>
                {% endif %}

                {# description #}
                {% if entry.content %}
                  {% for content in entry.content %}
                      <div>{{ content.value|safe }}</div>
                  {% endfor %}
                {% elif entry.summary %}
                  <div>{{ entry.summary|safe }}</div>
                {% endif %}

                {# enclosure #}
                {% if entry.links %}
                  {% for link in entry.links %}
                      {% if link.rel == 'enclosure' %}
                      <div>
                       <audio controls>
                          <source src="{{ link.href }}" type="{{ link.type }}">
                        </audio>
                        {{ link.length|filesizeformat }}
                        </div>
                      {% endif %}
                  {% endfor %}
                {% endif %}

              <a href="{{entry.link}}">read more...</a>
           </div>

        </div>
        {% endfor %}



    """
    args, kwargs = [], {}
    bits = token.split_contents()
    url_string = bits[1]
    context_var = bits[3]

    if len(bits) < 4:
        message = "'%s' tag requires more than 3" % bits[0]
        raise TemplateSyntaxError(_(message))

    if bits[2] != "as":
        message = "'%s' third argument must be 'as" % bits[0]
        raise TemplateSyntaxError(_(message))

    kwargs = parse_tag_kwargs(bits)

    if url_string[0] == url_string[-1] and url_string[0] in ('"', "'"):
        url = url_string[1:-1]
    else:
        url = url_string

    return RssParserNode(context_var, url, *args, **kwargs)
Exemple #17
0
 def __mod__(self, other):
     raise TemplateSyntaxError(_('Undefined variable: "%s"') % other)
Exemple #18
0
def do_tag_cloud_for_model(parser, token):
    """
    Retrieves a list of ``Tag`` objects for a given model, with tag
    cloud attributes set, and stores them in a context variable.

    Usage::

       {% tag_cloud_for_model [model] as [varname] %}

    The model is specified in ``[appname].[modelname]`` format.

    Extended usage::

       {% tag_cloud_for_model [model] as [varname] with [options] %}

    Extra options can be provided after an optional ``with`` argument,
    with each option being specified in ``[name]=[value]`` format. Valid
    extra options are:

       ``steps``
          Integer. Defines the range of font sizes.

       ``min_count``
          Integer. Defines the minimum number of times a tag must have
          been used to appear in the cloud.

       ``distribution``
          One of ``linear`` or ``log``. Defines the font-size
          distribution algorithm to use when generating the tag cloud.

    Examples::

       {% tag_cloud_for_model products.Widget as widget_tags %}
       {% tag_cloud_for_model products.Widget as widget_tags with steps=9 min_count=3 distribution=log %}

    """
    bits = token.contents.split()
    len_bits = len(bits)
    if len_bits != 4 and len_bits not in range(6, 9):
        raise TemplateSyntaxError(
            _('%s tag requires either three or between five and seven arguments'
              ) % bits[0])
    if bits[2] != 'as':
        raise TemplateSyntaxError(
            _("second argument to %s tag must be 'as'") % bits[0])
    kwargs = {}
    if len_bits > 5:
        if bits[4] != 'with':
            raise TemplateSyntaxError(
                _("if given, fourth argument to %s tag must be 'with'") %
                bits[0])
        for i in range(5, len_bits):
            try:
                name, value = bits[i].split('=')
                if name == 'steps' or name == 'min_count':
                    try:
                        kwargs[str(name)] = int(value)
                    except ValueError:
                        raise TemplateSyntaxError(
                            _("%(tag)s tag's '%(option)s' option was not a valid integer: '%(value)s'"
                              ) % {
                                  'tag': bits[0],
                                  'option': name,
                                  'value': value,
                              })
                elif name == 'distribution':
                    if value in ['linear', 'log']:
                        kwargs[str(name)] = {
                            'linear': LINEAR,
                            'log': LOGARITHMIC
                        }[value]
                    else:
                        raise TemplateSyntaxError(
                            _("%(tag)s tag's '%(option)s' option was not a valid choice: '%(value)s'"
                              ) % {
                                  'tag': bits[0],
                                  'option': name,
                                  'value': value,
                              })
                else:
                    raise TemplateSyntaxError(
                        _("%(tag)s tag was given an invalid option: '%(option)s'"
                          ) % {
                              'tag': bits[0],
                              'option': name,
                          })
            except ValueError:
                raise TemplateSyntaxError(
                    _("%(tag)s tag was given a badly formatted option: '%(option)s'"
                      ) % {
                          'tag': bits[0],
                          'option': bits[i],
                      })
    return TagCloudForModelNode(bits[1], bits[3], **kwargs)
Exemple #19
0
def _scan_nodes(nodelist,
                context,
                instance_types,
                current_block=None,
                ignore_blocks=None):
    """
    Loop through all nodes of a single scope level.

    :type nodelist: django.template.base.NodeList
    :type current_block: BlockNode
    :param instance_types: The instance to look for
    """
    results = []
    for node in nodelist:
        # first check if this is the object instance to look for.
        if isinstance(node, instance_types):
            results.append(node)
            # if it's a Constant Include Node ({% include "template_name.html" %})
        # scan the child template
        elif isinstance(node, IncludeNode):
            # if there's an error in the to-be-included template, node.template becomes None
            if node.template:
                # This is required for Django 1.7 but works on older version too
                # Check if it quacks like a template object, if not
                # presume is a template path and get the object out of it
                if not callable(getattr(node.template, 'render', None)):
                    template = get_template(node.template.var)
                else:
                    template = node.template

                if TemplateAdapter is not None and isinstance(
                        template, TemplateAdapter):
                    # Django 1.8: received a new object, take original template
                    template = template.template

                results += _scan_nodes(template.nodelist, context,
                                       instance_types, current_block)
        # handle {% extends ... %} tags
        elif isinstance(node, ExtendsNode):
            results += _extend_nodelist(node, context, instance_types)
        # in block nodes we have to scan for super blocks
        elif isinstance(node, VariableNode) and current_block:
            if node.filter_expression.token == 'block.super':
                # Found a {{ block.super }} line
                if not hasattr(current_block.parent, 'nodelist'):
                    raise TemplateSyntaxError(
                        "Cannot read {{{{ block.super }}}} for {{% block {0} %}}, "
                        "the parent template doesn't have this block.".format(
                            current_block.name))
                results += _scan_nodes(current_block.parent.nodelist, context,
                                       instance_types, current_block.parent)
        # ignore nested blocks which are already handled
        elif isinstance(
                node,
                BlockNode) and ignore_blocks and node.name in ignore_blocks:
            continue
        # if the node has the newly introduced 'child_nodelists' attribute, scan
        # those attributes for nodelists and recurse them
        elif hasattr(node, 'child_nodelists'):
            for nodelist_name in node.child_nodelists:
                if hasattr(node, nodelist_name):
                    subnodelist = getattr(node, nodelist_name)
                    if isinstance(subnodelist, NodeList):
                        if isinstance(node, BlockNode):
                            current_block = node
                        results += _scan_nodes(subnodelist, context,
                                               instance_types, current_block)
        # else just scan the node for nodelist instance attributes
        else:
            for attr in dir(node):
                obj = getattr(node, attr)
                if isinstance(obj, NodeList):
                    if isinstance(node, BlockNode):
                        current_block = node
                    results += _scan_nodes(obj, context, instance_types,
                                           current_block)
    return results
Exemple #20
0
def parse_bits(parser, bits, params, varargs, varkw, defaults,
               takes_context, name):
    """
    Parses bits for template tag helpers (simple_tag, include_tag and
    assignment_tag), in particular by detecting syntax errors and by
    extracting positional and keyword arguments.
    """
    if takes_context:
        if params[0] == 'context':
            params = params[1:]
        else:
            raise TemplateSyntaxError(
                "'%s' is decorated with takes_context=True so it must "
                "have a first argument of 'context'" % name)
    args = []
    kwargs = {}
    unhandled_params = list(params)
    for bit in bits:
        # First we try to extract a potential kwarg from the bit
        kwarg = token_kwargs([bit], parser)
        if kwarg:
            # The kwarg was successfully extracted
            param, value = kwarg.items()[0]
            if param not in params and varkw is None:
                # An unexpected keyword argument was supplied
                raise TemplateSyntaxError(
                    "'%s' received unexpected keyword argument '%s'" %
                    (name, param))
            elif param in kwargs:
                # The keyword argument has already been supplied once
                raise TemplateSyntaxError(
                    "'%s' received multiple values for keyword argument '%s'" %
                    (name, param))
            else:
                # All good, record the keyword argument
                kwargs[str(param)] = value
                if param in unhandled_params:
                    # If using the keyword syntax for a positional arg, then
                    # consume it.
                    unhandled_params.remove(param)
        else:
            if kwargs:
                raise TemplateSyntaxError(
                    "'%s' received some positional argument(s) after some "
                    "keyword argument(s)" % name)
            else:
                # Record the positional argument
                args.append(parser.compile_filter(bit))
                try:
                    # Consume from the list of expected positional arguments
                    unhandled_params.pop(0)
                except IndexError:
                    if varargs is None:
                        raise TemplateSyntaxError(
                            "'%s' received too many positional arguments" %
                            name)
    if defaults is not None:
        # Consider the last n params handled, where n is the
        # number of defaults.
        unhandled_params = unhandled_params[:-len(defaults)]
    if unhandled_params:
        # Some positional arguments were not supplied
        raise TemplateSyntaxError(
            u"'%s' did not receive value(s) for the argument(s): %s" %
            (name, u", ".join([u"'%s'" % p for p in unhandled_params])))
    return args, kwargs
def _validate_no_args(token):
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
Exemple #22
0
def date(parse, token):
    try:
        tagname, format_string = token.split_contents()
    except ValueError:
        raise TemplateSyntaxError('invalid args')
    return DateNode(eval(format_string))
Exemple #23
0
def get_news_list(parser, token):
    bits = list(token.split_contents())
    if len(bits) != 1:
        raise TemplateSyntaxError("%r take > 1 argument" % bits[0])
    return GetNewsListNode()
Exemple #24
0
def thumbnail(parser, token):
    """
    Creates a thumbnail of an ImageField.

    Basic tag Syntax::

        {% thumbnail [source] [size] [options] %}

    *source* must be a ``File`` object, usually an Image/FileField of a model
    instance.

    *size* can either be:

    * the name of an alias

    * the size in the format ``[width]x[height]`` (for example,
      ``{% thumbnail person.photo 100x50 %}``) or

    * a variable containing a valid size (i.e. either a string in the
      ``[width]x[height]`` format or a tuple containing two integers):
      ``{% thumbnail person.photo size_var %}``.

    *options* are a space separated list of options which are used when
    processing the image to a thumbnail such as ``sharpen``, ``crop`` and
    ``quality=90``.

    If *size* is specified as an alias name, *options* are used to override
    and/or supplement the options defined in that alias.

    The thumbnail tag can also place a
    :class:`~easy_thumbnails.files.ThumbnailFile` object in the context,
    providing access to the properties of the thumbnail such as the height and
    width::

        {% thumbnail [source] [size] [options] as [variable] %}

    When ``as [variable]`` is used, the tag doesn't output anything. Instead,
    use the variable like a standard ``ImageFieldFile`` object::

        {% thumbnail obj.picture 200x200 upscale as thumb %}
        <img src="{{ thumb.url }}"
             width="{{ thumb.width }}"
             height="{{ thumb.height }}" />

    **Debugging**

    By default, if there is an error creating the thumbnail or resolving the
    image variable then the thumbnail tag will just return an empty string (and
    if there was a context variable to be set then it will also be set to an
    empty string).

    For example, you will not see an error if the thumbnail could not
    be written to directory because of permissions error. To display those
    errors rather than failing silently, set ``THUMBNAIL_DEBUG = True`` in
    your Django project's settings module.

    """
    args = token.split_contents()
    tag = args[0]

    # Check to see if we're setting to a context variable.
    if len(args) > 4 and args[-2] == 'as':
        context_name = args[-1]
        args = args[:-2]
    else:
        context_name = None

    if len(args) < 3:
        raise TemplateSyntaxError(
            "Invalid syntax. Expected "
            "'{%% %s source size [option1 option2 ...] %%}' or "
            "'{%% %s source size [option1 option2 ...] as variable %%}'" %
            (tag, tag))

    opts = {}

    # The first argument is the source file.
    source_var = parser.compile_filter(args[1])

    # The second argument is the requested size. If it's the static "10x10"
    # format, wrap it in quotes so that it is compiled correctly.
    size = args[2]
    match = RE_SIZE.match(size)
    if match:
        size = '"%s"' % size
    opts['size'] = parser.compile_filter(size)

    # All further arguments are options.
    args_list = split_args(args[3:]).items()
    for arg, value in args_list:
        if arg in VALID_OPTIONS:
            if value and value is not True:
                value = parser.compile_filter(value)
            opts[arg] = value
        else:
            raise TemplateSyntaxError("'%s' tag received a bad argument: "
                                      "'%s'" % (tag, arg))
    return ThumbnailNode(source_var, opts=opts, context_name=context_name)
Exemple #25
0
class Page(models.Model):

    path = models.CharField(max_length=255, db_index=True)
    template = models.ForeignKey(Template, related_name='pages')
    is_published = models.BooleanField(default=False)

    title = models.CharField(max_length=255)
    content = MarkupField()

    tags = TaggableManager(blank=True)

    class Meta:
        ordering = ('path', )

    def __unicode__(self):
        return self.path

    def get_absolute_url(self):
        return self.path

    @property
    def cache_key(self):
        return 'pages.page.%s' % self.path

    def blocks_as_template_string(self):
        return "\n".join(
            [block.as_template_string() for block in self.blocks.all()])

    def as_template_string(self):
        cached = cache.get(self.cache_key)
        if cached:
            return cached
        base_template = getattr(settings, 'PAGES_BASE_TEMPLATE',
                                DEFAULT_BASE_TEMPLATE)
        ctx = {
            "template": self.template.loadable_name,
            "title": self.title,
            "blocks": self.blocks_as_template_string(),
            "content": self.content.rendered,
        }
        template_string = base_template.lstrip("\r\n\t").format(**ctx).replace(
            "%%", '%')
        cache.set(self.cache_key, template_string)
        return template_string

    def as_renderable(self):
        renderable = None
        tries = 0
        template_string = self.as_template_string()
        while renderable is None and tries < 100:
            try:
                renderable = get_template_from_string(template_string)
            except TemplateSyntaxError, e:
                tries += 1
                # This overrides blocks defined in the render template with
                # block objects, if there are multiples
                # FIXME: Find a better way to do this than catching the block name from exception messages
                match_obj = re.match(
                    r"'block' tag with name '(.+)' appears more than once",
                    e.message)
                if match_obj:
                    dupe_block = match_obj.groups()[0]
                    template_string = re.sub(
                        r'{%% block %s %%}.+{%% endblock( %s)? %%}' %
                        (dupe_block, dupe_block),
                        '',
                        template_string,
                        count=1,
                        flags=re.MULTILINE)
                else:
                    raise
        if renderable is None:
            raise TemplateSyntaxError('''The Pages app tried and failed to
                remove duplicate blocks from your template. Take a look
                at settings.PAGES_BASE_TEMPLATE''')
        return renderable
Exemple #26
0
    def render(self, context):
        # Note that this isn't a global constant because we need to change the
        # value for tests.
        raise_errors = settings.THUMBNAIL_DEBUG
        # Get the source file.
        try:
            source = self.source_var.resolve(context)
        except VariableDoesNotExist:
            if raise_errors:
                raise VariableDoesNotExist("Variable '%s' does not exist." %
                                           self.source_var)
            return self.bail_out(context)
        if not source:
            if raise_errors:
                raise TemplateSyntaxError(
                    "Variable '%s' is an invalid source." % self.source_var)
            return self.bail_out(context)
        # Resolve the thumbnail option values.
        try:
            opts = {}
            for key, value in self.opts.items():
                if hasattr(value, 'resolve'):
                    value = value.resolve(context)
                opts[str(key)] = value
        except Exception:
            if raise_errors:
                raise
            return self.bail_out(context)
        # Size variable can be either a tuple/list of two integers or a
        # valid string.
        size = opts['size']
        if isinstance(size, str):
            m = RE_SIZE.match(size)
            if m:
                opts['size'] = (int(m.group(1)), int(m.group(2)))
            else:
                # Size variable may alternatively be referencing an alias.
                alias = aliases.get(size, target=source)
                if alias:
                    del opts['size']
                    opts = dict(alias, **opts)
                else:
                    if raise_errors:
                        raise TemplateSyntaxError("%r is not a valid size." %
                                                  size)
                    return self.bail_out(context)
        # Ensure the quality is an integer.
        if 'quality' in opts:
            try:
                opts['quality'] = int(opts['quality'])
            except (TypeError, ValueError):
                if raise_errors:
                    raise TemplateSyntaxError("%r is an invalid quality." %
                                              opts['quality'])
                return self.bail_out(context)
        # Ensure the subsampling level is an integer.
        if 'subsampling' in opts:
            try:
                opts['subsampling'] = int(opts['subsampling'])
            except (TypeError, ValueError):
                if raise_errors:
                    raise TemplateSyntaxError(
                        "%r is an invalid subsampling level." %
                        opts['subsampling'])
                return self.bail_out(context)

        try:
            bits = False
            if settings.THUMBNAIL_PREVENT_GIF_CONVERT:
                bits = os.path.splitext(getattr(source, 'url', source.name))
            if bits and bits[1] == '.gif':
                thumbnail = source
            else:
                thumbnail = get_thumbnailer(source).get_thumbnail(opts)
        except Exception:
            if raise_errors:
                raise
            return self.bail_out(context)
        # Return the thumbnail file url, or put the file on the context.
        if self.context_name is None:
            return escape(thumbnail.url)
        else:
            context[self.context_name] = thumbnail
            return ''
Exemple #27
0
def cycle(parser, token):
    """
    Cycle among the given strings each time this tag is encountered

    Within a loop, cycles among the given strings each time through
    the loop::

        {% for o in some_list %}
            <tr class="{% cycle row1,row2 %}">
                ...
            </tr>
        {% endfor %}

    Outside of a loop, give the values a unique name the first time you call
    it, then use that name each sucessive time through::

            <tr class="{% cycle row1,row2,row3 as rowcolors %}">...</tr>
            <tr class="{% cycle rowcolors %}">...</tr>
            <tr class="{% cycle rowcolors %}">...</tr>

    You can use any number of values, seperated by commas. Make sure not to
    put spaces between the values -- only commas.
    """

    # Note: This returns the exact same node on each {% cycle name %} call; that
    # is, the node object returned from {% cycle a,b,c as name %} and the one
    # returned from {% cycle name %} are the exact same object.  This shouldn't
    # cause problems (heh), but if it does, now you know.
    #
    # Ugly hack warning: this stuffs the named template dict into parser so
    # that names are only unique within each template (as opposed to using
    # a global variable, which would make cycle names have to be unique across
    # *all* templates.

    args = token.contents.split()
    if len(args) < 2:
        raise TemplateSyntaxError(
            "'Cycle' statement requires at least two arguments")

    elif len(args) == 2 and "," in args[1]:
        # {% cycle a,b,c %}
        cyclevars = [v for v in args[1].split(",")
                     if v]  # split and kill blanks
        return CycleNode(cyclevars)
        # {% cycle name %}

    elif len(args) == 2:
        name = args[1]
        if not hasattr(parser, '_namedCycleNodes'):
            raise TemplateSyntaxError(
                "No named cycles in template: '%s' is not defined" % name)
        if not parser._namedCycleNodes.has_key(name):
            raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)
        return parser._namedCycleNodes[name]

    elif len(args) == 4:
        # {% cycle a,b,c as name %}
        if args[2] != 'as':
            raise TemplateSyntaxError("Second 'cycle' argument must be 'as'")
        cyclevars = [v for v in args[1].split(",")
                     if v]  # split and kill blanks
        name = args[3]
        node = CycleNode(cyclevars, name)

        if not hasattr(parser, '_namedCycleNodes'):
            parser._namedCycleNodes = {}

        parser._namedCycleNodes[name] = node
        return node

    else:
        raise TemplateSyntaxError("Invalid arguments to 'cycle': %s" % args)
Exemple #28
0
def do_translate(parser, token):
    """
    This will mark a string for translation and will
    translate the string for the current language.

    Usage::

        {% trans "this is a test" %}

    This will mark the string for translation so it will
    be pulled out by mark-messages.py into the .po files
    and will run the string through the translation engine.

    There is a second form::

        {% trans "this is a test" noop %}

    This will only mark for translation, but will return
    the string unchanged. Use it when you need to store
    values into forms that should be translated later on.

    You can use variables instead of constant strings
    to translate stuff you marked somewhere else::

        {% trans variable %}

    This will just try to translate the contents of
    the variable ``variable``. Make sure that the string
    in there is something that is in the .po file.

    It is possible to store the translated string into a variable::

        {% trans "this is a test" as var %}
        {{ var }}

    Contextual translations are also supported::

        {% trans "this is a test" context "greeting" %}

    This is equivalent to calling pgettext instead of (u)gettext.
    """
    bits = token.split_contents()
    if len(bits) < 2:
        raise TemplateSyntaxError("'%s' takes at least one argument" % bits[0])
    message_string = parser.compile_filter(bits[1])
    remaining = bits[2:]

    noop = False
    asvar = None
    message_context = None
    seen = set()
    invalid_context = {'as', 'noop'}

    while remaining:
        option = remaining.pop(0)
        if option in seen:
            raise TemplateSyntaxError(
                "The '%s' option was specified more than once." % option,
            )
        elif option == 'noop':
            noop = True
        elif option == 'context':
            try:
                value = remaining.pop(0)
            except IndexError:
                raise TemplateSyntaxError(
                    "No argument provided to the '%s' tag for the context option." % bits[0]
                )
            if value in invalid_context:
                raise TemplateSyntaxError(
                    "Invalid argument '%s' provided to the '%s' tag for the context option" % (value, bits[0]),
                )
            message_context = parser.compile_filter(value)
        elif option == 'as':
            try:
                value = remaining.pop(0)
            except IndexError:
                raise TemplateSyntaxError(
                    "No argument provided to the '%s' tag for the as option." % bits[0]
                )
            asvar = value
        else:
            raise TemplateSyntaxError(
                "Unknown argument for '%s' tag: '%s'. The only options "
                "available are 'noop', 'context' \"xxx\", and 'as VAR'." % (
                    bits[0], option,
                )
            )
        seen.add(option)

    return TranslateNode(message_string, noop, asvar, message_context)
def do_if(parser, token):
    """
    The ``{% if %}`` tag evaluates a variable, and if that variable is "true"
    (i.e. exists, is not empty, and is not a false boolean value) the contents
    of the block are output::

        {% if athlete_list %}
            Number of athletes: {{ athlete_list|count }}
        {% else %}
            No athletes.
        {% endif %}

    In the above, if ``athlete_list`` is not empty, the number of athletes will
    be displayed by the ``{{ athlete_list|count }}`` variable.

    As you can see, the ``if`` tag can take an option ``{% else %}`` clause
    that will be displayed if the test fails.

    ``if`` tags may use ``or``, ``and`` or ``not`` to test a number of
    variables or to negate a given variable::

        {% if not athlete_list %}
            There are no athletes.
        {% endif %}

        {% if athlete_list or coach_list %}
            There are some athletes or some coaches.
        {% endif %}

        {% if athlete_list and coach_list %}
            Both atheletes and coaches are available.
        {% endif %}

        {% if not athlete_list or coach_list %}
            There are no athletes, or there are some coaches.
        {% endif %}

        {% if athlete_list and not coach_list %}
            There are some athletes and absolutely no coaches.
        {% endif %}

    ``if`` tags do not allow ``and`` and ``or`` clauses with the same tag,
    because the order of logic would be ambigous. For example, this is
    invalid::

        {% if athlete_list and coach_list or cheerleader_list %}

    If you need to combine ``and`` and ``or`` to do advanced logic, just use
    nested if tags. For example::

        {% if athlete_list %}
            {% if coach_list or cheerleader_list %}
                We have athletes, and either coaches or cheerleaders!
            {% endif %}
        {% endif %}
    """
    bits = token.contents.split()
    del bits[0]
    if not bits:
        raise TemplateSyntaxError("'if' statement requires at least one argument")
    # Bits now looks something like this: ['a', 'or', 'not', 'b', 'or', 'c.d']
    bitstr = ' '.join(bits)
    boolpairs = bitstr.split(' and ')
    boolvars = []
    if len(boolpairs) == 1:
        link_type = IfNode.LinkTypes.or_
        boolpairs = bitstr.split(' or ')
    else:
        link_type = IfNode.LinkTypes.and_
        if ' or ' in bitstr:
            raise TemplateSyntaxError, "'if' tags can't mix 'and' and 'or'"
    for boolpair in boolpairs:
        if ' ' in boolpair:
            try:
                not_, boolvar = boolpair.split()
            except ValueError:
                raise TemplateSyntaxError, "'if' statement improperly formatted"
            if not_ != 'not':
                raise TemplateSyntaxError, "Expected 'not' in if statement"
            boolvars.append((True, parser.compile_filter(boolvar)))
        else:
            boolvars.append((False, parser.compile_filter(boolpair)))
    nodelist_true = parser.parse(('else', 'endif'))
    token = parser.next_token()
    if token.contents == 'else':
        nodelist_false = parser.parse(('endif',))
        parser.delete_first_token()
    else:
        nodelist_false = NodeList()
    return IfNode(boolvars, nodelist_true, nodelist_false, link_type)
Exemple #30
0
 def source_error(self, source,msg):
     e = TemplateSyntaxError(msg)
     e.source = source
     return e
Exemple #31
0
def review_body_replies(context, review, body_field, context_id):
    """Render a list of replies to a body field of a review.

    This loads all the replies made to a review's header/footer body field and
    renders them in order by timestamp, showing the author of each comment,
    the timestamp, and the text in the appropriate format.

    Args:
        context (django.template.RequestContext):
            The template context for the page.

        review (reviewboard.reviews.models.review.Review):
            The review being replied to.

        body_field (unicode):
            The body field to look up replies to. This can be either
            ``body_top`` or ``body_bottom``.

        context_id (unicode):
            An internal ID used by the JavaScript code for storing and
            categorizing replies.

    Returns:
        django.utils.safestring.SafeText:
        The resulting HTML for the replies.

    Raises:
        django.template.TemplateSyntaxError:
            There was an invalid ``body_field`` provided.
    """
    if body_field not in ('body_top', 'body_bottom'):
        raise TemplateSyntaxError('Invalid body field "%s" provided.'
                                  % body_field)

    siteconfig = SiteConfiguration.objects.get_current()
    use_avatars = siteconfig.get('avatars_enabled')
    user = context['request'].user
    last_visited = context.get('last_visited')
    anchor_field_alias = {
        'body_top': 'header',
        'body_bottom': 'footer',
    }

    replies = getattr(review, 'public_%s_replies' % body_field)(user)

    return mark_safe(''.join(
        _generate_reply_html(
            anchor_name='%s-reply%d' % (anchor_field_alias[body_field],
                                        reply.pk),
            context=context,
            context_id=context_id,
            last_visited=last_visited,
            reply=reply,
            review=review,
            rich_text=getattr(reply, '%s_rich_text' % body_field),
            text=getattr(reply, body_field),
            timestamp=reply.timestamp,
            use_avatars=use_avatars,
            user=user)
        for reply in replies
    ))
Exemple #32
0
def version_number(parser, token):
    try:
        key = token.split_contents()
    except ValueError:
        raise TemplateSyntaxError("tag requires a single argument")
    return VersionNumberNode(key[1])
Exemple #33
0
 def dummy_tag(parser, token):
     bits = token.split_contents()
     if len(bits) > 1:
         raise TemplateSyntaxError("'%s' tag takes no arguments" % bits[0])
     return _location_nodes[location]
 def enforce_form_tag(self, context):
     if not context.get(self.IN_FORM_CONTEXT_VAR, False):
         raise TemplateSyntaxError('%s must be used inside a form tag.' %
                                   self.tagname)
Exemple #35
0
def _generate_django_exception(e, source=None):
    '''Generate a Django exception from a Jinja exception'''
    from django.views.debug import linebreak_iter
    import re

    if source:
        exception = DjangoTemplateSyntaxError(e.message)
        exception_dict = e.__dict__
        del exception_dict['source']

        # Fetch the entire template in a string
        template_string = source[0].reload()

        # Get the line number from the error message, if available
        match = re.match('.* at (\d+)$', e.message)

        start_index = 0
        stop_index = 0
        if match:
            # Convert the position found in the stacktrace to a position
            # the Django template debug system can use
            position = int(match.group(1)) + source[1][0] + 1

            for index in linebreak_iter(template_string):
                if index >= position:
                    stop_index = min(index, position + 3)
                    start_index = min(index, position - 2)
                    break
                start_index = index

        else:
            # So there wasn't a matching error message, in that case we
            # simply have to highlight the entire line instead of the specific
            # words
            ignore_lines = -1
            for i, index in enumerate(linebreak_iter(template_string)):
                if source[1][0] > index:
                    ignore_lines += 1

                if i - ignore_lines == e.lineno:
                    stop_index = index
                    break

                start_index = index

        # Convert the positions to a source that is compatible with the
        # Django template debugger
        source = source[0], (
            start_index,
            stop_index,
        )
    else:
        # No source available so we let Django fetch it for us
        lineno = e.lineno - 1
        template_string, source = django_loader.find_template_source(e.name)
        exception = DjangoTemplateSyntaxError(e.message)

        # Find the positions by the line number given in the exception
        start_index = 0
        for i in range(lineno):
            start_index = template_string.index('\n', start_index + 1)

        source = source, (
            start_index + 1,
            template_string.index('\n', start_index + 1) + 1,
        )

    # Set our custom source as source for the exception so the Django
    # template debugger can use it
    exception.source = source
    return exception
def addthis(**kwargs):
    """
    addthis
    =======
    The addthis templatetag will insert the necessary scripts to make use of the 
    [AddThis](https://www.addthis.com) widget.

    Basic usage:
    ------------

        {% addthis %}

    Global settings:
    ----------------
    The only required argument is `pubid`.

    Add a dictionary of properties to your settings.py that will be added to the 
    AddThis Javascript configuration code whenever the templatetag `addthis` is used. 
    These are meant for site-wide configurations.

    `ADDTHIS_PROPERTIES = { 
            'pubid': 'your-pub-id',
            'ui-language': 'pt',
            'etc' : 'yet another value'
    }`

    See the [AddThis Client API](http://www.addthis.com/help/client-api) for 
    information on the available configuration parameters.

    Local (per-template) settings:
    ------------------------------
    The `addthis` templatetag accepts any number of keyword arguments, that 
    will be **specifically** used to generate the `addthis_share` configuration:
    
        {% addthis url="http://www.some-domain.ext/some/path/page.html" description="Some relevant description" %}
    
    See the [AddThis Client API: Sharing Configuration](http://www.addthis.com/help/client-api#configuration-sharing)
    for information on the available sharing configuration parameters.
    
    """
    
    #check for the required pubid
    addthis_config = getattr(settings, 'ADDTHIS_CONFIG', None)
    
    if addthis_config == None:
        raise TemplateSyntaxError('No ADDTHIS_CONFIG found in settings.py.')
    
    if not 'pubid' in addthis_config:
        raise TemplateSyntaxError('The addthis template tag requires a pubid. You set it within ADDTHIS_CONFIG in settings.py.')
    
    #apply some formatting to enable proper javascript values (type-wise)
    for key in addthis_config:
        addthis_config[key] = decorate(addthis_config[key])
    
    #generate keyword arguments js list
    if len(kwargs) > 0:
        addthis_share = kwargs
        
        for key in addthis_share:
            addthis_share[key] = decorate(addthis_share[key])
            
    else:
        addthis_share = None
    
    return { 'addthis': addthis_config, 'addthis_share' : addthis_share }
Exemple #37
0
def reply_list(context, entry, comment, context_type, context_id):
    """
    Renders a list of comments of a specified type.

    This is a complex, confusing function accepts lots of inputs in order
    to display replies to a type of object. In each case, the replies will
    be rendered using the template :template:`reviews/review_reply.html`.

    If ``context_type`` is ``"diff_comments"``, ``"screenshot_comments"``
    or ``"file_attachment_comments"``, the generated list of replies are to
    ``comment``.

    If ``context_type`` is ``"body_top"`` or ```"body_bottom"``,
    the generated list of replies are to ``review``. Depending on the
    ``context_type``, these will either be replies to the top of the
    review body or to the bottom.

    The ``context_id`` parameter has to do with the internal IDs used by
    the JavaScript code for storing and categorizing the comments.
    """
    def generate_reply_html(reply,
                            timestamp,
                            text,
                            rich_text,
                            use_gravatars,
                            comment_id=None):
        context.push()
        context.update({
            'context_id': context_id,
            'id': reply.id,
            'review': review,
            'timestamp': timestamp,
            'text': text,
            'reply_user': reply.user,
            'draft': not reply.public,
            'comment_id': comment_id,
            'rich_text': rich_text,
            'use_gravatars': use_gravatars,
        })

        result = render_to_string('reviews/review_reply.html', context)
        context.pop()

        return result

    def process_body_replies(queryset, attrname, user):
        if user.is_anonymous():
            queryset = queryset.filter(public=True)
        else:
            queryset = queryset.filter(Q(public=True) | Q(user=user))

        s = ""
        for reply_comment in queryset:
            s += generate_reply_html(reply, reply.timestamp,
                                     getattr(reply, attrname))

        return s

    siteconfig = SiteConfiguration.objects.get_current()
    use_gravatars = siteconfig.get('integration_gravatars')

    review = entry['review']

    user = context.get('user', None)
    if user.is_anonymous():
        user = None

    s = ""

    if context_type in ('diff_comments', 'screenshot_comments',
                        'file_attachment_comments'):
        for reply_comment in comment.public_replies(user):
            s += generate_reply_html(reply_comment.get_review(),
                                     reply_comment.timestamp,
                                     reply_comment.text,
                                     reply_comment.rich_text, use_gravatars,
                                     reply_comment.pk)
    elif context_type == "body_top" or context_type == "body_bottom":
        replies = getattr(review, "public_%s_replies" % context_type)()

        for reply in replies:
            s += generate_reply_html(
                reply, reply.timestamp, getattr(reply, context_type),
                getattr(reply, '%s_rich_text' % context_type), use_gravatars)

        return s
    else:
        raise TemplateSyntaxError("Invalid context type passed")

    return s
# Since this package contains a "django" module, this is required on Python 2.