##// END OF EJS Templates
removed .lower() from permission checking of cached repos list since repos can have capital letters now
removed .lower() from permission checking of cached repos list since repos can have capital letters now

File last commit:

r505:5aba7adf default
r511:0fce1f9e default
Show More
helpers.py
383 lines | 14.1 KiB | text/x-python | PythonLexer
Marcin Kuzminski
initial commit.
r0 """Helper functions
Consists of functions to typically be used within templates, but also
available to Controllers. This module is available to both as 'h'.
"""
Pygments code coloring rewrite, annotation was moved to vcs whitch had much better lib for that. Fixed code recognition based on mimetypes of filenodes, for better coloring.
r250 from pygments.formatters import HtmlFormatter
from pygments import highlight as code_highlight
implemented pygmentize codes into webhelpers. Together with color_dict caching into pylons globals
r165 from pylons import url, app_globals as g
added helper for filesize
r97 from pylons.i18n.translation import _, ungettext
Pygments code coloring rewrite, annotation was moved to vcs whitch had much better lib for that. Fixed code recognition based on mimetypes of filenodes, for better coloring.
r250 from vcs.utils.annotate import annotate_highlight
from webhelpers.html import literal, HTML, escape
implemented yui tooltip, and added it into annotation and main page.
r281 from webhelpers.html.tools import *
added pygments webhelper
r98 from webhelpers.html.builder import make_tag
Pygments code coloring rewrite, annotation was moved to vcs whitch had much better lib for that. Fixed code recognition based on mimetypes of filenodes, for better coloring.
r250 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, \
implemented yui tooltip, and added it into annotation and main page.
r281 password, textarea, title, ul, xml_declaration, radio
Pygments code coloring rewrite, annotation was moved to vcs whitch had much better lib for that. Fixed code recognition based on mimetypes of filenodes, for better coloring.
r250 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
Marcin Kuzminski
initial commit.
r0 from webhelpers.pylonslib import Flash as _Flash
from webhelpers.pylonslib.secure_form import secure_form
Pygments code coloring rewrite, annotation was moved to vcs whitch had much better lib for that. Fixed code recognition based on mimetypes of filenodes, for better coloring.
r250 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
convert_misc_entities, lchop, plural, rchop, remove_formatting, \
implemented yui tooltip, and added it into annotation and main page.
r281 replace_whitespace, urlify, truncate, wrap_paragraphs
Marcin Kuzminski
initial commit.
r0
implemented yui tooltip, and added it into annotation and main page.
r281 #Custom helpers here :)
Marcin Kuzminski
initial commit.
r0 class _Link(object):
'''
Make a url based on label and url with help of url_for
@param label:name of link if not defined url is used
@param url: the url for link
'''
changed for pylons 0.1 / 1.0...
r43 def __call__(self, label='', *url_, **urlargs):
Marcin Kuzminski
initial commit.
r0 if label is None or '':
label = url
changed for pylons 0.1 / 1.0...
r43 link_fn = link_to(label, url(*url_, **urlargs))
Marcin Kuzminski
initial commit.
r0 return link_fn
implemented yui tooltip, and added it into annotation and main page.
r281 link = _Link()
Marcin Kuzminski
initial commit.
r0
class _GetError(object):
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))
implemented yui tooltip, and added it into annotation and main page.
r281 get_error = _GetError()
def recursive_replace(str, replace=' '):
"""
Recursive replace of given sign to just one instance
@param str: given string
@param replace:char to find and replace multiple instances
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)
return recursive_replace(str, replace)
class _ToolTip(object):
def __call__(self, tooltip_title, trim_at=50):
"""
Special function just to wrap our text into nice formatted autowrapped
text
@param tooltip_title:
"""
fixed escaping in tooltip
r444 return wrap_paragraphs(escape(tooltip_title), trim_at)\
.replace('\n', '<br/>')
implemented yui tooltip, and added it into annotation and main page.
r281
def activate(self):
"""
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
"""
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++) {
//if element doesn not have and id autgenerate one for tooltip
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,
});
fixed paragraphs wrapping for ultralong commit messages. Disabled tooltips for new repos without a last commit message. ie. when tooltip_title is empty (there is a strange bug on empty tooltip_title)
r284 //Mouse Over event disabled for new repositories since they dont
//have last commit message
implemented yui tooltip, and added it into annotation and main page.
r281 myToolTips.contextMouseOverEvent.subscribe(
function(type, args) {
var context = args[0];
fixed paragraphs wrapping for ultralong commit messages. Disabled tooltips for new repos without a last commit message. ie. when tooltip_title is empty (there is a strange bug on empty tooltip_title)
r284 var txt = context.getAttribute('tooltip_title');
tooltip updates, added display layout managment inspired by jQuerys tipsy.
r292 if(txt){
fixed paragraphs wrapping for ultralong commit messages. Disabled tooltips for new repos without a last commit message. ie. when tooltip_title is empty (there is a strange bug on empty tooltip_title)
r284 return true;
}
else{
return false;
}
implemented yui tooltip, and added it into annotation and main page.
r281 });
tooltip display bugfix
r286
implemented yui tooltip, and added it into annotation and main page.
r281 // Set the text for the tooltip just before we display it. Lazy method
myToolTips.contextTriggerEvent.subscribe(
function(type, args) {
tooltip updates, added display layout managment inspired by jQuerys tipsy.
r292
implemented yui tooltip, and added it into annotation and main page.
r281 var context = args[0];
tooltip updates, added display layout managment inspired by jQuerys tipsy.
r292
implemented yui tooltip, and added it into annotation and main page.
r281 var txt = context.getAttribute('tooltip_title');
tooltip display bugfix
r286 this.cfg.setProperty("text", txt);
tooltip updates, added display layout managment inspired by jQuerys tipsy.
r292
// positioning of tooltip
var tt_w = this.element.clientWidth;
var tt_h = this.element.clientHeight;
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);
tooltip display bugfix
r286
tooltip updates, added display layout managment inspired by jQuerys tipsy.
r292 var display_strategy = 'top';
Ie graph support....
r293 var xy_pos = [0,0];
tooltip updates, added display layout managment inspired by jQuerys tipsy.
r292 switch (display_strategy){
case 'top':
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;
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;
Ie graph support....
r293 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;
tooltip updates, added display layout managment inspired by jQuerys tipsy.
r292 }
this.cfg.setProperty("xy",xy_pos);
tooltip display bugfix
r286
implemented yui tooltip, and added it into annotation and main page.
r281 });
tooltip updates, added display layout managment inspired by jQuerys tipsy.
r292
tooltip display bugfix
r286 //Mouse out
myToolTips.contextMouseOutEvent.subscribe(
function(type, args) {
var context = args[0];
});
implemented yui tooltip, and added it into annotation and main page.
r281 });
'''
return literal(js)
tooltip = _ToolTip()
Updated tempaltes, added file browser breadcrumbs, and feed icons
r102 class _FilesBreadCrumbs(object):
def __call__(self, repo_name, rev, paths):
webhelpers breadcrumbs bugfix
r287 url_l = [link_to(repo_name, url('files_home',
repo_name=repo_name,
revision=rev, f_path=''))]
paths_l = paths.split('/')
Updated tempaltes, added file browser breadcrumbs, and feed icons
r102
for cnt, p in enumerate(paths_l, 1):
if p != '':
webhelpers breadcrumbs bugfix
r287 url_l.append(link_to(p, url('files_home',
repo_name=repo_name,
revision=rev,
f_path='/'.join(paths_l[:cnt]))))
added helper for filesize
r97
more css html fixes (+cleanups), rewrote definition list for files...
r448 return literal('/'.join(url_l))
added pygments webhelper
r98
implemented yui tooltip, and added it into annotation and main page.
r281 files_breadcrumbs = _FilesBreadCrumbs()
little gui change for file source
r505 class CodeHtmlFormatter(HtmlFormatter):
implemented yui tooltip, and added it into annotation and main page.
r281
little gui change for file source
r505 def wrap(self, source, outfile):
return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
def _wrap_code(self, source):
for cnt, it in enumerate(source, 1):
i, t = it
t = '<div id="#S-%s">%s</div>' % (cnt, t)
yield i, t
Pygments code coloring rewrite, annotation was moved to vcs whitch had much better lib for that. Fixed code recognition based on mimetypes of filenodes, for better coloring.
r250 def pygmentize(filenode, **kwargs):
implemented pygmentize codes into webhelpers. Together with color_dict caching into pylons globals
r165 """
Pygments code coloring rewrite, annotation was moved to vcs whitch had much better lib for that. Fixed code recognition based on mimetypes of filenodes, for better coloring.
r250 pygmentize function using pygments
@param filenode:
implemented pygmentize codes into webhelpers. Together with color_dict caching into pylons globals
r165 """
fixed, empty cs bug....
r450 return literal(code_highlight(filenode.content,
little gui change for file source
r505 filenode.lexer, CodeHtmlFormatter(**kwargs)))
implemented pygmentize codes into webhelpers. Together with color_dict caching into pylons globals
r165
Pygments code coloring rewrite, annotation was moved to vcs whitch had much better lib for that. Fixed code recognition based on mimetypes of filenodes, for better coloring.
r250 def pygmentize_annotation(filenode, **kwargs):
implemented pygmentize codes into webhelpers. Together with color_dict caching into pylons globals
r165 """
Pygments code coloring rewrite, annotation was moved to vcs whitch had much better lib for that. Fixed code recognition based on mimetypes of filenodes, for better coloring.
r250 pygmentize function for annotation
@param filenode:
implemented pygmentize codes into webhelpers. Together with color_dict caching into pylons globals
r165 """
Pygments code coloring rewrite, annotation was moved to vcs whitch had much better lib for that. Fixed code recognition based on mimetypes of filenodes, for better coloring.
r250
fixes #24, added generator that generates equally distrybuted colors. Thus skipping creating one large coloring history.
r438 color_dict = {}
implemented pygmentize codes into webhelpers. Together with color_dict caching into pylons globals
r165 def gen_color():
fixes #24, added generator that generates equally distrybuted colors. Thus skipping creating one large coloring history.
r438 """generator for getting 10k of evenly distibuted colors using hsv color
and golden ratio.
"""
import colorsys
n = 10000
golden_ratio = 0.618033988749895
h = 0.22717784590367374
#generate 10k nice web friendly colors in the same order
for c in xrange(n):
fixed, empty cs bug....
r450 h += golden_ratio
fixes #24, added generator that generates equally distrybuted colors. Thus skipping creating one large coloring history.
r438 h %= 1
HSV_tuple = [h, 0.95, 0.95]
RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
fixed, empty cs bug....
r450 yield map(lambda x:str(int(x * 256)), RGB_tuple)
fixes #24, added generator that generates equally distrybuted colors. Thus skipping creating one large coloring history.
r438
cgenerator = gen_color()
implemented pygmentize codes into webhelpers. Together with color_dict caching into pylons globals
r165 def get_color_string(cs):
if color_dict.has_key(cs):
col = color_dict[cs]
else:
fixes #24, added generator that generates equally distrybuted colors. Thus skipping creating one large coloring history.
r438 col = color_dict[cs] = cgenerator.next()
return "color: rgb(%s)! important;" % (', '.join(col))
Pygments code coloring rewrite, annotation was moved to vcs whitch had much better lib for that. Fixed code recognition based on mimetypes of filenodes, for better coloring.
r250
def url_func(changeset):
fixed, empty cs bug....
r450 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
*** failed to import extension hggit: No module named hggit
removed decodes, thus it should be implemented on vcs side...
r428 " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
implemented yui tooltip, and added it into annotation and main page.
r281
tooltip_html = tooltip_html % (changeset.author,
changeset.date,
tooltip(changeset.message))
fixes #24, added generator that generates equally distrybuted colors. Thus skipping creating one large coloring history.
r438 lnk_format = 'r%-5s:%s' % (changeset.revision,
implemented yui tooltip, and added it into annotation and main page.
r281 changeset.raw_id)
uri = link_to(
lnk_format,
*** failed to import extension hggit: No module named hggit
removed decodes, thus it should be implemented on vcs side...
r428 url('changeset_home', repo_name=changeset.repository.name,
implemented yui tooltip, and added it into annotation and main page.
r281 revision=changeset.raw_id),
style=get_color_string(changeset.raw_id),
class_='tooltip',
tooltip_title=tooltip_html
)
uri += '\n'
return uri
Pygments code coloring rewrite, annotation was moved to vcs whitch had much better lib for that. Fixed code recognition based on mimetypes of filenodes, for better coloring.
r250 return literal(annotate_highlight(filenode, url_func, **kwargs))
made global funcion to clean repo names, and remove all special chars from the name....
r260
def repo_name_slug(value):
reimplemented name slug to accept capitalized repositories names
r481 """Return slug of name of repository
This function is called on each creation/modification
of repository to prevent bad names in repo
made global funcion to clean repo names, and remove all special chars from the name....
r260 """
reimplemented name slug to accept capitalized repositories names
r481 slug = remove_formatting(value)
slug = strip_tags(slug)
for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
made global funcion to clean repo names, and remove all special chars from the name....
r260 slug = slug.replace(c, '-')
slug = recursive_replace(slug, '-')
reimplemented name slug to accept capitalized repositories names
r481 slug = collapse(slug, '-')
made global funcion to clean repo names, and remove all special chars from the name....
r260 return slug
implemented yui tooltip, and added it into annotation and main page.
r281
fixed, empty cs bug....
r450 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))
try:
cs = repo.get_changeset(rev)
except RepositoryError:
from pylons_app.lib.utils import EmptyChangeset
cs = EmptyChangeset()
return cs
Marcin Kuzminski
initial commit.
r0 flash = _Flash()
switched filters into webhelpers for easy of usage....
r282
#===============================================================================
# MERCURIAL FILTERS available via h.
#===============================================================================
from mercurial import util
from mercurial.templatefilters import age as _age, person as _person
age = lambda x:_age(x)
capitalize = lambda x: x.capitalize()
date = lambda x: util.datestr(x)
email = util.email
implemented gravatars to changesets, updated styling for changesets...
r401 email_or_none = lambda x: util.email(x) if util.email(x) != x else None
switched filters into webhelpers for easy of usage....
r282 person = lambda x: _person(x)
hgdate = lambda x: "%d %d" % x
isodate = lambda x: util.datestr(x, '%Y-%m-%d %H:%M %1%2')
isodatesec = lambda x: util.datestr(x, '%Y-%m-%d %H:%M:%S %1%2')
localdate = lambda x: (x[0], util.makedate()[1])
rfc822date = lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S %1%2")
some code fixes templates+helpers new rfc date without tz, added timerproxy formatting
r494 rfc822date_notz = lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S")
switched filters into webhelpers for easy of usage....
r282 rfc3339date = lambda x: util.datestr(x, "%Y-%m-%dT%H:%M:%S%1:%2")
time_ago = lambda x: util.datestr(_age(x), "%a, %d %b %Y %H:%M:%S %1%2")
added permission functions to webhelpers, updated dbmanage permissions
r307 #===============================================================================
# PERMS
#===============================================================================
from pylons_app.lib.auth import HasPermissionAny, HasPermissionAll, \
HasRepoPermissionAny, HasRepoPermissionAll
switched filters into webhelpers for easy of usage....
r282
Implemented basic gravatar support on admin pages only for now
r398 #===============================================================================
# GRAVATAR URL
#===============================================================================
import hashlib
import urllib
webhelpers import bugfix for gravatar...
r400 from pylons import request
switched filters into webhelpers for easy of usage....
r282
implemented gravatars to changesets, updated styling for changesets...
r401 def gravatar_url(email_address, size=30):
Implemented basic gravatar support on admin pages only for now
r398 ssl_enabled = 'https' == request.environ.get('HTTP_X_URL_SCHEME')
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
# construct the url
implemented gravatars to changesets, updated styling for changesets...
r401 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
Implemented basic gravatar support on admin pages only for now
r398 gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
return gravatar_url
added safe unicode funtion, and implemented it in whoosh indexer
r443
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 """
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'))
fixed, empty cs bug....
r450 return u_str