Passed
Push — master ( ee130d...7ca39f )
by Jochen
02:25
created

url_for_snippet()   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
"""
2
byceps.blueprints.snippet.templating
3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
5
:Copyright: 2006-2019 Jochen Kupperschmidt
6
:License: Modified BSD, see LICENSE for details.
7
"""
8
9
import sys
10
import traceback
11
12
from flask import abort, g, render_template, url_for
13
from jinja2 import TemplateNotFound
14
15
from ...services.snippet import service as snippet_service
16
from ...services.snippet.service import SnippetNotFound
17
from ...services.snippet.transfer.models import Scope
18
from ...util.templating import get_variable_value, load_template
19
20
21
def render_snippet_as_page(version):
22
    """Render the given version of the snippet, or an error page if
23
    that fails.
24
    """
25
    try:
26
        context = get_snippet_context(version)
27
        return render_template('snippet/view.html', **context)
28
    except TemplateNotFound:
29
        abort(404)
30
    except Exception as e:
31
        print('Error in snippet markup:', e, file=sys.stderr)
32
        traceback.print_exc()
33
        context = {
34
            'message': str(e),
35
        }
36
        return render_template('snippet/error.html', **context), 500
37
38
39
def get_snippet_context(version):
40
    """Return the snippet context to insert into the outer template."""
41
    template = _load_template_with_globals(version.body)
42
43
    current_page = get_variable_value(template, 'current_page')
44
    title = version.title
45
    head = _render_template(version.head) if version.head else None
46
    body = template.render()
47
48
    return {
49
        'title': title,
50
        'current_page': current_page,
51
        'head': head,
52
        'body': body,
53
    }
54
55
56
def render_snippet_as_partial(
57
    name, *, scope=None, ignore_if_unknown=False, context=None
58
):
59
    """Render the latest version of the snippet with the given name and
60
    return the result.
61
    """
62
    if scope is None:
63
        scope = Scope.for_site(g.site_id)
64
65
    current_version = snippet_service.find_current_version_of_snippet_with_name(
66
        scope, name
67
    )
68
69
    if current_version is None:
70
        if ignore_if_unknown:
71
            return ''
72
        else:
73
            raise SnippetNotFound(scope, name)
74
75
    if context is None:
76
        context = {}
77
78
    return _render_template(current_version.body, context=context)
79
80
81
def _render_template(source, *, context=None):
82
    template = _load_template_with_globals(source)
83
84
    if context is None:
85
        context = {}
86
87
    return template.render(**context)
88
89
90
def _load_template_with_globals(source):
91
    template_globals = {
92
        'render_snippet': render_snippet_as_partial,
93
        'url_for': url_for,
94
        'url_for_snippet': url_for_snippet,
95
    }
96
97
    return load_template(source, template_globals=template_globals)
98
99
100
def url_for_snippet(name):
101
    """Render an URL pointing to the snippet document's mountpoint."""
102
    return url_for(f'snippet.{name}')
103