annotate rhodecode/lib/utils2.py @ 2865:6d9b3ade3051 beta

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