##// END OF EJS Templates
webhelpers: port most of the items from webhelpers to webhelpers2...
dan -
r4090:5358a9a7 default
parent child Browse files
Show More
@@ -0,0 +1,165 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 import re
21
22 from webhelpers.paginate import Page as _Page
23 from webhelpers.paginate import PageURL
24 from webhelpers2.html import literal, HTML
25
26
27 class Page(_Page):
28 """
29 Custom pager to match rendering style with paginator
30 """
31
32 def _get_pos(self, cur_page, max_page, items):
33 edge = (items / 2) + 1
34 if (cur_page <= edge):
35 radius = max(items / 2, items - cur_page)
36 elif (max_page - cur_page) < edge:
37 radius = (items - 1) - (max_page - cur_page)
38 else:
39 radius = items / 2
40
41 left = max(1, (cur_page - (radius)))
42 right = min(max_page, cur_page + (radius))
43 return left, cur_page, right
44
45 def _range(self, regexp_match):
46 """
47 Return range of linked pages (e.g. '1 2 [3] 4 5 6 7 8').
48
49 Arguments:
50
51 regexp_match
52 A "re" (regular expressions) match object containing the
53 radius of linked pages around the current page in
54 regexp_match.group(1) as a string
55
56 This function is supposed to be called as a callable in
57 re.sub.
58
59 """
60 radius = int(regexp_match.group(1))
61
62 # Compute the first and last page number within the radius
63 # e.g. '1 .. 5 6 [7] 8 9 .. 12'
64 # -> leftmost_page = 5
65 # -> rightmost_page = 9
66 leftmost_page, _cur, rightmost_page = self._get_pos(self.page,
67 self.last_page,
68 (radius * 2) + 1)
69 nav_items = []
70
71 # Create a link to the first page (unless we are on the first page
72 # or there would be no need to insert '..' spacers)
73 if self.page != self.first_page and self.first_page < leftmost_page:
74 nav_items.append(self._pagerlink(self.first_page, self.first_page))
75
76 # Insert dots if there are pages between the first page
77 # and the currently displayed page range
78 if leftmost_page - self.first_page > 1:
79 # Wrap in a SPAN tag if nolink_attr is set
80 text = '..'
81 if self.dotdot_attr:
82 text = HTML.span(c=text, **self.dotdot_attr)
83 nav_items.append(text)
84
85 for thispage in xrange(leftmost_page, rightmost_page + 1):
86 # Hilight the current page number and do not use a link
87 if thispage == self.page:
88 text = '%s' % (thispage,)
89 # Wrap in a SPAN tag if nolink_attr is set
90 if self.curpage_attr:
91 text = HTML.span(c=text, **self.curpage_attr)
92 nav_items.append(text)
93 # Otherwise create just a link to that page
94 else:
95 text = '%s' % (thispage,)
96 nav_items.append(self._pagerlink(thispage, text))
97
98 # Insert dots if there are pages between the displayed
99 # page numbers and the end of the page range
100 if self.last_page - rightmost_page > 1:
101 text = '..'
102 # Wrap in a SPAN tag if nolink_attr is set
103 if self.dotdot_attr:
104 text = HTML.span(c=text, **self.dotdot_attr)
105 nav_items.append(text)
106
107 # Create a link to the very last page (unless we are on the last
108 # page or there would be no need to insert '..' spacers)
109 if self.page != self.last_page and rightmost_page < self.last_page:
110 nav_items.append(self._pagerlink(self.last_page, self.last_page))
111
112 ## prerender links
113 #_page_link = url.current()
114 #nav_items.append(literal('<link rel="prerender" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
115 #nav_items.append(literal('<link rel="prefetch" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
116 return self.separator.join(nav_items)
117
118 def pager(self, format='~2~', page_param='page', partial_param='partial',
119 show_if_single_page=False, separator=' ', onclick=None,
120 symbol_first='<<', symbol_last='>>',
121 symbol_previous='<', symbol_next='>',
122 link_attr={'class': 'pager_link', 'rel': 'prerender'},
123 curpage_attr={'class': 'pager_curpage'},
124 dotdot_attr={'class': 'pager_dotdot'}, **kwargs):
125
126 self.curpage_attr = curpage_attr
127 self.separator = separator
128 self.pager_kwargs = kwargs
129 self.page_param = page_param
130 self.partial_param = partial_param
131 self.onclick = onclick
132 self.link_attr = link_attr
133 self.dotdot_attr = dotdot_attr
134
135 # Don't show navigator if there is no more than one page
136 if self.page_count == 0 or (self.page_count == 1 and not show_if_single_page):
137 return ''
138
139 from string import Template
140 # Replace ~...~ in token format by range of pages
141 result = re.sub(r'~(\d+)~', self._range, format)
142
143 # Interpolate '%' variables
144 result = Template(result).safe_substitute({
145 'first_page': self.first_page,
146 'last_page': self.last_page,
147 'page': self.page,
148 'page_count': self.page_count,
149 'items_per_page': self.items_per_page,
150 'first_item': self.first_item,
151 'last_item': self.last_item,
152 'item_count': self.item_count,
153 'link_first': self.page > self.first_page and \
154 self._pagerlink(self.first_page, symbol_first) or '',
155 'link_last': self.page < self.last_page and \
156 self._pagerlink(self.last_page, symbol_last) or '',
157 'link_previous': self.previous_page and \
158 self._pagerlink(self.previous_page, symbol_previous) \
159 or HTML.span(symbol_previous, class_="pg-previous disabled"),
160 'link_next': self.next_page and \
161 self._pagerlink(self.next_page, symbol_next) \
162 or HTML.span(symbol_next, class_="pg-next disabled")
163 })
164
165 return literal(result)
@@ -123,5 +123,5 b' class TestHomeController(TestController)'
123 123 def test_logout_form_contains_csrf(self, autologin_user, csrf_token):
124 124 response = self.app.get(route_path('home'))
125 125 assert_response = response.assert_response()
126 element = assert_response.get_element('.logout #csrf_token')
126 element = assert_response.get_element('.logout [name=csrf_token]')
127 127 assert element.value == csrf_token
@@ -21,7 +21,7 b''
21 21 import logging
22 22 import urllib
23 23 from pyramid.view import view_config
24 from webhelpers.util import update_params
24 from webhelpers2.html.tools import update_params
25 25
26 26 from rhodecode.apps._base import BaseAppView, RepoAppView, RepoGroupAppView
27 27 from rhodecode.lib.auth import (
@@ -21,13 +21,13 b''
21 21 import deform
22 22 import logging
23 23 import peppercorn
24 import webhelpers.paginate
25 24
26 25 from pyramid.httpexceptions import HTTPFound, HTTPForbidden, HTTPNotFound
27 26
28 27 from rhodecode.integrations import integration_type_registry
29 28 from rhodecode.apps._base import BaseAppView
30 29 from rhodecode.apps._base.navigation import navigation_list
30 from rhodecode.lib.paginate import PageURL
31 31 from rhodecode.lib.auth import (
32 32 LoginRequired, CSRFRequired, HasPermissionAnyDecorator,
33 33 HasRepoPermissionAnyDecorator, HasRepoGroupPermissionAnyDecorator)
@@ -219,8 +219,7 b' class IntegrationSettingsViewBase(BaseAp'
219 219 key=lambda x: getattr(x[1], sort_field),
220 220 reverse=(sort_dir == 'desc'))
221 221
222 page_url = webhelpers.paginate.PageURL(
223 self.request.path, self.request.GET)
222 page_url = PageURL(self.request.path, self.request.GET)
224 223 page = safe_int(self.request.GET.get('page', 1), 1)
225 224
226 225 integrations = h.Page(
@@ -20,8 +20,8 b''
20 20
21 21 import logging
22 22
23 from webhelpers.html.builder import literal
24 from webhelpers.html.tags import link_to
23 from webhelpers2.html.builder import literal
24 from webhelpers2.html.tags import link_to
25 25
26 26 from rhodecode.lib.utils2 import AttributeDict
27 27 from rhodecode.lib.vcs.backends.base import BaseCommit
@@ -1540,11 +1540,10 b' class CSRFRequired(object):'
1540 1540 http://en.wikipedia.org/wiki/Cross-site_request_forgery for more
1541 1541 information).
1542 1542
1543 For use with the ``webhelpers.secure_form`` helper functions.
1543 For use with the ``secure_form`` helper functions.
1544 1544
1545 1545 """
1546 def __init__(self, token=csrf_token_key, header='X-CSRF-Token',
1547 except_methods=None):
1546 def __init__(self, token=csrf_token_key, header='X-CSRF-Token', except_methods=None):
1548 1547 self.token = token
1549 1548 self.header = header
1550 1549 self.except_methods = except_methods or []
@@ -2334,7 +2334,7 b' class RepoGroup(Base, BaseModel):'
2334 2334
2335 2335 @classmethod
2336 2336 def _generate_choice(cls, repo_group):
2337 from webhelpers.html import literal as _literal
2337 from webhelpers2.html import literal as _literal
2338 2338 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2339 2339 return repo_group.group_id, _name(repo_group.full_path_splitted)
2340 2340
@@ -2400,7 +2400,7 b' class RepoGroup(Base, BaseModel):'
2400 2400
2401 2401 @classmethod
2402 2402 def _generate_choice(cls, repo_group):
2403 from webhelpers.html import literal as _literal
2403 from webhelpers2.html import literal as _literal
2404 2404 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2405 2405 return repo_group.group_id, _name(repo_group.full_path_splitted)
2406 2406
@@ -2474,7 +2474,7 b' class RepoGroup(Base, BaseModel):'
2474 2474
2475 2475 @classmethod
2476 2476 def _generate_choice(cls, repo_group):
2477 from webhelpers.html import literal as _literal
2477 from webhelpers2.html import literal as _literal
2478 2478 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2479 2479 return repo_group.group_id, _name(repo_group.full_path_splitted)
2480 2480
@@ -2497,7 +2497,7 b' class RepoGroup(Base, BaseModel):'
2497 2497
2498 2498 @classmethod
2499 2499 def _generate_choice(cls, repo_group):
2500 from webhelpers.html import literal as _literal
2500 from webhelpers2.html import literal as _literal
2501 2501 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2502 2502 return repo_group.group_id, _name(repo_group.full_path_splitted)
2503 2503
@@ -2497,7 +2497,7 b' class RepoGroup(Base, BaseModel):'
2497 2497
2498 2498 @classmethod
2499 2499 def _generate_choice(cls, repo_group):
2500 from webhelpers.html import literal as _literal
2500 from webhelpers2.html import literal as _literal
2501 2501 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2502 2502 return repo_group.group_id, _name(repo_group.full_path_splitted)
2503 2503
@@ -52,7 +52,7 b' from sqlalchemy.dialects.mysql import LO'
52 52 from zope.cachedescriptors.property import Lazy as LazyProperty
53 53 from pyramid import compat
54 54 from pyramid.threadlocal import get_current_request
55 from webhelpers.text import collapse, remove_formatting
55 from webhelpers2.text import collapse, remove_formatting
56 56
57 57 from rhodecode.translation import _
58 58 from rhodecode.lib.vcs import get_vcs_instance
@@ -2624,7 +2624,7 b' class RepoGroup(Base, BaseModel):'
2624 2624
2625 2625 @classmethod
2626 2626 def _generate_choice(cls, repo_group):
2627 from webhelpers.html import literal as _literal
2627 from webhelpers2.html import literal as _literal
2628 2628 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2629 2629 return repo_group.group_id, _name(repo_group.full_path_splitted)
2630 2630
@@ -2037,7 +2037,7 b' class RepoGroup(Base, BaseModel):'
2037 2037
2038 2038 @classmethod
2039 2039 def _generate_choice(cls, repo_group):
2040 from webhelpers.html import literal as _literal
2040 from webhelpers2.html import literal as _literal
2041 2041 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2042 2042 return repo_group.group_id, _name(repo_group.full_path_splitted)
2043 2043
@@ -2029,7 +2029,7 b' class RepoGroup(Base, BaseModel):'
2029 2029
2030 2030 @classmethod
2031 2031 def _generate_choice(cls, repo_group):
2032 from webhelpers.html import literal as _literal
2032 from webhelpers2.html import literal as _literal
2033 2033 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2034 2034 return repo_group.group_id, _name(repo_group.full_path_splitted)
2035 2035
@@ -2028,7 +2028,7 b' class RepoGroup(Base, BaseModel):'
2028 2028
2029 2029 @classmethod
2030 2030 def _generate_choice(cls, repo_group):
2031 from webhelpers.html import literal as _literal
2031 from webhelpers2.html import literal as _literal
2032 2032 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2033 2033 return repo_group.group_id, _name(repo_group.full_path_splitted)
2034 2034
@@ -2032,7 +2032,7 b' class RepoGroup(Base, BaseModel):'
2032 2032
2033 2033 @classmethod
2034 2034 def _generate_choice(cls, repo_group):
2035 from webhelpers.html import literal as _literal
2035 from webhelpers2.html import literal as _literal
2036 2036 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2037 2037 return repo_group.group_id, _name(repo_group.full_path_splitted)
2038 2038
@@ -2032,7 +2032,7 b' class RepoGroup(Base, BaseModel):'
2032 2032
2033 2033 @classmethod
2034 2034 def _generate_choice(cls, repo_group):
2035 from webhelpers.html import literal as _literal
2035 from webhelpers2.html import literal as _literal
2036 2036 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2037 2037 return repo_group.group_id, _name(repo_group.full_path_splitted)
2038 2038
@@ -2076,7 +2076,7 b' class RepoGroup(Base, BaseModel):'
2076 2076
2077 2077 @classmethod
2078 2078 def _generate_choice(cls, repo_group):
2079 from webhelpers.html import literal as _literal
2079 from webhelpers2.html import literal as _literal
2080 2080 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2081 2081 return repo_group.group_id, _name(repo_group.full_path_splitted)
2082 2082
@@ -2077,7 +2077,7 b' class RepoGroup(Base, BaseModel):'
2077 2077
2078 2078 @classmethod
2079 2079 def _generate_choice(cls, repo_group):
2080 from webhelpers.html import literal as _literal
2080 from webhelpers2.html import literal as _literal
2081 2081 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2082 2082 return repo_group.group_id, _name(repo_group.full_path_splitted)
2083 2083
@@ -2270,7 +2270,7 b' class RepoGroup(Base, BaseModel):'
2270 2270
2271 2271 @classmethod
2272 2272 def _generate_choice(cls, repo_group):
2273 from webhelpers.html import literal as _literal
2273 from webhelpers2.html import literal as _literal
2274 2274 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2275 2275 return repo_group.group_id, _name(repo_group.full_path_splitted)
2276 2276
@@ -53,25 +53,29 b' from pygments.lexers import ('
53 53
54 54 from pyramid.threadlocal import get_current_request
55 55
56 from webhelpers.html import literal, HTML, escape
57 from webhelpers.html.tools import *
58 from webhelpers.html.builder import make_tag
59 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
60 end_form, file, form as wh_form, hidden, image, javascript_link, link_to, \
61 link_to_if, link_to_unless, ol, required_legend, select, stylesheet_link, \
62 submit, text, password, textarea, title, ul, xml_declaration, radio
63 from webhelpers.html.tools import auto_link, button_to, highlight, \
64 js_obfuscate, mail_to, strip_links, strip_tags, tag_re
65 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
66 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
67 replace_whitespace, urlify, truncate, wrap_paragraphs
68 from webhelpers.date import time_ago_in_words
69 from webhelpers.paginate import Page as _Page
70 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
71 convert_boolean_attrs, NotGiven, _make_safe_id_component
56 from webhelpers2.html import literal, HTML, escape
57 from webhelpers2.html._autolink import _auto_link_urls
58 from webhelpers2.html.tools import (
59 button_to, highlight, js_obfuscate, strip_links, strip_tags)
60
61 from webhelpers2.text import (
62 chop_at, collapse, convert_accented_entities,
63 convert_misc_entities, lchop, plural, rchop, remove_formatting,
64 replace_whitespace, urlify, truncate, wrap_paragraphs)
65 from webhelpers2.date import time_ago_in_words
66
67 from webhelpers2.html.tags import (
68 _input, NotGiven, _make_safe_id_component as safeid,
69 form as insecure_form,
70 auto_discovery_link, checkbox, end_form, file,
71 hidden, image, javascript_link, link_to, link_to_if, link_to_unless, ol,
72 select as raw_select, stylesheet_link, submit, text, password, textarea,
73 ul, radio, Options)
74
72 75 from webhelpers2.number import format_byte_size
73 76
74 77 from rhodecode.lib.action_parser import action_parser
78 from rhodecode.lib.paginate import Page
75 79 from rhodecode.lib.ext_json import json
76 80 from rhodecode.lib.utils import repo_name_slug, get_custom_lexer
77 81 from rhodecode.lib.utils2 import (
@@ -162,17 +166,42 b' def shorter(text, size=20, prefix=False)'
162 166 return text
163 167
164 168
165 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
169 def reset(name, value=None, id=NotGiven, type="reset", **attrs):
166 170 """
167 171 Reset button
168 172 """
169 _set_input_attrs(attrs, type, name, value)
170 _set_id_attr(attrs, id, name)
171 convert_boolean_attrs(attrs, ["disabled"])
172 return HTML.input(**attrs)
173 return _input(type, name, value, id, attrs)
174
175
176 def select(name, selected_values, options, id=NotGiven, **attrs):
173 177
174 reset = _reset
175 safeid = _make_safe_id_component
178 if isinstance(options, (list, tuple)):
179 options_iter = options
180 # Handle old value,label lists ... where value also can be value,label lists
181 options = Options()
182 for opt in options_iter:
183 if isinstance(opt, tuple) and len(opt) == 2:
184 value, label = opt
185 elif isinstance(opt, basestring):
186 value = label = opt
187 else:
188 raise ValueError('invalid select option type %r' % type(opt))
189
190 if isinstance(value, (list, tuple)):
191 option_group = options.add_optgroup(label)
192 for opt2 in value:
193 if isinstance(opt2, tuple) and len(opt2) == 2:
194 group_value, group_label = opt
195 elif isinstance(opt2, basestring):
196 group_value = group_label = opt2
197 else:
198 raise ValueError('invalid select option type %r' % type(opt2))
199
200 option_group.add_option(group_label, group_value)
201 else:
202 options.add_option(label, value)
203
204 return raw_select(name, selected_values, options, id=id, **attrs)
176 205
177 206
178 207 def branding(name, length=40):
@@ -1280,145 +1309,6 b' def gravatar_url(email_address, size=30,'
1280 1309 return initials_gravatar(email_address, '', '', size=size)
1281 1310
1282 1311
1283 class Page(_Page):
1284 """
1285 Custom pager to match rendering style with paginator
1286 """
1287
1288 def _get_pos(self, cur_page, max_page, items):
1289 edge = (items / 2) + 1
1290 if (cur_page <= edge):
1291 radius = max(items / 2, items - cur_page)
1292 elif (max_page - cur_page) < edge:
1293 radius = (items - 1) - (max_page - cur_page)
1294 else:
1295 radius = items / 2
1296
1297 left = max(1, (cur_page - (radius)))
1298 right = min(max_page, cur_page + (radius))
1299 return left, cur_page, right
1300
1301 def _range(self, regexp_match):
1302 """
1303 Return range of linked pages (e.g. '1 2 [3] 4 5 6 7 8').
1304
1305 Arguments:
1306
1307 regexp_match
1308 A "re" (regular expressions) match object containing the
1309 radius of linked pages around the current page in
1310 regexp_match.group(1) as a string
1311
1312 This function is supposed to be called as a callable in
1313 re.sub.
1314
1315 """
1316 radius = int(regexp_match.group(1))
1317
1318 # Compute the first and last page number within the radius
1319 # e.g. '1 .. 5 6 [7] 8 9 .. 12'
1320 # -> leftmost_page = 5
1321 # -> rightmost_page = 9
1322 leftmost_page, _cur, rightmost_page = self._get_pos(self.page,
1323 self.last_page,
1324 (radius * 2) + 1)
1325 nav_items = []
1326
1327 # Create a link to the first page (unless we are on the first page
1328 # or there would be no need to insert '..' spacers)
1329 if self.page != self.first_page and self.first_page < leftmost_page:
1330 nav_items.append(self._pagerlink(self.first_page, self.first_page))
1331
1332 # Insert dots if there are pages between the first page
1333 # and the currently displayed page range
1334 if leftmost_page - self.first_page > 1:
1335 # Wrap in a SPAN tag if nolink_attr is set
1336 text = '..'
1337 if self.dotdot_attr:
1338 text = HTML.span(c=text, **self.dotdot_attr)
1339 nav_items.append(text)
1340
1341 for thispage in xrange(leftmost_page, rightmost_page + 1):
1342 # Hilight the current page number and do not use a link
1343 if thispage == self.page:
1344 text = '%s' % (thispage,)
1345 # Wrap in a SPAN tag if nolink_attr is set
1346 if self.curpage_attr:
1347 text = HTML.span(c=text, **self.curpage_attr)
1348 nav_items.append(text)
1349 # Otherwise create just a link to that page
1350 else:
1351 text = '%s' % (thispage,)
1352 nav_items.append(self._pagerlink(thispage, text))
1353
1354 # Insert dots if there are pages between the displayed
1355 # page numbers and the end of the page range
1356 if self.last_page - rightmost_page > 1:
1357 text = '..'
1358 # Wrap in a SPAN tag if nolink_attr is set
1359 if self.dotdot_attr:
1360 text = HTML.span(c=text, **self.dotdot_attr)
1361 nav_items.append(text)
1362
1363 # Create a link to the very last page (unless we are on the last
1364 # page or there would be no need to insert '..' spacers)
1365 if self.page != self.last_page and rightmost_page < self.last_page:
1366 nav_items.append(self._pagerlink(self.last_page, self.last_page))
1367
1368 ## prerender links
1369 #_page_link = url.current()
1370 #nav_items.append(literal('<link rel="prerender" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1371 #nav_items.append(literal('<link rel="prefetch" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1372 return self.separator.join(nav_items)
1373
1374 def pager(self, format='~2~', page_param='page', partial_param='partial',
1375 show_if_single_page=False, separator=' ', onclick=None,
1376 symbol_first='<<', symbol_last='>>',
1377 symbol_previous='<', symbol_next='>',
1378 link_attr={'class': 'pager_link', 'rel': 'prerender'},
1379 curpage_attr={'class': 'pager_curpage'},
1380 dotdot_attr={'class': 'pager_dotdot'}, **kwargs):
1381
1382 self.curpage_attr = curpage_attr
1383 self.separator = separator
1384 self.pager_kwargs = kwargs
1385 self.page_param = page_param
1386 self.partial_param = partial_param
1387 self.onclick = onclick
1388 self.link_attr = link_attr
1389 self.dotdot_attr = dotdot_attr
1390
1391 # Don't show navigator if there is no more than one page
1392 if self.page_count == 0 or (self.page_count == 1 and not show_if_single_page):
1393 return ''
1394
1395 from string import Template
1396 # Replace ~...~ in token format by range of pages
1397 result = re.sub(r'~(\d+)~', self._range, format)
1398
1399 # Interpolate '%' variables
1400 result = Template(result).safe_substitute({
1401 'first_page': self.first_page,
1402 'last_page': self.last_page,
1403 'page': self.page,
1404 'page_count': self.page_count,
1405 'items_per_page': self.items_per_page,
1406 'first_item': self.first_item,
1407 'last_item': self.last_item,
1408 'item_count': self.item_count,
1409 'link_first': self.page > self.first_page and \
1410 self._pagerlink(self.first_page, symbol_first) or '',
1411 'link_last': self.page < self.last_page and \
1412 self._pagerlink(self.last_page, symbol_last) or '',
1413 'link_previous': self.previous_page and \
1414 self._pagerlink(self.previous_page, symbol_previous) \
1415 or HTML.span(symbol_previous, class_="pg-previous disabled"),
1416 'link_next': self.next_page and \
1417 self._pagerlink(self.next_page, symbol_next) \
1418 or HTML.span(symbol_next, class_="pg-next disabled")
1419 })
1420
1421 return literal(result)
1422 1312
1423 1313
1424 1314 #==============================================================================
@@ -1564,11 +1454,9 b' def format_byte_size_binary(file_size):'
1564 1454 return formatted_size
1565 1455
1566 1456
1567 def urlify_text(text_, safe=True):
1457 def urlify_text(text_, safe=True, **href_attrs):
1568 1458 """
1569 Extrac urls from text and make html links out of them
1570
1571 :param text_:
1459 Extract urls from text and make html links out of them
1572 1460 """
1573 1461
1574 1462 url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@#.&+]'''
@@ -1576,8 +1464,13 b' def urlify_text(text_, safe=True):'
1576 1464
1577 1465 def url_func(match_obj):
1578 1466 url_full = match_obj.groups()[0]
1579 return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
1467 a_options = dict(href_attrs)
1468 a_options['href'] = url_full
1469 a_text = url_full
1470 return HTML.tag("a", a_text, **a_options)
1471
1580 1472 _new_text = url_pat.sub(url_func, text_)
1473
1581 1474 if safe:
1582 1475 return literal(_new_text)
1583 1476 return _new_text
@@ -1939,7 +1832,7 b" def form(url, method='post', needs_csrf_"
1939 1832 'CSRF token. If the endpoint does not require such token you can ' +
1940 1833 'explicitly set the parameter needs_csrf_token to false.')
1941 1834
1942 return wh_form(url, method=method, **attrs)
1835 return insecure_form(url, method=method, **attrs)
1943 1836
1944 1837
1945 1838 def secure_form(form_url, method="POST", multipart=False, **attrs):
@@ -1961,7 +1854,6 b' def secure_form(form_url, method="POST",'
1961 1854 over POST.
1962 1855
1963 1856 """
1964 from webhelpers.pylonslib.secure_form import insecure_form
1965 1857
1966 1858 if 'request' in attrs:
1967 1859 session = attrs['request'].session
@@ -1970,12 +1862,12 b' def secure_form(form_url, method="POST",'
1970 1862 raise ValueError(
1971 1863 'Calling this form requires request= to be passed as argument')
1972 1864
1973 form = insecure_form(form_url, method, multipart, **attrs)
1865 _form = insecure_form(form_url, method, multipart, **attrs)
1974 1866 token = literal(
1975 '<input type="hidden" id="{}" name="{}" value="{}">'.format(
1976 csrf_token_key, csrf_token_key, get_csrf_token(session)))
1867 '<input type="hidden" name="{}" value="{}">'.format(
1868 csrf_token_key, get_csrf_token(session)))
1977 1869
1978 return literal("%s\n%s" % (form, token))
1870 return literal("%s\n%s" % (_form, token))
1979 1871
1980 1872
1981 1873 def dropdownmenu(name, selected, options, enable_filter=False, **attrs):
@@ -39,7 +39,7 b' from os.path import join as jn'
39 39
40 40 import paste
41 41 import pkg_resources
42 from webhelpers.text import collapse, remove_formatting, strip_tags
42 from webhelpers2.text import collapse, remove_formatting
43 43 from mako import exceptions
44 44 from pyramid.threadlocal import get_current_registry
45 45 from rhodecode.lib.request import Request
@@ -52,7 +52,7 b' from sqlalchemy.dialects.mysql import LO'
52 52 from zope.cachedescriptors.property import Lazy as LazyProperty
53 53 from pyramid import compat
54 54 from pyramid.threadlocal import get_current_request
55 from webhelpers.text import collapse, remove_formatting
55 from webhelpers2.text import remove_formatting
56 56
57 57 from rhodecode.translation import _
58 58 from rhodecode.lib.vcs import get_vcs_instance
@@ -2675,7 +2675,7 b' class RepoGroup(Base, BaseModel):'
2675 2675
2676 2676 @classmethod
2677 2677 def _generate_choice(cls, repo_group):
2678 from webhelpers.html import literal as _literal
2678 from webhelpers2.html import literal as _literal
2679 2679 _name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
2680 2680 return repo_group.group_id, _name(repo_group.full_path_splitted)
2681 2681
@@ -29,11 +29,14 b' from rhodecode.tests import no_newline_i'
29 29
30 30
31 31 @pytest.mark.parametrize('url, expected_url', [
32 ('http://rc.rc/test', '<a href="http://rc.rc/test">http://rc.rc/test</a>'),
33 ('http://rc.rc/@foo', '<a href="http://rc.rc/@foo">http://rc.rc/@foo</a>'),
34 ('http://rc.rc/!foo', '<a href="http://rc.rc/!foo">http://rc.rc/!foo</a>'),
35 ('http://rc.rc/&foo', '<a href="http://rc.rc/&foo">http://rc.rc/&foo</a>'),
36 ('http://rc.rc/#foo', '<a href="http://rc.rc/#foo">http://rc.rc/#foo</a>'),
32 ('http://rc.com', '<a href="http://rc.com">http://rc.com</a>'),
33 ('http://rc.com/test', '<a href="http://rc.com/test">http://rc.com/test</a>'),
34 ('http://rc.com/!foo', '<a href="http://rc.com/!foo">http://rc.com/!foo</a>'),
35 ('http://rc.com/&foo', '<a href="http://rc.com/&amp;foo">http://rc.com/&amp;foo</a>'),
36 ('http://rc.com/?foo-1&bar=1', '<a href="http://rc.com/?foo-1&amp;bar=1">http://rc.com/?foo-1&amp;bar=1</a>'),
37 ('http://rc.com?foo-1&bar=1', '<a href="http://rc.com?foo-1&amp;bar=1">http://rc.com?foo-1&amp;bar=1</a>'),
38 ('http://rc.com/#foo', '<a href="http://rc.com/#foo">http://rc.com/#foo</a>'),
39 ('http://rc.com/@foo', '<a href="http://rc.com/@foo">http://rc.com/@foo</a>'),
37 40 ])
38 41 def test_urlify_text(url, expected_url):
39 42 assert helpers.urlify_text(url) == expected_url
@@ -43,7 +43,7 b' import psutil'
43 43 import logging
44 44 import socket
45 45
46 from webhelpers.number import format_byte_size
46 from webhelpers2.number import format_byte_size
47 47
48 48 logging.basicConfig(level=logging.DEBUG)
49 49
General Comments 0
You need to be logged in to leave comments. Login now