Mercurial > kallithea
annotate rhodecode/lib/utils2.py @ 2865:6d9b3ade3051 beta
Allowing multiple issue servers to be autolinked in the changeset view;
linking is now contingent on issue_server_link, issue_pat and issue_prefix
being defined; multiple servers can be used by specifying a common suffix on all
the above variables, ie ..
issue_server_link_1
issue_pat_1
issue_prefix_1
.. and ..
issue_server_link_other
issue_pat_other
issue_prefix_other
.. would be treated as two distinct servers, but ..
issue_pat_thing
.. would be ignored (since the other two requisite vars aren't present).
This patch is backwards compatible with existing variables (as a suffix
isn't needed).
author | Zachary Auclair <zach101@gmail.com> |
---|---|
date | Thu, 20 Sep 2012 20:30:55 -0400 |
parents | 6b176c679896 |
children | ccbdff90e5a0 |
rev | line source |
---|---|
2109 | 1 # -*- coding: utf-8 -*- |
2 """ | |
3 rhodecode.lib.utils | |
4 ~~~~~~~~~~~~~~~~~~~ | |
5 | |
6 Some simple helper functions | |
7 | |
8 :created_on: Jan 5, 2011 | |
9 :author: marcink | |
10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com> | |
11 :license: GPLv3, see COPYING for more details. | |
12 """ | |
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 | |
15 # the Free Software Foundation, either version 3 of the License, or | |
16 # (at your option) any later version. | |
17 # | |
18 # This program is distributed in the hope that it will be useful, | |
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 # GNU General Public License for more details. | |
22 # | |
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/>. | |
25 | |
26 import re | |
2699
4eef5eeb81a3
fixed sorting by last_login in users admin page
Marcin Kuzminski <marcin@python-works.com>
parents:
2684
diff
changeset
|
27 import time |
2726
aa17c7a1b8a5
Implemented basic locking functionality.
Marcin Kuzminski <marcin@python-works.com>
parents:
2699
diff
changeset
|
28 import datetime |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
29 from pylons.i18n.translation import _, ungettext |
2109 | 30 from rhodecode.lib.vcs.utils.lazy import LazyProperty |
31 | |
32 | |
33 def __get_lem(): | |
34 """ | |
35 Get language extension map based on what's inside pygments lexers | |
36 """ | |
37 from pygments import lexers | |
38 from string import lower | |
39 from collections import defaultdict | |
40 | |
41 d = defaultdict(lambda: []) | |
42 | |
43 def __clean(s): | |
44 s = s.lstrip('*') | |
45 s = s.lstrip('.') | |
46 | |
47 if s.find('[') != -1: | |
48 exts = [] | |
49 start, stop = s.find('['), s.find(']') | |
50 | |
51 for suffix in s[start + 1:stop]: | |
52 exts.append(s[:s.find('[')] + suffix) | |
53 return map(lower, exts) | |
54 else: | |
55 return map(lower, [s]) | |
56 | |
57 for lx, t in sorted(lexers.LEXERS.items()): | |
58 m = map(__clean, t[-2]) | |
59 if m: | |
60 m = reduce(lambda x, y: x + y, m) | |
61 for ext in m: | |
62 desc = lx.replace('Lexer', '') | |
63 d[ext].append(desc) | |
64 | |
65 return dict(d) | |
66 | |
67 def str2bool(_str): | |
68 """ | |
69 returs True/False value from given string, it tries to translate the | |
70 string into boolean | |
71 | |
72 :param _str: string value to translate into boolean | |
73 :rtype: boolean | |
74 :returns: boolean from given string | |
75 """ | |
76 if _str is None: | |
77 return False | |
78 if _str in (True, False): | |
79 return _str | |
80 _str = str(_str).strip().lower() | |
81 return _str in ('t', 'true', 'y', 'yes', 'on', '1') | |
82 | |
83 | |
84 def convert_line_endings(line, mode): | |
85 """ | |
86 Converts a given line "line end" accordingly to given mode | |
87 | |
88 Available modes are:: | |
89 0 - Unix | |
90 1 - Mac | |
91 2 - DOS | |
92 | |
93 :param line: given line to convert | |
94 :param mode: mode to convert to | |
95 :rtype: str | |
96 :return: converted line according to mode | |
97 """ | |
98 from string import replace | |
99 | |
100 if mode == 0: | |
101 line = replace(line, '\r\n', '\n') | |
102 line = replace(line, '\r', '\n') | |
103 elif mode == 1: | |
104 line = replace(line, '\r\n', '\r') | |
105 line = replace(line, '\n', '\r') | |
106 elif mode == 2: | |
107 line = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", line) | |
108 return line | |
109 | |
110 | |
111 def detect_mode(line, default): | |
112 """ | |
113 Detects line break for given line, if line break couldn't be found | |
114 given default value is returned | |
115 | |
116 :param line: str line | |
117 :param default: default | |
118 :rtype: int | |
119 :return: value of line end on of 0 - Unix, 1 - Mac, 2 - DOS | |
120 """ | |
121 if line.endswith('\r\n'): | |
122 return 2 | |
123 elif line.endswith('\n'): | |
124 return 0 | |
125 elif line.endswith('\r'): | |
126 return 1 | |
127 else: | |
128 return default | |
129 | |
130 | |
131 def generate_api_key(username, salt=None): | |
132 """ | |
133 Generates unique API key for given username, if salt is not given | |
134 it'll be generated from some random string | |
135 | |
136 :param username: username as string | |
137 :param salt: salt to hash generate KEY | |
138 :rtype: str | |
139 :returns: sha1 hash from username+salt | |
140 """ | |
141 from tempfile import _RandomNameSequence | |
142 import hashlib | |
143 | |
144 if salt is None: | |
145 salt = _RandomNameSequence().next() | |
146 | |
147 return hashlib.sha1(username + salt).hexdigest() | |
148 | |
149 | |
2845
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
150 def safe_int(val, default=None): |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
151 """ |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
152 Returns int() of val if val is not convertable to int use default |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
153 instead |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
154 |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
155 :param val: |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
156 :param default: |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
157 """ |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
158 |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
159 try: |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
160 val = int(val) |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
161 except ValueError: |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
162 val = default |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
163 |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
164 return val |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
165 |
6b176c679896
failsafe the GET `page` argument
Marcin Kuzminski <marcin@python-works.com>
parents:
2759
diff
changeset
|
166 |
2109 | 167 def safe_unicode(str_, from_encoding=None): |
168 """ | |
169 safe unicode function. Does few trick to turn str_ into unicode | |
170 | |
171 In case of UnicodeDecode error we try to return it with encoding detected | |
172 by chardet library if it fails fallback to unicode with errors replaced | |
173 | |
174 :param str_: string to decode | |
175 :rtype: unicode | |
176 :returns: unicode object | |
177 """ | |
178 if isinstance(str_, unicode): | |
179 return str_ | |
180 | |
181 if not from_encoding: | |
182 import rhodecode | |
183 DEFAULT_ENCODING = rhodecode.CONFIG.get('default_encoding','utf8') | |
184 from_encoding = DEFAULT_ENCODING | |
185 | |
186 try: | |
187 return unicode(str_) | |
188 except UnicodeDecodeError: | |
189 pass | |
190 | |
191 try: | |
192 return unicode(str_, from_encoding) | |
193 except UnicodeDecodeError: | |
194 pass | |
195 | |
196 try: | |
197 import chardet | |
198 encoding = chardet.detect(str_)['encoding'] | |
199 if encoding is None: | |
200 raise Exception() | |
201 return str_.decode(encoding) | |
202 except (ImportError, UnicodeDecodeError, Exception): | |
203 return unicode(str_, from_encoding, 'replace') | |
204 | |
205 | |
206 def safe_str(unicode_, to_encoding=None): | |
207 """ | |
208 safe str function. Does few trick to turn unicode_ into string | |
209 | |
210 In case of UnicodeEncodeError we try to return it with encoding detected | |
211 by chardet library if it fails fallback to string with errors replaced | |
212 | |
213 :param unicode_: unicode to encode | |
214 :rtype: str | |
215 :returns: str object | |
216 """ | |
217 | |
218 # if it's not basestr cast to str | |
219 if not isinstance(unicode_, basestring): | |
220 return str(unicode_) | |
221 | |
222 if isinstance(unicode_, str): | |
223 return unicode_ | |
224 | |
225 if not to_encoding: | |
226 import rhodecode | |
227 DEFAULT_ENCODING = rhodecode.CONFIG.get('default_encoding','utf8') | |
228 to_encoding = DEFAULT_ENCODING | |
229 | |
230 try: | |
231 return unicode_.encode(to_encoding) | |
232 except UnicodeEncodeError: | |
233 pass | |
234 | |
235 try: | |
236 import chardet | |
237 encoding = chardet.detect(unicode_)['encoding'] | |
238 if encoding is None: | |
239 raise UnicodeEncodeError() | |
240 | |
241 return unicode_.encode(encoding) | |
242 except (ImportError, UnicodeEncodeError): | |
243 return unicode_.encode(to_encoding, 'replace') | |
244 | |
245 return safe_str | |
246 | |
247 | |
248 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs): | |
249 """ | |
250 Custom engine_from_config functions that makes sure we use NullPool for | |
251 file based sqlite databases. This prevents errors on sqlite. This only | |
252 applies to sqlalchemy versions < 0.7.0 | |
253 | |
254 """ | |
255 import sqlalchemy | |
256 from sqlalchemy import engine_from_config as efc | |
257 import logging | |
258 | |
259 if int(sqlalchemy.__version__.split('.')[1]) < 7: | |
260 | |
261 # This solution should work for sqlalchemy < 0.7.0, and should use | |
262 # proxy=TimerProxy() for execution time profiling | |
263 | |
264 from sqlalchemy.pool import NullPool | |
265 url = configuration[prefix + 'url'] | |
266 | |
267 if url.startswith('sqlite'): | |
268 kwargs.update({'poolclass': NullPool}) | |
269 return efc(configuration, prefix, **kwargs) | |
270 else: | |
271 import time | |
272 from sqlalchemy import event | |
273 from sqlalchemy.engine import Engine | |
274 | |
275 log = logging.getLogger('sqlalchemy.engine') | |
276 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38) | |
277 engine = efc(configuration, prefix, **kwargs) | |
278 | |
279 def color_sql(sql): | |
280 COLOR_SEQ = "\033[1;%dm" | |
281 COLOR_SQL = YELLOW | |
282 normal = '\x1b[0m' | |
283 return ''.join([COLOR_SEQ % COLOR_SQL, sql, normal]) | |
284 | |
285 if configuration['debug']: | |
286 #attach events only for debug configuration | |
287 | |
288 def before_cursor_execute(conn, cursor, statement, | |
289 parameters, context, executemany): | |
290 context._query_start_time = time.time() | |
291 log.info(color_sql(">>>>> STARTING QUERY >>>>>")) | |
292 | |
293 def after_cursor_execute(conn, cursor, statement, | |
294 parameters, context, executemany): | |
295 total = time.time() - context._query_start_time | |
296 log.info(color_sql("<<<<< TOTAL TIME: %f <<<<<" % total)) | |
297 | |
298 event.listen(engine, "before_cursor_execute", | |
299 before_cursor_execute) | |
300 event.listen(engine, "after_cursor_execute", | |
301 after_cursor_execute) | |
302 | |
303 return engine | |
304 | |
305 | |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
306 def age(prevdate): |
2109 | 307 """ |
308 turns a datetime into an age string. | |
309 | |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
310 :param prevdate: datetime object |
2109 | 311 :rtype: unicode |
312 :returns: unicode words describing age | |
313 """ | |
314 | |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
315 order = ['year', 'month', 'day', 'hour', 'minute', 'second'] |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
316 deltas = {} |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
317 |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
318 # Get date parts deltas |
2726
aa17c7a1b8a5
Implemented basic locking functionality.
Marcin Kuzminski <marcin@python-works.com>
parents:
2699
diff
changeset
|
319 now = datetime.datetime.now() |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
320 for part in order: |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
321 deltas[part] = getattr(now, part) - getattr(prevdate, part) |
2109 | 322 |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
323 # Fix negative offsets (there is 1 second between 10:59:59 and 11:00:00, |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
324 # not 1 hour, -59 minutes and -59 seconds) |
2109 | 325 |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
326 for num, length in [(5, 60), (4, 60), (3, 24)]: # seconds, minutes, hours |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
327 part = order[num] |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
328 carry_part = order[num - 1] |
2367
86aa4f1f130b
white space cleanup
Marcin Kuzminski <marcin@python-works.com>
parents:
2303
diff
changeset
|
329 |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
330 if deltas[part] < 0: |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
331 deltas[part] += length |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
332 deltas[carry_part] -= 1 |
2109 | 333 |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
334 # Same thing for days except that the increment depends on the (variable) |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
335 # number of days in the month |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
336 month_lengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
337 if deltas['day'] < 0: |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
338 if prevdate.month == 2 and (prevdate.year % 4 == 0 and |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
339 (prevdate.year % 100 != 0 or prevdate.year % 400 == 0)): |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
340 deltas['day'] += 29 |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
341 else: |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
342 deltas['day'] += month_lengths[prevdate.month - 1] |
2367
86aa4f1f130b
white space cleanup
Marcin Kuzminski <marcin@python-works.com>
parents:
2303
diff
changeset
|
343 |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
344 deltas['month'] -= 1 |
2367
86aa4f1f130b
white space cleanup
Marcin Kuzminski <marcin@python-works.com>
parents:
2303
diff
changeset
|
345 |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
346 if deltas['month'] < 0: |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
347 deltas['month'] += 12 |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
348 deltas['year'] -= 1 |
2367
86aa4f1f130b
white space cleanup
Marcin Kuzminski <marcin@python-works.com>
parents:
2303
diff
changeset
|
349 |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
350 # Format the result |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
351 fmt_funcs = { |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
352 'year': lambda d: ungettext(u'%d year', '%d years', d) % d, |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
353 'month': lambda d: ungettext(u'%d month', '%d months', d) % d, |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
354 'day': lambda d: ungettext(u'%d day', '%d days', d) % d, |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
355 'hour': lambda d: ungettext(u'%d hour', '%d hours', d) % d, |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
356 'minute': lambda d: ungettext(u'%d minute', '%d minutes', d) % d, |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
357 'second': lambda d: ungettext(u'%d second', '%d seconds', d) % d, |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
358 } |
2367
86aa4f1f130b
white space cleanup
Marcin Kuzminski <marcin@python-works.com>
parents:
2303
diff
changeset
|
359 |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
360 for i, part in enumerate(order): |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
361 value = deltas[part] |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
362 if value == 0: |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
363 continue |
2367
86aa4f1f130b
white space cleanup
Marcin Kuzminski <marcin@python-works.com>
parents:
2303
diff
changeset
|
364 |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
365 if i < 5: |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
366 sub_part = order[i + 1] |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
367 sub_value = deltas[sub_part] |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
368 else: |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
369 sub_value = 0 |
2367
86aa4f1f130b
white space cleanup
Marcin Kuzminski <marcin@python-works.com>
parents:
2303
diff
changeset
|
370 |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
371 if sub_value == 0: |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
372 return _(u'%s ago') % fmt_funcs[part](value) |
2367
86aa4f1f130b
white space cleanup
Marcin Kuzminski <marcin@python-works.com>
parents:
2303
diff
changeset
|
373 |
2303
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
374 return _(u'%s and %s ago') % (fmt_funcs[part](value), |
7090e394df06
Rewrite of the age() utility function so it can be translated.
Vincent Duvert <vincent@duvert.net>
parents:
2278
diff
changeset
|
375 fmt_funcs[sub_part](sub_value)) |
2109 | 376 |
377 return _(u'just now') | |
378 | |
379 | |
380 def uri_filter(uri): | |
381 """ | |
382 Removes user:password from given url string | |
383 | |
384 :param uri: | |
385 :rtype: unicode | |
386 :returns: filtered list of strings | |
387 """ | |
388 if not uri: | |
389 return '' | |
390 | |
391 proto = '' | |
392 | |
393 for pat in ('https://', 'http://'): | |
394 if uri.startswith(pat): | |
395 uri = uri[len(pat):] | |
396 proto = pat | |
397 break | |
398 | |
399 # remove passwords and username | |
400 uri = uri[uri.find('@') + 1:] | |
401 | |
402 # get the port | |
403 cred_pos = uri.find(':') | |
404 if cred_pos == -1: | |
405 host, port = uri, None | |
406 else: | |
407 host, port = uri[:cred_pos], uri[cred_pos + 1:] | |
408 | |
409 return filter(None, [proto, host, port]) | |
410 | |
411 | |
412 def credentials_filter(uri): | |
413 """ | |
414 Returns a url with removed credentials | |
415 | |
416 :param uri: | |
417 """ | |
418 | |
419 uri = uri_filter(uri) | |
420 #check if we have port | |
421 if len(uri) > 2 and uri[2]: | |
422 uri[2] = ':' + uri[2] | |
423 | |
424 return ''.join(uri) | |
425 | |
426 | |
427 def get_changeset_safe(repo, rev): | |
428 """ | |
429 Safe version of get_changeset if this changeset doesn't exists for a | |
430 repo it returns a Dummy one instead | |
431 | |
432 :param repo: | |
433 :param rev: | |
434 """ | |
435 from rhodecode.lib.vcs.backends.base import BaseRepository | |
436 from rhodecode.lib.vcs.exceptions import RepositoryError | |
2684
2b6939a77052
Bumped mercurial version to 2.3
Marcin Kuzminski <marcin@python-works.com>
parents:
2674
diff
changeset
|
437 from rhodecode.lib.vcs.backends.base import EmptyChangeset |
2109 | 438 if not isinstance(repo, BaseRepository): |
439 raise Exception('You must pass an Repository ' | |
440 'object as first argument got %s', type(repo)) | |
441 | |
442 try: | |
443 cs = repo.get_changeset(rev) | |
444 except RepositoryError: | |
445 cs = EmptyChangeset(requested_revision=rev) | |
446 return cs | |
447 | |
448 | |
2699
4eef5eeb81a3
fixed sorting by last_login in users admin page
Marcin Kuzminski <marcin@python-works.com>
parents:
2684
diff
changeset
|
449 def datetime_to_time(dt): |
4eef5eeb81a3
fixed sorting by last_login in users admin page
Marcin Kuzminski <marcin@python-works.com>
parents:
2684
diff
changeset
|
450 if dt: |
4eef5eeb81a3
fixed sorting by last_login in users admin page
Marcin Kuzminski <marcin@python-works.com>
parents:
2684
diff
changeset
|
451 return time.mktime(dt.timetuple()) |
4eef5eeb81a3
fixed sorting by last_login in users admin page
Marcin Kuzminski <marcin@python-works.com>
parents:
2684
diff
changeset
|
452 |
4eef5eeb81a3
fixed sorting by last_login in users admin page
Marcin Kuzminski <marcin@python-works.com>
parents:
2684
diff
changeset
|
453 |
2726
aa17c7a1b8a5
Implemented basic locking functionality.
Marcin Kuzminski <marcin@python-works.com>
parents:
2699
diff
changeset
|
454 def time_to_datetime(tm): |
aa17c7a1b8a5
Implemented basic locking functionality.
Marcin Kuzminski <marcin@python-works.com>
parents:
2699
diff
changeset
|
455 if tm: |
aa17c7a1b8a5
Implemented basic locking functionality.
Marcin Kuzminski <marcin@python-works.com>
parents:
2699
diff
changeset
|
456 if isinstance(tm, basestring): |
aa17c7a1b8a5
Implemented basic locking functionality.
Marcin Kuzminski <marcin@python-works.com>
parents:
2699
diff
changeset
|
457 try: |
aa17c7a1b8a5
Implemented basic locking functionality.
Marcin Kuzminski <marcin@python-works.com>
parents:
2699
diff
changeset
|
458 tm = float(tm) |
aa17c7a1b8a5
Implemented basic locking functionality.
Marcin Kuzminski <marcin@python-works.com>
parents:
2699
diff
changeset
|
459 except ValueError: |
aa17c7a1b8a5
Implemented basic locking functionality.
Marcin Kuzminski <marcin@python-works.com>
parents:
2699
diff
changeset
|
460 return |
aa17c7a1b8a5
Implemented basic locking functionality.
Marcin Kuzminski <marcin@python-works.com>
parents:
2699
diff
changeset
|
461 return datetime.datetime.fromtimestamp(tm) |
aa17c7a1b8a5
Implemented basic locking functionality.
Marcin Kuzminski <marcin@python-works.com>
parents:
2699
diff
changeset
|
462 |
2201
ea5ff843b200
#426 fixed mention extracting regex
Marcin Kuzminski <marcin@python-works.com>
parents:
2109
diff
changeset
|
463 MENTIONS_REGEX = r'(?:^@|\s@)([a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+)(?:\s{1})' |
ea5ff843b200
#426 fixed mention extracting regex
Marcin Kuzminski <marcin@python-works.com>
parents:
2109
diff
changeset
|
464 |
ea5ff843b200
#426 fixed mention extracting regex
Marcin Kuzminski <marcin@python-works.com>
parents:
2109
diff
changeset
|
465 |
2109 | 466 def extract_mentioned_users(s): |
467 """ | |
468 Returns unique usernames from given string s that have @mention | |
469 | |
470 :param s: string to get mentions | |
471 """ | |
2201
ea5ff843b200
#426 fixed mention extracting regex
Marcin Kuzminski <marcin@python-works.com>
parents:
2109
diff
changeset
|
472 usrs = set() |
ea5ff843b200
#426 fixed mention extracting regex
Marcin Kuzminski <marcin@python-works.com>
parents:
2109
diff
changeset
|
473 for username in re.findall(MENTIONS_REGEX, s): |
ea5ff843b200
#426 fixed mention extracting regex
Marcin Kuzminski <marcin@python-works.com>
parents:
2109
diff
changeset
|
474 usrs.add(username) |
2109 | 475 |
2201
ea5ff843b200
#426 fixed mention extracting regex
Marcin Kuzminski <marcin@python-works.com>
parents:
2109
diff
changeset
|
476 return sorted(list(usrs), key=lambda k: k.lower()) |
2674
a221706dab50
merged + fixed pull request #62: Implemented metatags and visualisation options.
Marcin Kuzminski <marcin@python-works.com>
parents:
2367
diff
changeset
|
477 |
2699
4eef5eeb81a3
fixed sorting by last_login in users admin page
Marcin Kuzminski <marcin@python-works.com>
parents:
2684
diff
changeset
|
478 |
2674
a221706dab50
merged + fixed pull request #62: Implemented metatags and visualisation options.
Marcin Kuzminski <marcin@python-works.com>
parents:
2367
diff
changeset
|
479 class AttributeDict(dict): |
a221706dab50
merged + fixed pull request #62: Implemented metatags and visualisation options.
Marcin Kuzminski <marcin@python-works.com>
parents:
2367
diff
changeset
|
480 def __getattr__(self, attr): |
a221706dab50
merged + fixed pull request #62: Implemented metatags and visualisation options.
Marcin Kuzminski <marcin@python-works.com>
parents:
2367
diff
changeset
|
481 return self.get(attr, None) |
a221706dab50
merged + fixed pull request #62: Implemented metatags and visualisation options.
Marcin Kuzminski <marcin@python-works.com>
parents:
2367
diff
changeset
|
482 __setattr__ = dict.__setitem__ |
a221706dab50
merged + fixed pull request #62: Implemented metatags and visualisation options.
Marcin Kuzminski <marcin@python-works.com>
parents:
2367
diff
changeset
|
483 __delattr__ = dict.__delitem__ |