webhelpers: port most of the items from webhelpers to webhelpers2
- webhelpers are deprecated and py2 only
This commit is contained in:
parent
1f5c42b787
commit
4057ada739
25 changed files with 265 additions and 207 deletions
|
|
@ -123,5 +123,5 @@ class TestHomeController(TestController):
|
|||
def test_logout_form_contains_csrf(self, autologin_user, csrf_token):
|
||||
response = self.app.get(route_path('home'))
|
||||
assert_response = response.assert_response()
|
||||
element = assert_response.get_element('.logout #csrf_token')
|
||||
element = assert_response.get_element('.logout [name=csrf_token]')
|
||||
assert element.value == csrf_token
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
import logging
|
||||
import urllib
|
||||
from pyramid.view import view_config
|
||||
from webhelpers.util import update_params
|
||||
from webhelpers2.html.tools import update_params
|
||||
|
||||
from rhodecode.apps._base import BaseAppView, RepoAppView, RepoGroupAppView
|
||||
from rhodecode.lib.auth import (
|
||||
|
|
|
|||
|
|
@ -21,13 +21,13 @@
|
|||
import deform
|
||||
import logging
|
||||
import peppercorn
|
||||
import webhelpers.paginate
|
||||
|
||||
from pyramid.httpexceptions import HTTPFound, HTTPForbidden, HTTPNotFound
|
||||
|
||||
from rhodecode.integrations import integration_type_registry
|
||||
from rhodecode.apps._base import BaseAppView
|
||||
from rhodecode.apps._base.navigation import navigation_list
|
||||
from rhodecode.lib.paginate import PageURL
|
||||
from rhodecode.lib.auth import (
|
||||
LoginRequired, CSRFRequired, HasPermissionAnyDecorator,
|
||||
HasRepoPermissionAnyDecorator, HasRepoGroupPermissionAnyDecorator)
|
||||
|
|
@ -219,8 +219,7 @@ class IntegrationSettingsViewBase(BaseAppView):
|
|||
key=lambda x: getattr(x[1], sort_field),
|
||||
reverse=(sort_dir == 'desc'))
|
||||
|
||||
page_url = webhelpers.paginate.PageURL(
|
||||
self.request.path, self.request.GET)
|
||||
page_url = PageURL(self.request.path, self.request.GET)
|
||||
page = safe_int(self.request.GET.get('page', 1), 1)
|
||||
|
||||
integrations = h.Page(
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
import logging
|
||||
|
||||
from webhelpers.html.builder import literal
|
||||
from webhelpers.html.tags import link_to
|
||||
from webhelpers2.html.builder import literal
|
||||
from webhelpers2.html.tags import link_to
|
||||
|
||||
from rhodecode.lib.utils2 import AttributeDict
|
||||
from rhodecode.lib.vcs.backends.base import BaseCommit
|
||||
|
|
|
|||
|
|
@ -1540,11 +1540,10 @@ class CSRFRequired(object):
|
|||
http://en.wikipedia.org/wiki/Cross-site_request_forgery for more
|
||||
information).
|
||||
|
||||
For use with the ``webhelpers.secure_form`` helper functions.
|
||||
For use with the ``secure_form`` helper functions.
|
||||
|
||||
"""
|
||||
def __init__(self, token=csrf_token_key, header='X-CSRF-Token',
|
||||
except_methods=None):
|
||||
def __init__(self, token=csrf_token_key, header='X-CSRF-Token', except_methods=None):
|
||||
self.token = token
|
||||
self.header = header
|
||||
self.except_methods = except_methods or []
|
||||
|
|
|
|||
|
|
@ -2334,7 +2334,7 @@ class RepoGroup(Base, BaseModel):
|
|||
|
||||
@classmethod
|
||||
def _generate_choice(cls, repo_group):
|
||||
from webhelpers.html import literal as _literal
|
||||
from webhelpers2.html import literal as _literal
|
||||
_name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
|
||||
return repo_group.group_id, _name(repo_group.full_path_splitted)
|
||||
|
||||
|
|
|
|||
|
|
@ -2400,7 +2400,7 @@ class RepoGroup(Base, BaseModel):
|
|||
|
||||
@classmethod
|
||||
def _generate_choice(cls, repo_group):
|
||||
from webhelpers.html import literal as _literal
|
||||
from webhelpers2.html import literal as _literal
|
||||
_name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
|
||||
return repo_group.group_id, _name(repo_group.full_path_splitted)
|
||||
|
||||
|
|
|
|||
|
|
@ -2474,7 +2474,7 @@ class RepoGroup(Base, BaseModel):
|
|||
|
||||
@classmethod
|
||||
def _generate_choice(cls, repo_group):
|
||||
from webhelpers.html import literal as _literal
|
||||
from webhelpers2.html import literal as _literal
|
||||
_name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
|
||||
return repo_group.group_id, _name(repo_group.full_path_splitted)
|
||||
|
||||
|
|
|
|||
|
|
@ -2497,7 +2497,7 @@ class RepoGroup(Base, BaseModel):
|
|||
|
||||
@classmethod
|
||||
def _generate_choice(cls, repo_group):
|
||||
from webhelpers.html import literal as _literal
|
||||
from webhelpers2.html import literal as _literal
|
||||
_name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
|
||||
return repo_group.group_id, _name(repo_group.full_path_splitted)
|
||||
|
||||
|
|
|
|||
|
|
@ -2497,7 +2497,7 @@ class RepoGroup(Base, BaseModel):
|
|||
|
||||
@classmethod
|
||||
def _generate_choice(cls, repo_group):
|
||||
from webhelpers.html import literal as _literal
|
||||
from webhelpers2.html import literal as _literal
|
||||
_name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
|
||||
return repo_group.group_id, _name(repo_group.full_path_splitted)
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ from sqlalchemy.dialects.mysql import LONGTEXT
|
|||
from zope.cachedescriptors.property import Lazy as LazyProperty
|
||||
from pyramid import compat
|
||||
from pyramid.threadlocal import get_current_request
|
||||
from webhelpers.text import collapse, remove_formatting
|
||||
from webhelpers2.text import collapse, remove_formatting
|
||||
|
||||
from rhodecode.translation import _
|
||||
from rhodecode.lib.vcs import get_vcs_instance
|
||||
|
|
@ -2624,7 +2624,7 @@ class RepoGroup(Base, BaseModel):
|
|||
|
||||
@classmethod
|
||||
def _generate_choice(cls, repo_group):
|
||||
from webhelpers.html import literal as _literal
|
||||
from webhelpers2.html import literal as _literal
|
||||
_name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
|
||||
return repo_group.group_id, _name(repo_group.full_path_splitted)
|
||||
|
||||
|
|
|
|||
|
|
@ -2037,7 +2037,7 @@ class RepoGroup(Base, BaseModel):
|
|||
|
||||
@classmethod
|
||||
def _generate_choice(cls, repo_group):
|
||||
from webhelpers.html import literal as _literal
|
||||
from webhelpers2.html import literal as _literal
|
||||
_name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
|
||||
return repo_group.group_id, _name(repo_group.full_path_splitted)
|
||||
|
||||
|
|
|
|||
|
|
@ -2029,7 +2029,7 @@ class RepoGroup(Base, BaseModel):
|
|||
|
||||
@classmethod
|
||||
def _generate_choice(cls, repo_group):
|
||||
from webhelpers.html import literal as _literal
|
||||
from webhelpers2.html import literal as _literal
|
||||
_name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
|
||||
return repo_group.group_id, _name(repo_group.full_path_splitted)
|
||||
|
||||
|
|
|
|||
|
|
@ -2028,7 +2028,7 @@ class RepoGroup(Base, BaseModel):
|
|||
|
||||
@classmethod
|
||||
def _generate_choice(cls, repo_group):
|
||||
from webhelpers.html import literal as _literal
|
||||
from webhelpers2.html import literal as _literal
|
||||
_name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
|
||||
return repo_group.group_id, _name(repo_group.full_path_splitted)
|
||||
|
||||
|
|
|
|||
|
|
@ -2032,7 +2032,7 @@ class RepoGroup(Base, BaseModel):
|
|||
|
||||
@classmethod
|
||||
def _generate_choice(cls, repo_group):
|
||||
from webhelpers.html import literal as _literal
|
||||
from webhelpers2.html import literal as _literal
|
||||
_name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
|
||||
return repo_group.group_id, _name(repo_group.full_path_splitted)
|
||||
|
||||
|
|
|
|||
|
|
@ -2032,7 +2032,7 @@ class RepoGroup(Base, BaseModel):
|
|||
|
||||
@classmethod
|
||||
def _generate_choice(cls, repo_group):
|
||||
from webhelpers.html import literal as _literal
|
||||
from webhelpers2.html import literal as _literal
|
||||
_name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
|
||||
return repo_group.group_id, _name(repo_group.full_path_splitted)
|
||||
|
||||
|
|
|
|||
|
|
@ -2076,7 +2076,7 @@ class RepoGroup(Base, BaseModel):
|
|||
|
||||
@classmethod
|
||||
def _generate_choice(cls, repo_group):
|
||||
from webhelpers.html import literal as _literal
|
||||
from webhelpers2.html import literal as _literal
|
||||
_name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
|
||||
return repo_group.group_id, _name(repo_group.full_path_splitted)
|
||||
|
||||
|
|
|
|||
|
|
@ -2077,7 +2077,7 @@ class RepoGroup(Base, BaseModel):
|
|||
|
||||
@classmethod
|
||||
def _generate_choice(cls, repo_group):
|
||||
from webhelpers.html import literal as _literal
|
||||
from webhelpers2.html import literal as _literal
|
||||
_name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
|
||||
return repo_group.group_id, _name(repo_group.full_path_splitted)
|
||||
|
||||
|
|
|
|||
|
|
@ -2270,7 +2270,7 @@ class RepoGroup(Base, BaseModel):
|
|||
|
||||
@classmethod
|
||||
def _generate_choice(cls, repo_group):
|
||||
from webhelpers.html import literal as _literal
|
||||
from webhelpers2.html import literal as _literal
|
||||
_name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
|
||||
return repo_group.group_id, _name(repo_group.full_path_splitted)
|
||||
|
||||
|
|
|
|||
|
|
@ -53,25 +53,29 @@ from pygments.lexers import (
|
|||
|
||||
from pyramid.threadlocal import get_current_request
|
||||
|
||||
from webhelpers.html import literal, HTML, escape
|
||||
from webhelpers.html.tools import *
|
||||
from webhelpers.html.builder import make_tag
|
||||
from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
|
||||
end_form, file, form as wh_form, hidden, image, javascript_link, link_to, \
|
||||
link_to_if, link_to_unless, ol, required_legend, select, stylesheet_link, \
|
||||
submit, text, password, textarea, title, ul, xml_declaration, radio
|
||||
from webhelpers.html.tools import auto_link, button_to, highlight, \
|
||||
js_obfuscate, mail_to, strip_links, strip_tags, tag_re
|
||||
from webhelpers.text import chop_at, collapse, convert_accented_entities, \
|
||||
convert_misc_entities, lchop, plural, rchop, remove_formatting, \
|
||||
replace_whitespace, urlify, truncate, wrap_paragraphs
|
||||
from webhelpers.date import time_ago_in_words
|
||||
from webhelpers.paginate import Page as _Page
|
||||
from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
|
||||
convert_boolean_attrs, NotGiven, _make_safe_id_component
|
||||
from webhelpers2.html import literal, HTML, escape
|
||||
from webhelpers2.html._autolink import _auto_link_urls
|
||||
from webhelpers2.html.tools import (
|
||||
button_to, highlight, js_obfuscate, strip_links, strip_tags)
|
||||
|
||||
from webhelpers2.text import (
|
||||
chop_at, collapse, convert_accented_entities,
|
||||
convert_misc_entities, lchop, plural, rchop, remove_formatting,
|
||||
replace_whitespace, urlify, truncate, wrap_paragraphs)
|
||||
from webhelpers2.date import time_ago_in_words
|
||||
|
||||
from webhelpers2.html.tags import (
|
||||
_input, NotGiven, _make_safe_id_component as safeid,
|
||||
form as insecure_form,
|
||||
auto_discovery_link, checkbox, end_form, file,
|
||||
hidden, image, javascript_link, link_to, link_to_if, link_to_unless, ol,
|
||||
select as raw_select, stylesheet_link, submit, text, password, textarea,
|
||||
ul, radio, Options)
|
||||
|
||||
from webhelpers2.number import format_byte_size
|
||||
|
||||
from rhodecode.lib.action_parser import action_parser
|
||||
from rhodecode.lib.paginate import Page
|
||||
from rhodecode.lib.ext_json import json
|
||||
from rhodecode.lib.utils import repo_name_slug, get_custom_lexer
|
||||
from rhodecode.lib.utils2 import (
|
||||
|
|
@ -162,17 +166,42 @@ def shorter(text, size=20, prefix=False):
|
|||
return text
|
||||
|
||||
|
||||
def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
|
||||
def reset(name, value=None, id=NotGiven, type="reset", **attrs):
|
||||
"""
|
||||
Reset button
|
||||
"""
|
||||
_set_input_attrs(attrs, type, name, value)
|
||||
_set_id_attr(attrs, id, name)
|
||||
convert_boolean_attrs(attrs, ["disabled"])
|
||||
return HTML.input(**attrs)
|
||||
return _input(type, name, value, id, attrs)
|
||||
|
||||
reset = _reset
|
||||
safeid = _make_safe_id_component
|
||||
|
||||
def select(name, selected_values, options, id=NotGiven, **attrs):
|
||||
|
||||
if isinstance(options, (list, tuple)):
|
||||
options_iter = options
|
||||
# Handle old value,label lists ... where value also can be value,label lists
|
||||
options = Options()
|
||||
for opt in options_iter:
|
||||
if isinstance(opt, tuple) and len(opt) == 2:
|
||||
value, label = opt
|
||||
elif isinstance(opt, basestring):
|
||||
value = label = opt
|
||||
else:
|
||||
raise ValueError('invalid select option type %r' % type(opt))
|
||||
|
||||
if isinstance(value, (list, tuple)):
|
||||
option_group = options.add_optgroup(label)
|
||||
for opt2 in value:
|
||||
if isinstance(opt2, tuple) and len(opt2) == 2:
|
||||
group_value, group_label = opt
|
||||
elif isinstance(opt2, basestring):
|
||||
group_value = group_label = opt2
|
||||
else:
|
||||
raise ValueError('invalid select option type %r' % type(opt2))
|
||||
|
||||
option_group.add_option(group_label, group_value)
|
||||
else:
|
||||
options.add_option(label, value)
|
||||
|
||||
return raw_select(name, selected_values, options, id=id, **attrs)
|
||||
|
||||
|
||||
def branding(name, length=40):
|
||||
|
|
@ -1280,145 +1309,6 @@ def gravatar_url(email_address, size=30, request=None):
|
|||
return initials_gravatar(email_address, '', '', size=size)
|
||||
|
||||
|
||||
class Page(_Page):
|
||||
"""
|
||||
Custom pager to match rendering style with paginator
|
||||
"""
|
||||
|
||||
def _get_pos(self, cur_page, max_page, items):
|
||||
edge = (items / 2) + 1
|
||||
if (cur_page <= edge):
|
||||
radius = max(items / 2, items - cur_page)
|
||||
elif (max_page - cur_page) < edge:
|
||||
radius = (items - 1) - (max_page - cur_page)
|
||||
else:
|
||||
radius = items / 2
|
||||
|
||||
left = max(1, (cur_page - (radius)))
|
||||
right = min(max_page, cur_page + (radius))
|
||||
return left, cur_page, right
|
||||
|
||||
def _range(self, regexp_match):
|
||||
"""
|
||||
Return range of linked pages (e.g. '1 2 [3] 4 5 6 7 8').
|
||||
|
||||
Arguments:
|
||||
|
||||
regexp_match
|
||||
A "re" (regular expressions) match object containing the
|
||||
radius of linked pages around the current page in
|
||||
regexp_match.group(1) as a string
|
||||
|
||||
This function is supposed to be called as a callable in
|
||||
re.sub.
|
||||
|
||||
"""
|
||||
radius = int(regexp_match.group(1))
|
||||
|
||||
# Compute the first and last page number within the radius
|
||||
# e.g. '1 .. 5 6 [7] 8 9 .. 12'
|
||||
# -> leftmost_page = 5
|
||||
# -> rightmost_page = 9
|
||||
leftmost_page, _cur, rightmost_page = self._get_pos(self.page,
|
||||
self.last_page,
|
||||
(radius * 2) + 1)
|
||||
nav_items = []
|
||||
|
||||
# Create a link to the first page (unless we are on the first page
|
||||
# or there would be no need to insert '..' spacers)
|
||||
if self.page != self.first_page and self.first_page < leftmost_page:
|
||||
nav_items.append(self._pagerlink(self.first_page, self.first_page))
|
||||
|
||||
# Insert dots if there are pages between the first page
|
||||
# and the currently displayed page range
|
||||
if leftmost_page - self.first_page > 1:
|
||||
# Wrap in a SPAN tag if nolink_attr is set
|
||||
text = '..'
|
||||
if self.dotdot_attr:
|
||||
text = HTML.span(c=text, **self.dotdot_attr)
|
||||
nav_items.append(text)
|
||||
|
||||
for thispage in xrange(leftmost_page, rightmost_page + 1):
|
||||
# Hilight the current page number and do not use a link
|
||||
if thispage == self.page:
|
||||
text = '%s' % (thispage,)
|
||||
# Wrap in a SPAN tag if nolink_attr is set
|
||||
if self.curpage_attr:
|
||||
text = HTML.span(c=text, **self.curpage_attr)
|
||||
nav_items.append(text)
|
||||
# Otherwise create just a link to that page
|
||||
else:
|
||||
text = '%s' % (thispage,)
|
||||
nav_items.append(self._pagerlink(thispage, text))
|
||||
|
||||
# Insert dots if there are pages between the displayed
|
||||
# page numbers and the end of the page range
|
||||
if self.last_page - rightmost_page > 1:
|
||||
text = '..'
|
||||
# Wrap in a SPAN tag if nolink_attr is set
|
||||
if self.dotdot_attr:
|
||||
text = HTML.span(c=text, **self.dotdot_attr)
|
||||
nav_items.append(text)
|
||||
|
||||
# Create a link to the very last page (unless we are on the last
|
||||
# page or there would be no need to insert '..' spacers)
|
||||
if self.page != self.last_page and rightmost_page < self.last_page:
|
||||
nav_items.append(self._pagerlink(self.last_page, self.last_page))
|
||||
|
||||
## prerender links
|
||||
#_page_link = url.current()
|
||||
#nav_items.append(literal('<link rel="prerender" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
|
||||
#nav_items.append(literal('<link rel="prefetch" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
|
||||
return self.separator.join(nav_items)
|
||||
|
||||
def pager(self, format='~2~', page_param='page', partial_param='partial',
|
||||
show_if_single_page=False, separator=' ', onclick=None,
|
||||
symbol_first='<<', symbol_last='>>',
|
||||
symbol_previous='<', symbol_next='>',
|
||||
link_attr={'class': 'pager_link', 'rel': 'prerender'},
|
||||
curpage_attr={'class': 'pager_curpage'},
|
||||
dotdot_attr={'class': 'pager_dotdot'}, **kwargs):
|
||||
|
||||
self.curpage_attr = curpage_attr
|
||||
self.separator = separator
|
||||
self.pager_kwargs = kwargs
|
||||
self.page_param = page_param
|
||||
self.partial_param = partial_param
|
||||
self.onclick = onclick
|
||||
self.link_attr = link_attr
|
||||
self.dotdot_attr = dotdot_attr
|
||||
|
||||
# Don't show navigator if there is no more than one page
|
||||
if self.page_count == 0 or (self.page_count == 1 and not show_if_single_page):
|
||||
return ''
|
||||
|
||||
from string import Template
|
||||
# Replace ~...~ in token format by range of pages
|
||||
result = re.sub(r'~(\d+)~', self._range, format)
|
||||
|
||||
# Interpolate '%' variables
|
||||
result = Template(result).safe_substitute({
|
||||
'first_page': self.first_page,
|
||||
'last_page': self.last_page,
|
||||
'page': self.page,
|
||||
'page_count': self.page_count,
|
||||
'items_per_page': self.items_per_page,
|
||||
'first_item': self.first_item,
|
||||
'last_item': self.last_item,
|
||||
'item_count': self.item_count,
|
||||
'link_first': self.page > self.first_page and \
|
||||
self._pagerlink(self.first_page, symbol_first) or '',
|
||||
'link_last': self.page < self.last_page and \
|
||||
self._pagerlink(self.last_page, symbol_last) or '',
|
||||
'link_previous': self.previous_page and \
|
||||
self._pagerlink(self.previous_page, symbol_previous) \
|
||||
or HTML.span(symbol_previous, class_="pg-previous disabled"),
|
||||
'link_next': self.next_page and \
|
||||
self._pagerlink(self.next_page, symbol_next) \
|
||||
or HTML.span(symbol_next, class_="pg-next disabled")
|
||||
})
|
||||
|
||||
return literal(result)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
|
|
@ -1564,11 +1454,9 @@ def format_byte_size_binary(file_size):
|
|||
return formatted_size
|
||||
|
||||
|
||||
def urlify_text(text_, safe=True):
|
||||
def urlify_text(text_, safe=True, **href_attrs):
|
||||
"""
|
||||
Extrac urls from text and make html links out of them
|
||||
|
||||
:param text_:
|
||||
Extract urls from text and make html links out of them
|
||||
"""
|
||||
|
||||
url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@#.&+]'''
|
||||
|
|
@ -1576,8 +1464,13 @@ def urlify_text(text_, safe=True):
|
|||
|
||||
def url_func(match_obj):
|
||||
url_full = match_obj.groups()[0]
|
||||
return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
|
||||
a_options = dict(href_attrs)
|
||||
a_options['href'] = url_full
|
||||
a_text = url_full
|
||||
return HTML.tag("a", a_text, **a_options)
|
||||
|
||||
_new_text = url_pat.sub(url_func, text_)
|
||||
|
||||
if safe:
|
||||
return literal(_new_text)
|
||||
return _new_text
|
||||
|
|
@ -1939,7 +1832,7 @@ def form(url, method='post', needs_csrf_token=True, **attrs):
|
|||
'CSRF token. If the endpoint does not require such token you can ' +
|
||||
'explicitly set the parameter needs_csrf_token to false.')
|
||||
|
||||
return wh_form(url, method=method, **attrs)
|
||||
return insecure_form(url, method=method, **attrs)
|
||||
|
||||
|
||||
def secure_form(form_url, method="POST", multipart=False, **attrs):
|
||||
|
|
@ -1961,7 +1854,6 @@ def secure_form(form_url, method="POST", multipart=False, **attrs):
|
|||
over POST.
|
||||
|
||||
"""
|
||||
from webhelpers.pylonslib.secure_form import insecure_form
|
||||
|
||||
if 'request' in attrs:
|
||||
session = attrs['request'].session
|
||||
|
|
@ -1970,12 +1862,12 @@ def secure_form(form_url, method="POST", multipart=False, **attrs):
|
|||
raise ValueError(
|
||||
'Calling this form requires request= to be passed as argument')
|
||||
|
||||
form = insecure_form(form_url, method, multipart, **attrs)
|
||||
_form = insecure_form(form_url, method, multipart, **attrs)
|
||||
token = literal(
|
||||
'<input type="hidden" id="{}" name="{}" value="{}">'.format(
|
||||
csrf_token_key, csrf_token_key, get_csrf_token(session)))
|
||||
'<input type="hidden" name="{}" value="{}">'.format(
|
||||
csrf_token_key, get_csrf_token(session)))
|
||||
|
||||
return literal("%s\n%s" % (form, token))
|
||||
return literal("%s\n%s" % (_form, token))
|
||||
|
||||
|
||||
def dropdownmenu(name, selected, options, enable_filter=False, **attrs):
|
||||
|
|
|
|||
165
rhodecode/lib/paginate.py
Normal file
165
rhodecode/lib/paginate.py
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2010-2019 RhodeCode GmbH
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License, version 3
|
||||
# (only), as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# This program is dual-licensed. If you wish to learn more about the
|
||||
# RhodeCode Enterprise Edition, including its added features, Support services,
|
||||
# and proprietary license terms, please see https://rhodecode.com/licenses/
|
||||
import re
|
||||
|
||||
from webhelpers.paginate import Page as _Page
|
||||
from webhelpers.paginate import PageURL
|
||||
from webhelpers2.html import literal, HTML
|
||||
|
||||
|
||||
class Page(_Page):
|
||||
"""
|
||||
Custom pager to match rendering style with paginator
|
||||
"""
|
||||
|
||||
def _get_pos(self, cur_page, max_page, items):
|
||||
edge = (items / 2) + 1
|
||||
if (cur_page <= edge):
|
||||
radius = max(items / 2, items - cur_page)
|
||||
elif (max_page - cur_page) < edge:
|
||||
radius = (items - 1) - (max_page - cur_page)
|
||||
else:
|
||||
radius = items / 2
|
||||
|
||||
left = max(1, (cur_page - (radius)))
|
||||
right = min(max_page, cur_page + (radius))
|
||||
return left, cur_page, right
|
||||
|
||||
def _range(self, regexp_match):
|
||||
"""
|
||||
Return range of linked pages (e.g. '1 2 [3] 4 5 6 7 8').
|
||||
|
||||
Arguments:
|
||||
|
||||
regexp_match
|
||||
A "re" (regular expressions) match object containing the
|
||||
radius of linked pages around the current page in
|
||||
regexp_match.group(1) as a string
|
||||
|
||||
This function is supposed to be called as a callable in
|
||||
re.sub.
|
||||
|
||||
"""
|
||||
radius = int(regexp_match.group(1))
|
||||
|
||||
# Compute the first and last page number within the radius
|
||||
# e.g. '1 .. 5 6 [7] 8 9 .. 12'
|
||||
# -> leftmost_page = 5
|
||||
# -> rightmost_page = 9
|
||||
leftmost_page, _cur, rightmost_page = self._get_pos(self.page,
|
||||
self.last_page,
|
||||
(radius * 2) + 1)
|
||||
nav_items = []
|
||||
|
||||
# Create a link to the first page (unless we are on the first page
|
||||
# or there would be no need to insert '..' spacers)
|
||||
if self.page != self.first_page and self.first_page < leftmost_page:
|
||||
nav_items.append(self._pagerlink(self.first_page, self.first_page))
|
||||
|
||||
# Insert dots if there are pages between the first page
|
||||
# and the currently displayed page range
|
||||
if leftmost_page - self.first_page > 1:
|
||||
# Wrap in a SPAN tag if nolink_attr is set
|
||||
text = '..'
|
||||
if self.dotdot_attr:
|
||||
text = HTML.span(c=text, **self.dotdot_attr)
|
||||
nav_items.append(text)
|
||||
|
||||
for thispage in xrange(leftmost_page, rightmost_page + 1):
|
||||
# Hilight the current page number and do not use a link
|
||||
if thispage == self.page:
|
||||
text = '%s' % (thispage,)
|
||||
# Wrap in a SPAN tag if nolink_attr is set
|
||||
if self.curpage_attr:
|
||||
text = HTML.span(c=text, **self.curpage_attr)
|
||||
nav_items.append(text)
|
||||
# Otherwise create just a link to that page
|
||||
else:
|
||||
text = '%s' % (thispage,)
|
||||
nav_items.append(self._pagerlink(thispage, text))
|
||||
|
||||
# Insert dots if there are pages between the displayed
|
||||
# page numbers and the end of the page range
|
||||
if self.last_page - rightmost_page > 1:
|
||||
text = '..'
|
||||
# Wrap in a SPAN tag if nolink_attr is set
|
||||
if self.dotdot_attr:
|
||||
text = HTML.span(c=text, **self.dotdot_attr)
|
||||
nav_items.append(text)
|
||||
|
||||
# Create a link to the very last page (unless we are on the last
|
||||
# page or there would be no need to insert '..' spacers)
|
||||
if self.page != self.last_page and rightmost_page < self.last_page:
|
||||
nav_items.append(self._pagerlink(self.last_page, self.last_page))
|
||||
|
||||
## prerender links
|
||||
#_page_link = url.current()
|
||||
#nav_items.append(literal('<link rel="prerender" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
|
||||
#nav_items.append(literal('<link rel="prefetch" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
|
||||
return self.separator.join(nav_items)
|
||||
|
||||
def pager(self, format='~2~', page_param='page', partial_param='partial',
|
||||
show_if_single_page=False, separator=' ', onclick=None,
|
||||
symbol_first='<<', symbol_last='>>',
|
||||
symbol_previous='<', symbol_next='>',
|
||||
link_attr={'class': 'pager_link', 'rel': 'prerender'},
|
||||
curpage_attr={'class': 'pager_curpage'},
|
||||
dotdot_attr={'class': 'pager_dotdot'}, **kwargs):
|
||||
|
||||
self.curpage_attr = curpage_attr
|
||||
self.separator = separator
|
||||
self.pager_kwargs = kwargs
|
||||
self.page_param = page_param
|
||||
self.partial_param = partial_param
|
||||
self.onclick = onclick
|
||||
self.link_attr = link_attr
|
||||
self.dotdot_attr = dotdot_attr
|
||||
|
||||
# Don't show navigator if there is no more than one page
|
||||
if self.page_count == 0 or (self.page_count == 1 and not show_if_single_page):
|
||||
return ''
|
||||
|
||||
from string import Template
|
||||
# Replace ~...~ in token format by range of pages
|
||||
result = re.sub(r'~(\d+)~', self._range, format)
|
||||
|
||||
# Interpolate '%' variables
|
||||
result = Template(result).safe_substitute({
|
||||
'first_page': self.first_page,
|
||||
'last_page': self.last_page,
|
||||
'page': self.page,
|
||||
'page_count': self.page_count,
|
||||
'items_per_page': self.items_per_page,
|
||||
'first_item': self.first_item,
|
||||
'last_item': self.last_item,
|
||||
'item_count': self.item_count,
|
||||
'link_first': self.page > self.first_page and \
|
||||
self._pagerlink(self.first_page, symbol_first) or '',
|
||||
'link_last': self.page < self.last_page and \
|
||||
self._pagerlink(self.last_page, symbol_last) or '',
|
||||
'link_previous': self.previous_page and \
|
||||
self._pagerlink(self.previous_page, symbol_previous) \
|
||||
or HTML.span(symbol_previous, class_="pg-previous disabled"),
|
||||
'link_next': self.next_page and \
|
||||
self._pagerlink(self.next_page, symbol_next) \
|
||||
or HTML.span(symbol_next, class_="pg-next disabled")
|
||||
})
|
||||
|
||||
return literal(result)
|
||||
|
|
@ -39,7 +39,7 @@ from os.path import join as jn
|
|||
|
||||
import paste
|
||||
import pkg_resources
|
||||
from webhelpers.text import collapse, remove_formatting, strip_tags
|
||||
from webhelpers2.text import collapse, remove_formatting
|
||||
from mako import exceptions
|
||||
from pyramid.threadlocal import get_current_registry
|
||||
from rhodecode.lib.request import Request
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ from sqlalchemy.dialects.mysql import LONGTEXT
|
|||
from zope.cachedescriptors.property import Lazy as LazyProperty
|
||||
from pyramid import compat
|
||||
from pyramid.threadlocal import get_current_request
|
||||
from webhelpers.text import collapse, remove_formatting
|
||||
from webhelpers2.text import remove_formatting
|
||||
|
||||
from rhodecode.translation import _
|
||||
from rhodecode.lib.vcs import get_vcs_instance
|
||||
|
|
@ -2675,7 +2675,7 @@ class RepoGroup(Base, BaseModel):
|
|||
|
||||
@classmethod
|
||||
def _generate_choice(cls, repo_group):
|
||||
from webhelpers.html import literal as _literal
|
||||
from webhelpers2.html import literal as _literal
|
||||
_name = lambda k: _literal(cls.CHOICES_SEPARATOR.join(k))
|
||||
return repo_group.group_id, _name(repo_group.full_path_splitted)
|
||||
|
||||
|
|
|
|||
|
|
@ -29,11 +29,14 @@ from rhodecode.tests import no_newline_id_generator
|
|||
|
||||
|
||||
@pytest.mark.parametrize('url, expected_url', [
|
||||
('http://rc.rc/test', '<a href="http://rc.rc/test">http://rc.rc/test</a>'),
|
||||
('http://rc.rc/@foo', '<a href="http://rc.rc/@foo">http://rc.rc/@foo</a>'),
|
||||
('http://rc.rc/!foo', '<a href="http://rc.rc/!foo">http://rc.rc/!foo</a>'),
|
||||
('http://rc.rc/&foo', '<a href="http://rc.rc/&foo">http://rc.rc/&foo</a>'),
|
||||
('http://rc.rc/#foo', '<a href="http://rc.rc/#foo">http://rc.rc/#foo</a>'),
|
||||
('http://rc.com', '<a href="http://rc.com">http://rc.com</a>'),
|
||||
('http://rc.com/test', '<a href="http://rc.com/test">http://rc.com/test</a>'),
|
||||
('http://rc.com/!foo', '<a href="http://rc.com/!foo">http://rc.com/!foo</a>'),
|
||||
('http://rc.com/&foo', '<a href="http://rc.com/&foo">http://rc.com/&foo</a>'),
|
||||
('http://rc.com/?foo-1&bar=1', '<a href="http://rc.com/?foo-1&bar=1">http://rc.com/?foo-1&bar=1</a>'),
|
||||
('http://rc.com?foo-1&bar=1', '<a href="http://rc.com?foo-1&bar=1">http://rc.com?foo-1&bar=1</a>'),
|
||||
('http://rc.com/#foo', '<a href="http://rc.com/#foo">http://rc.com/#foo</a>'),
|
||||
('http://rc.com/@foo', '<a href="http://rc.com/@foo">http://rc.com/@foo</a>'),
|
||||
])
|
||||
def test_urlify_text(url, expected_url):
|
||||
assert helpers.urlify_text(url) == expected_url
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import psutil
|
|||
import logging
|
||||
import socket
|
||||
|
||||
from webhelpers.number import format_byte_size
|
||||
from webhelpers2.number import format_byte_size
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue