Mercurial > kallithea
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 |