File: utils.py

package info (click to toggle)
python-werkzeug 1.0.1%2Bdfsg1-2%2Bdeb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 2,888 kB
  • sloc: python: 21,897; javascript: 173; makefile: 36; xml: 16
file content (161 lines) | stat: -rw-r--r-- 4,219 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# -*- coding: utf-8 -*-
"""
    plnt.utils
    ~~~~~~~~~~

    The planet utilities.

    :copyright: 2007 Pallets
    :license: BSD-3-Clause
"""
import re
from os import path

from jinja2 import Environment
from jinja2 import FileSystemLoader
from werkzeug._compat import unichr
from werkzeug.local import Local
from werkzeug.local import LocalManager
from werkzeug.routing import Map
from werkzeug.routing import Rule
from werkzeug.utils import cached_property
from werkzeug.wrappers import Response


# context locals.  these two objects are use by the application to
# bind objects to the current context.  A context is defined as the
# current thread and the current greenlet if there is greenlet support.
# the `get_request` and `get_application` functions look up the request
# and application objects from this local manager.
local = Local()
local_manager = LocalManager([local])


# proxy objects
request = local("request")
application = local("application")
url_adapter = local("url_adapter")


# let's use jinja for templates this time
template_path = path.join(path.dirname(__file__), "templates")
jinja_env = Environment(loader=FileSystemLoader(template_path))


# the collected url patterns
url_map = Map([Rule("/shared/<path:file>", endpoint="shared")])
endpoints = {}


_par_re = re.compile(r"\n{2,}")
_entity_re = re.compile(r"&([^;]+);")
_striptags_re = re.compile(r"(<!--.*-->|<[^>]*>)")

try:
    from html.entities import name2codepoint
except ImportError:
    from htmlentitydefs import name2codepoint

html_entities = name2codepoint.copy()
html_entities["apos"] = 39
del name2codepoint


def expose(url_rule, endpoint=None, **kwargs):
    """Expose this function to the web layer."""

    def decorate(f):
        e = endpoint or f.__name__
        endpoints[e] = f
        url_map.add(Rule(url_rule, endpoint=e, **kwargs))
        return f

    return decorate


def render_template(template_name, **context):
    """Render a template into a response."""
    tmpl = jinja_env.get_template(template_name)
    context["url_for"] = url_for
    return Response(tmpl.render(context), mimetype="text/html")


def nl2p(s):
    """Add paragraphs to a text."""
    return u"\n".join(u"<p>%s</p>" % p for p in _par_re.split(s))


def url_for(endpoint, **kw):
    """Simple function for URL generation."""
    return url_adapter.build(endpoint, kw)


def strip_tags(s):
    """Resolve HTML entities and remove tags from a string."""

    def handle_match(m):
        name = m.group(1)
        if name in html_entities:
            return unichr(html_entities[name])
        if name[:2] in ("#x", "#X"):
            try:
                return unichr(int(name[2:], 16))
            except ValueError:
                return u""
        elif name.startswith("#"):
            try:
                return unichr(int(name[1:]))
            except ValueError:
                return u""
        return u""

    return _entity_re.sub(handle_match, _striptags_re.sub("", s))


class Pagination(object):
    """
    Paginate a SQLAlchemy query object.
    """

    def __init__(self, query, per_page, page, endpoint):
        self.query = query
        self.per_page = per_page
        self.page = page
        self.endpoint = endpoint

    @cached_property
    def entries(self):
        return (
            self.query.offset((self.page - 1) * self.per_page)
            .limit(self.per_page)
            .all()
        )

    @cached_property
    def count(self):
        return self.query.count()

    @property
    def has_previous(self):
        """Return True if there are pages before the current one."""
        return self.page > 1

    @property
    def has_next(self):
        """Return True if there are pages after the current one."""
        return self.page < self.pages

    @property
    def previous(self):
        """Return the URL for the previous page."""
        return url_for(self.endpoint, page=self.page - 1)

    @property
    def next(self):
        """Return the URL for the next page."""
        return url_for(self.endpoint, page=self.page + 1)

    @property
    def pages(self):
        """Return the number of pages."""
        return max(0, self.count - 1) // self.per_page + 1