##// END OF EJS Templates
fixes for #99, added casting to unicode for int chars as utf-8 files
fixes for #99, added casting to unicode for int chars as utf-8 files

File last commit:

r955:129eb072 beta
r955:129eb072 beta
Show More
helpers.py
528 lines | 18.7 KiB | text/x-python | PythonLexer
renamed project to rhodecode
r547 """Helper functions
Consists of functions to typically be used within templates, but also
available to Controllers. This module is available to both as 'h'.
"""
implemented user dashboards, and following system.
r734 import random
import hashlib
renamed project to rhodecode
r547 from pygments.formatters import HtmlFormatter
from pygments import highlight as code_highlight
from pylons import url, app_globals as g
from pylons.i18n.translation import _, ungettext
from vcs.utils.annotate import annotate_highlight
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, 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.number import format_byte_size, format_bit_size
from webhelpers.pylonslib import Flash as _Flash
from webhelpers.pylonslib.secure_form import secure_form
from webhelpers.text import chop_at, collapse, convert_accented_entities, \
convert_misc_entities, lchop, plural, rchop, remove_formatting, \
replace_whitespace, urlify, truncate, wrap_paragraphs
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 from webhelpers.date import time_ago_in_words
renamed project to rhodecode
r547
fixes #65, Added reset buttons to edit forms
r698 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
convert_boolean_attrs, NotGiven
def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
Added message tooltip into journal revisions in push....
r899 """Reset button
"""
fixes #65, Added reset buttons to edit forms
r698 _set_input_attrs(attrs, type, name, value)
_set_id_attr(attrs, id, name)
convert_boolean_attrs(attrs, ["disabled"])
return HTML.input(**attrs)
reset = _reset
implemented user dashboards, and following system.
r734
def get_token():
"""Return the current authentication token, creating one if one doesn't
already exist.
"""
token_key = "_authentication_token"
from pylons import session
if not token_key in session:
try:
token = hashlib.sha1(str(random.getrandbits(128))).hexdigest()
except AttributeError: # Python < 2.4
token = hashlib.sha1(str(random.randrange(2 ** 128))).hexdigest()
session[token_key] = token
if hasattr(session, 'save'):
session.save()
return session[token_key]
renamed project to rhodecode
r547 class _GetError(object):
Added message tooltip into journal revisions in push....
r899 """Get error from form_errors, and represent it as span wrapped error
message
:param field_name: field to fetch errors for
:param form_errors: form errors dict
"""
renamed project to rhodecode
r547
def __call__(self, field_name, form_errors):
tmpl = """<span class="error_msg">%s</span>"""
if form_errors and form_errors.has_key(field_name):
return literal(tmpl % form_errors.get(field_name))
get_error = _GetError()
def recursive_replace(str, replace=' '):
Added message tooltip into journal revisions in push....
r899 """Recursive replace of given sign to just one instance
fixed @repo into :repo for docs...
r604 :param str: given string
Added message tooltip into journal revisions in push....
r899 :param replace: char to find and replace multiple instances
renamed project to rhodecode
r547
Examples::
>>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
'Mighty-Mighty-Bo-sstones'
"""
if str.find(replace * 2) == -1:
return str
else:
str = str.replace(replace * 2, replace)
Hacking for git support,and new faster repo scan
r631 return recursive_replace(str, replace)
renamed project to rhodecode
r547
class _ToolTip(object):
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 def __call__(self, tooltip_title, trim_at=50):
added wrapping of long tooltips in index page
r905 """Special function just to wrap our text into nice formatted
autowrapped text
fixed @repo into :repo for docs...
r604 :param tooltip_title:
renamed project to rhodecode
r547 """
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 return wrap_paragraphs(escape(tooltip_title), trim_at)\
.replace('\n', '<br/>')
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 def activate(self):
reimplemented tooltip, refactored tooltip_title into title for proper html,...
r904 """Adds tooltip mechanism to the given Html all tooltips have to have
set class `tooltip` and set attribute `tooltip_title`.
Then a tooltip will be generated based on that. All with yui js tooltip
renamed project to rhodecode
r547 """
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 js = '''
YAHOO.util.Event.onDOMReady(function(){
function toolTipsId(){
var ids = [];
var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
for (var i = 0; i < tts.length; i++) {
reimplemented tooltip, refactored tooltip_title into title for proper html,...
r904 //if element doesn't not have and id autogenerate one for tooltip
renamed project to rhodecode
r547
if (!tts[i].id){
tts[i].id='tt'+i*100;
}
ids.push(tts[i].id);
}
return ids
};
var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
context: toolTipsId(),
monitorresize:false,
xyoffset :[0,0],
autodismissdelay:300000,
hidedelay:5,
showdelay:20,
});
// Set the text for the tooltip just before we display it. Lazy method
myToolTips.contextTriggerEvent.subscribe(
function(type, args) {
var context = args[0];
reimplemented tooltip, refactored tooltip_title into title for proper html,...
r904 //positioning of tooltip
var tt_w = this.element.clientWidth;//tooltip width
var tt_h = this.element.clientHeight;//tooltip height
renamed project to rhodecode
r547
var context_w = context.offsetWidth;
var context_h = context.offsetHeight;
var pos_x = YAHOO.util.Dom.getX(context);
var pos_y = YAHOO.util.Dom.getY(context);
reimplemented tooltip, refactored tooltip_title into title for proper html,...
r904 var display_strategy = 'right';
renamed project to rhodecode
r547 var xy_pos = [0,0];
switch (display_strategy){
case 'top':
var cur_x = (pos_x+context_w/2)-(tt_w/2);
reimplemented tooltip, refactored tooltip_title into title for proper html,...
r904 var cur_y = (pos_y-tt_h-4);
renamed project to rhodecode
r547 xy_pos = [cur_x,cur_y];
break;
case 'bottom':
var cur_x = (pos_x+context_w/2)-(tt_w/2);
var cur_y = pos_y+context_h+4;
xy_pos = [cur_x,cur_y];
break;
case 'left':
var cur_x = (pos_x-tt_w-4);
var cur_y = pos_y-((tt_h/2)-context_h/2);
xy_pos = [cur_x,cur_y];
break;
case 'right':
var cur_x = (pos_x+context_w+4);
var cur_y = pos_y-((tt_h/2)-context_h/2);
xy_pos = [cur_x,cur_y];
break;
default:
var cur_x = (pos_x+context_w/2)-(tt_w/2);
var cur_y = pos_y-tt_h-4;
xy_pos = [cur_x,cur_y];
break;
}
this.cfg.setProperty("xy",xy_pos);
});
//Mouse out
myToolTips.contextMouseOutEvent.subscribe(
function(type, args) {
var context = args[0];
});
});
Hacking for git support,and new faster repo scan
r631 '''
renamed project to rhodecode
r547 return literal(js)
tooltip = _ToolTip()
class _FilesBreadCrumbs(object):
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 def __call__(self, repo_name, rev, paths):
fixes for #99, added casting to unicode for int chars as utf-8 files
r955 if isinstance(paths, str):
paths = paths.decode('utf-8')
renamed project to rhodecode
r547 url_l = [link_to(repo_name, url('files_home',
repo_name=repo_name,
revision=rev, f_path=''))]
paths_l = paths.split('/')
fixed python2.5 incompatible enumerate calls
r740 for cnt, p in enumerate(paths_l):
renamed project to rhodecode
r547 if p != '':
url_l.append(link_to(p, url('files_home',
repo_name=repo_name,
revision=rev,
fixed python2.5 incompatible enumerate calls
r740 f_path='/'.join(paths_l[:cnt + 1]))))
renamed project to rhodecode
r547
return literal('/'.join(url_l))
files_breadcrumbs = _FilesBreadCrumbs()
Added message tooltip into journal revisions in push....
r899
renamed project to rhodecode
r547 class CodeHtmlFormatter(HtmlFormatter):
def wrap(self, source, outfile):
return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
def _wrap_code(self, source):
fixed python2.5 incompatible enumerate calls
r740 for cnt, it in enumerate(source):
renamed project to rhodecode
r547 i, t = it
fixed python2.5 incompatible enumerate calls
r740 t = '<div id="#S-%s">%s</div>' % (cnt + 1, t)
renamed project to rhodecode
r547 yield i, t
def pygmentize(filenode, **kwargs):
Added message tooltip into journal revisions in push....
r899 """pygmentize function using pygments
fixed @repo into :repo for docs...
r604 :param filenode:
renamed project to rhodecode
r547 """
Added message tooltip into journal revisions in push....
r899
renamed project to rhodecode
r547 return literal(code_highlight(filenode.content,
filenode.lexer, CodeHtmlFormatter(**kwargs)))
def pygmentize_annotation(filenode, **kwargs):
Added message tooltip into journal revisions in push....
r899 """pygmentize function for annotation
fixed @repo into :repo for docs...
r604 :param filenode:
renamed project to rhodecode
r547 """
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 color_dict = {}
Fixed whoosh daemon, for depracated walk method
r947 def gen_color(n=10000):
"""generator for getting n of evenly distributed colors using
hsv color and golden ratio. It always return same order of colors
:returns: RGB tuple
Hacking for git support,and new faster repo scan
r631 """
renamed project to rhodecode
r547 import colorsys
golden_ratio = 0.618033988749895
h = 0.22717784590367374
Fixed whoosh daemon, for depracated walk method
r947
renamed project to rhodecode
r547 for c in xrange(n):
h += golden_ratio
h %= 1
HSV_tuple = [h, 0.95, 0.95]
RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
Hacking for git support,and new faster repo scan
r631 yield map(lambda x:str(int(x * 256)), RGB_tuple)
renamed project to rhodecode
r547
cgenerator = gen_color()
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 def get_color_string(cs):
if color_dict.has_key(cs):
col = color_dict[cs]
else:
col = color_dict[cs] = cgenerator.next()
return "color: rgb(%s)! important;" % (', '.join(col))
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 def url_func(changeset):
tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
Hacking for git support,and new faster repo scan
r631 " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
renamed project to rhodecode
r547 tooltip_html = tooltip_html % (changeset.author,
changeset.date,
tooltip(changeset.message))
fixed annotation bug, added history to annotation....
r662 lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
short_id(changeset.raw_id))
renamed project to rhodecode
r547 uri = link_to(
lnk_format,
url('changeset_home', repo_name=changeset.repository.name,
Fixes for raw_id, needed for git...
r636 revision=changeset.raw_id),
style=get_color_string(changeset.raw_id),
renamed project to rhodecode
r547 class_='tooltip',
reimplemented tooltip, refactored tooltip_title into title for proper html,...
r904 title=tooltip_html
renamed project to rhodecode
r547 )
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 uri += '\n'
Hacking for git support,and new faster repo scan
r631 return uri
renamed project to rhodecode
r547 return literal(annotate_highlight(filenode, url_func, **kwargs))
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 def repo_name_slug(value):
"""Return slug of name of repository
This function is called on each creation/modification
of repository to prevent bad names in repo
"""
Added message tooltip into journal revisions in push....
r899
renamed project to rhodecode
r547 slug = remove_formatting(value)
slug = strip_tags(slug)
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
slug = slug.replace(c, '-')
slug = recursive_replace(slug, '-')
slug = collapse(slug, '-')
return slug
def get_changeset_safe(repo, rev):
from vcs.backends.base import BaseRepository
from vcs.exceptions import RepositoryError
if not isinstance(repo, BaseRepository):
raise Exception('You must pass an Repository '
'object as first argument got %s', type(repo))
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 try:
cs = repo.get_changeset(rev)
except RepositoryError:
from rhodecode.lib.utils import EmptyChangeset
cs = EmptyChangeset()
return cs
flash = _Flash()
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 #==============================================================================
renamed project to rhodecode
r547 # MERCURIAL FILTERS available via h.
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 #==============================================================================
renamed project to rhodecode
r547 from mercurial import util
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 from mercurial.templatefilters import person as _person
def _age(curdate):
"""turns a datetime into an age string."""
#48 rewrote action logger, translated action logger messages, added some extra messages. Linked and showed pushed revisions in logs
r660
updated setup for all newest versions...
r643 if not curdate:
return ''
renamed project to rhodecode
r547
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 from datetime import timedelta, datetime
updated setup for all newest versions...
r643
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 agescales = [("year", 3600 * 24 * 365),
fixed a bug when age of last change is less than one minute
r653 ("month", 3600 * 24 * 30),
("day", 3600 * 24),
("hour", 3600),
("minute", 60),
("second", 1), ]
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635
age = datetime.now() - curdate
age_seconds = (age.days * agescales[2][1]) + age.seconds
pos = 1
for scale in agescales:
if scale[1] <= age_seconds:
fixed a bug when age of last change is less than one minute
r653 if pos == 6:pos = 5
fixed deletion of repository on filesystem, works based on scm type for git and hg....
r668 return time_ago_in_words(curdate, agescales[pos][0]) + ' ' + _('ago')
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 pos += 1
fixed deletion of repository on filesystem, works based on scm type for git and hg....
r668 return _('just now')
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 age = lambda x:_age(x)
renamed project to rhodecode
r547 capitalize = lambda x: x.capitalize()
email = util.email
email_or_none = lambda x: util.email(x) if util.email(x) != x else None
person = lambda x: _person(x)
Fixes for raw_id, needed for git...
r636 short_id = lambda x: x[:12]
renamed project to rhodecode
r547
#48 rewrote action logger, translated action logger messages, added some extra messages. Linked and showed pushed revisions in logs
r660
Added ldap info on admin users, added bool2icon helper for nicer representation of...
r712 def bool2icon(value):
Added message tooltip into journal revisions in push....
r899 """Returns True/False values represented as small html image of true/false
Added ldap info on admin users, added bool2icon helper for nicer representation of...
r712 icons
Added message tooltip into journal revisions in push....
r899
Added ldap info on admin users, added bool2icon helper for nicer representation of...
r712 :param value: bool value
"""
if value is True:
html w3c fixes
r714 return HTML.tag('img', src="/images/icons/accept.png", alt=_('True'))
Added ldap info on admin users, added bool2icon helper for nicer representation of...
r712
if value is False:
html w3c fixes
r714 return HTML.tag('img', src="/images/icons/cancel.png", alt=_('False'))
Added ldap info on admin users, added bool2icon helper for nicer representation of...
r712
return value
#48 rewrote action logger, translated action logger messages, added some extra messages. Linked and showed pushed revisions in logs
r660 def action_parser(user_log):
Added message tooltip into journal revisions in push....
r899 """This helper will map the specified string action into translated
#48 rewrote action logger, translated action logger messages, added some extra messages. Linked and showed pushed revisions in logs
r660 fancy names with icons and links
Added message tooltip into journal revisions in push....
r899 :param user_log: user log instance
#48 rewrote action logger, translated action logger messages, added some extra messages. Linked and showed pushed revisions in logs
r660 """
Added message tooltip into journal revisions in push....
r899
#48 rewrote action logger, translated action logger messages, added some extra messages. Linked and showed pushed revisions in logs
r660 action = user_log.action
action logger upgrade, for working with migrations
r840 action_params = ' '
#48 rewrote action logger, translated action logger messages, added some extra messages. Linked and showed pushed revisions in logs
r660
x = action.split(':')
if len(x) > 1:
action, action_params = x
Added fork name to journal...
r718 def get_cs_links():
fixed vcs import....
r953 revs_limit = 5 #display this amount always
revs_top_limit = 50 #show upto this amount of changesets hidden
revs = action_params.split(',')
repo_name = user_log.repository.repo_name
from rhodecode.model.scm import ScmModel
Added message tooltip into journal revisions in push....
r899
fixed vcs import....
r953 message = lambda rev: get_changeset_safe(ScmModel().get(repo_name),
rev).message
Added message tooltip into journal revisions in push....
r899
fixed vcs import....
r953 cs_links = " " + ', '.join ([link_to(rev,
url('changeset_home',
repo_name=repo_name,
revision=rev), title=tooltip(message(rev)),
class_='tooltip') for rev in revs[:revs_limit] ])
if len(revs) > revs_limit:
uniq_id = revs[0]
html_tmpl = ('<span> %s '
'<a class="show_more" id="_%s" href="#">%s</a> '
'%s</span>')
cs_links += html_tmpl % (_('and'), uniq_id, _('%s more') \
% (len(revs) - revs_limit),
_('revisions'))
added icons to journal, extend show more to actually show more pushed revisions,
r808
fixed vcs import....
r953 html_tmpl = '<span id="%s" style="display:none"> %s </span>'
cs_links += html_tmpl % (uniq_id, ', '.join([link_to(rev,
url('changeset_home',
repo_name=repo_name, revision=rev),
title=message(rev), class_='tooltip')
for rev in revs[revs_limit:revs_top_limit]]))
implemented user dashboards, and following system.
r734
fixed vcs import....
r953 return cs_links
implemented user dashboards, and following system.
r734
Added fork name to journal...
r718 def get_fork_name():
fixed vcs import....
r953 from rhodecode.model.scm import ScmModel
repo_name = action_params
repo = ScmModel().get(repo_name)
if repo is None:
return repo_name
return link_to(action_params, url('summary_home',
repo_name=repo.name,),
title=repo.dbrepo.description)
map = {'user_deleted_repo':(_('User [deleted] repository'), None),
'user_created_repo':(_('User [created] repository'), None),
'user_forked_repo':(_('User [forked] repository as:'), get_fork_name),
'user_updated_repo':(_('User [updated] repository'), None),
'admin_deleted_repo':(_('Admin [delete] repository'), None),
'admin_created_repo':(_('Admin [created] repository'), None),
'admin_forked_repo':(_('Admin [forked] repository'), None),
'admin_updated_repo':(_('Admin [updated] repository'), None),
'push':(_('[Pushed]'), get_cs_links),
'pull':(_('[Pulled]'), None),
'started_following_repo':(_('User [started following] repository'), None),
'stopped_following_repo':(_('User [stopped following] repository'), None),
added action loggers to following repositories,...
r735 }
#48 rewrote action logger, translated action logger messages, added some extra messages. Linked and showed pushed revisions in logs
r660
some stylings to journal
r764 action_str = map.get(action, action)
fixed vcs import....
r953 action = action_str[0].replace('[', '<span class="journal_highlight">')\
.replace(']', '</span>')
if action_str[1] is not None:
action = action + " " + action_str[1]()
return literal(action)
added icons to journal, extend show more to actually show more pushed revisions,
r808
def action_parser_icon(user_log):
action = user_log.action
action_params = None
x = action.split(':')
if len(x) > 1:
action, action_params = x
fixed some w3c html
r817 tmpl = """<img src="/images/icons/%s" alt="%s"/>"""
added icons to journal, extend show more to actually show more pushed revisions,
r808 map = {'user_deleted_repo':'database_delete.png',
'user_created_repo':'database_add.png',
'user_forked_repo':'arrow_divide.png',
'user_updated_repo':'database_edit.png',
'admin_deleted_repo':'database_delete.png',
Added message tooltip into journal revisions in push....
r899 'admin_created_repo':'database_add.png',
added icons to journal, extend show more to actually show more pushed revisions,
r808 'admin_forked_repo':'arrow_divide.png',
'admin_updated_repo':'database_edit.png',
'push':'script_add.png',
'pull':'down_16.png',
'started_following_repo':'heart_add.png',
'stopped_following_repo':'heart_delete.png',
}
fixed some w3c html
r817 return literal(tmpl % (map.get(action, action), action))
#48 rewrote action logger, translated action logger messages, added some extra messages. Linked and showed pushed revisions in logs
r660
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 #==============================================================================
renamed project to rhodecode
r547 # PERMS
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 #==============================================================================
renamed project to rhodecode
r547 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
HasRepoPermissionAny, HasRepoPermissionAll
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 #==============================================================================
renamed project to rhodecode
r547 # GRAVATAR URL
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 #==============================================================================
renamed project to rhodecode
r547 import hashlib
import urllib
from pylons import request
def gravatar_url(email_address, size=30):
patched gravatar url generation to properly support new https force flag from settings.
r946 ssl_enabled = 'https' == request.environ.get('wsgi.url_scheme')
renamed project to rhodecode
r547 default = 'identicon'
baseurl_nossl = "http://www.gravatar.com/avatar/"
baseurl_ssl = "https://secure.gravatar.com/avatar/"
baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 # construct the url
gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
return gravatar_url
def safe_unicode(str):
"""safe unicode function. In case of UnicodeDecode error we try to return
unicode with errors replace, if this failes we return unicode with
string_escape decoding """
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 try:
u_str = unicode(str)
except UnicodeDecodeError:
try:
u_str = unicode(str, 'utf-8', 'replace')
except UnicodeDecodeError:
#incase we have a decode error just represent as byte string
u_str = unicode(str(str).encode('string_escape'))
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 return u_str