Mercurial > kallithea
comparison rhodecode/lib/__init__.py @ 2031:82a88013a3fd
merge 1.3 into stable
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Sun, 26 Feb 2012 17:25:09 +0200 |
parents | 54e84659cb3a 6020e3884a58 |
children | abe75448253c |
comparison
equal
deleted
inserted
replaced
2005:ab0e122b38a7 | 2031:82a88013a3fd |
---|---|
22 # | 22 # |
23 # You should have received a copy of the GNU General Public License | 23 # You should have received a copy of the GNU General Public License |
24 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 24 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
25 | 25 |
26 import os | 26 import os |
27 import re | |
28 from rhodecode.lib.vcs.utils.lazy import LazyProperty | |
29 | |
27 | 30 |
28 def __get_lem(): | 31 def __get_lem(): |
29 from pygments import lexers | 32 from pygments import lexers |
30 from string import lower | 33 from string import lower |
31 from collections import defaultdict | 34 from collections import defaultdict |
64 # NOTE: that this will overide any mappings in LANGUAGES_EXTENSIONS_MAP | 67 # NOTE: that this will overide any mappings in LANGUAGES_EXTENSIONS_MAP |
65 ADDITIONAL_MAPPINGS = {'xaml': 'XAML'} | 68 ADDITIONAL_MAPPINGS = {'xaml': 'XAML'} |
66 | 69 |
67 LANGUAGES_EXTENSIONS_MAP.update(ADDITIONAL_MAPPINGS) | 70 LANGUAGES_EXTENSIONS_MAP.update(ADDITIONAL_MAPPINGS) |
68 | 71 |
72 # list of readme files to search in file tree and display in summary | |
73 # attached weights defines the search order lower is first | |
74 ALL_READMES = [ | |
75 ('readme', 0), ('README', 0), ('Readme', 0), | |
76 ('doc/readme', 1), ('doc/README', 1), ('doc/Readme', 1), | |
77 ('Docs/readme', 2), ('Docs/README', 2), ('Docs/Readme', 2), | |
78 ('DOCS/readme', 2), ('DOCS/README', 2), ('DOCS/Readme', 2), | |
79 ('docs/readme', 2), ('docs/README', 2), ('docs/Readme', 2), | |
80 ] | |
81 | |
82 # extension together with weights to search lower is first | |
83 RST_EXTS = [ | |
84 ('', 0), ('.rst', 1), ('.rest', 1), | |
85 ('.RST', 2), ('.REST', 2), | |
86 ('.txt', 3), ('.TXT', 3) | |
87 ] | |
88 | |
89 MARKDOWN_EXTS = [ | |
90 ('.md', 1), ('.MD', 1), | |
91 ('.mkdn', 2), ('.MKDN', 2), | |
92 ('.mdown', 3), ('.MDOWN', 3), | |
93 ('.markdown', 4), ('.MARKDOWN', 4) | |
94 ] | |
95 | |
96 PLAIN_EXTS = [('.text', 2), ('.TEXT', 2)] | |
97 | |
98 ALL_EXTS = MARKDOWN_EXTS + RST_EXTS + PLAIN_EXTS | |
99 | |
69 | 100 |
70 def str2bool(_str): | 101 def str2bool(_str): |
71 """ | 102 """ |
72 returs True/False value from given string, it tries to translate the | 103 returs True/False value from given string, it tries to translate the |
73 string into boolean | 104 string into boolean |
105 line = replace(line, '\r', '\n') | 136 line = replace(line, '\r', '\n') |
106 elif mode == 1: | 137 elif mode == 1: |
107 line = replace(line, '\r\n', '\r') | 138 line = replace(line, '\r\n', '\r') |
108 line = replace(line, '\n', '\r') | 139 line = replace(line, '\n', '\r') |
109 elif mode == 2: | 140 elif mode == 2: |
110 import re | |
111 line = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", line) | 141 line = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", line) |
112 return line | 142 return line |
113 | 143 |
114 | 144 |
115 def detect_mode(line, default): | 145 def detect_mode(line, default): |
149 salt = _RandomNameSequence().next() | 179 salt = _RandomNameSequence().next() |
150 | 180 |
151 return hashlib.sha1(username + salt).hexdigest() | 181 return hashlib.sha1(username + salt).hexdigest() |
152 | 182 |
153 | 183 |
154 def safe_unicode(str_, from_encoding='utf8'): | 184 def safe_unicode(str_, from_encoding=None): |
155 """ | 185 """ |
156 safe unicode function. Does few trick to turn str_ into unicode | 186 safe unicode function. Does few trick to turn str_ into unicode |
157 | 187 |
158 In case of UnicodeDecode error we try to return it with encoding detected | 188 In case of UnicodeDecode error we try to return it with encoding detected |
159 by chardet library if it fails fallback to unicode with errors replaced | 189 by chardet library if it fails fallback to unicode with errors replaced |
162 :rtype: unicode | 192 :rtype: unicode |
163 :returns: unicode object | 193 :returns: unicode object |
164 """ | 194 """ |
165 if isinstance(str_, unicode): | 195 if isinstance(str_, unicode): |
166 return str_ | 196 return str_ |
197 | |
198 if not from_encoding: | |
199 import rhodecode | |
200 DEFAULT_ENCODING = rhodecode.CONFIG.get('default_encoding','utf8') | |
201 from_encoding = DEFAULT_ENCODING | |
167 | 202 |
168 try: | 203 try: |
169 return unicode(str_) | 204 return unicode(str_) |
170 except UnicodeDecodeError: | 205 except UnicodeDecodeError: |
171 pass | 206 pass |
182 raise Exception() | 217 raise Exception() |
183 return str_.decode(encoding) | 218 return str_.decode(encoding) |
184 except (ImportError, UnicodeDecodeError, Exception): | 219 except (ImportError, UnicodeDecodeError, Exception): |
185 return unicode(str_, from_encoding, 'replace') | 220 return unicode(str_, from_encoding, 'replace') |
186 | 221 |
187 def safe_str(unicode_, to_encoding='utf8'): | 222 |
223 def safe_str(unicode_, to_encoding=None): | |
188 """ | 224 """ |
189 safe str function. Does few trick to turn unicode_ into string | 225 safe str function. Does few trick to turn unicode_ into string |
190 | 226 |
191 In case of UnicodeEncodeError we try to return it with encoding detected | 227 In case of UnicodeEncodeError we try to return it with encoding detected |
192 by chardet library if it fails fallback to string with errors replaced | 228 by chardet library if it fails fallback to string with errors replaced |
193 | 229 |
194 :param unicode_: unicode to encode | 230 :param unicode_: unicode to encode |
195 :rtype: str | 231 :rtype: str |
197 """ | 233 """ |
198 | 234 |
199 if not isinstance(unicode_, basestring): | 235 if not isinstance(unicode_, basestring): |
200 return str(unicode_) | 236 return str(unicode_) |
201 | 237 |
238 if not isinstance(unicode_, basestring): | |
239 return str(unicode_) | |
240 | |
202 if isinstance(unicode_, str): | 241 if isinstance(unicode_, str): |
203 return unicode_ | 242 return unicode_ |
243 | |
244 if not to_encoding: | |
245 import rhodecode | |
246 DEFAULT_ENCODING = rhodecode.CONFIG.get('default_encoding','utf8') | |
247 to_encoding = DEFAULT_ENCODING | |
204 | 248 |
205 try: | 249 try: |
206 return unicode_.encode(to_encoding) | 250 return unicode_.encode(to_encoding) |
207 except UnicodeEncodeError: | 251 except UnicodeEncodeError: |
208 pass | 252 pass |
219 return unicode_.encode(to_encoding, 'replace') | 263 return unicode_.encode(to_encoding, 'replace') |
220 | 264 |
221 return safe_str | 265 return safe_str |
222 | 266 |
223 | 267 |
224 | |
225 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs): | 268 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs): |
226 """ | 269 """ |
227 Custom engine_from_config functions that makes sure we use NullPool for | 270 Custom engine_from_config functions that makes sure we use NullPool for |
228 file based sqlite databases. This prevents errors on sqlite. This only | 271 file based sqlite databases. This prevents errors on sqlite. This only |
229 applies to sqlalchemy versions < 0.7.0 | 272 applies to sqlalchemy versions < 0.7.0 |
230 | 273 |
231 """ | 274 """ |
232 import sqlalchemy | 275 import sqlalchemy |
233 from sqlalchemy import engine_from_config as efc | 276 from sqlalchemy import engine_from_config as efc |
282 | 325 |
283 | 326 |
284 def age(curdate): | 327 def age(curdate): |
285 """ | 328 """ |
286 turns a datetime into an age string. | 329 turns a datetime into an age string. |
287 | 330 |
288 :param curdate: datetime object | 331 :param curdate: datetime object |
289 :rtype: unicode | 332 :rtype: unicode |
290 :returns: unicode words describing age | 333 :returns: unicode words describing age |
291 """ | 334 """ |
292 | 335 |
293 from datetime import datetime | 336 from datetime import datetime |
294 from webhelpers.date import time_ago_in_words | 337 from webhelpers.date import time_ago_in_words |
295 | 338 |
296 _ = lambda s:s | 339 _ = lambda s: s |
297 | 340 |
298 if not curdate: | 341 if not curdate: |
299 return '' | 342 return '' |
300 | 343 |
301 agescales = [(_(u"year"), 3600 * 24 * 365), | 344 agescales = [(_(u"year"), 3600 * 24 * 365), |
308 age = datetime.now() - curdate | 351 age = datetime.now() - curdate |
309 age_seconds = (age.days * agescales[2][1]) + age.seconds | 352 age_seconds = (age.days * agescales[2][1]) + age.seconds |
310 pos = 1 | 353 pos = 1 |
311 for scale in agescales: | 354 for scale in agescales: |
312 if scale[1] <= age_seconds: | 355 if scale[1] <= age_seconds: |
313 if pos == 6:pos = 5 | 356 if pos == 6: |
357 pos = 5 | |
314 return '%s %s' % (time_ago_in_words(curdate, | 358 return '%s %s' % (time_ago_in_words(curdate, |
315 agescales[pos][0]), _('ago')) | 359 agescales[pos][0]), _('ago')) |
316 pos += 1 | 360 pos += 1 |
317 | 361 |
318 return _(u'just now') | 362 return _(u'just now') |
319 | 363 |
320 | 364 |
321 def uri_filter(uri): | 365 def uri_filter(uri): |
322 """ | 366 """ |
323 Removes user:password from given url string | 367 Removes user:password from given url string |
324 | 368 |
325 :param uri: | 369 :param uri: |
326 :rtype: unicode | 370 :rtype: unicode |
327 :returns: filtered list of strings | 371 :returns: filtered list of strings |
328 """ | 372 """ |
329 if not uri: | 373 if not uri: |
330 return '' | 374 return '' |
331 | 375 |
332 proto = '' | 376 proto = '' |
351 | 395 |
352 | 396 |
353 def credentials_filter(uri): | 397 def credentials_filter(uri): |
354 """ | 398 """ |
355 Returns a url with removed credentials | 399 Returns a url with removed credentials |
356 | 400 |
357 :param uri: | 401 :param uri: |
358 """ | 402 """ |
359 | 403 |
360 uri = uri_filter(uri) | 404 uri = uri_filter(uri) |
361 #check if we have port | 405 #check if we have port |
362 if len(uri) > 2 and uri[2]: | 406 if len(uri) > 2 and uri[2]: |
363 uri[2] = ':' + uri[2] | 407 uri[2] = ':' + uri[2] |
364 | 408 |
365 return ''.join(uri) | 409 return ''.join(uri) |
366 | 410 |
411 | |
367 def get_changeset_safe(repo, rev): | 412 def get_changeset_safe(repo, rev): |
368 """ | 413 """ |
369 Safe version of get_changeset if this changeset doesn't exists for a | 414 Safe version of get_changeset if this changeset doesn't exists for a |
370 repo it returns a Dummy one instead | 415 repo it returns a Dummy one instead |
371 | 416 |
372 :param repo: | 417 :param repo: |
373 :param rev: | 418 :param rev: |
374 """ | 419 """ |
375 from vcs.backends.base import BaseRepository | 420 from rhodecode.lib.vcs.backends.base import BaseRepository |
376 from vcs.exceptions import RepositoryError | 421 from rhodecode.lib.vcs.exceptions import RepositoryError |
377 if not isinstance(repo, BaseRepository): | 422 if not isinstance(repo, BaseRepository): |
378 raise Exception('You must pass an Repository ' | 423 raise Exception('You must pass an Repository ' |
379 'object as first argument got %s', type(repo)) | 424 'object as first argument got %s', type(repo)) |
380 | 425 |
381 try: | 426 try: |
388 | 433 |
389 def get_current_revision(quiet=False): | 434 def get_current_revision(quiet=False): |
390 """ | 435 """ |
391 Returns tuple of (number, id) from repository containing this package | 436 Returns tuple of (number, id) from repository containing this package |
392 or None if repository could not be found. | 437 or None if repository could not be found. |
393 | 438 |
394 :param quiet: prints error for fetching revision if True | 439 :param quiet: prints error for fetching revision if True |
395 """ | 440 """ |
396 | 441 |
397 try: | 442 try: |
398 from vcs import get_repo | 443 from rhodecode.lib.vcs import get_repo |
399 from vcs.utils.helpers import get_scm | 444 from rhodecode.lib.vcs.utils.helpers import get_scm |
400 repopath = os.path.join(os.path.dirname(__file__), '..', '..') | 445 repopath = os.path.join(os.path.dirname(__file__), '..', '..') |
401 scm = get_scm(repopath)[0] | 446 scm = get_scm(repopath)[0] |
402 repo = get_repo(path=repopath, alias=scm) | 447 repo = get_repo(path=repopath, alias=scm) |
403 tip = repo.get_changeset() | 448 tip = repo.get_changeset() |
404 return (tip.revision, tip.short_id) | 449 return (tip.revision, tip.short_id) |
406 if not quiet: | 451 if not quiet: |
407 print ("Cannot retrieve rhodecode's revision. Original error " | 452 print ("Cannot retrieve rhodecode's revision. Original error " |
408 "was: %s" % err) | 453 "was: %s" % err) |
409 return None | 454 return None |
410 | 455 |
456 | |
457 def extract_mentioned_users(s): | |
458 """ | |
459 Returns unique usernames from given string s that have @mention | |
460 | |
461 :param s: string to get mentions | |
462 """ | |
463 usrs = {} | |
464 for username in re.findall(r'(?:^@|\s@)(\w+)', s): | |
465 usrs[username] = username | |
466 | |
467 return sorted(usrs.keys()) |