##// END OF EJS Templates
timerproxy will use the same logger as sqlalchemy, in order to be controlled by sqlalchemy logger settings
marcink -
r1362:4c9bd42f beta
parent child Browse files
Show More
@@ -1,286 +1,286 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.__init__
3 rhodecode.lib.__init__
4 ~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Some simple helper functions
6 Some simple helper functions
7
7
8 :created_on: Jan 5, 2011
8 :created_on: Jan 5, 2011
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26
26
27 def __get_lem():
27 def __get_lem():
28 from pygments import lexers
28 from pygments import lexers
29 from string import lower
29 from string import lower
30 from collections import defaultdict
30 from collections import defaultdict
31
31
32 d = defaultdict(lambda: [])
32 d = defaultdict(lambda: [])
33
33
34 def __clean(s):
34 def __clean(s):
35 s = s.lstrip('*')
35 s = s.lstrip('*')
36 s = s.lstrip('.')
36 s = s.lstrip('.')
37
37
38 if s.find('[') != -1:
38 if s.find('[') != -1:
39 exts = []
39 exts = []
40 start, stop = s.find('['), s.find(']')
40 start, stop = s.find('['), s.find(']')
41
41
42 for suffix in s[start + 1:stop]:
42 for suffix in s[start + 1:stop]:
43 exts.append(s[:s.find('[')] + suffix)
43 exts.append(s[:s.find('[')] + suffix)
44 return map(lower, exts)
44 return map(lower, exts)
45 else:
45 else:
46 return map(lower, [s])
46 return map(lower, [s])
47
47
48 for lx, t in sorted(lexers.LEXERS.items()):
48 for lx, t in sorted(lexers.LEXERS.items()):
49 m = map(__clean, t[-2])
49 m = map(__clean, t[-2])
50 if m:
50 if m:
51 m = reduce(lambda x, y: x + y, m)
51 m = reduce(lambda x, y: x + y, m)
52 for ext in m:
52 for ext in m:
53 desc = lx.replace('Lexer', '')
53 desc = lx.replace('Lexer', '')
54 d[ext].append(desc)
54 d[ext].append(desc)
55
55
56 return dict(d)
56 return dict(d)
57
57
58 # language map is also used by whoosh indexer, which for those specified
58 # language map is also used by whoosh indexer, which for those specified
59 # extensions will index it's content
59 # extensions will index it's content
60 LANGUAGES_EXTENSIONS_MAP = __get_lem()
60 LANGUAGES_EXTENSIONS_MAP = __get_lem()
61
61
62 # Additional mappings that are not present in the pygments lexers
62 # Additional mappings that are not present in the pygments lexers
63 # NOTE: that this will overide any mappings in LANGUAGES_EXTENSIONS_MAP
63 # NOTE: that this will overide any mappings in LANGUAGES_EXTENSIONS_MAP
64 ADDITIONAL_MAPPINGS = {'xaml': 'XAML'}
64 ADDITIONAL_MAPPINGS = {'xaml': 'XAML'}
65
65
66 LANGUAGES_EXTENSIONS_MAP.update(ADDITIONAL_MAPPINGS)
66 LANGUAGES_EXTENSIONS_MAP.update(ADDITIONAL_MAPPINGS)
67
67
68
68
69 def str2bool(_str):
69 def str2bool(_str):
70 """
70 """
71 returs True/False value from given string, it tries to translate the
71 returs True/False value from given string, it tries to translate the
72 string into boolean
72 string into boolean
73
73
74 :param _str: string value to translate into boolean
74 :param _str: string value to translate into boolean
75 :rtype: boolean
75 :rtype: boolean
76 :returns: boolean from given string
76 :returns: boolean from given string
77 """
77 """
78 if _str is None:
78 if _str is None:
79 return False
79 return False
80 if _str in (True, False):
80 if _str in (True, False):
81 return _str
81 return _str
82 _str = str(_str).strip().lower()
82 _str = str(_str).strip().lower()
83 return _str in ('t', 'true', 'y', 'yes', 'on', '1')
83 return _str in ('t', 'true', 'y', 'yes', 'on', '1')
84
84
85
85
86 def convert_line_endings(temp, mode):
86 def convert_line_endings(temp, mode):
87 from string import replace
87 from string import replace
88 #modes: 0 - Unix, 1 - Mac, 2 - DOS
88 #modes: 0 - Unix, 1 - Mac, 2 - DOS
89 if mode == 0:
89 if mode == 0:
90 temp = replace(temp, '\r\n', '\n')
90 temp = replace(temp, '\r\n', '\n')
91 temp = replace(temp, '\r', '\n')
91 temp = replace(temp, '\r', '\n')
92 elif mode == 1:
92 elif mode == 1:
93 temp = replace(temp, '\r\n', '\r')
93 temp = replace(temp, '\r\n', '\r')
94 temp = replace(temp, '\n', '\r')
94 temp = replace(temp, '\n', '\r')
95 elif mode == 2:
95 elif mode == 2:
96 import re
96 import re
97 temp = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", temp)
97 temp = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", temp)
98 return temp
98 return temp
99
99
100
100
101 def detect_mode(line, default):
101 def detect_mode(line, default):
102 """
102 """
103 Detects line break for given line, if line break couldn't be found
103 Detects line break for given line, if line break couldn't be found
104 given default value is returned
104 given default value is returned
105
105
106 :param line: str line
106 :param line: str line
107 :param default: default
107 :param default: default
108 :rtype: int
108 :rtype: int
109 :return: value of line end on of 0 - Unix, 1 - Mac, 2 - DOS
109 :return: value of line end on of 0 - Unix, 1 - Mac, 2 - DOS
110 """
110 """
111 if line.endswith('\r\n'):
111 if line.endswith('\r\n'):
112 return 2
112 return 2
113 elif line.endswith('\n'):
113 elif line.endswith('\n'):
114 return 0
114 return 0
115 elif line.endswith('\r'):
115 elif line.endswith('\r'):
116 return 1
116 return 1
117 else:
117 else:
118 return default
118 return default
119
119
120
120
121 def generate_api_key(username, salt=None):
121 def generate_api_key(username, salt=None):
122 """
122 """
123 Generates unique API key for given username,if salt is not given
123 Generates unique API key for given username,if salt is not given
124 it'll be generated from some random string
124 it'll be generated from some random string
125
125
126 :param username: username as string
126 :param username: username as string
127 :param salt: salt to hash generate KEY
127 :param salt: salt to hash generate KEY
128 :rtype: str
128 :rtype: str
129 :returns: sha1 hash from username+salt
129 :returns: sha1 hash from username+salt
130 """
130 """
131 from tempfile import _RandomNameSequence
131 from tempfile import _RandomNameSequence
132 import hashlib
132 import hashlib
133
133
134 if salt is None:
134 if salt is None:
135 salt = _RandomNameSequence().next()
135 salt = _RandomNameSequence().next()
136
136
137 return hashlib.sha1(username + salt).hexdigest()
137 return hashlib.sha1(username + salt).hexdigest()
138
138
139
139
140 def safe_unicode(_str, from_encoding='utf8'):
140 def safe_unicode(_str, from_encoding='utf8'):
141 """
141 """
142 safe unicode function. In case of UnicodeDecode error we try to return
142 safe unicode function. In case of UnicodeDecode error we try to return
143 unicode with errors replace
143 unicode with errors replace
144
144
145 :param _str: string to decode
145 :param _str: string to decode
146 :rtype: unicode
146 :rtype: unicode
147 :returns: unicode object
147 :returns: unicode object
148 """
148 """
149
149
150 if isinstance(_str, unicode):
150 if isinstance(_str, unicode):
151 return _str
151 return _str
152
152
153 try:
153 try:
154 u_str = unicode(_str, from_encoding)
154 u_str = unicode(_str, from_encoding)
155 except UnicodeDecodeError:
155 except UnicodeDecodeError:
156 u_str = unicode(_str, from_encoding, 'replace')
156 u_str = unicode(_str, from_encoding, 'replace')
157
157
158 return u_str
158 return u_str
159
159
160
160
161 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
161 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
162 """
162 """
163 Custom engine_from_config functions that makes sure we use NullPool for
163 Custom engine_from_config functions that makes sure we use NullPool for
164 file based sqlite databases. This prevents errors on sqlite. This only
164 file based sqlite databases. This prevents errors on sqlite. This only
165 applies to sqlalchemy versions < 0.7.0
165 applies to sqlalchemy versions < 0.7.0
166
166
167 """
167 """
168 import sqlalchemy
168 import sqlalchemy
169 from sqlalchemy import engine_from_config as efc
169 from sqlalchemy import engine_from_config as efc
170 import logging
170 import logging
171
171
172 if int(sqlalchemy.__version__.split('.')[1]) < 7:
172 if int(sqlalchemy.__version__.split('.')[1]) < 7:
173
173
174 # This solution should work for sqlalchemy < 0.7.0, and should use
174 # This solution should work for sqlalchemy < 0.7.0, and should use
175 # proxy=TimerProxy() for execution time profiling
175 # proxy=TimerProxy() for execution time profiling
176
176
177 from sqlalchemy.pool import NullPool
177 from sqlalchemy.pool import NullPool
178 url = configuration[prefix + 'url']
178 url = configuration[prefix + 'url']
179
179
180 if url.startswith('sqlite'):
180 if url.startswith('sqlite'):
181 kwargs.update({'poolclass': NullPool})
181 kwargs.update({'poolclass': NullPool})
182 return efc(configuration, prefix, **kwargs)
182 return efc(configuration, prefix, **kwargs)
183 else:
183 else:
184 import time
184 import time
185 from sqlalchemy import event
185 from sqlalchemy import event
186 from sqlalchemy.engine import Engine
186 from sqlalchemy.engine import Engine
187
187
188 log = logging.getLogger('timerproxy')
188 log = logging.getLogger('sqlalchemy.engine')
189 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38)
189 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38)
190 engine = efc(configuration, prefix, **kwargs)
190 engine = efc(configuration, prefix, **kwargs)
191
191
192 def color_sql(sql):
192 def color_sql(sql):
193 COLOR_SEQ = "\033[1;%dm"
193 COLOR_SEQ = "\033[1;%dm"
194 COLOR_SQL = YELLOW
194 COLOR_SQL = YELLOW
195 normal = '\x1b[0m'
195 normal = '\x1b[0m'
196 return ''.join([COLOR_SEQ % COLOR_SQL, sql, normal])
196 return ''.join([COLOR_SEQ % COLOR_SQL, sql, normal])
197
197
198 if configuration['debug']:
198 if configuration['debug']:
199 #attach events only for debug configuration
199 #attach events only for debug configuration
200
200
201 def before_cursor_execute(conn, cursor, statement,
201 def before_cursor_execute(conn, cursor, statement,
202 parameters, context, executemany):
202 parameters, context, executemany):
203 context._query_start_time = time.time()
203 context._query_start_time = time.time()
204 log.info(color_sql(">>>>> STARTING QUERY >>>>>"))
204 log.info(color_sql(">>>>> STARTING QUERY >>>>>"))
205
205
206
206
207 def after_cursor_execute(conn, cursor, statement,
207 def after_cursor_execute(conn, cursor, statement,
208 parameters, context, executemany):
208 parameters, context, executemany):
209 total = time.time() - context._query_start_time
209 total = time.time() - context._query_start_time
210 log.info(color_sql("<<<<< TOTAL TIME: %f <<<<<" % total))
210 log.info(color_sql("<<<<< TOTAL TIME: %f <<<<<" % total))
211
211
212 event.listen(engine, "before_cursor_execute",
212 event.listen(engine, "before_cursor_execute",
213 before_cursor_execute)
213 before_cursor_execute)
214 event.listen(engine, "after_cursor_execute",
214 event.listen(engine, "after_cursor_execute",
215 after_cursor_execute)
215 after_cursor_execute)
216
216
217 return engine
217 return engine
218
218
219
219
220 def age(curdate):
220 def age(curdate):
221 """
221 """
222 turns a datetime into an age string.
222 turns a datetime into an age string.
223
223
224 :param curdate: datetime object
224 :param curdate: datetime object
225 :rtype: unicode
225 :rtype: unicode
226 :returns: unicode words describing age
226 :returns: unicode words describing age
227 """
227 """
228
228
229 from datetime import datetime
229 from datetime import datetime
230 from webhelpers.date import time_ago_in_words
230 from webhelpers.date import time_ago_in_words
231
231
232 _ = lambda s:s
232 _ = lambda s:s
233
233
234 if not curdate:
234 if not curdate:
235 return ''
235 return ''
236
236
237 agescales = [(_(u"year"), 3600 * 24 * 365),
237 agescales = [(_(u"year"), 3600 * 24 * 365),
238 (_(u"month"), 3600 * 24 * 30),
238 (_(u"month"), 3600 * 24 * 30),
239 (_(u"day"), 3600 * 24),
239 (_(u"day"), 3600 * 24),
240 (_(u"hour"), 3600),
240 (_(u"hour"), 3600),
241 (_(u"minute"), 60),
241 (_(u"minute"), 60),
242 (_(u"second"), 1), ]
242 (_(u"second"), 1), ]
243
243
244 age = datetime.now() - curdate
244 age = datetime.now() - curdate
245 age_seconds = (age.days * agescales[2][1]) + age.seconds
245 age_seconds = (age.days * agescales[2][1]) + age.seconds
246 pos = 1
246 pos = 1
247 for scale in agescales:
247 for scale in agescales:
248 if scale[1] <= age_seconds:
248 if scale[1] <= age_seconds:
249 if pos == 6:pos = 5
249 if pos == 6:pos = 5
250 return '%s %s' % (time_ago_in_words(curdate,
250 return '%s %s' % (time_ago_in_words(curdate,
251 agescales[pos][0]), _('ago'))
251 agescales[pos][0]), _('ago'))
252 pos += 1
252 pos += 1
253
253
254 return _(u'just now')
254 return _(u'just now')
255
255
256
256
257 def credentials_hidder(uri):
257 def credentials_hidder(uri):
258 """
258 """
259 Removes user:password from given url string
259 Removes user:password from given url string
260
260
261 :param uri:
261 :param uri:
262 :rtype: unicode
262 :rtype: unicode
263 :returns: filtered list of strings
263 :returns: filtered list of strings
264 """
264 """
265 if not uri:
265 if not uri:
266 return ''
266 return ''
267
267
268 proto = ''
268 proto = ''
269
269
270 for pat in ('https://', 'http://'):
270 for pat in ('https://', 'http://'):
271 if uri.startswith(pat):
271 if uri.startswith(pat):
272 uri = uri[len(pat):]
272 uri = uri[len(pat):]
273 proto = pat
273 proto = pat
274 break
274 break
275
275
276 # remove passwords and username
276 # remove passwords and username
277 uri = uri[uri.find('@') + 1:]
277 uri = uri[uri.find('@') + 1:]
278
278
279 # get the port
279 # get the port
280 cred_pos = uri.find(':')
280 cred_pos = uri.find(':')
281 if cred_pos == -1:
281 if cred_pos == -1:
282 host, port = uri, None
282 host, port = uri, None
283 else:
283 else:
284 host, port = uri[:cred_pos], uri[cred_pos + 1:]
284 host, port = uri[:cred_pos], uri[cred_pos + 1:]
285
285
286 return filter(None, [proto, host, port])
286 return filter(None, [proto, host, port])
General Comments 0
You need to be logged in to leave comments. Login now