##// END OF EJS Templates
catch errors in obfuscate password function
marcink -
r3497:47a0d3d1 default
parent child Browse files
Show More
@@ -1,569 +1,573 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.utils
3 rhodecode.lib.utils
4 ~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~
5
5
6 Some simple helper functions
6 Some simple helper functions
7
7
8 :created_on: Jan 5, 2011
8 :created_on: Jan 5, 2011
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
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 re
26 import re
27 import time
27 import time
28 import datetime
28 import datetime
29 import webob
29 import webob
30
30
31 from pylons.i18n.translation import _, ungettext
31 from pylons.i18n.translation import _, ungettext
32 from rhodecode.lib.vcs.utils.lazy import LazyProperty
32 from rhodecode.lib.vcs.utils.lazy import LazyProperty
33
33
34
34
35 def __get_lem():
35 def __get_lem():
36 """
36 """
37 Get language extension map based on what's inside pygments lexers
37 Get language extension map based on what's inside pygments lexers
38 """
38 """
39 from pygments import lexers
39 from pygments import lexers
40 from string import lower
40 from string import lower
41 from collections import defaultdict
41 from collections import defaultdict
42
42
43 d = defaultdict(lambda: [])
43 d = defaultdict(lambda: [])
44
44
45 def __clean(s):
45 def __clean(s):
46 s = s.lstrip('*')
46 s = s.lstrip('*')
47 s = s.lstrip('.')
47 s = s.lstrip('.')
48
48
49 if s.find('[') != -1:
49 if s.find('[') != -1:
50 exts = []
50 exts = []
51 start, stop = s.find('['), s.find(']')
51 start, stop = s.find('['), s.find(']')
52
52
53 for suffix in s[start + 1:stop]:
53 for suffix in s[start + 1:stop]:
54 exts.append(s[:s.find('[')] + suffix)
54 exts.append(s[:s.find('[')] + suffix)
55 return map(lower, exts)
55 return map(lower, exts)
56 else:
56 else:
57 return map(lower, [s])
57 return map(lower, [s])
58
58
59 for lx, t in sorted(lexers.LEXERS.items()):
59 for lx, t in sorted(lexers.LEXERS.items()):
60 m = map(__clean, t[-2])
60 m = map(__clean, t[-2])
61 if m:
61 if m:
62 m = reduce(lambda x, y: x + y, m)
62 m = reduce(lambda x, y: x + y, m)
63 for ext in m:
63 for ext in m:
64 desc = lx.replace('Lexer', '')
64 desc = lx.replace('Lexer', '')
65 d[ext].append(desc)
65 d[ext].append(desc)
66
66
67 return dict(d)
67 return dict(d)
68
68
69
69
70 def str2bool(_str):
70 def str2bool(_str):
71 """
71 """
72 returs True/False value from given string, it tries to translate the
72 returs True/False value from given string, it tries to translate the
73 string into boolean
73 string into boolean
74
74
75 :param _str: string value to translate into boolean
75 :param _str: string value to translate into boolean
76 :rtype: boolean
76 :rtype: boolean
77 :returns: boolean from given string
77 :returns: boolean from given string
78 """
78 """
79 if _str is None:
79 if _str is None:
80 return False
80 return False
81 if _str in (True, False):
81 if _str in (True, False):
82 return _str
82 return _str
83 _str = str(_str).strip().lower()
83 _str = str(_str).strip().lower()
84 return _str in ('t', 'true', 'y', 'yes', 'on', '1')
84 return _str in ('t', 'true', 'y', 'yes', 'on', '1')
85
85
86
86
87 def aslist(obj, sep=None, strip=True):
87 def aslist(obj, sep=None, strip=True):
88 """
88 """
89 Returns given string separated by sep as list
89 Returns given string separated by sep as list
90
90
91 :param obj:
91 :param obj:
92 :param sep:
92 :param sep:
93 :param strip:
93 :param strip:
94 """
94 """
95 if isinstance(obj, (basestring)):
95 if isinstance(obj, (basestring)):
96 lst = obj.split(sep)
96 lst = obj.split(sep)
97 if strip:
97 if strip:
98 lst = [v.strip() for v in lst]
98 lst = [v.strip() for v in lst]
99 return lst
99 return lst
100 elif isinstance(obj, (list, tuple)):
100 elif isinstance(obj, (list, tuple)):
101 return obj
101 return obj
102 elif obj is None:
102 elif obj is None:
103 return []
103 return []
104 else:
104 else:
105 return [obj]
105 return [obj]
106
106
107
107
108 def convert_line_endings(line, mode):
108 def convert_line_endings(line, mode):
109 """
109 """
110 Converts a given line "line end" accordingly to given mode
110 Converts a given line "line end" accordingly to given mode
111
111
112 Available modes are::
112 Available modes are::
113 0 - Unix
113 0 - Unix
114 1 - Mac
114 1 - Mac
115 2 - DOS
115 2 - DOS
116
116
117 :param line: given line to convert
117 :param line: given line to convert
118 :param mode: mode to convert to
118 :param mode: mode to convert to
119 :rtype: str
119 :rtype: str
120 :return: converted line according to mode
120 :return: converted line according to mode
121 """
121 """
122 from string import replace
122 from string import replace
123
123
124 if mode == 0:
124 if mode == 0:
125 line = replace(line, '\r\n', '\n')
125 line = replace(line, '\r\n', '\n')
126 line = replace(line, '\r', '\n')
126 line = replace(line, '\r', '\n')
127 elif mode == 1:
127 elif mode == 1:
128 line = replace(line, '\r\n', '\r')
128 line = replace(line, '\r\n', '\r')
129 line = replace(line, '\n', '\r')
129 line = replace(line, '\n', '\r')
130 elif mode == 2:
130 elif mode == 2:
131 line = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", line)
131 line = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", line)
132 return line
132 return line
133
133
134
134
135 def detect_mode(line, default):
135 def detect_mode(line, default):
136 """
136 """
137 Detects line break for given line, if line break couldn't be found
137 Detects line break for given line, if line break couldn't be found
138 given default value is returned
138 given default value is returned
139
139
140 :param line: str line
140 :param line: str line
141 :param default: default
141 :param default: default
142 :rtype: int
142 :rtype: int
143 :return: value of line end on of 0 - Unix, 1 - Mac, 2 - DOS
143 :return: value of line end on of 0 - Unix, 1 - Mac, 2 - DOS
144 """
144 """
145 if line.endswith('\r\n'):
145 if line.endswith('\r\n'):
146 return 2
146 return 2
147 elif line.endswith('\n'):
147 elif line.endswith('\n'):
148 return 0
148 return 0
149 elif line.endswith('\r'):
149 elif line.endswith('\r'):
150 return 1
150 return 1
151 else:
151 else:
152 return default
152 return default
153
153
154
154
155 def generate_api_key(username, salt=None):
155 def generate_api_key(username, salt=None):
156 """
156 """
157 Generates unique API key for given username, if salt is not given
157 Generates unique API key for given username, if salt is not given
158 it'll be generated from some random string
158 it'll be generated from some random string
159
159
160 :param username: username as string
160 :param username: username as string
161 :param salt: salt to hash generate KEY
161 :param salt: salt to hash generate KEY
162 :rtype: str
162 :rtype: str
163 :returns: sha1 hash from username+salt
163 :returns: sha1 hash from username+salt
164 """
164 """
165 from tempfile import _RandomNameSequence
165 from tempfile import _RandomNameSequence
166 import hashlib
166 import hashlib
167
167
168 if salt is None:
168 if salt is None:
169 salt = _RandomNameSequence().next()
169 salt = _RandomNameSequence().next()
170
170
171 return hashlib.sha1(username + salt).hexdigest()
171 return hashlib.sha1(username + salt).hexdigest()
172
172
173
173
174 def safe_int(val, default=None):
174 def safe_int(val, default=None):
175 """
175 """
176 Returns int() of val if val is not convertable to int use default
176 Returns int() of val if val is not convertable to int use default
177 instead
177 instead
178
178
179 :param val:
179 :param val:
180 :param default:
180 :param default:
181 """
181 """
182
182
183 try:
183 try:
184 val = int(val)
184 val = int(val)
185 except (ValueError, TypeError):
185 except (ValueError, TypeError):
186 val = default
186 val = default
187
187
188 return val
188 return val
189
189
190
190
191 def safe_unicode(str_, from_encoding=None):
191 def safe_unicode(str_, from_encoding=None):
192 """
192 """
193 safe unicode function. Does few trick to turn str_ into unicode
193 safe unicode function. Does few trick to turn str_ into unicode
194
194
195 In case of UnicodeDecode error we try to return it with encoding detected
195 In case of UnicodeDecode error we try to return it with encoding detected
196 by chardet library if it fails fallback to unicode with errors replaced
196 by chardet library if it fails fallback to unicode with errors replaced
197
197
198 :param str_: string to decode
198 :param str_: string to decode
199 :rtype: unicode
199 :rtype: unicode
200 :returns: unicode object
200 :returns: unicode object
201 """
201 """
202 if isinstance(str_, unicode):
202 if isinstance(str_, unicode):
203 return str_
203 return str_
204
204
205 if not from_encoding:
205 if not from_encoding:
206 import rhodecode
206 import rhodecode
207 DEFAULT_ENCODINGS = aslist(rhodecode.CONFIG.get('default_encoding',
207 DEFAULT_ENCODINGS = aslist(rhodecode.CONFIG.get('default_encoding',
208 'utf8'), sep=',')
208 'utf8'), sep=',')
209 from_encoding = DEFAULT_ENCODINGS
209 from_encoding = DEFAULT_ENCODINGS
210
210
211 if not isinstance(from_encoding, (list, tuple)):
211 if not isinstance(from_encoding, (list, tuple)):
212 from_encoding = [from_encoding]
212 from_encoding = [from_encoding]
213
213
214 try:
214 try:
215 return unicode(str_)
215 return unicode(str_)
216 except UnicodeDecodeError:
216 except UnicodeDecodeError:
217 pass
217 pass
218
218
219 for enc in from_encoding:
219 for enc in from_encoding:
220 try:
220 try:
221 return unicode(str_, enc)
221 return unicode(str_, enc)
222 except UnicodeDecodeError:
222 except UnicodeDecodeError:
223 pass
223 pass
224
224
225 try:
225 try:
226 import chardet
226 import chardet
227 encoding = chardet.detect(str_)['encoding']
227 encoding = chardet.detect(str_)['encoding']
228 if encoding is None:
228 if encoding is None:
229 raise Exception()
229 raise Exception()
230 return str_.decode(encoding)
230 return str_.decode(encoding)
231 except (ImportError, UnicodeDecodeError, Exception):
231 except (ImportError, UnicodeDecodeError, Exception):
232 return unicode(str_, from_encoding[0], 'replace')
232 return unicode(str_, from_encoding[0], 'replace')
233
233
234
234
235 def safe_str(unicode_, to_encoding=None):
235 def safe_str(unicode_, to_encoding=None):
236 """
236 """
237 safe str function. Does few trick to turn unicode_ into string
237 safe str function. Does few trick to turn unicode_ into string
238
238
239 In case of UnicodeEncodeError we try to return it with encoding detected
239 In case of UnicodeEncodeError we try to return it with encoding detected
240 by chardet library if it fails fallback to string with errors replaced
240 by chardet library if it fails fallback to string with errors replaced
241
241
242 :param unicode_: unicode to encode
242 :param unicode_: unicode to encode
243 :rtype: str
243 :rtype: str
244 :returns: str object
244 :returns: str object
245 """
245 """
246
246
247 # if it's not basestr cast to str
247 # if it's not basestr cast to str
248 if not isinstance(unicode_, basestring):
248 if not isinstance(unicode_, basestring):
249 return str(unicode_)
249 return str(unicode_)
250
250
251 if isinstance(unicode_, str):
251 if isinstance(unicode_, str):
252 return unicode_
252 return unicode_
253
253
254 if not to_encoding:
254 if not to_encoding:
255 import rhodecode
255 import rhodecode
256 DEFAULT_ENCODINGS = aslist(rhodecode.CONFIG.get('default_encoding',
256 DEFAULT_ENCODINGS = aslist(rhodecode.CONFIG.get('default_encoding',
257 'utf8'), sep=',')
257 'utf8'), sep=',')
258 to_encoding = DEFAULT_ENCODINGS
258 to_encoding = DEFAULT_ENCODINGS
259
259
260 if not isinstance(to_encoding, (list, tuple)):
260 if not isinstance(to_encoding, (list, tuple)):
261 to_encoding = [to_encoding]
261 to_encoding = [to_encoding]
262
262
263 for enc in to_encoding:
263 for enc in to_encoding:
264 try:
264 try:
265 return unicode_.encode(enc)
265 return unicode_.encode(enc)
266 except UnicodeEncodeError:
266 except UnicodeEncodeError:
267 pass
267 pass
268
268
269 try:
269 try:
270 import chardet
270 import chardet
271 encoding = chardet.detect(unicode_)['encoding']
271 encoding = chardet.detect(unicode_)['encoding']
272 if encoding is None:
272 if encoding is None:
273 raise UnicodeEncodeError()
273 raise UnicodeEncodeError()
274
274
275 return unicode_.encode(encoding)
275 return unicode_.encode(encoding)
276 except (ImportError, UnicodeEncodeError):
276 except (ImportError, UnicodeEncodeError):
277 return unicode_.encode(to_encoding[0], 'replace')
277 return unicode_.encode(to_encoding[0], 'replace')
278
278
279 return safe_str
279 return safe_str
280
280
281
281
282 def remove_suffix(s, suffix):
282 def remove_suffix(s, suffix):
283 if s.endswith(suffix):
283 if s.endswith(suffix):
284 s = s[:-1 * len(suffix)]
284 s = s[:-1 * len(suffix)]
285 return s
285 return s
286
286
287
287
288 def remove_prefix(s, prefix):
288 def remove_prefix(s, prefix):
289 if s.startswith(prefix):
289 if s.startswith(prefix):
290 s = s[len(prefix):]
290 s = s[len(prefix):]
291 return s
291 return s
292
292
293
293
294 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
294 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
295 """
295 """
296 Custom engine_from_config functions that makes sure we use NullPool for
296 Custom engine_from_config functions that makes sure we use NullPool for
297 file based sqlite databases. This prevents errors on sqlite. This only
297 file based sqlite databases. This prevents errors on sqlite. This only
298 applies to sqlalchemy versions < 0.7.0
298 applies to sqlalchemy versions < 0.7.0
299
299
300 """
300 """
301 import sqlalchemy
301 import sqlalchemy
302 from sqlalchemy import engine_from_config as efc
302 from sqlalchemy import engine_from_config as efc
303 import logging
303 import logging
304
304
305 if int(sqlalchemy.__version__.split('.')[1]) < 7:
305 if int(sqlalchemy.__version__.split('.')[1]) < 7:
306
306
307 # This solution should work for sqlalchemy < 0.7.0, and should use
307 # This solution should work for sqlalchemy < 0.7.0, and should use
308 # proxy=TimerProxy() for execution time profiling
308 # proxy=TimerProxy() for execution time profiling
309
309
310 from sqlalchemy.pool import NullPool
310 from sqlalchemy.pool import NullPool
311 url = configuration[prefix + 'url']
311 url = configuration[prefix + 'url']
312
312
313 if url.startswith('sqlite'):
313 if url.startswith('sqlite'):
314 kwargs.update({'poolclass': NullPool})
314 kwargs.update({'poolclass': NullPool})
315 return efc(configuration, prefix, **kwargs)
315 return efc(configuration, prefix, **kwargs)
316 else:
316 else:
317 import time
317 import time
318 from sqlalchemy import event
318 from sqlalchemy import event
319 from sqlalchemy.engine import Engine
319 from sqlalchemy.engine import Engine
320
320
321 log = logging.getLogger('sqlalchemy.engine')
321 log = logging.getLogger('sqlalchemy.engine')
322 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38)
322 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38)
323 engine = efc(configuration, prefix, **kwargs)
323 engine = efc(configuration, prefix, **kwargs)
324
324
325 def color_sql(sql):
325 def color_sql(sql):
326 COLOR_SEQ = "\033[1;%dm"
326 COLOR_SEQ = "\033[1;%dm"
327 COLOR_SQL = YELLOW
327 COLOR_SQL = YELLOW
328 normal = '\x1b[0m'
328 normal = '\x1b[0m'
329 return ''.join([COLOR_SEQ % COLOR_SQL, sql, normal])
329 return ''.join([COLOR_SEQ % COLOR_SQL, sql, normal])
330
330
331 if configuration['debug']:
331 if configuration['debug']:
332 #attach events only for debug configuration
332 #attach events only for debug configuration
333
333
334 def before_cursor_execute(conn, cursor, statement,
334 def before_cursor_execute(conn, cursor, statement,
335 parameters, context, executemany):
335 parameters, context, executemany):
336 context._query_start_time = time.time()
336 context._query_start_time = time.time()
337 log.info(color_sql(">>>>> STARTING QUERY >>>>>"))
337 log.info(color_sql(">>>>> STARTING QUERY >>>>>"))
338
338
339 def after_cursor_execute(conn, cursor, statement,
339 def after_cursor_execute(conn, cursor, statement,
340 parameters, context, executemany):
340 parameters, context, executemany):
341 total = time.time() - context._query_start_time
341 total = time.time() - context._query_start_time
342 log.info(color_sql("<<<<< TOTAL TIME: %f <<<<<" % total))
342 log.info(color_sql("<<<<< TOTAL TIME: %f <<<<<" % total))
343
343
344 event.listen(engine, "before_cursor_execute",
344 event.listen(engine, "before_cursor_execute",
345 before_cursor_execute)
345 before_cursor_execute)
346 event.listen(engine, "after_cursor_execute",
346 event.listen(engine, "after_cursor_execute",
347 after_cursor_execute)
347 after_cursor_execute)
348
348
349 return engine
349 return engine
350
350
351
351
352 def age(prevdate):
352 def age(prevdate):
353 """
353 """
354 turns a datetime into an age string.
354 turns a datetime into an age string.
355
355
356 :param prevdate: datetime object
356 :param prevdate: datetime object
357 :rtype: unicode
357 :rtype: unicode
358 :returns: unicode words describing age
358 :returns: unicode words describing age
359 """
359 """
360
360
361 order = ['year', 'month', 'day', 'hour', 'minute', 'second']
361 order = ['year', 'month', 'day', 'hour', 'minute', 'second']
362 deltas = {}
362 deltas = {}
363 future = False
363 future = False
364
364
365 # Get date parts deltas
365 # Get date parts deltas
366 now = datetime.datetime.now()
366 now = datetime.datetime.now()
367 if prevdate > now:
367 if prevdate > now:
368 now, prevdate = prevdate, now
368 now, prevdate = prevdate, now
369 future = True
369 future = True
370
370
371 for part in order:
371 for part in order:
372 deltas[part] = getattr(now, part) - getattr(prevdate, part)
372 deltas[part] = getattr(now, part) - getattr(prevdate, part)
373
373
374 # Fix negative offsets (there is 1 second between 10:59:59 and 11:00:00,
374 # Fix negative offsets (there is 1 second between 10:59:59 and 11:00:00,
375 # not 1 hour, -59 minutes and -59 seconds)
375 # not 1 hour, -59 minutes and -59 seconds)
376
376
377 for num, length in [(5, 60), (4, 60), (3, 24)]: # seconds, minutes, hours
377 for num, length in [(5, 60), (4, 60), (3, 24)]: # seconds, minutes, hours
378 part = order[num]
378 part = order[num]
379 carry_part = order[num - 1]
379 carry_part = order[num - 1]
380
380
381 if deltas[part] < 0:
381 if deltas[part] < 0:
382 deltas[part] += length
382 deltas[part] += length
383 deltas[carry_part] -= 1
383 deltas[carry_part] -= 1
384
384
385 # Same thing for days except that the increment depends on the (variable)
385 # Same thing for days except that the increment depends on the (variable)
386 # number of days in the month
386 # number of days in the month
387 month_lengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
387 month_lengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
388 if deltas['day'] < 0:
388 if deltas['day'] < 0:
389 if prevdate.month == 2 and (prevdate.year % 4 == 0 and
389 if prevdate.month == 2 and (prevdate.year % 4 == 0 and
390 (prevdate.year % 100 != 0 or prevdate.year % 400 == 0)):
390 (prevdate.year % 100 != 0 or prevdate.year % 400 == 0)):
391 deltas['day'] += 29
391 deltas['day'] += 29
392 else:
392 else:
393 deltas['day'] += month_lengths[prevdate.month - 1]
393 deltas['day'] += month_lengths[prevdate.month - 1]
394
394
395 deltas['month'] -= 1
395 deltas['month'] -= 1
396
396
397 if deltas['month'] < 0:
397 if deltas['month'] < 0:
398 deltas['month'] += 12
398 deltas['month'] += 12
399 deltas['year'] -= 1
399 deltas['year'] -= 1
400
400
401 # Format the result
401 # Format the result
402 fmt_funcs = {
402 fmt_funcs = {
403 'year': lambda d: ungettext(u'%d year', '%d years', d) % d,
403 'year': lambda d: ungettext(u'%d year', '%d years', d) % d,
404 'month': lambda d: ungettext(u'%d month', '%d months', d) % d,
404 'month': lambda d: ungettext(u'%d month', '%d months', d) % d,
405 'day': lambda d: ungettext(u'%d day', '%d days', d) % d,
405 'day': lambda d: ungettext(u'%d day', '%d days', d) % d,
406 'hour': lambda d: ungettext(u'%d hour', '%d hours', d) % d,
406 'hour': lambda d: ungettext(u'%d hour', '%d hours', d) % d,
407 'minute': lambda d: ungettext(u'%d minute', '%d minutes', d) % d,
407 'minute': lambda d: ungettext(u'%d minute', '%d minutes', d) % d,
408 'second': lambda d: ungettext(u'%d second', '%d seconds', d) % d,
408 'second': lambda d: ungettext(u'%d second', '%d seconds', d) % d,
409 }
409 }
410
410
411 for i, part in enumerate(order):
411 for i, part in enumerate(order):
412 value = deltas[part]
412 value = deltas[part]
413 if value == 0:
413 if value == 0:
414 continue
414 continue
415
415
416 if i < 5:
416 if i < 5:
417 sub_part = order[i + 1]
417 sub_part = order[i + 1]
418 sub_value = deltas[sub_part]
418 sub_value = deltas[sub_part]
419 else:
419 else:
420 sub_value = 0
420 sub_value = 0
421
421
422 if sub_value == 0:
422 if sub_value == 0:
423 if future:
423 if future:
424 return _(u'in %s') % fmt_funcs[part](value)
424 return _(u'in %s') % fmt_funcs[part](value)
425 else:
425 else:
426 return _(u'%s ago') % fmt_funcs[part](value)
426 return _(u'%s ago') % fmt_funcs[part](value)
427 if future:
427 if future:
428 return _(u'in %s and %s') % (fmt_funcs[part](value),
428 return _(u'in %s and %s') % (fmt_funcs[part](value),
429 fmt_funcs[sub_part](sub_value))
429 fmt_funcs[sub_part](sub_value))
430 else:
430 else:
431 return _(u'%s and %s ago') % (fmt_funcs[part](value),
431 return _(u'%s and %s ago') % (fmt_funcs[part](value),
432 fmt_funcs[sub_part](sub_value))
432 fmt_funcs[sub_part](sub_value))
433
433
434 return _(u'just now')
434 return _(u'just now')
435
435
436
436
437 def uri_filter(uri):
437 def uri_filter(uri):
438 """
438 """
439 Removes user:password from given url string
439 Removes user:password from given url string
440
440
441 :param uri:
441 :param uri:
442 :rtype: unicode
442 :rtype: unicode
443 :returns: filtered list of strings
443 :returns: filtered list of strings
444 """
444 """
445 if not uri:
445 if not uri:
446 return ''
446 return ''
447
447
448 proto = ''
448 proto = ''
449
449
450 for pat in ('https://', 'http://'):
450 for pat in ('https://', 'http://'):
451 if uri.startswith(pat):
451 if uri.startswith(pat):
452 uri = uri[len(pat):]
452 uri = uri[len(pat):]
453 proto = pat
453 proto = pat
454 break
454 break
455
455
456 # remove passwords and username
456 # remove passwords and username
457 uri = uri[uri.find('@') + 1:]
457 uri = uri[uri.find('@') + 1:]
458
458
459 # get the port
459 # get the port
460 cred_pos = uri.find(':')
460 cred_pos = uri.find(':')
461 if cred_pos == -1:
461 if cred_pos == -1:
462 host, port = uri, None
462 host, port = uri, None
463 else:
463 else:
464 host, port = uri[:cred_pos], uri[cred_pos + 1:]
464 host, port = uri[:cred_pos], uri[cred_pos + 1:]
465
465
466 return filter(None, [proto, host, port])
466 return filter(None, [proto, host, port])
467
467
468
468
469 def credentials_filter(uri):
469 def credentials_filter(uri):
470 """
470 """
471 Returns a url with removed credentials
471 Returns a url with removed credentials
472
472
473 :param uri:
473 :param uri:
474 """
474 """
475
475
476 uri = uri_filter(uri)
476 uri = uri_filter(uri)
477 #check if we have port
477 #check if we have port
478 if len(uri) > 2 and uri[2]:
478 if len(uri) > 2 and uri[2]:
479 uri[2] = ':' + uri[2]
479 uri[2] = ':' + uri[2]
480
480
481 return ''.join(uri)
481 return ''.join(uri)
482
482
483
483
484 def get_changeset_safe(repo, rev):
484 def get_changeset_safe(repo, rev):
485 """
485 """
486 Safe version of get_changeset if this changeset doesn't exists for a
486 Safe version of get_changeset if this changeset doesn't exists for a
487 repo it returns a Dummy one instead
487 repo it returns a Dummy one instead
488
488
489 :param repo:
489 :param repo:
490 :param rev:
490 :param rev:
491 """
491 """
492 from rhodecode.lib.vcs.backends.base import BaseRepository
492 from rhodecode.lib.vcs.backends.base import BaseRepository
493 from rhodecode.lib.vcs.exceptions import RepositoryError
493 from rhodecode.lib.vcs.exceptions import RepositoryError
494 from rhodecode.lib.vcs.backends.base import EmptyChangeset
494 from rhodecode.lib.vcs.backends.base import EmptyChangeset
495 if not isinstance(repo, BaseRepository):
495 if not isinstance(repo, BaseRepository):
496 raise Exception('You must pass an Repository '
496 raise Exception('You must pass an Repository '
497 'object as first argument got %s', type(repo))
497 'object as first argument got %s', type(repo))
498
498
499 try:
499 try:
500 cs = repo.get_changeset(rev)
500 cs = repo.get_changeset(rev)
501 except RepositoryError:
501 except RepositoryError:
502 cs = EmptyChangeset(requested_revision=rev)
502 cs = EmptyChangeset(requested_revision=rev)
503 return cs
503 return cs
504
504
505
505
506 def datetime_to_time(dt):
506 def datetime_to_time(dt):
507 if dt:
507 if dt:
508 return time.mktime(dt.timetuple())
508 return time.mktime(dt.timetuple())
509
509
510
510
511 def time_to_datetime(tm):
511 def time_to_datetime(tm):
512 if tm:
512 if tm:
513 if isinstance(tm, basestring):
513 if isinstance(tm, basestring):
514 try:
514 try:
515 tm = float(tm)
515 tm = float(tm)
516 except ValueError:
516 except ValueError:
517 return
517 return
518 return datetime.datetime.fromtimestamp(tm)
518 return datetime.datetime.fromtimestamp(tm)
519
519
520 MENTIONS_REGEX = r'(?:^@|\s@)([a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+)(?:\s{1})'
520 MENTIONS_REGEX = r'(?:^@|\s@)([a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+)(?:\s{1})'
521
521
522
522
523 def extract_mentioned_users(s):
523 def extract_mentioned_users(s):
524 """
524 """
525 Returns unique usernames from given string s that have @mention
525 Returns unique usernames from given string s that have @mention
526
526
527 :param s: string to get mentions
527 :param s: string to get mentions
528 """
528 """
529 usrs = set()
529 usrs = set()
530 for username in re.findall(MENTIONS_REGEX, s):
530 for username in re.findall(MENTIONS_REGEX, s):
531 usrs.add(username)
531 usrs.add(username)
532
532
533 return sorted(list(usrs), key=lambda k: k.lower())
533 return sorted(list(usrs), key=lambda k: k.lower())
534
534
535
535
536 class AttributeDict(dict):
536 class AttributeDict(dict):
537 def __getattr__(self, attr):
537 def __getattr__(self, attr):
538 return self.get(attr, None)
538 return self.get(attr, None)
539 __setattr__ = dict.__setitem__
539 __setattr__ = dict.__setitem__
540 __delattr__ = dict.__delitem__
540 __delattr__ = dict.__delitem__
541
541
542
542
543 def fix_PATH(os_=None):
543 def fix_PATH(os_=None):
544 """
544 """
545 Get current active python path, and append it to PATH variable to fix issues
545 Get current active python path, and append it to PATH variable to fix issues
546 of subprocess calls and different python versions
546 of subprocess calls and different python versions
547 """
547 """
548 import sys
548 import sys
549 if os_ is None:
549 if os_ is None:
550 import os
550 import os
551 else:
551 else:
552 os = os_
552 os = os_
553
553
554 cur_path = os.path.split(sys.executable)[0]
554 cur_path = os.path.split(sys.executable)[0]
555 if not os.environ['PATH'].startswith(cur_path):
555 if not os.environ['PATH'].startswith(cur_path):
556 os.environ['PATH'] = '%s:%s' % (cur_path, os.environ['PATH'])
556 os.environ['PATH'] = '%s:%s' % (cur_path, os.environ['PATH'])
557
557
558
558
559 def obfuscate_url_pw(engine):
559 def obfuscate_url_pw(engine):
560 from sqlalchemy.engine import url
560 _url = engine or ''
561 url = url.make_url(engine)
561 from sqlalchemy.engine import url as sa_url
562 if url.password:
562 try:
563 url.password = 'XXXXX'
563 _url = sa_url.make_url(engine)
564 return str(url)
564 if _url.password:
565 _url.password = 'XXXXX'
566 except:
567 pass
568 return str(_url)
565
569
566
570
567 def get_server_url(environ):
571 def get_server_url(environ):
568 req = webob.Request(environ)
572 req = webob.Request(environ)
569 return req.host_url + req.script_name
573 return req.host_url + req.script_name
General Comments 0
You need to be logged in to leave comments. Login now