comparison rhodecode/lib/helpers.py @ 671:bee56f209c40 rhodecode-0.0.1.0.1

fixes few bugs - fixed #53 python2.5 incompatible enumerate calls - fixed #52 disable mercurial extension for web - fixed #51 deleting repositories don't delete it's dependent objects - small css updated
author Marcin Kuzminski <marcin@python-works.com>
date Wed, 10 Nov 2010 01:14:44 +0100
parents 5cc96df705b9
children 3d0661b8aaa4
comparison
equal deleted inserted replaced
641:fe8c3989ab0e 671:bee56f209c40
62 62
63 if str.find(replace * 2) == -1: 63 if str.find(replace * 2) == -1:
64 return str 64 return str
65 else: 65 else:
66 str = str.replace(replace * 2, replace) 66 str = str.replace(replace * 2, replace)
67 return recursive_replace(str, replace) 67 return recursive_replace(str, replace)
68 68
69 class _ToolTip(object): 69 class _ToolTip(object):
70 70
71 def __call__(self, tooltip_title, trim_at=50): 71 def __call__(self, tooltip_title, trim_at=50):
72 """ 72 """
73 Special function just to wrap our text into nice formatted autowrapped 73 Special function just to wrap our text into nice formatted autowrapped
74 text 74 text
75 :param tooltip_title: 75 :param tooltip_title:
76 """ 76 """
77 77
78 return wrap_paragraphs(escape(tooltip_title), trim_at)\ 78 return wrap_paragraphs(escape(tooltip_title), trim_at)\
79 .replace('\n', '<br/>') 79 .replace('\n', '<br/>')
80 80
81 def activate(self): 81 def activate(self):
82 """ 82 """
83 Adds tooltip mechanism to the given Html all tooltips have to have 83 Adds tooltip mechanism to the given Html all tooltips have to have
84 set class tooltip and set attribute tooltip_title. 84 set class tooltip and set attribute tooltip_title.
85 Then a tooltip will be generated based on that 85 Then a tooltip will be generated based on that
86 All with yui js tooltip 86 All with yui js tooltip
87 """ 87 """
88 88
89 js = ''' 89 js = '''
90 YAHOO.util.Event.onDOMReady(function(){ 90 YAHOO.util.Event.onDOMReady(function(){
91 function toolTipsId(){ 91 function toolTipsId(){
92 var ids = []; 92 var ids = [];
93 var tts = YAHOO.util.Dom.getElementsByClassName('tooltip'); 93 var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
188 function(type, args) { 188 function(type, args) {
189 var context = args[0]; 189 var context = args[0];
190 190
191 }); 191 });
192 }); 192 });
193 ''' 193 '''
194 return literal(js) 194 return literal(js)
195 195
196 tooltip = _ToolTip() 196 tooltip = _ToolTip()
197 197
198 class _FilesBreadCrumbs(object): 198 class _FilesBreadCrumbs(object):
199 199
200 def __call__(self, repo_name, rev, paths): 200 def __call__(self, repo_name, rev, paths):
201 url_l = [link_to(repo_name, url('files_home', 201 url_l = [link_to(repo_name, url('files_home',
202 repo_name=repo_name, 202 repo_name=repo_name,
203 revision=rev, f_path=''))] 203 revision=rev, f_path=''))]
204 paths_l = paths.split('/') 204 paths_l = paths.split('/')
205 205
206 for cnt, p in enumerate(paths_l, 1): 206 for cnt, p in enumerate(paths_l):
207 if p != '': 207 if p != '':
208 url_l.append(link_to(p, url('files_home', 208 url_l.append(link_to(p, url('files_home',
209 repo_name=repo_name, 209 repo_name=repo_name,
210 revision=rev, 210 revision=rev,
211 f_path='/'.join(paths_l[:cnt])))) 211 f_path='/'.join(paths_l[:cnt + 1]))))
212 212
213 return literal('/'.join(url_l)) 213 return literal('/'.join(url_l))
214 214
215 files_breadcrumbs = _FilesBreadCrumbs() 215 files_breadcrumbs = _FilesBreadCrumbs()
216 class CodeHtmlFormatter(HtmlFormatter): 216 class CodeHtmlFormatter(HtmlFormatter):
217 217
218 def wrap(self, source, outfile): 218 def wrap(self, source, outfile):
219 return self._wrap_div(self._wrap_pre(self._wrap_code(source))) 219 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
220 220
221 def _wrap_code(self, source): 221 def _wrap_code(self, source):
222 for cnt, it in enumerate(source, 1): 222 for cnt, it in enumerate(source):
223 i, t = it 223 i, t = it
224 t = '<div id="#S-%s">%s</div>' % (cnt, t) 224 t = '<div id="#S-%s">%s</div>' % (cnt + 1, t)
225 yield i, t 225 yield i, t
226 def pygmentize(filenode, **kwargs): 226 def pygmentize(filenode, **kwargs):
227 """ 227 """
228 pygmentize function using pygments 228 pygmentize function using pygments
229 :param filenode: 229 :param filenode:
234 def pygmentize_annotation(filenode, **kwargs): 234 def pygmentize_annotation(filenode, **kwargs):
235 """ 235 """
236 pygmentize function for annotation 236 pygmentize function for annotation
237 :param filenode: 237 :param filenode:
238 """ 238 """
239 239
240 color_dict = {} 240 color_dict = {}
241 def gen_color(): 241 def gen_color():
242 """generator for getting 10k of evenly distibuted colors using hsv color 242 """generator for getting 10k of evenly distibuted colors using hsv color
243 and golden ratio. 243 and golden ratio.
244 """ 244 """
245 import colorsys 245 import colorsys
246 n = 10000 246 n = 10000
247 golden_ratio = 0.618033988749895 247 golden_ratio = 0.618033988749895
248 h = 0.22717784590367374 248 h = 0.22717784590367374
249 #generate 10k nice web friendly colors in the same order 249 #generate 10k nice web friendly colors in the same order
250 for c in xrange(n): 250 for c in xrange(n):
251 h += golden_ratio 251 h += golden_ratio
252 h %= 1 252 h %= 1
253 HSV_tuple = [h, 0.95, 0.95] 253 HSV_tuple = [h, 0.95, 0.95]
254 RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple) 254 RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
255 yield map(lambda x:str(int(x * 256)), RGB_tuple) 255 yield map(lambda x:str(int(x * 256)), RGB_tuple)
256 256
257 cgenerator = gen_color() 257 cgenerator = gen_color()
258 258
259 def get_color_string(cs): 259 def get_color_string(cs):
260 if color_dict.has_key(cs): 260 if color_dict.has_key(cs):
261 col = color_dict[cs] 261 col = color_dict[cs]
262 else: 262 else:
263 col = color_dict[cs] = cgenerator.next() 263 col = color_dict[cs] = cgenerator.next()
264 return "color: rgb(%s)! important;" % (', '.join(col)) 264 return "color: rgb(%s)! important;" % (', '.join(col))
265 265
266 def url_func(changeset): 266 def url_func(changeset):
267 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \ 267 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
268 " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>" 268 " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
269 269
270 tooltip_html = tooltip_html % (changeset.author, 270 tooltip_html = tooltip_html % (changeset.author,
271 changeset.date, 271 changeset.date,
272 tooltip(changeset.message)) 272 tooltip(changeset.message))
273 lnk_format = 'r%-5s:%s' % (changeset.revision, 273 lnk_format = 'r%-5s:%s' % (changeset.revision,
274 changeset.short_id) 274 changeset.short_id)
278 revision=changeset.short_id), 278 revision=changeset.short_id),
279 style=get_color_string(changeset.short_id), 279 style=get_color_string(changeset.short_id),
280 class_='tooltip', 280 class_='tooltip',
281 tooltip_title=tooltip_html 281 tooltip_title=tooltip_html
282 ) 282 )
283 283
284 uri += '\n' 284 uri += '\n'
285 return uri 285 return uri
286 return literal(annotate_highlight(filenode, url_func, **kwargs)) 286 return literal(annotate_highlight(filenode, url_func, **kwargs))
287 287
288 def repo_name_slug(value): 288 def repo_name_slug(value):
289 """Return slug of name of repository 289 """Return slug of name of repository
290 This function is called on each creation/modification 290 This function is called on each creation/modification
291 of repository to prevent bad names in repo 291 of repository to prevent bad names in repo
292 """ 292 """
293 slug = remove_formatting(value) 293 slug = remove_formatting(value)
294 slug = strip_tags(slug) 294 slug = strip_tags(slug)
295 295
296 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """: 296 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
297 slug = slug.replace(c, '-') 297 slug = slug.replace(c, '-')
298 slug = recursive_replace(slug, '-') 298 slug = recursive_replace(slug, '-')
299 slug = collapse(slug, '-') 299 slug = collapse(slug, '-')
300 return slug 300 return slug
303 from vcs.backends.base import BaseRepository 303 from vcs.backends.base import BaseRepository
304 from vcs.exceptions import RepositoryError 304 from vcs.exceptions import RepositoryError
305 if not isinstance(repo, BaseRepository): 305 if not isinstance(repo, BaseRepository):
306 raise Exception('You must pass an Repository ' 306 raise Exception('You must pass an Repository '
307 'object as first argument got %s', type(repo)) 307 'object as first argument got %s', type(repo))
308 308
309 try: 309 try:
310 cs = repo.get_changeset(rev) 310 cs = repo.get_changeset(rev)
311 except RepositoryError: 311 except RepositoryError:
312 from rhodecode.lib.utils import EmptyChangeset 312 from rhodecode.lib.utils import EmptyChangeset
313 cs = EmptyChangeset() 313 cs = EmptyChangeset()
356 ssl_enabled = 'https' == request.environ.get('HTTP_X_URL_SCHEME') 356 ssl_enabled = 'https' == request.environ.get('HTTP_X_URL_SCHEME')
357 default = 'identicon' 357 default = 'identicon'
358 baseurl_nossl = "http://www.gravatar.com/avatar/" 358 baseurl_nossl = "http://www.gravatar.com/avatar/"
359 baseurl_ssl = "https://secure.gravatar.com/avatar/" 359 baseurl_ssl = "https://secure.gravatar.com/avatar/"
360 baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl 360 baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
361 361
362 362
363 # construct the url 363 # construct the url
364 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?" 364 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
365 gravatar_url += urllib.urlencode({'d':default, 's':str(size)}) 365 gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
366 366
367 return gravatar_url 367 return gravatar_url
368 368
369 def safe_unicode(str): 369 def safe_unicode(str):
370 """safe unicode function. In case of UnicodeDecode error we try to return 370 """safe unicode function. In case of UnicodeDecode error we try to return
371 unicode with errors replace, if this failes we return unicode with 371 unicode with errors replace, if this failes we return unicode with
372 string_escape decoding """ 372 string_escape decoding """
373 373
374 try: 374 try:
375 u_str = unicode(str) 375 u_str = unicode(str)
376 except UnicodeDecodeError: 376 except UnicodeDecodeError:
377 try: 377 try:
378 u_str = unicode(str, 'utf-8', 'replace') 378 u_str = unicode(str, 'utf-8', 'replace')
379 except UnicodeDecodeError: 379 except UnicodeDecodeError:
380 #incase we have a decode error just represent as byte string 380 #incase we have a decode error just represent as byte string
381 u_str = unicode(str(str).encode('string_escape')) 381 u_str = unicode(str(str).encode('string_escape'))
382 382
383 return u_str 383 return u_str