##// END OF EJS Templates
utils/conf...
marcink -
r2109:8ecfed1d beta
parent child Browse files
Show More
@@ -0,0 +1,58 b''
1 # -*- coding: utf-8 -*-
2 """
3 package.rhodecode.config.conf
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 Various config settings for RhodeCode
7
8 :created_on: Mar 7, 2012
9 :author: marcink
10 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
11 :license: <name>, see LICENSE_FILE for more details.
12 """
13 from rhodecode import EXTENSIONS
14
15 from rhodecode.lib.utils2 import __get_lem
16
17
18 # language map is also used by whoosh indexer, which for those specified
19 # extensions will index it's content
20 LANGUAGES_EXTENSIONS_MAP = __get_lem()
21
22 #==============================================================================
23 # WHOOSH INDEX EXTENSIONS
24 #==============================================================================
25 # EXTENSIONS WE WANT TO INDEX CONTENT OFF USING WHOOSH
26 INDEX_EXTENSIONS = LANGUAGES_EXTENSIONS_MAP.keys()
27
28 # list of readme files to search in file tree and display in summary
29 # attached weights defines the search order lower is first
30 ALL_READMES = [
31 ('readme', 0), ('README', 0), ('Readme', 0),
32 ('doc/readme', 1), ('doc/README', 1), ('doc/Readme', 1),
33 ('Docs/readme', 2), ('Docs/README', 2), ('Docs/Readme', 2),
34 ('DOCS/readme', 2), ('DOCS/README', 2), ('DOCS/Readme', 2),
35 ('docs/readme', 2), ('docs/README', 2), ('docs/Readme', 2),
36 ]
37
38 # extension together with weights to search lower is first
39 RST_EXTS = [
40 ('', 0), ('.rst', 1), ('.rest', 1),
41 ('.RST', 2), ('.REST', 2),
42 ('.txt', 3), ('.TXT', 3)
43 ]
44
45 MARKDOWN_EXTS = [
46 ('.md', 1), ('.MD', 1),
47 ('.mkdn', 2), ('.MKDN', 2),
48 ('.mdown', 3), ('.MDOWN', 3),
49 ('.markdown', 4), ('.MARKDOWN', 4)
50 ]
51
52 PLAIN_EXTS = [('.text', 2), ('.TEXT', 2)]
53
54 ALL_EXTS = MARKDOWN_EXTS + RST_EXTS + PLAIN_EXTS
55
56 DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
57
58 DATE_FORMAT = "%Y-%m-%d"
@@ -0,0 +1,405 b''
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
27 from rhodecode.lib.vcs.utils.lazy import LazyProperty
28
29
30 def __get_lem():
31 """
32 Get language extension map based on what's inside pygments lexers
33 """
34 from pygments import lexers
35 from string import lower
36 from collections import defaultdict
37
38 d = defaultdict(lambda: [])
39
40 def __clean(s):
41 s = s.lstrip('*')
42 s = s.lstrip('.')
43
44 if s.find('[') != -1:
45 exts = []
46 start, stop = s.find('['), s.find(']')
47
48 for suffix in s[start + 1:stop]:
49 exts.append(s[:s.find('[')] + suffix)
50 return map(lower, exts)
51 else:
52 return map(lower, [s])
53
54 for lx, t in sorted(lexers.LEXERS.items()):
55 m = map(__clean, t[-2])
56 if m:
57 m = reduce(lambda x, y: x + y, m)
58 for ext in m:
59 desc = lx.replace('Lexer', '')
60 d[ext].append(desc)
61
62 return dict(d)
63
64 def str2bool(_str):
65 """
66 returs True/False value from given string, it tries to translate the
67 string into boolean
68
69 :param _str: string value to translate into boolean
70 :rtype: boolean
71 :returns: boolean from given string
72 """
73 if _str is None:
74 return False
75 if _str in (True, False):
76 return _str
77 _str = str(_str).strip().lower()
78 return _str in ('t', 'true', 'y', 'yes', 'on', '1')
79
80
81 def convert_line_endings(line, mode):
82 """
83 Converts a given line "line end" accordingly to given mode
84
85 Available modes are::
86 0 - Unix
87 1 - Mac
88 2 - DOS
89
90 :param line: given line to convert
91 :param mode: mode to convert to
92 :rtype: str
93 :return: converted line according to mode
94 """
95 from string import replace
96
97 if mode == 0:
98 line = replace(line, '\r\n', '\n')
99 line = replace(line, '\r', '\n')
100 elif mode == 1:
101 line = replace(line, '\r\n', '\r')
102 line = replace(line, '\n', '\r')
103 elif mode == 2:
104 line = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", line)
105 return line
106
107
108 def detect_mode(line, default):
109 """
110 Detects line break for given line, if line break couldn't be found
111 given default value is returned
112
113 :param line: str line
114 :param default: default
115 :rtype: int
116 :return: value of line end on of 0 - Unix, 1 - Mac, 2 - DOS
117 """
118 if line.endswith('\r\n'):
119 return 2
120 elif line.endswith('\n'):
121 return 0
122 elif line.endswith('\r'):
123 return 1
124 else:
125 return default
126
127
128 def generate_api_key(username, salt=None):
129 """
130 Generates unique API key for given username, if salt is not given
131 it'll be generated from some random string
132
133 :param username: username as string
134 :param salt: salt to hash generate KEY
135 :rtype: str
136 :returns: sha1 hash from username+salt
137 """
138 from tempfile import _RandomNameSequence
139 import hashlib
140
141 if salt is None:
142 salt = _RandomNameSequence().next()
143
144 return hashlib.sha1(username + salt).hexdigest()
145
146
147 def safe_unicode(str_, from_encoding=None):
148 """
149 safe unicode function. Does few trick to turn str_ into unicode
150
151 In case of UnicodeDecode error we try to return it with encoding detected
152 by chardet library if it fails fallback to unicode with errors replaced
153
154 :param str_: string to decode
155 :rtype: unicode
156 :returns: unicode object
157 """
158 if isinstance(str_, unicode):
159 return str_
160
161 if not from_encoding:
162 import rhodecode
163 DEFAULT_ENCODING = rhodecode.CONFIG.get('default_encoding','utf8')
164 from_encoding = DEFAULT_ENCODING
165
166 try:
167 return unicode(str_)
168 except UnicodeDecodeError:
169 pass
170
171 try:
172 return unicode(str_, from_encoding)
173 except UnicodeDecodeError:
174 pass
175
176 try:
177 import chardet
178 encoding = chardet.detect(str_)['encoding']
179 if encoding is None:
180 raise Exception()
181 return str_.decode(encoding)
182 except (ImportError, UnicodeDecodeError, Exception):
183 return unicode(str_, from_encoding, 'replace')
184
185
186 def safe_str(unicode_, to_encoding=None):
187 """
188 safe str function. Does few trick to turn unicode_ into string
189
190 In case of UnicodeEncodeError we try to return it with encoding detected
191 by chardet library if it fails fallback to string with errors replaced
192
193 :param unicode_: unicode to encode
194 :rtype: str
195 :returns: str object
196 """
197
198 # if it's not basestr cast to str
199 if not isinstance(unicode_, basestring):
200 return str(unicode_)
201
202 if isinstance(unicode_, str):
203 return unicode_
204
205 if not to_encoding:
206 import rhodecode
207 DEFAULT_ENCODING = rhodecode.CONFIG.get('default_encoding','utf8')
208 to_encoding = DEFAULT_ENCODING
209
210 try:
211 return unicode_.encode(to_encoding)
212 except UnicodeEncodeError:
213 pass
214
215 try:
216 import chardet
217 encoding = chardet.detect(unicode_)['encoding']
218 print encoding
219 if encoding is None:
220 raise UnicodeEncodeError()
221
222 return unicode_.encode(encoding)
223 except (ImportError, UnicodeEncodeError):
224 return unicode_.encode(to_encoding, 'replace')
225
226 return safe_str
227
228
229 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
230 """
231 Custom engine_from_config functions that makes sure we use NullPool for
232 file based sqlite databases. This prevents errors on sqlite. This only
233 applies to sqlalchemy versions < 0.7.0
234
235 """
236 import sqlalchemy
237 from sqlalchemy import engine_from_config as efc
238 import logging
239
240 if int(sqlalchemy.__version__.split('.')[1]) < 7:
241
242 # This solution should work for sqlalchemy < 0.7.0, and should use
243 # proxy=TimerProxy() for execution time profiling
244
245 from sqlalchemy.pool import NullPool
246 url = configuration[prefix + 'url']
247
248 if url.startswith('sqlite'):
249 kwargs.update({'poolclass': NullPool})
250 return efc(configuration, prefix, **kwargs)
251 else:
252 import time
253 from sqlalchemy import event
254 from sqlalchemy.engine import Engine
255
256 log = logging.getLogger('sqlalchemy.engine')
257 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38)
258 engine = efc(configuration, prefix, **kwargs)
259
260 def color_sql(sql):
261 COLOR_SEQ = "\033[1;%dm"
262 COLOR_SQL = YELLOW
263 normal = '\x1b[0m'
264 return ''.join([COLOR_SEQ % COLOR_SQL, sql, normal])
265
266 if configuration['debug']:
267 #attach events only for debug configuration
268
269 def before_cursor_execute(conn, cursor, statement,
270 parameters, context, executemany):
271 context._query_start_time = time.time()
272 log.info(color_sql(">>>>> STARTING QUERY >>>>>"))
273
274
275 def after_cursor_execute(conn, cursor, statement,
276 parameters, context, executemany):
277 total = time.time() - context._query_start_time
278 log.info(color_sql("<<<<< TOTAL TIME: %f <<<<<" % total))
279
280 event.listen(engine, "before_cursor_execute",
281 before_cursor_execute)
282 event.listen(engine, "after_cursor_execute",
283 after_cursor_execute)
284
285 return engine
286
287
288 def age(curdate):
289 """
290 turns a datetime into an age string.
291
292 :param curdate: datetime object
293 :rtype: unicode
294 :returns: unicode words describing age
295 """
296
297 from datetime import datetime
298 from webhelpers.date import time_ago_in_words
299
300 _ = lambda s: s
301
302 if not curdate:
303 return ''
304
305 agescales = [(_(u"year"), 3600 * 24 * 365),
306 (_(u"month"), 3600 * 24 * 30),
307 (_(u"day"), 3600 * 24),
308 (_(u"hour"), 3600),
309 (_(u"minute"), 60),
310 (_(u"second"), 1), ]
311
312 age = datetime.now() - curdate
313 age_seconds = (age.days * agescales[2][1]) + age.seconds
314 pos = 1
315 for scale in agescales:
316 if scale[1] <= age_seconds:
317 if pos == 6:
318 pos = 5
319 return '%s %s' % (time_ago_in_words(curdate,
320 agescales[pos][0]), _('ago'))
321 pos += 1
322
323 return _(u'just now')
324
325
326 def uri_filter(uri):
327 """
328 Removes user:password from given url string
329
330 :param uri:
331 :rtype: unicode
332 :returns: filtered list of strings
333 """
334 if not uri:
335 return ''
336
337 proto = ''
338
339 for pat in ('https://', 'http://'):
340 if uri.startswith(pat):
341 uri = uri[len(pat):]
342 proto = pat
343 break
344
345 # remove passwords and username
346 uri = uri[uri.find('@') + 1:]
347
348 # get the port
349 cred_pos = uri.find(':')
350 if cred_pos == -1:
351 host, port = uri, None
352 else:
353 host, port = uri[:cred_pos], uri[cred_pos + 1:]
354
355 return filter(None, [proto, host, port])
356
357
358 def credentials_filter(uri):
359 """
360 Returns a url with removed credentials
361
362 :param uri:
363 """
364
365 uri = uri_filter(uri)
366 #check if we have port
367 if len(uri) > 2 and uri[2]:
368 uri[2] = ':' + uri[2]
369
370 return ''.join(uri)
371
372
373 def get_changeset_safe(repo, rev):
374 """
375 Safe version of get_changeset if this changeset doesn't exists for a
376 repo it returns a Dummy one instead
377
378 :param repo:
379 :param rev:
380 """
381 from rhodecode.lib.vcs.backends.base import BaseRepository
382 from rhodecode.lib.vcs.exceptions import RepositoryError
383 if not isinstance(repo, BaseRepository):
384 raise Exception('You must pass an Repository '
385 'object as first argument got %s', type(repo))
386
387 try:
388 cs = repo.get_changeset(rev)
389 except RepositoryError:
390 from rhodecode.lib.utils import EmptyChangeset
391 cs = EmptyChangeset(requested_revision=rev)
392 return cs
393
394
395 def extract_mentioned_users(s):
396 """
397 Returns unique usernames from given string s that have @mention
398
399 :param s: string to get mentions
400 """
401 usrs = {}
402 for username in re.findall(r'(?:^@|\s@)(\w+)', s):
403 usrs[username] = username
404
405 return sorted(usrs.keys())
@@ -2,40 +2,45 b''
2
2
3 import os
3 import os
4 import logging
4 import logging
5 import rhodecode
5
6
6 from mako.lookup import TemplateLookup
7 from mako.lookup import TemplateLookup
7 from pylons.configuration import PylonsConfig
8 from pylons.configuration import PylonsConfig
8 from pylons.error import handle_mako_error
9 from pylons.error import handle_mako_error
9
10
10 import rhodecode
11 # don't remove this import it does magic for celery
12 from rhodecode.lib import celerypylons
13
11 import rhodecode.lib.app_globals as app_globals
14 import rhodecode.lib.app_globals as app_globals
12 import rhodecode.lib.helpers
13
15
14 from rhodecode.config.routing import make_map
16 from rhodecode.config.routing import make_map
15 # don't remove this import it does magic for celery
17
16 from rhodecode.lib import celerypylons, str2bool
18 from rhodecode.lib import helpers
17 from rhodecode.lib import engine_from_config
18 from rhodecode.lib.auth import set_available_permissions
19 from rhodecode.lib.auth import set_available_permissions
19 from rhodecode.lib.utils import repo2db_mapper, make_ui, set_rhodecode_config
20 from rhodecode.lib.utils import repo2db_mapper, make_ui, set_rhodecode_config,\
21 load_rcextensions
22 from rhodecode.lib.utils2 import engine_from_config, str2bool
20 from rhodecode.model import init_model
23 from rhodecode.model import init_model
21 from rhodecode.model.scm import ScmModel
24 from rhodecode.model.scm import ScmModel
22 from rhodecode.lib.vcs.utils.fakemod import create_module
23
25
24 log = logging.getLogger(__name__)
26 log = logging.getLogger(__name__)
25
27
26
28
27 def load_environment(global_conf, app_conf, initial=False):
29 def load_environment(global_conf, app_conf, initial=False):
28 """Configure the Pylons environment via the ``pylons.config``
30 """
31 Configure the Pylons environment via the ``pylons.config``
29 object
32 object
30 """
33 """
31 config = PylonsConfig()
34 config = PylonsConfig()
32
35
33 # Pylons paths
36 # Pylons paths
34 root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
37 root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
35 paths = dict(root=root,
38 paths = dict(
36 controllers=os.path.join(root, 'controllers'),
39 root=root,
37 static_files=os.path.join(root, 'public'),
40 controllers=os.path.join(root, 'controllers'),
38 templates=[os.path.join(root, 'templates')])
41 static_files=os.path.join(root, 'public'),
42 templates=[os.path.join(root, 'templates')]
43 )
39
44
40 # Initialize config with the basic options
45 # Initialize config with the basic options
41 config.init_app(global_conf, app_conf, package='rhodecode', paths=paths)
46 config.init_app(global_conf, app_conf, package='rhodecode', paths=paths)
@@ -45,14 +50,11 b' def load_environment(global_conf, app_co'
45
50
46 config['routes.map'] = make_map(config)
51 config['routes.map'] = make_map(config)
47 config['pylons.app_globals'] = app_globals.Globals(config)
52 config['pylons.app_globals'] = app_globals.Globals(config)
48 config['pylons.h'] = rhodecode.lib.helpers
53 config['pylons.h'] = helpers
49 rhodecode.CONFIG = config
54 rhodecode.CONFIG = config
50
55
51 path = os.path.join(config['here'], 'rcextensions', '__init__.py')
56 load_rcextensions(root_path=config['here'])
52 if os.path.isfile(path):
57
53 rcext = create_module('rc', path)
54 rhodecode.EXTENSIONS = rcext
55 log.debug('Found rcextensions now loading %s...' % rcext)
56 # Setup cache object as early as possible
58 # Setup cache object as early as possible
57 import pylons
59 import pylons
58 pylons.cache._push_object(config['pylons.app_globals'].cache)
60 pylons.cache._push_object(config['pylons.app_globals'].cache)
@@ -77,5 +77,3 b' class MakeRcExt(BasePasterCommand):'
77
77
78 def update_parser(self):
78 def update_parser(self):
79 pass
79 pass
80
81
@@ -32,8 +32,9 b' from pylons import request, session, tmp'
32 from pylons.controllers.util import abort, redirect
32 from pylons.controllers.util import abort, redirect
33 from pylons.i18n.translation import _
33 from pylons.i18n.translation import _
34
34
35 from rhodecode.lib import helpers as h
35 from rhodecode.lib.exceptions import UsersGroupsAssignedException
36 from rhodecode.lib.exceptions import UsersGroupsAssignedException
36 from rhodecode.lib import helpers as h, safe_unicode
37 from rhodecode.lib.utils2 import safe_unicode
37 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
38 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
38 from rhodecode.lib.base import BaseController, render
39 from rhodecode.lib.base import BaseController, render
39
40
@@ -31,7 +31,7 b' import binascii'
31 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
31 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
32 from rhodecode.lib.base import BaseRepoController, render
32 from rhodecode.lib.base import BaseRepoController, render
33 from rhodecode.lib.compat import OrderedDict
33 from rhodecode.lib.compat import OrderedDict
34 from rhodecode.lib import safe_unicode
34 from rhodecode.lib.utils2 import safe_unicode
35 log = logging.getLogger(__name__)
35 log = logging.getLogger(__name__)
36
36
37
37
@@ -28,7 +28,7 b' import logging'
28 from pylons import url, response, tmpl_context as c
28 from pylons import url, response, tmpl_context as c
29 from pylons.i18n.translation import _
29 from pylons.i18n.translation import _
30
30
31 from rhodecode.lib import safe_unicode
31 from rhodecode.lib.utils2 import safe_unicode
32 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
32 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
33 from rhodecode.lib.base import BaseRepoController
33 from rhodecode.lib.base import BaseRepoController
34
34
@@ -32,24 +32,26 b' from pylons.i18n.translation import _'
32 from pylons.controllers.util import redirect
32 from pylons.controllers.util import redirect
33 from pylons.decorators import jsonify
33 from pylons.decorators import jsonify
34
34
35 from rhodecode.lib.vcs.conf import settings
35 from rhodecode.lib import diffs
36 from rhodecode.lib.vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
36 from rhodecode.lib import helpers as h
37 EmptyRepositoryError, ImproperArchiveTypeError, VCSError, \
38 NodeAlreadyExistsError
39 from rhodecode.lib.vcs.nodes import FileNode
40
37
41 from rhodecode.lib.compat import OrderedDict
38 from rhodecode.lib.compat import OrderedDict
42 from rhodecode.lib import convert_line_endings, detect_mode, safe_str
39 from rhodecode.lib.utils2 import convert_line_endings, detect_mode, safe_str
43 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
40 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
44 from rhodecode.lib.base import BaseRepoController, render
41 from rhodecode.lib.base import BaseRepoController, render
45 from rhodecode.lib.utils import EmptyChangeset
42 from rhodecode.lib.utils import EmptyChangeset
46 from rhodecode.lib import diffs
43 from rhodecode.lib.vcs.conf import settings
47 import rhodecode.lib.helpers as h
44 from rhodecode.lib.vcs.exceptions import RepositoryError, \
45 ChangesetDoesNotExistError, EmptyRepositoryError, \
46 ImproperArchiveTypeError, VCSError, NodeAlreadyExistsError
47 from rhodecode.lib.vcs.nodes import FileNode
48
48 from rhodecode.model.repo import RepoModel
49 from rhodecode.model.repo import RepoModel
50 from rhodecode.model.scm import ScmModel
51
49 from rhodecode.controllers.changeset import anchor_url, _ignorews_url,\
52 from rhodecode.controllers.changeset import anchor_url, _ignorews_url,\
50 _context_url, get_line_ctx, get_ignore_ws
53 _context_url, get_line_ctx, get_ignore_ws
51 from rhodecode.lib.diffs import wrapped_diff
54
52 from rhodecode.model.scm import ScmModel
53
55
54 log = logging.getLogger(__name__)
56 log = logging.getLogger(__name__)
55
57
@@ -447,7 +449,7 b' class FilesController(BaseRepoController'
447 ign_whitespace_lcl = get_ignore_ws(fid, request.GET)
449 ign_whitespace_lcl = get_ignore_ws(fid, request.GET)
448
450
449 lim = request.GET.get('fulldiff') or self.cut_off_limit
451 lim = request.GET.get('fulldiff') or self.cut_off_limit
450 _, cs1, cs2, diff, st = wrapped_diff(filenode_old=node1,
452 _, cs1, cs2, diff, st = diffs.wrapped_diff(filenode_old=node1,
451 filenode_new=node2,
453 filenode_new=node2,
452 cut_off_limit=lim,
454 cut_off_limit=lim,
453 ignore_whitespace=ign_whitespace_lcl,
455 ignore_whitespace=ign_whitespace_lcl,
@@ -40,15 +40,15 b' from pylons.i18n.translation import _'
40
40
41 from beaker.cache import cache_region, region_invalidate
41 from beaker.cache import cache_region, region_invalidate
42
42
43 from rhodecode.config.conf import ALL_READMES, ALL_EXTS, LANGUAGES_EXTENSIONS_MAP
43 from rhodecode.model.db import Statistics, CacheInvalidation
44 from rhodecode.model.db import Statistics, CacheInvalidation
44 from rhodecode.lib import ALL_READMES, ALL_EXTS, safe_unicode
45 from rhodecode.lib.utils2 import safe_unicode
45 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
46 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
46 from rhodecode.lib.base import BaseRepoController, render
47 from rhodecode.lib.base import BaseRepoController, render
47 from rhodecode.lib.utils import EmptyChangeset
48 from rhodecode.lib.utils import EmptyChangeset
48 from rhodecode.lib.markup_renderer import MarkupRenderer
49 from rhodecode.lib.markup_renderer import MarkupRenderer
49 from rhodecode.lib.celerylib import run_task
50 from rhodecode.lib.celerylib import run_task
50 from rhodecode.lib.celerylib.tasks import get_commits_stats, \
51 from rhodecode.lib.celerylib.tasks import get_commits_stats
51 LANGUAGES_EXTENSIONS_MAP
52 from rhodecode.lib.helpers import RepoPage
52 from rhodecode.lib.helpers import RepoPage
53 from rhodecode.lib.compat import json, OrderedDict
53 from rhodecode.lib.compat import json, OrderedDict
54
54
@@ -1,444 +1,4 b''
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.lib.__init__
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 os
1 import os
27 import re
28 from rhodecode import EXTENSIONS
29 from rhodecode.lib.vcs.utils.lazy import LazyProperty
30
31
32 def __get_lem():
33 from pygments import lexers
34 from string import lower
35 from collections import defaultdict
36
37 d = defaultdict(lambda: [])
38
39 def __clean(s):
40 s = s.lstrip('*')
41 s = s.lstrip('.')
42
43 if s.find('[') != -1:
44 exts = []
45 start, stop = s.find('['), s.find(']')
46
47 for suffix in s[start + 1:stop]:
48 exts.append(s[:s.find('[')] + suffix)
49 return map(lower, exts)
50 else:
51 return map(lower, [s])
52
53 for lx, t in sorted(lexers.LEXERS.items()):
54 m = map(__clean, t[-2])
55 if m:
56 m = reduce(lambda x, y: x + y, m)
57 for ext in m:
58 desc = lx.replace('Lexer', '')
59 d[ext].append(desc)
60
61 return dict(d)
62
63 # language map is also used by whoosh indexer, which for those specified
64 # extensions will index it's content
65 LANGUAGES_EXTENSIONS_MAP = __get_lem()
66
67 # Additional mappings that are not present in the pygments lexers
68 LANGUAGES_EXTENSIONS_MAP.update(getattr(EXTENSIONS, 'EXTRA_MAPPINGS', {}))
69
70 #==============================================================================
71 # WHOOSH INDEX EXTENSIONS
72 #==============================================================================
73 # EXTENSIONS WE WANT TO INDEX CONTENT OFF USING WHOOSH
74 INDEX_EXTENSIONS = LANGUAGES_EXTENSIONS_MAP.keys()
75
76 #OVERRIDE OUR EXTENSIONS FROM RC-EXTENSIONS (if present)
77
78 if getattr(EXTENSIONS, 'INDEX_EXTENSIONS', []) != []:
79 INDEX_EXTENSIONS = getattr(EXTENSIONS, 'INDEX_EXTENSIONS', [])
80
81 #ADDITIONAL MAPPINGS
82 INDEX_EXTENSIONS.extend(getattr(EXTENSIONS, 'EXTRA_INDEX_EXTENSIONS', []))
83
84 # list of readme files to search in file tree and display in summary
85 # attached weights defines the search order lower is first
86 ALL_READMES = [
87 ('readme', 0), ('README', 0), ('Readme', 0),
88 ('doc/readme', 1), ('doc/README', 1), ('doc/Readme', 1),
89 ('Docs/readme', 2), ('Docs/README', 2), ('Docs/Readme', 2),
90 ('DOCS/readme', 2), ('DOCS/README', 2), ('DOCS/Readme', 2),
91 ('docs/readme', 2), ('docs/README', 2), ('docs/Readme', 2),
92 ]
93
94 # extension together with weights to search lower is first
95 RST_EXTS = [
96 ('', 0), ('.rst', 1), ('.rest', 1),
97 ('.RST', 2), ('.REST', 2),
98 ('.txt', 3), ('.TXT', 3)
99 ]
100
101 MARKDOWN_EXTS = [
102 ('.md', 1), ('.MD', 1),
103 ('.mkdn', 2), ('.MKDN', 2),
104 ('.mdown', 3), ('.MDOWN', 3),
105 ('.markdown', 4), ('.MARKDOWN', 4)
106 ]
107
108 PLAIN_EXTS = [('.text', 2), ('.TEXT', 2)]
109
110 ALL_EXTS = MARKDOWN_EXTS + RST_EXTS + PLAIN_EXTS
111
112
113 def str2bool(_str):
114 """
115 returs True/False value from given string, it tries to translate the
116 string into boolean
117
118 :param _str: string value to translate into boolean
119 :rtype: boolean
120 :returns: boolean from given string
121 """
122 if _str is None:
123 return False
124 if _str in (True, False):
125 return _str
126 _str = str(_str).strip().lower()
127 return _str in ('t', 'true', 'y', 'yes', 'on', '1')
128
129
130 def convert_line_endings(line, mode):
131 """
132 Converts a given line "line end" accordingly to given mode
133
134 Available modes are::
135 0 - Unix
136 1 - Mac
137 2 - DOS
138
139 :param line: given line to convert
140 :param mode: mode to convert to
141 :rtype: str
142 :return: converted line according to mode
143 """
144 from string import replace
145
146 if mode == 0:
147 line = replace(line, '\r\n', '\n')
148 line = replace(line, '\r', '\n')
149 elif mode == 1:
150 line = replace(line, '\r\n', '\r')
151 line = replace(line, '\n', '\r')
152 elif mode == 2:
153 line = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", line)
154 return line
155
156
157 def detect_mode(line, default):
158 """
159 Detects line break for given line, if line break couldn't be found
160 given default value is returned
161
162 :param line: str line
163 :param default: default
164 :rtype: int
165 :return: value of line end on of 0 - Unix, 1 - Mac, 2 - DOS
166 """
167 if line.endswith('\r\n'):
168 return 2
169 elif line.endswith('\n'):
170 return 0
171 elif line.endswith('\r'):
172 return 1
173 else:
174 return default
175
176
177 def generate_api_key(username, salt=None):
178 """
179 Generates unique API key for given username, if salt is not given
180 it'll be generated from some random string
181
182 :param username: username as string
183 :param salt: salt to hash generate KEY
184 :rtype: str
185 :returns: sha1 hash from username+salt
186 """
187 from tempfile import _RandomNameSequence
188 import hashlib
189
190 if salt is None:
191 salt = _RandomNameSequence().next()
192
193 return hashlib.sha1(username + salt).hexdigest()
194
195
196 def safe_unicode(str_, from_encoding=None):
197 """
198 safe unicode function. Does few trick to turn str_ into unicode
199
200 In case of UnicodeDecode error we try to return it with encoding detected
201 by chardet library if it fails fallback to unicode with errors replaced
202
203 :param str_: string to decode
204 :rtype: unicode
205 :returns: unicode object
206 """
207 if isinstance(str_, unicode):
208 return str_
209
210 if not from_encoding:
211 import rhodecode
212 DEFAULT_ENCODING = rhodecode.CONFIG.get('default_encoding','utf8')
213 from_encoding = DEFAULT_ENCODING
214
215 try:
216 return unicode(str_)
217 except UnicodeDecodeError:
218 pass
219
220 try:
221 return unicode(str_, from_encoding)
222 except UnicodeDecodeError:
223 pass
224
225 try:
226 import chardet
227 encoding = chardet.detect(str_)['encoding']
228 if encoding is None:
229 raise Exception()
230 return str_.decode(encoding)
231 except (ImportError, UnicodeDecodeError, Exception):
232 return unicode(str_, from_encoding, 'replace')
233
234
235 def safe_str(unicode_, to_encoding=None):
236 """
237 safe str function. Does few trick to turn unicode_ into string
238
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
241
242 :param unicode_: unicode to encode
243 :rtype: str
244 :returns: str object
245 """
246
247 # if it's not basestr cast to str
248 if not isinstance(unicode_, basestring):
249 return str(unicode_)
250
251 if isinstance(unicode_, str):
252 return unicode_
253
254 if not to_encoding:
255 import rhodecode
256 DEFAULT_ENCODING = rhodecode.CONFIG.get('default_encoding','utf8')
257 to_encoding = DEFAULT_ENCODING
258
259 try:
260 return unicode_.encode(to_encoding)
261 except UnicodeEncodeError:
262 pass
263
264 try:
265 import chardet
266 encoding = chardet.detect(unicode_)['encoding']
267 print encoding
268 if encoding is None:
269 raise UnicodeEncodeError()
270
271 return unicode_.encode(encoding)
272 except (ImportError, UnicodeEncodeError):
273 return unicode_.encode(to_encoding, 'replace')
274
275 return safe_str
276
277
278 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
279 """
280 Custom engine_from_config functions that makes sure we use NullPool for
281 file based sqlite databases. This prevents errors on sqlite. This only
282 applies to sqlalchemy versions < 0.7.0
283
284 """
285 import sqlalchemy
286 from sqlalchemy import engine_from_config as efc
287 import logging
288
289 if int(sqlalchemy.__version__.split('.')[1]) < 7:
290
291 # This solution should work for sqlalchemy < 0.7.0, and should use
292 # proxy=TimerProxy() for execution time profiling
293
294 from sqlalchemy.pool import NullPool
295 url = configuration[prefix + 'url']
296
297 if url.startswith('sqlite'):
298 kwargs.update({'poolclass': NullPool})
299 return efc(configuration, prefix, **kwargs)
300 else:
301 import time
302 from sqlalchemy import event
303 from sqlalchemy.engine import Engine
304
305 log = logging.getLogger('sqlalchemy.engine')
306 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38)
307 engine = efc(configuration, prefix, **kwargs)
308
309 def color_sql(sql):
310 COLOR_SEQ = "\033[1;%dm"
311 COLOR_SQL = YELLOW
312 normal = '\x1b[0m'
313 return ''.join([COLOR_SEQ % COLOR_SQL, sql, normal])
314
315 if configuration['debug']:
316 #attach events only for debug configuration
317
318 def before_cursor_execute(conn, cursor, statement,
319 parameters, context, executemany):
320 context._query_start_time = time.time()
321 log.info(color_sql(">>>>> STARTING QUERY >>>>>"))
322
323
324 def after_cursor_execute(conn, cursor, statement,
325 parameters, context, executemany):
326 total = time.time() - context._query_start_time
327 log.info(color_sql("<<<<< TOTAL TIME: %f <<<<<" % total))
328
329 event.listen(engine, "before_cursor_execute",
330 before_cursor_execute)
331 event.listen(engine, "after_cursor_execute",
332 after_cursor_execute)
333
334 return engine
335
336
337 def age(curdate):
338 """
339 turns a datetime into an age string.
340
341 :param curdate: datetime object
342 :rtype: unicode
343 :returns: unicode words describing age
344 """
345
346 from datetime import datetime
347 from webhelpers.date import time_ago_in_words
348
349 _ = lambda s: s
350
351 if not curdate:
352 return ''
353
354 agescales = [(_(u"year"), 3600 * 24 * 365),
355 (_(u"month"), 3600 * 24 * 30),
356 (_(u"day"), 3600 * 24),
357 (_(u"hour"), 3600),
358 (_(u"minute"), 60),
359 (_(u"second"), 1), ]
360
361 age = datetime.now() - curdate
362 age_seconds = (age.days * agescales[2][1]) + age.seconds
363 pos = 1
364 for scale in agescales:
365 if scale[1] <= age_seconds:
366 if pos == 6:
367 pos = 5
368 return '%s %s' % (time_ago_in_words(curdate,
369 agescales[pos][0]), _('ago'))
370 pos += 1
371
372 return _(u'just now')
373
374
375 def uri_filter(uri):
376 """
377 Removes user:password from given url string
378
379 :param uri:
380 :rtype: unicode
381 :returns: filtered list of strings
382 """
383 if not uri:
384 return ''
385
386 proto = ''
387
388 for pat in ('https://', 'http://'):
389 if uri.startswith(pat):
390 uri = uri[len(pat):]
391 proto = pat
392 break
393
394 # remove passwords and username
395 uri = uri[uri.find('@') + 1:]
396
397 # get the port
398 cred_pos = uri.find(':')
399 if cred_pos == -1:
400 host, port = uri, None
401 else:
402 host, port = uri[:cred_pos], uri[cred_pos + 1:]
403
404 return filter(None, [proto, host, port])
405
406
407 def credentials_filter(uri):
408 """
409 Returns a url with removed credentials
410
411 :param uri:
412 """
413
414 uri = uri_filter(uri)
415 #check if we have port
416 if len(uri) > 2 and uri[2]:
417 uri[2] = ':' + uri[2]
418
419 return ''.join(uri)
420
421
422 def get_changeset_safe(repo, rev):
423 """
424 Safe version of get_changeset if this changeset doesn't exists for a
425 repo it returns a Dummy one instead
426
427 :param repo:
428 :param rev:
429 """
430 from rhodecode.lib.vcs.backends.base import BaseRepository
431 from rhodecode.lib.vcs.exceptions import RepositoryError
432 if not isinstance(repo, BaseRepository):
433 raise Exception('You must pass an Repository '
434 'object as first argument got %s', type(repo))
435
436 try:
437 cs = repo.get_changeset(rev)
438 except RepositoryError:
439 from rhodecode.lib.utils import EmptyChangeset
440 cs = EmptyChangeset(requested_revision=rev)
441 return cs
442
2
443
3
444 def get_current_revision(quiet=False):
4 def get_current_revision(quiet=False):
@@ -462,16 +22,3 b' def get_current_revision(quiet=False):'
462 print ("Cannot retrieve rhodecode's revision. Original error "
22 print ("Cannot retrieve rhodecode's revision. Original error "
463 "was: %s" % err)
23 "was: %s" % err)
464 return None
24 return None
465
466
467 def extract_mentioned_users(s):
468 """
469 Returns unique usernames from given string s that have @mention
470
471 :param s: string to get mentions
472 """
473 usrs = {}
474 for username in re.findall(r'(?:^@|\s@)(\w+)', s):
475 usrs[username] = username
476
477 return sorted(usrs.keys())
@@ -43,7 +43,7 b' if __platform__ in PLATFORM_WIN:'
43 if __platform__ in PLATFORM_OTHERS:
43 if __platform__ in PLATFORM_OTHERS:
44 import bcrypt
44 import bcrypt
45
45
46 from rhodecode.lib import str2bool, safe_unicode
46 from rhodecode.lib.utils2 import str2bool, safe_unicode
47 from rhodecode.lib.exceptions import LdapPasswordError, LdapUsernameError
47 from rhodecode.lib.exceptions import LdapPasswordError, LdapUsernameError
48 from rhodecode.lib.utils import get_repo_slug, get_repos_group_slug
48 from rhodecode.lib.utils import get_repo_slug, get_repos_group_slug
49 from rhodecode.lib.auth_ldap import AuthLdap
49 from rhodecode.lib.auth_ldap import AuthLdap
@@ -795,7 +795,7 b' class HasPermissionAnyMiddleware(object)'
795 try:
795 try:
796 self.user_perms = set([usr.permissions['repositories'][repo_name]])
796 self.user_perms = set([usr.permissions['repositories'][repo_name]])
797 except Exception:
797 except Exception:
798 log.error('Exception while accessing permissions %s' %
798 log.error('Exception while accessing permissions %s' %
799 traceback.format_exc())
799 traceback.format_exc())
800 self.user_perms = set()
800 self.user_perms = set()
801 self.granted_for = ''
801 self.granted_for = ''
@@ -15,7 +15,7 b' from pylons.templating import render_mak'
15
15
16 from rhodecode import __version__, BACKENDS
16 from rhodecode import __version__, BACKENDS
17
17
18 from rhodecode.lib import str2bool, safe_unicode
18 from rhodecode.lib.utils2 import str2bool, safe_unicode
19 from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\
19 from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\
20 HasPermissionAnyMiddleware, CookieStoreWrapper
20 HasPermissionAnyMiddleware, CookieStoreWrapper
21 from rhodecode.lib.utils import get_repo_slug, invalidate_cache
21 from rhodecode.lib.utils import get_repo_slug, invalidate_cache
@@ -24,7 +24,7 b' from beaker.exceptions import BeakerExce'
24 from sqlalchemy.orm.interfaces import MapperOption
24 from sqlalchemy.orm.interfaces import MapperOption
25 from sqlalchemy.orm.query import Query
25 from sqlalchemy.orm.query import Query
26 from sqlalchemy.sql import visitors
26 from sqlalchemy.sql import visitors
27 from rhodecode.lib import safe_str
27 from rhodecode.lib.utils2 import safe_str
28
28
29
29
30 class CachingQuery(Query):
30 class CachingQuery(Query):
@@ -36,7 +36,7 b' from decorator import decorator'
36
36
37 from rhodecode.lib.vcs.utils.lazy import LazyProperty
37 from rhodecode.lib.vcs.utils.lazy import LazyProperty
38 from rhodecode import CELERY_ON
38 from rhodecode import CELERY_ON
39 from rhodecode.lib import str2bool, safe_str
39 from rhodecode.lib.utils2 import str2bool, safe_str
40 from rhodecode.lib.pidlock import DaemonLock, LockHeld
40 from rhodecode.lib.pidlock import DaemonLock, LockHeld
41 from rhodecode.model import init_model
41 from rhodecode.model import init_model
42 from rhodecode.model import meta
42 from rhodecode.model import meta
@@ -40,7 +40,7 b' from pylons.i18n.translation import _'
40 from rhodecode.lib.vcs import get_backend
40 from rhodecode.lib.vcs import get_backend
41
41
42 from rhodecode import CELERY_ON
42 from rhodecode import CELERY_ON
43 from rhodecode.lib import LANGUAGES_EXTENSIONS_MAP, safe_str
43 from rhodecode.lib.utils2 import safe_str
44 from rhodecode.lib.celerylib import run_task, locked_task, dbsession, \
44 from rhodecode.lib.celerylib import run_task, locked_task, dbsession, \
45 str2bool, __get_lockkey, LockHeld, DaemonLock, get_session
45 str2bool, __get_lockkey, LockHeld, DaemonLock, get_session
46 from rhodecode.lib.helpers import person
46 from rhodecode.lib.helpers import person
@@ -147,6 +147,7 b' def get_commits_stats(repo_name, ts_min_'
147 last_rev, last_rev + parse_limit)
147 last_rev, last_rev + parse_limit)
148 )
148 )
149 for cs in repo[last_rev:last_rev + parse_limit]:
149 for cs in repo[last_rev:last_rev + parse_limit]:
150 log.debug('parsing %s' % cs)
150 last_cs = cs # remember last parsed changeset
151 last_cs = cs # remember last parsed changeset
151 k = lmktime([cs.date.timetuple()[0], cs.date.timetuple()[1],
152 k = lmktime([cs.date.timetuple()[0], cs.date.timetuple()[1],
152 cs.date.timetuple()[2], 0, 0, 0, 0, 0, 0])
153 cs.date.timetuple()[2], 0, 0, 0, 0, 0, 0])
@@ -233,10 +234,10 b' def get_commits_stats(repo_name, ts_min_'
233 lock.release()
234 lock.release()
234 return False
235 return False
235
236
236 #final release
237 # final release
237 lock.release()
238 lock.release()
238
239
239 #execute another task if celery is enabled
240 # execute another task if celery is enabled
240 if len(repo.revisions) > 1 and CELERY_ON:
241 if len(repo.revisions) > 1 and CELERY_ON:
241 run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
242 run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
242 return True
243 return True
@@ -395,6 +396,7 b' def create_repo_fork(form_data, cur_user'
395 DBS.commit()
396 DBS.commit()
396
397
397 def __get_codes_stats(repo_name):
398 def __get_codes_stats(repo_name):
399 from rhodecode.config.conf import LANGUAGES_EXTENSIONS_MAP
398 repo = Repository.get_by_repo_name(repo_name).scm_instance
400 repo = Repository.get_by_repo_name(repo_name).scm_instance
399
401
400 tip = repo.get_changeset()
402 tip = repo.get_changeset()
@@ -1,9 +1,9 b''
1 import rhodecode
1 import rhodecode
2 from rhodecode.lib.utils import BasePasterCommand, Command
2 from rhodecode.lib.utils import BasePasterCommand, Command, load_rcextensions
3 from celery.app import app_or_default
3 from celery.app import app_or_default
4 from celery.bin import camqadm, celerybeat, celeryd, celeryev
4 from celery.bin import camqadm, celerybeat, celeryd, celeryev
5
5
6 from rhodecode.lib import str2bool
6 from rhodecode.lib.utils2 import str2bool
7
7
8 __all__ = ['CeleryDaemonCommand', 'CeleryBeatCommand',
8 __all__ = ['CeleryDaemonCommand', 'CeleryBeatCommand',
9 'CAMQPAdminCommand', 'CeleryEventCommand']
9 'CAMQPAdminCommand', 'CeleryEventCommand']
@@ -39,9 +39,11 b' class CeleryCommand(BasePasterCommand):'
39 raise Exception('Please enable celery_on in .ini config '
39 raise Exception('Please enable celery_on in .ini config '
40 'file before running celeryd')
40 'file before running celeryd')
41 rhodecode.CELERY_ON = CELERY_ON
41 rhodecode.CELERY_ON = CELERY_ON
42 load_rcextensions(config['here'])
42 cmd = self.celery_command(app_or_default())
43 cmd = self.celery_command(app_or_default())
43 return cmd.run(**vars(self.options))
44 return cmd.run(**vars(self.options))
44
45
46
45 class CeleryDaemonCommand(CeleryCommand):
47 class CeleryDaemonCommand(CeleryCommand):
46 """Start the celery worker
48 """Start the celery worker
47
49
@@ -82,6 +84,7 b' class CAMQPAdminCommand(CeleryCommand):'
82 parser = Command.standard_parser(quiet=True)
84 parser = Command.standard_parser(quiet=True)
83 celery_command = camqadm.AMQPAdminCommand
85 celery_command = camqadm.AMQPAdminCommand
84
86
87
85 class CeleryEventCommand(CeleryCommand):
88 class CeleryEventCommand(CeleryCommand):
86 """Celery event command.
89 """Celery event command.
87
90
@@ -71,9 +71,6 b' class InvalidScriptError(ScriptError):'
71 """Invalid script error."""
71 """Invalid script error."""
72
72
73
73
74 class InvalidVersionError(Error):
75 """Invalid version error."""
76
77 # migrate.changeset
74 # migrate.changeset
78
75
79 class NotSupportedError(Error):
76 class NotSupportedError(Error):
@@ -39,7 +39,7 b' from rhodecode.lib.vcs.utils.helpers imp'
39 from rhodecode.lib.vcs.exceptions import VCSError
39 from rhodecode.lib.vcs.exceptions import VCSError
40 from rhodecode.lib.vcs.utils.lazy import LazyProperty
40 from rhodecode.lib.vcs.utils.lazy import LazyProperty
41
41
42 from rhodecode.lib import str2bool, safe_str, get_changeset_safe, \
42 from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \
43 generate_api_key, safe_unicode
43 generate_api_key, safe_unicode
44 from rhodecode.lib.exceptions import UsersGroupsAssignedException
44 from rhodecode.lib.exceptions import UsersGroupsAssignedException
45 from rhodecode.lib.compat import json
45 from rhodecode.lib.compat import json
@@ -717,7 +717,7 b' class Repository(Base, BaseModel):'
717 return repo
717 return repo
718
718
719
719
720 class RepoGroup(Base, BaseModel):
720 class Group(Base, BaseModel):
721 __tablename__ = 'groups'
721 __tablename__ = 'groups'
722 __table_args__ = (UniqueConstraint('group_name', 'group_parent_id'),
722 __table_args__ = (UniqueConstraint('group_name', 'group_parent_id'),
723 CheckConstraint('group_id != group_parent_id'), {'extend_existing':True},)
723 CheckConstraint('group_id != group_parent_id'), {'extend_existing':True},)
@@ -728,8 +728,7 b' class RepoGroup(Base, BaseModel):'
728 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
728 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
729 group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
729 group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
730
730
731 parent_group = relationship('RepoGroup', remote_side=group_id)
731 parent_group = relationship('Group', remote_side=group_id)
732
733
732
734 def __init__(self, group_name='', parent_group=None):
733 def __init__(self, group_name='', parent_group=None):
735 self.group_name = group_name
734 self.group_name = group_name
@@ -39,7 +39,8 b' from webhelpers.html.tags import _set_in'
39
39
40 from rhodecode.lib.annotate import annotate_highlight
40 from rhodecode.lib.annotate import annotate_highlight
41 from rhodecode.lib.utils import repo_name_slug
41 from rhodecode.lib.utils import repo_name_slug
42 from rhodecode.lib import str2bool, safe_unicode, safe_str, get_changeset_safe
42 from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \
43 get_changeset_safe
43 from rhodecode.lib.markup_renderer import MarkupRenderer
44 from rhodecode.lib.markup_renderer import MarkupRenderer
44
45
45 log = logging.getLogger(__name__)
46 log = logging.getLogger(__name__)
@@ -319,7 +320,7 b' flash = _Flash()'
319 # SCM FILTERS available via h.
320 # SCM FILTERS available via h.
320 #==============================================================================
321 #==============================================================================
321 from rhodecode.lib.vcs.utils import author_name, author_email
322 from rhodecode.lib.vcs.utils import author_name, author_email
322 from rhodecode.lib import credentials_filter, age as _age
323 from rhodecode.lib.utils2 import credentials_filter, age as _age
323 from rhodecode.model.db import User
324 from rhodecode.model.db import User
324
325
325 age = lambda x: _age(x)
326 age = lambda x: _age(x)
@@ -139,7 +139,7 b' def log_push_action(ui, repo, **kwargs):'
139 def log_create_repository(repository_dict, created_by, **kwargs):
139 def log_create_repository(repository_dict, created_by, **kwargs):
140 """
140 """
141 Post create repository Hook. This is a dummy function for admins to re-use
141 Post create repository Hook. This is a dummy function for admins to re-use
142 if needed. It's taken from rhodecode-extensions module and executed
142 if needed. It's taken from rhodecode-extensions module and executed
143 if present
143 if present
144
144
145 :param repository: dict dump of repository object
145 :param repository: dict dump of repository object
@@ -47,9 +47,9 b' from rhodecode.model import init_model'
47 from rhodecode.model.scm import ScmModel
47 from rhodecode.model.scm import ScmModel
48 from rhodecode.model.repo import RepoModel
48 from rhodecode.model.repo import RepoModel
49 from rhodecode.config.environment import load_environment
49 from rhodecode.config.environment import load_environment
50 from rhodecode.lib import LANGUAGES_EXTENSIONS_MAP, INDEX_EXTENSIONS, \
50 from rhodecode.lib.utils2 import LazyProperty
51 LazyProperty
51 from rhodecode.lib.utils import BasePasterCommand, Command, add_cache,\
52 from rhodecode.lib.utils import BasePasterCommand, Command, add_cache
52 load_rcextensions
53
53
54 # CUSTOM ANALYZER wordsplit + lowercase filter
54 # CUSTOM ANALYZER wordsplit + lowercase filter
55 ANALYZER = RegexTokenizer(expression=r"\w+") | LowercaseFilter()
55 ANALYZER = RegexTokenizer(expression=r"\w+") | LowercaseFilter()
@@ -88,13 +88,12 b' class MakeIndex(BasePasterCommand):'
88 add_cache(config)
88 add_cache(config)
89 engine = engine_from_config(config, 'sqlalchemy.db1.')
89 engine = engine_from_config(config, 'sqlalchemy.db1.')
90 init_model(engine)
90 init_model(engine)
91
92 index_location = config['index_dir']
91 index_location = config['index_dir']
93 repo_location = self.options.repo_location \
92 repo_location = self.options.repo_location \
94 if self.options.repo_location else RepoModel().repos_path
93 if self.options.repo_location else RepoModel().repos_path
95 repo_list = map(strip, self.options.repo_list.split(',')) \
94 repo_list = map(strip, self.options.repo_list.split(',')) \
96 if self.options.repo_list else None
95 if self.options.repo_list else None
97
96 load_rcextensions(config['here'])
98 #======================================================================
97 #======================================================================
99 # WHOOSH DAEMON
98 # WHOOSH DAEMON
100 #======================================================================
99 #======================================================================
@@ -104,7 +103,7 b' class MakeIndex(BasePasterCommand):'
104 l = DaemonLock(file_=jn(dn(dn(index_location)), 'make_index.lock'))
103 l = DaemonLock(file_=jn(dn(dn(index_location)), 'make_index.lock'))
105 WhooshIndexingDaemon(index_location=index_location,
104 WhooshIndexingDaemon(index_location=index_location,
106 repo_location=repo_location,
105 repo_location=repo_location,
107 repo_list=repo_list)\
106 repo_list=repo_list,)\
108 .run(full_index=self.options.full_index)
107 .run(full_index=self.options.full_index)
109 l.release()
108 l.release()
110 except LockHeld:
109 except LockHeld:
@@ -38,10 +38,10 b' from os.path import join as jn'
38 project_path = dn(dn(dn(dn(os.path.realpath(__file__)))))
38 project_path = dn(dn(dn(dn(os.path.realpath(__file__)))))
39 sys.path.append(project_path)
39 sys.path.append(project_path)
40
40
41
41 from rhodecode.config.conf import INDEX_EXTENSIONS
42 from rhodecode.model.scm import ScmModel
42 from rhodecode.model.scm import ScmModel
43 from rhodecode.lib import safe_unicode
43 from rhodecode.lib.utils2 import safe_unicode
44 from rhodecode.lib.indexers import INDEX_EXTENSIONS, SCHEMA, IDX_NAME
44 from rhodecode.lib.indexers import SCHEMA, IDX_NAME
45
45
46 from rhodecode.lib.vcs.exceptions import ChangesetError, RepositoryError, \
46 from rhodecode.lib.vcs.exceptions import ChangesetError, RepositoryError, \
47 NodeDoesNotExistError
47 NodeDoesNotExistError
@@ -117,10 +117,9 b' class WhooshIndexingDaemon(object):'
117 """
117 """
118
118
119 node = self.get_node(repo, path)
119 node = self.get_node(repo, path)
120
120 indexed = indexed_w_content = 0
121 # we just index the content of chosen files, and skip binary files
121 # we just index the content of chosen files, and skip binary files
122 if node.extension in INDEX_EXTENSIONS and not node.is_binary:
122 if node.extension in INDEX_EXTENSIONS and not node.is_binary:
123
124 u_content = node.content
123 u_content = node.content
125 if not isinstance(u_content, unicode):
124 if not isinstance(u_content, unicode):
126 log.warning(' >> %s Could not get this content as unicode '
125 log.warning(' >> %s Could not get this content as unicode '
@@ -128,11 +127,13 b' class WhooshIndexingDaemon(object):'
128 u_content = u''
127 u_content = u''
129 else:
128 else:
130 log.debug(' >> %s [WITH CONTENT]' % path)
129 log.debug(' >> %s [WITH CONTENT]' % path)
130 indexed_w_content += 1
131
131
132 else:
132 else:
133 log.debug(' >> %s' % path)
133 log.debug(' >> %s' % path)
134 # just index file name without it's content
134 # just index file name without it's content
135 u_content = u''
135 u_content = u''
136 indexed += 1
136
137
137 writer.add_document(
138 writer.add_document(
138 owner=unicode(repo.contact),
139 owner=unicode(repo.contact),
@@ -142,6 +143,7 b' class WhooshIndexingDaemon(object):'
142 modtime=self.get_node_mtime(node),
143 modtime=self.get_node_mtime(node),
143 extension=node.extension
144 extension=node.extension
144 )
145 )
146 return indexed, indexed_w_content
145
147
146 def build_index(self):
148 def build_index(self):
147 if os.path.exists(self.index_location):
149 if os.path.exists(self.index_location):
@@ -153,19 +155,25 b' class WhooshIndexingDaemon(object):'
153
155
154 idx = create_in(self.index_location, SCHEMA, indexname=IDX_NAME)
156 idx = create_in(self.index_location, SCHEMA, indexname=IDX_NAME)
155 writer = idx.writer()
157 writer = idx.writer()
156
158 log.debug('BUILDIN INDEX FOR EXTENSIONS %s' % INDEX_EXTENSIONS)
157 for repo_name, repo in self.repo_paths.items():
159 for repo_name, repo in self.repo_paths.items():
158 log.debug('building index @ %s' % repo.path)
160 log.debug('building index @ %s' % repo.path)
159
161 i_cnt = iwc_cnt = 0
160 for idx_path in self.get_paths(repo):
162 for idx_path in self.get_paths(repo):
161 self.add_doc(writer, idx_path, repo, repo_name)
163 i, iwc = self.add_doc(writer, idx_path, repo, repo_name)
164 i_cnt += i
165 iwc_cnt += iwc
166 log.debug('added %s files %s with content for repo %s' % (
167 i_cnt + iwc_cnt, iwc_cnt, repo.path)
168 )
162
169
163 log.debug('>> COMMITING CHANGES <<')
170 log.debug('>> COMMITING CHANGES <<')
164 writer.commit(merge=True)
171 writer.commit(merge=True)
165 log.debug('>>> FINISHED BUILDING INDEX <<<')
172 log.debug('>>> FINISHED BUILDING INDEX <<<')
166
173
167 def update_index(self):
174 def update_index(self):
168 log.debug('STARTING INCREMENTAL INDEXING UPDATE')
175 log.debug('STARTING INCREMENTAL INDEXING UPDATE FOR EXTENSIONS %s' %
176 INDEX_EXTENSIONS)
169
177
170 idx = open_dir(self.index_location, indexname=self.indexname)
178 idx = open_dir(self.index_location, indexname=self.indexname)
171 # The set of all paths in the index
179 # The set of all paths in the index
@@ -204,14 +212,19 b' class WhooshIndexingDaemon(object):'
204 # Loop over the files in the filesystem
212 # Loop over the files in the filesystem
205 # Assume we have a function that gathers the filenames of the
213 # Assume we have a function that gathers the filenames of the
206 # documents to be indexed
214 # documents to be indexed
215 ri_cnt = riwc_cnt = 0
207 for repo_name, repo in self.repo_paths.items():
216 for repo_name, repo in self.repo_paths.items():
208 for path in self.get_paths(repo):
217 for path in self.get_paths(repo):
209 if path in to_index or path not in indexed_paths:
218 if path in to_index or path not in indexed_paths:
210 # This is either a file that's changed, or a new file
219 # This is either a file that's changed, or a new file
211 # that wasn't indexed before. So index it!
220 # that wasn't indexed before. So index it!
212 self.add_doc(writer, path, repo, repo_name)
221 i, iwc = self.add_doc(writer, path, repo, repo_name)
213 log.debug('re indexing %s' % path)
222 log.debug('re indexing %s' % path)
214
223 ri_cnt += i
224 riwc_cnt += iwc
225 log.debug('added %s files %s with content for repo %s' % (
226 ri_cnt + riwc_cnt, riwc_cnt, repo.path)
227 )
215 log.debug('>> COMMITING CHANGES <<')
228 log.debug('>> COMMITING CHANGES <<')
216 writer.commit(merge=True)
229 writer.commit(merge=True)
217 log.debug('>>> FINISHED REBUILDING INDEX <<<')
230 log.debug('>>> FINISHED REBUILDING INDEX <<<')
@@ -27,7 +27,7 b''
27 import re
27 import re
28 import logging
28 import logging
29
29
30 from rhodecode.lib import safe_unicode
30 from rhodecode.lib.utils2 import safe_unicode
31
31
32 log = logging.getLogger(__name__)
32 log = logging.getLogger(__name__)
33
33
@@ -23,7 +23,7 b''
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 from rhodecode.lib import str2bool
26 from rhodecode.lib.utils2 import str2bool
27
27
28
28
29 class HttpsFixup(object):
29 class HttpsFixup(object):
@@ -69,7 +69,7 b' from dulwich.web import HTTPGitApplicati'
69
69
70 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
70 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
71
71
72 from rhodecode.lib import safe_str
72 from rhodecode.lib.utils2 import safe_str
73 from rhodecode.lib.base import BaseVCSController
73 from rhodecode.lib.base import BaseVCSController
74 from rhodecode.lib.auth import get_container_username
74 from rhodecode.lib.auth import get_container_username
75 from rhodecode.lib.utils import is_valid_repo
75 from rhodecode.lib.utils import is_valid_repo
@@ -34,7 +34,7 b' from mercurial.hgweb import hgweb_mod'
34
34
35 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
35 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
36
36
37 from rhodecode.lib import safe_str
37 from rhodecode.lib.utils2 import safe_str
38 from rhodecode.lib.base import BaseVCSController
38 from rhodecode.lib.base import BaseVCSController
39 from rhodecode.lib.auth import get_container_username
39 from rhodecode.lib.auth import get_container_username
40 from rhodecode.lib.utils import make_ui, is_valid_repo, ui_sections
40 from rhodecode.lib.utils import make_ui, is_valid_repo, ui_sections
@@ -54,7 +54,8 b' from rhodecode.model.db import Repositor'
54 UserLog, RepoGroup, RhodeCodeSetting, UserRepoGroupToPerm
54 UserLog, RepoGroup, RhodeCodeSetting, UserRepoGroupToPerm
55 from rhodecode.model.meta import Session
55 from rhodecode.model.meta import Session
56 from rhodecode.model.repos_group import ReposGroupModel
56 from rhodecode.model.repos_group import ReposGroupModel
57 from rhodecode.lib import safe_str, safe_unicode
57 from rhodecode.lib.utils2 import safe_str, safe_unicode
58 from rhodecode.lib.vcs.utils.fakemod import create_module
58
59
59 log = logging.getLogger(__name__)
60 log = logging.getLogger(__name__)
60
61
@@ -62,7 +63,8 b" REMOVED_REPO_PAT = re.compile(r'rm__\\d{8"
62
63
63
64
64 def recursive_replace(str_, replace=' '):
65 def recursive_replace(str_, replace=' '):
65 """Recursive replace of given sign to just one instance
66 """
67 Recursive replace of given sign to just one instance
66
68
67 :param str_: given string
69 :param str_: given string
68 :param replace: char to find and replace multiple instances
70 :param replace: char to find and replace multiple instances
@@ -80,7 +82,8 b" def recursive_replace(str_, replace=' ')"
80
82
81
83
82 def repo_name_slug(value):
84 def repo_name_slug(value):
83 """Return slug of name of repository
85 """
86 Return slug of name of repository
84 This function is called on each creation/modification
87 This function is called on each creation/modification
85 of repository to prevent bad names in repo
88 of repository to prevent bad names in repo
86 """
89 """
@@ -263,7 +266,8 b" ui_sections = ['alias', 'auth',"
263
266
264
267
265 def make_ui(read_from='file', path=None, checkpaths=True):
268 def make_ui(read_from='file', path=None, checkpaths=True):
266 """A function that will read python rc files or database
269 """
270 A function that will read python rc files or database
267 and make an mercurial ui object from read options
271 and make an mercurial ui object from read options
268
272
269 :param path: path to mercurial config file
273 :param path: path to mercurial config file
@@ -489,6 +493,30 b' def add_cache(settings):'
489 beaker.cache.cache_regions[region] = region_settings
493 beaker.cache.cache_regions[region] = region_settings
490
494
491
495
496 def load_rcextensions(root_path):
497 import rhodecode
498 from rhodecode.config import conf
499
500 path = os.path.join(root_path, 'rcextensions', '__init__.py')
501 if os.path.isfile(path):
502 rcext = create_module('rc', path)
503 EXT = rhodecode.EXTENSIONS = rcext
504 log.debug('Found rcextensions now loading %s...' % rcext)
505
506 # Additional mappings that are not present in the pygments lexers
507 conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {}))
508
509 #OVERRIDE OUR EXTENSIONS FROM RC-EXTENSIONS (if present)
510
511 if getattr(EXT, 'INDEX_EXTENSIONS', []) != []:
512 log.debug('settings custom INDEX_EXTENSIONS')
513 conf.INDEX_EXTENSIONS = getattr(EXT, 'INDEX_EXTENSIONS', [])
514
515 #ADDITIONAL MAPPINGS
516 log.debug('adding extra into INDEX_EXTENSIONS')
517 conf.INDEX_EXTENSIONS.extend(getattr(EXT, 'EXTRA_INDEX_EXTENSIONS', []))
518
519
492 #==============================================================================
520 #==============================================================================
493 # TEST FUNCTIONS AND CREATORS
521 # TEST FUNCTIONS AND CREATORS
494 #==============================================================================
522 #==============================================================================
@@ -29,7 +29,7 b' import traceback'
29 from pylons.i18n.translation import _
29 from pylons.i18n.translation import _
30 from sqlalchemy.util.compat import defaultdict
30 from sqlalchemy.util.compat import defaultdict
31
31
32 from rhodecode.lib import extract_mentioned_users
32 from rhodecode.lib.utils2 import extract_mentioned_users
33 from rhodecode.lib import helpers as h
33 from rhodecode.lib import helpers as h
34 from rhodecode.model import BaseModel
34 from rhodecode.model import BaseModel
35 from rhodecode.model.db import ChangesetComment, User, Repository, Notification
35 from rhodecode.model.db import ChangesetComment, User, Repository, Notification
@@ -39,7 +39,8 b' from rhodecode.lib.vcs.utils.helpers imp'
39 from rhodecode.lib.vcs.exceptions import VCSError
39 from rhodecode.lib.vcs.exceptions import VCSError
40 from rhodecode.lib.vcs.utils.lazy import LazyProperty
40 from rhodecode.lib.vcs.utils.lazy import LazyProperty
41
41
42 from rhodecode.lib import str2bool, safe_str, get_changeset_safe, safe_unicode
42 from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \
43 safe_unicode
43 from rhodecode.lib.compat import json
44 from rhodecode.lib.compat import json
44 from rhodecode.lib.caching_query import FromCache
45 from rhodecode.lib.caching_query import FromCache
45
46
@@ -32,6 +32,7 b' import datetime'
32 from pylons.i18n.translation import _
32 from pylons.i18n.translation import _
33
33
34 import rhodecode
34 import rhodecode
35 from rhodecode.config.conf import DATETIME_FORMAT
35 from rhodecode.lib import helpers as h
36 from rhodecode.lib import helpers as h
36 from rhodecode.model import BaseModel
37 from rhodecode.model import BaseModel
37 from rhodecode.model.db import Notification, User, UserNotification
38 from rhodecode.model.db import Notification, User, UserNotification
@@ -176,8 +177,6 b' class NotificationModel(BaseModel):'
176 notification.TYPE_REGISTRATION: _('registered in RhodeCode')
177 notification.TYPE_REGISTRATION: _('registered in RhodeCode')
177 }
178 }
178
179
179 DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
180
181 tmpl = "%(user)s %(action)s %(when)s"
180 tmpl = "%(user)s %(action)s %(when)s"
182 if show_age:
181 if show_age:
183 when = h.age(notification.created_on)
182 when = h.age(notification.created_on)
@@ -30,8 +30,7 b' from datetime import datetime'
30
30
31 from rhodecode.lib.vcs.backends import get_backend
31 from rhodecode.lib.vcs.backends import get_backend
32
32
33 from rhodecode.lib import LazyProperty
33 from rhodecode.lib.utils2 import LazyProperty, safe_str, safe_unicode
34 from rhodecode.lib import safe_str, safe_unicode
35 from rhodecode.lib.caching_query import FromCache
34 from rhodecode.lib.caching_query import FromCache
36 from rhodecode.lib.hooks import log_create_repository
35 from rhodecode.lib.hooks import log_create_repository
37
36
@@ -28,7 +28,7 b' import logging'
28 import traceback
28 import traceback
29 import shutil
29 import shutil
30
30
31 from rhodecode.lib import LazyProperty
31 from rhodecode.lib.utils2 import LazyProperty
32
32
33 from rhodecode.model import BaseModel
33 from rhodecode.model import BaseModel
34 from rhodecode.model.db import RepoGroup, RhodeCodeUi, UserRepoGroupToPerm, \
34 from rhodecode.model.db import RepoGroup, RhodeCodeUi, UserRepoGroupToPerm, \
@@ -35,7 +35,7 b' from rhodecode.lib.vcs.nodes import File'
35
35
36 from rhodecode import BACKENDS
36 from rhodecode import BACKENDS
37 from rhodecode.lib import helpers as h
37 from rhodecode.lib import helpers as h
38 from rhodecode.lib import safe_str
38 from rhodecode.lib.utils2 import safe_str
39 from rhodecode.lib.auth import HasRepoPermissionAny, HasReposGroupPermissionAny
39 from rhodecode.lib.auth import HasRepoPermissionAny, HasReposGroupPermissionAny
40 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
40 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
41 action_logger, EmptyChangeset, REMOVED_REPO_PAT
41 action_logger, EmptyChangeset, REMOVED_REPO_PAT
@@ -29,7 +29,7 b' import traceback'
29 from pylons import url
29 from pylons import url
30 from pylons.i18n.translation import _
30 from pylons.i18n.translation import _
31
31
32 from rhodecode.lib import safe_unicode
32 from rhodecode.lib.utils2 import safe_unicode, generate_api_key
33 from rhodecode.lib.caching_query import FromCache
33 from rhodecode.lib.caching_query import FromCache
34
34
35 from rhodecode.model import BaseModel
35 from rhodecode.model import BaseModel
@@ -40,7 +40,7 b' from rhodecode.lib.exceptions import Def'
40 UserOwnsReposException
40 UserOwnsReposException
41
41
42 from sqlalchemy.exc import DatabaseError
42 from sqlalchemy.exc import DatabaseError
43 from rhodecode.lib import generate_api_key
43
44 from sqlalchemy.orm import joinedload
44 from sqlalchemy.orm import joinedload
45
45
46 log = logging.getLogger(__name__)
46 log = logging.getLogger(__name__)
@@ -3112,7 +3112,12 b' table.code-browser .browser-dir {'
3112 top: 5px;
3112 top: 5px;
3113 width: 16px;
3113 width: 16px;
3114 }
3114 }
3115
3115 div#legend_data{
3116 padding-left:10px;
3117 }
3118 div#legend_container table{
3119 border: none !important;
3120 }
3116 div#legend_container table,div#legend_choices table {
3121 div#legend_container table,div#legend_choices table {
3117 width: auto !important;
3122 width: auto !important;
3118 }
3123 }
@@ -1,10 +1,11 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 from rhodecode.tests import *
2 from rhodecode.tests import *
3 from rhodecode.model.db import User, Notification
3 from rhodecode.model.db import User, Notification
4 from rhodecode.lib import generate_api_key
4 from rhodecode.lib.utils2 import generate_api_key
5 from rhodecode.lib.auth import check_password
5 from rhodecode.lib.auth import check_password
6 from rhodecode.model.meta import Session
6 from rhodecode.model.meta import Session
7
7
8
8 class TestLoginController(TestController):
9 class TestLoginController(TestController):
9
10
10 def tearDown(self):
11 def tearDown(self):
@@ -65,22 +65,20 b' TEST_URLS += ['
65
65
66 class TestLibs(unittest.TestCase):
66 class TestLibs(unittest.TestCase):
67
67
68
69 def test_uri_filter(self):
68 def test_uri_filter(self):
70 from rhodecode.lib import uri_filter
69 from rhodecode.lib.utils2 import uri_filter
71
70
72 for url in TEST_URLS:
71 for url in TEST_URLS:
73 self.assertEqual(uri_filter(url[0]), url[1])
72 self.assertEqual(uri_filter(url[0]), url[1])
74
73
75 def test_credentials_filter(self):
74 def test_credentials_filter(self):
76 from rhodecode.lib import credentials_filter
75 from rhodecode.lib.utils2 import credentials_filter
77
76
78 for url in TEST_URLS:
77 for url in TEST_URLS:
79 self.assertEqual(credentials_filter(url[0]), url[2])
78 self.assertEqual(credentials_filter(url[0]), url[2])
80
79
81
82 def test_str2bool(self):
80 def test_str2bool(self):
83 from rhodecode.lib import str2bool
81 from rhodecode.lib.utils2 import str2bool
84 test_cases = [
82 test_cases = [
85 ('t', True),
83 ('t', True),
86 ('true', True),
84 ('true', True),
@@ -103,9 +101,8 b' class TestLibs(unittest.TestCase):'
103 for case in test_cases:
101 for case in test_cases:
104 self.assertEqual(str2bool(case[0]), case[1])
102 self.assertEqual(str2bool(case[0]), case[1])
105
103
106
107 def test_mention_extractor(self):
104 def test_mention_extractor(self):
108 from rhodecode.lib import extract_mentioned_users
105 from rhodecode.lib.utils2 import extract_mentioned_users
109 sample = ("@first hi there @marcink here's my email marcin@email.com "
106 sample = ("@first hi there @marcink here's my email marcin@email.com "
110 "@lukaszb check it pls @ ttwelve @D[] @one@two@three "
107 "@lukaszb check it pls @ ttwelve @D[] @one@two@three "
111 "@MARCIN @maRCiN @2one_more22")
108 "@MARCIN @maRCiN @2one_more22")
General Comments 0
You need to be logged in to leave comments. Login now