##// END OF EJS Templates
added quiet flag into get_current_revision
marcink -
r1571:a9888895 beta
parent child Browse files
Show More
@@ -1,404 +1,408 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.__init__
4 4 ~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Some simple helper functions
7 7
8 8 :created_on: Jan 5, 2011
9 9 :author: marcink
10 10 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import os
27 27
28 28 def __get_lem():
29 29 from pygments import lexers
30 30 from string import lower
31 31 from collections import defaultdict
32 32
33 33 d = defaultdict(lambda: [])
34 34
35 35 def __clean(s):
36 36 s = s.lstrip('*')
37 37 s = s.lstrip('.')
38 38
39 39 if s.find('[') != -1:
40 40 exts = []
41 41 start, stop = s.find('['), s.find(']')
42 42
43 43 for suffix in s[start + 1:stop]:
44 44 exts.append(s[:s.find('[')] + suffix)
45 45 return map(lower, exts)
46 46 else:
47 47 return map(lower, [s])
48 48
49 49 for lx, t in sorted(lexers.LEXERS.items()):
50 50 m = map(__clean, t[-2])
51 51 if m:
52 52 m = reduce(lambda x, y: x + y, m)
53 53 for ext in m:
54 54 desc = lx.replace('Lexer', '')
55 55 d[ext].append(desc)
56 56
57 57 return dict(d)
58 58
59 59 # language map is also used by whoosh indexer, which for those specified
60 60 # extensions will index it's content
61 61 LANGUAGES_EXTENSIONS_MAP = __get_lem()
62 62
63 63 # Additional mappings that are not present in the pygments lexers
64 64 # NOTE: that this will overide any mappings in LANGUAGES_EXTENSIONS_MAP
65 65 ADDITIONAL_MAPPINGS = {'xaml': 'XAML'}
66 66
67 67 LANGUAGES_EXTENSIONS_MAP.update(ADDITIONAL_MAPPINGS)
68 68
69 69
70 70 def str2bool(_str):
71 71 """
72 72 returs True/False value from given string, it tries to translate the
73 73 string into boolean
74 74
75 75 :param _str: string value to translate into boolean
76 76 :rtype: boolean
77 77 :returns: boolean from given string
78 78 """
79 79 if _str is None:
80 80 return False
81 81 if _str in (True, False):
82 82 return _str
83 83 _str = str(_str).strip().lower()
84 84 return _str in ('t', 'true', 'y', 'yes', 'on', '1')
85 85
86 86
87 87 def convert_line_endings(line, mode):
88 88 """
89 89 Converts a given line "line end" accordingly to given mode
90 90
91 91 Available modes are::
92 92 0 - Unix
93 93 1 - Mac
94 94 2 - DOS
95 95
96 96 :param line: given line to convert
97 97 :param mode: mode to convert to
98 98 :rtype: str
99 99 :return: converted line according to mode
100 100 """
101 101 from string import replace
102 102
103 103 if mode == 0:
104 104 line = replace(line, '\r\n', '\n')
105 105 line = replace(line, '\r', '\n')
106 106 elif mode == 1:
107 107 line = replace(line, '\r\n', '\r')
108 108 line = replace(line, '\n', '\r')
109 109 elif mode == 2:
110 110 import re
111 111 line = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", line)
112 112 return line
113 113
114 114
115 115 def detect_mode(line, default):
116 116 """
117 117 Detects line break for given line, if line break couldn't be found
118 118 given default value is returned
119 119
120 120 :param line: str line
121 121 :param default: default
122 122 :rtype: int
123 123 :return: value of line end on of 0 - Unix, 1 - Mac, 2 - DOS
124 124 """
125 125 if line.endswith('\r\n'):
126 126 return 2
127 127 elif line.endswith('\n'):
128 128 return 0
129 129 elif line.endswith('\r'):
130 130 return 1
131 131 else:
132 132 return default
133 133
134 134
135 135 def generate_api_key(username, salt=None):
136 136 """
137 137 Generates unique API key for given username, if salt is not given
138 138 it'll be generated from some random string
139 139
140 140 :param username: username as string
141 141 :param salt: salt to hash generate KEY
142 142 :rtype: str
143 143 :returns: sha1 hash from username+salt
144 144 """
145 145 from tempfile import _RandomNameSequence
146 146 import hashlib
147 147
148 148 if salt is None:
149 149 salt = _RandomNameSequence().next()
150 150
151 151 return hashlib.sha1(username + salt).hexdigest()
152 152
153 153
154 154 def safe_unicode(str_, from_encoding='utf8'):
155 155 """
156 156 safe unicode function. Does few trick to turn str_ into unicode
157 157
158 158 In case of UnicodeDecode error we try to return it with encoding detected
159 159 by chardet library if it fails fallback to unicode with errors replaced
160 160
161 161 :param str_: string to decode
162 162 :rtype: unicode
163 163 :returns: unicode object
164 164 """
165 165 if isinstance(str_, unicode):
166 166 return str_
167 167
168 168 try:
169 169 return unicode(str_)
170 170 except UnicodeDecodeError:
171 171 pass
172 172
173 173 try:
174 174 return unicode(str_, from_encoding)
175 175 except UnicodeDecodeError:
176 176 pass
177 177
178 178 try:
179 179 import chardet
180 180 encoding = chardet.detect(str_)['encoding']
181 181 if encoding is None:
182 182 raise Exception()
183 183 return str_.decode(encoding)
184 184 except (ImportError, UnicodeDecodeError, Exception):
185 185 return unicode(str_, from_encoding, 'replace')
186 186
187 187 def safe_str(unicode_, to_encoding='utf8'):
188 188 """
189 189 safe str function. Does few trick to turn unicode_ into string
190 190
191 191 In case of UnicodeEncodeError we try to return it with encoding detected
192 192 by chardet library if it fails fallback to string with errors replaced
193 193
194 194 :param unicode_: unicode to encode
195 195 :rtype: str
196 196 :returns: str object
197 197 """
198 198
199 199 if isinstance(unicode_, str):
200 200 return unicode_
201 201
202 202 try:
203 203 return unicode_.encode(to_encoding)
204 204 except UnicodeEncodeError:
205 205 pass
206 206
207 207 try:
208 208 import chardet
209 209 encoding = chardet.detect(unicode_)['encoding']
210 210 print encoding
211 211 if encoding is None:
212 212 raise UnicodeEncodeError()
213 213
214 214 return unicode_.encode(encoding)
215 215 except (ImportError, UnicodeEncodeError):
216 216 return unicode_.encode(to_encoding, 'replace')
217 217
218 218 return safe_str
219 219
220 220
221 221
222 222 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
223 223 """
224 224 Custom engine_from_config functions that makes sure we use NullPool for
225 225 file based sqlite databases. This prevents errors on sqlite. This only
226 226 applies to sqlalchemy versions < 0.7.0
227 227
228 228 """
229 229 import sqlalchemy
230 230 from sqlalchemy import engine_from_config as efc
231 231 import logging
232 232
233 233 if int(sqlalchemy.__version__.split('.')[1]) < 7:
234 234
235 235 # This solution should work for sqlalchemy < 0.7.0, and should use
236 236 # proxy=TimerProxy() for execution time profiling
237 237
238 238 from sqlalchemy.pool import NullPool
239 239 url = configuration[prefix + 'url']
240 240
241 241 if url.startswith('sqlite'):
242 242 kwargs.update({'poolclass': NullPool})
243 243 return efc(configuration, prefix, **kwargs)
244 244 else:
245 245 import time
246 246 from sqlalchemy import event
247 247 from sqlalchemy.engine import Engine
248 248
249 249 log = logging.getLogger('sqlalchemy.engine')
250 250 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38)
251 251 engine = efc(configuration, prefix, **kwargs)
252 252
253 253 def color_sql(sql):
254 254 COLOR_SEQ = "\033[1;%dm"
255 255 COLOR_SQL = YELLOW
256 256 normal = '\x1b[0m'
257 257 return ''.join([COLOR_SEQ % COLOR_SQL, sql, normal])
258 258
259 259 if configuration['debug']:
260 260 #attach events only for debug configuration
261 261
262 262 def before_cursor_execute(conn, cursor, statement,
263 263 parameters, context, executemany):
264 264 context._query_start_time = time.time()
265 265 log.info(color_sql(">>>>> STARTING QUERY >>>>>"))
266 266
267 267
268 268 def after_cursor_execute(conn, cursor, statement,
269 269 parameters, context, executemany):
270 270 total = time.time() - context._query_start_time
271 271 log.info(color_sql("<<<<< TOTAL TIME: %f <<<<<" % total))
272 272
273 273 event.listen(engine, "before_cursor_execute",
274 274 before_cursor_execute)
275 275 event.listen(engine, "after_cursor_execute",
276 276 after_cursor_execute)
277 277
278 278 return engine
279 279
280 280
281 281 def age(curdate):
282 282 """
283 283 turns a datetime into an age string.
284 284
285 285 :param curdate: datetime object
286 286 :rtype: unicode
287 287 :returns: unicode words describing age
288 288 """
289 289
290 290 from datetime import datetime
291 291 from webhelpers.date import time_ago_in_words
292 292
293 293 _ = lambda s:s
294 294
295 295 if not curdate:
296 296 return ''
297 297
298 298 agescales = [(_(u"year"), 3600 * 24 * 365),
299 299 (_(u"month"), 3600 * 24 * 30),
300 300 (_(u"day"), 3600 * 24),
301 301 (_(u"hour"), 3600),
302 302 (_(u"minute"), 60),
303 303 (_(u"second"), 1), ]
304 304
305 305 age = datetime.now() - curdate
306 306 age_seconds = (age.days * agescales[2][1]) + age.seconds
307 307 pos = 1
308 308 for scale in agescales:
309 309 if scale[1] <= age_seconds:
310 310 if pos == 6:pos = 5
311 311 return '%s %s' % (time_ago_in_words(curdate,
312 312 agescales[pos][0]), _('ago'))
313 313 pos += 1
314 314
315 315 return _(u'just now')
316 316
317 317
318 318 def uri_filter(uri):
319 319 """
320 320 Removes user:password from given url string
321 321
322 322 :param uri:
323 323 :rtype: unicode
324 324 :returns: filtered list of strings
325 325 """
326 326 if not uri:
327 327 return ''
328 328
329 329 proto = ''
330 330
331 331 for pat in ('https://', 'http://'):
332 332 if uri.startswith(pat):
333 333 uri = uri[len(pat):]
334 334 proto = pat
335 335 break
336 336
337 337 # remove passwords and username
338 338 uri = uri[uri.find('@') + 1:]
339 339
340 340 # get the port
341 341 cred_pos = uri.find(':')
342 342 if cred_pos == -1:
343 343 host, port = uri, None
344 344 else:
345 345 host, port = uri[:cred_pos], uri[cred_pos + 1:]
346 346
347 347 return filter(None, [proto, host, port])
348 348
349 349
350 350 def credentials_filter(uri):
351 351 """
352 352 Returns a url with removed credentials
353 353
354 354 :param uri:
355 355 """
356 356
357 357 uri = uri_filter(uri)
358 358 #check if we have port
359 359 if len(uri) > 2 and uri[2]:
360 360 uri[2] = ':' + uri[2]
361 361
362 362 return ''.join(uri)
363 363
364 364 def get_changeset_safe(repo, rev):
365 365 """
366 366 Safe version of get_changeset if this changeset doesn't exists for a
367 367 repo it returns a Dummy one instead
368 368
369 369 :param repo:
370 370 :param rev:
371 371 """
372 372 from vcs.backends.base import BaseRepository
373 373 from vcs.exceptions import RepositoryError
374 374 if not isinstance(repo, BaseRepository):
375 375 raise Exception('You must pass an Repository '
376 376 'object as first argument got %s', type(repo))
377 377
378 378 try:
379 379 cs = repo.get_changeset(rev)
380 380 except RepositoryError:
381 381 from rhodecode.lib.utils import EmptyChangeset
382 382 cs = EmptyChangeset(requested_revision=rev)
383 383 return cs
384 384
385 385
386 def get_current_revision():
386 def get_current_revision(quiet=False):
387 387 """
388 388 Returns tuple of (number, id) from repository containing this package
389 389 or None if repository could not be found.
390
391 :param quiet: prints error for fetching revision if True
390 392 """
391 393
392 394 try:
393 395 from vcs import get_repo
394 396 from vcs.utils.helpers import get_scm
395 397 from vcs.exceptions import RepositoryError, VCSError
396 398 repopath = os.path.join(os.path.dirname(__file__), '..', '..')
397 399 scm = get_scm(repopath)[0]
398 400 repo = get_repo(path=repopath, alias=scm)
399 401 tip = repo.get_changeset()
400 402 return (tip.revision, tip.short_id)
401 403 except (ImportError, RepositoryError, VCSError), err:
404 if not quiet:
402 405 print ("Cannot retrieve rhodecode's revision. Original error "
403 406 "was: %s" % err)
404 407 return None
408
General Comments 0
You need to be logged in to leave comments. Login now