##// END OF EJS Templates
visual-settings: fill in default clone/ssh clone urls if they aren't provided....
marcink -
r2616:11d0d959 default
parent child Browse files
Show More
@@ -1,616 +1,617 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 this is forms validation classes
22 this is forms validation classes
23 http://formencode.org/module-formencode.validators.html
23 http://formencode.org/module-formencode.validators.html
24 for list off all availible validators
24 for list off all availible validators
25
25
26 we can create our own validators
26 we can create our own validators
27
27
28 The table below outlines the options which can be used in a schema in addition to the validators themselves
28 The table below outlines the options which can be used in a schema in addition to the validators themselves
29 pre_validators [] These validators will be applied before the schema
29 pre_validators [] These validators will be applied before the schema
30 chained_validators [] These validators will be applied after the schema
30 chained_validators [] These validators will be applied after the schema
31 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
31 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
32 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
32 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
33 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
33 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
34 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
34 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
35
35
36
36
37 <name> = formencode.validators.<name of validator>
37 <name> = formencode.validators.<name of validator>
38 <name> must equal form name
38 <name> must equal form name
39 list=[1,2,3,4,5]
39 list=[1,2,3,4,5]
40 for SELECT use formencode.All(OneOf(list), Int())
40 for SELECT use formencode.All(OneOf(list), Int())
41
41
42 """
42 """
43
43
44 import deform
44 import deform
45 import logging
45 import logging
46 import formencode
46 import formencode
47
47
48 from pkg_resources import resource_filename
48 from pkg_resources import resource_filename
49 from formencode import All, Pipe
49 from formencode import All, Pipe
50
50
51 from pyramid.threadlocal import get_current_request
51 from pyramid.threadlocal import get_current_request
52
52
53 from rhodecode import BACKENDS
53 from rhodecode import BACKENDS
54 from rhodecode.lib import helpers
54 from rhodecode.lib import helpers
55 from rhodecode.model import validators as v
55 from rhodecode.model import validators as v
56
56
57 log = logging.getLogger(__name__)
57 log = logging.getLogger(__name__)
58
58
59
59
60 deform_templates = resource_filename('deform', 'templates')
60 deform_templates = resource_filename('deform', 'templates')
61 rhodecode_templates = resource_filename('rhodecode', 'templates/forms')
61 rhodecode_templates = resource_filename('rhodecode', 'templates/forms')
62 search_path = (rhodecode_templates, deform_templates)
62 search_path = (rhodecode_templates, deform_templates)
63
63
64
64
65 class RhodecodeFormZPTRendererFactory(deform.ZPTRendererFactory):
65 class RhodecodeFormZPTRendererFactory(deform.ZPTRendererFactory):
66 """ Subclass of ZPTRendererFactory to add rhodecode context variables """
66 """ Subclass of ZPTRendererFactory to add rhodecode context variables """
67 def __call__(self, template_name, **kw):
67 def __call__(self, template_name, **kw):
68 kw['h'] = helpers
68 kw['h'] = helpers
69 kw['request'] = get_current_request()
69 kw['request'] = get_current_request()
70 return self.load(template_name)(**kw)
70 return self.load(template_name)(**kw)
71
71
72
72
73 form_renderer = RhodecodeFormZPTRendererFactory(search_path)
73 form_renderer = RhodecodeFormZPTRendererFactory(search_path)
74 deform.Form.set_default_renderer(form_renderer)
74 deform.Form.set_default_renderer(form_renderer)
75
75
76
76
77 def LoginForm(localizer):
77 def LoginForm(localizer):
78 _ = localizer
78 _ = localizer
79
79
80 class _LoginForm(formencode.Schema):
80 class _LoginForm(formencode.Schema):
81 allow_extra_fields = True
81 allow_extra_fields = True
82 filter_extra_fields = True
82 filter_extra_fields = True
83 username = v.UnicodeString(
83 username = v.UnicodeString(
84 strip=True,
84 strip=True,
85 min=1,
85 min=1,
86 not_empty=True,
86 not_empty=True,
87 messages={
87 messages={
88 'empty': _(u'Please enter a login'),
88 'empty': _(u'Please enter a login'),
89 'tooShort': _(u'Enter a value %(min)i characters long or more')
89 'tooShort': _(u'Enter a value %(min)i characters long or more')
90 }
90 }
91 )
91 )
92
92
93 password = v.UnicodeString(
93 password = v.UnicodeString(
94 strip=False,
94 strip=False,
95 min=3,
95 min=3,
96 max=72,
96 max=72,
97 not_empty=True,
97 not_empty=True,
98 messages={
98 messages={
99 'empty': _(u'Please enter a password'),
99 'empty': _(u'Please enter a password'),
100 'tooShort': _(u'Enter %(min)i characters or more')}
100 'tooShort': _(u'Enter %(min)i characters or more')}
101 )
101 )
102
102
103 remember = v.StringBoolean(if_missing=False)
103 remember = v.StringBoolean(if_missing=False)
104
104
105 chained_validators = [v.ValidAuth(localizer)]
105 chained_validators = [v.ValidAuth(localizer)]
106 return _LoginForm
106 return _LoginForm
107
107
108
108
109 def UserForm(localizer, edit=False, available_languages=None, old_data=None):
109 def UserForm(localizer, edit=False, available_languages=None, old_data=None):
110 old_data = old_data or {}
110 old_data = old_data or {}
111 available_languages = available_languages or []
111 available_languages = available_languages or []
112 _ = localizer
112 _ = localizer
113
113
114 class _UserForm(formencode.Schema):
114 class _UserForm(formencode.Schema):
115 allow_extra_fields = True
115 allow_extra_fields = True
116 filter_extra_fields = True
116 filter_extra_fields = True
117 username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
117 username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
118 v.ValidUsername(localizer, edit, old_data))
118 v.ValidUsername(localizer, edit, old_data))
119 if edit:
119 if edit:
120 new_password = All(
120 new_password = All(
121 v.ValidPassword(localizer),
121 v.ValidPassword(localizer),
122 v.UnicodeString(strip=False, min=6, max=72, not_empty=False)
122 v.UnicodeString(strip=False, min=6, max=72, not_empty=False)
123 )
123 )
124 password_confirmation = All(
124 password_confirmation = All(
125 v.ValidPassword(localizer),
125 v.ValidPassword(localizer),
126 v.UnicodeString(strip=False, min=6, max=72, not_empty=False),
126 v.UnicodeString(strip=False, min=6, max=72, not_empty=False),
127 )
127 )
128 admin = v.StringBoolean(if_missing=False)
128 admin = v.StringBoolean(if_missing=False)
129 else:
129 else:
130 password = All(
130 password = All(
131 v.ValidPassword(localizer),
131 v.ValidPassword(localizer),
132 v.UnicodeString(strip=False, min=6, max=72, not_empty=True)
132 v.UnicodeString(strip=False, min=6, max=72, not_empty=True)
133 )
133 )
134 password_confirmation = All(
134 password_confirmation = All(
135 v.ValidPassword(localizer),
135 v.ValidPassword(localizer),
136 v.UnicodeString(strip=False, min=6, max=72, not_empty=False)
136 v.UnicodeString(strip=False, min=6, max=72, not_empty=False)
137 )
137 )
138
138
139 password_change = v.StringBoolean(if_missing=False)
139 password_change = v.StringBoolean(if_missing=False)
140 create_repo_group = v.StringBoolean(if_missing=False)
140 create_repo_group = v.StringBoolean(if_missing=False)
141
141
142 active = v.StringBoolean(if_missing=False)
142 active = v.StringBoolean(if_missing=False)
143 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
143 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
144 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
144 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
145 email = All(v.UniqSystemEmail(localizer, old_data), v.Email(not_empty=True))
145 email = All(v.UniqSystemEmail(localizer, old_data), v.Email(not_empty=True))
146 extern_name = v.UnicodeString(strip=True)
146 extern_name = v.UnicodeString(strip=True)
147 extern_type = v.UnicodeString(strip=True)
147 extern_type = v.UnicodeString(strip=True)
148 language = v.OneOf(available_languages, hideList=False,
148 language = v.OneOf(available_languages, hideList=False,
149 testValueList=True, if_missing=None)
149 testValueList=True, if_missing=None)
150 chained_validators = [v.ValidPasswordsMatch(localizer)]
150 chained_validators = [v.ValidPasswordsMatch(localizer)]
151 return _UserForm
151 return _UserForm
152
152
153
153
154 def UserGroupForm(localizer, edit=False, old_data=None, allow_disabled=False):
154 def UserGroupForm(localizer, edit=False, old_data=None, allow_disabled=False):
155 old_data = old_data or {}
155 old_data = old_data or {}
156 _ = localizer
156 _ = localizer
157
157
158 class _UserGroupForm(formencode.Schema):
158 class _UserGroupForm(formencode.Schema):
159 allow_extra_fields = True
159 allow_extra_fields = True
160 filter_extra_fields = True
160 filter_extra_fields = True
161
161
162 users_group_name = All(
162 users_group_name = All(
163 v.UnicodeString(strip=True, min=1, not_empty=True),
163 v.UnicodeString(strip=True, min=1, not_empty=True),
164 v.ValidUserGroup(localizer, edit, old_data)
164 v.ValidUserGroup(localizer, edit, old_data)
165 )
165 )
166 user_group_description = v.UnicodeString(strip=True, min=1,
166 user_group_description = v.UnicodeString(strip=True, min=1,
167 not_empty=False)
167 not_empty=False)
168
168
169 users_group_active = v.StringBoolean(if_missing=False)
169 users_group_active = v.StringBoolean(if_missing=False)
170
170
171 if edit:
171 if edit:
172 # this is user group owner
172 # this is user group owner
173 user = All(
173 user = All(
174 v.UnicodeString(not_empty=True),
174 v.UnicodeString(not_empty=True),
175 v.ValidRepoUser(localizer, allow_disabled))
175 v.ValidRepoUser(localizer, allow_disabled))
176 return _UserGroupForm
176 return _UserGroupForm
177
177
178
178
179 def RepoGroupForm(localizer, edit=False, old_data=None, available_groups=None,
179 def RepoGroupForm(localizer, edit=False, old_data=None, available_groups=None,
180 can_create_in_root=False, allow_disabled=False):
180 can_create_in_root=False, allow_disabled=False):
181 _ = localizer
181 _ = localizer
182 old_data = old_data or {}
182 old_data = old_data or {}
183 available_groups = available_groups or []
183 available_groups = available_groups or []
184
184
185 class _RepoGroupForm(formencode.Schema):
185 class _RepoGroupForm(formencode.Schema):
186 allow_extra_fields = True
186 allow_extra_fields = True
187 filter_extra_fields = False
187 filter_extra_fields = False
188
188
189 group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
189 group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
190 v.SlugifyName(localizer),)
190 v.SlugifyName(localizer),)
191 group_description = v.UnicodeString(strip=True, min=1,
191 group_description = v.UnicodeString(strip=True, min=1,
192 not_empty=False)
192 not_empty=False)
193 group_copy_permissions = v.StringBoolean(if_missing=False)
193 group_copy_permissions = v.StringBoolean(if_missing=False)
194
194
195 group_parent_id = v.OneOf(available_groups, hideList=False,
195 group_parent_id = v.OneOf(available_groups, hideList=False,
196 testValueList=True, not_empty=True)
196 testValueList=True, not_empty=True)
197 enable_locking = v.StringBoolean(if_missing=False)
197 enable_locking = v.StringBoolean(if_missing=False)
198 chained_validators = [
198 chained_validators = [
199 v.ValidRepoGroup(localizer, edit, old_data, can_create_in_root)]
199 v.ValidRepoGroup(localizer, edit, old_data, can_create_in_root)]
200
200
201 if edit:
201 if edit:
202 # this is repo group owner
202 # this is repo group owner
203 user = All(
203 user = All(
204 v.UnicodeString(not_empty=True),
204 v.UnicodeString(not_empty=True),
205 v.ValidRepoUser(localizer, allow_disabled))
205 v.ValidRepoUser(localizer, allow_disabled))
206 return _RepoGroupForm
206 return _RepoGroupForm
207
207
208
208
209 def RegisterForm(localizer, edit=False, old_data=None):
209 def RegisterForm(localizer, edit=False, old_data=None):
210 _ = localizer
210 _ = localizer
211 old_data = old_data or {}
211 old_data = old_data or {}
212
212
213 class _RegisterForm(formencode.Schema):
213 class _RegisterForm(formencode.Schema):
214 allow_extra_fields = True
214 allow_extra_fields = True
215 filter_extra_fields = True
215 filter_extra_fields = True
216 username = All(
216 username = All(
217 v.ValidUsername(localizer, edit, old_data),
217 v.ValidUsername(localizer, edit, old_data),
218 v.UnicodeString(strip=True, min=1, not_empty=True)
218 v.UnicodeString(strip=True, min=1, not_empty=True)
219 )
219 )
220 password = All(
220 password = All(
221 v.ValidPassword(localizer),
221 v.ValidPassword(localizer),
222 v.UnicodeString(strip=False, min=6, max=72, not_empty=True)
222 v.UnicodeString(strip=False, min=6, max=72, not_empty=True)
223 )
223 )
224 password_confirmation = All(
224 password_confirmation = All(
225 v.ValidPassword(localizer),
225 v.ValidPassword(localizer),
226 v.UnicodeString(strip=False, min=6, max=72, not_empty=True)
226 v.UnicodeString(strip=False, min=6, max=72, not_empty=True)
227 )
227 )
228 active = v.StringBoolean(if_missing=False)
228 active = v.StringBoolean(if_missing=False)
229 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
229 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
230 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
230 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
231 email = All(v.UniqSystemEmail(localizer, old_data), v.Email(not_empty=True))
231 email = All(v.UniqSystemEmail(localizer, old_data), v.Email(not_empty=True))
232
232
233 chained_validators = [v.ValidPasswordsMatch(localizer)]
233 chained_validators = [v.ValidPasswordsMatch(localizer)]
234 return _RegisterForm
234 return _RegisterForm
235
235
236
236
237 def PasswordResetForm(localizer):
237 def PasswordResetForm(localizer):
238 _ = localizer
238 _ = localizer
239
239
240 class _PasswordResetForm(formencode.Schema):
240 class _PasswordResetForm(formencode.Schema):
241 allow_extra_fields = True
241 allow_extra_fields = True
242 filter_extra_fields = True
242 filter_extra_fields = True
243 email = All(v.ValidSystemEmail(localizer), v.Email(not_empty=True))
243 email = All(v.ValidSystemEmail(localizer), v.Email(not_empty=True))
244 return _PasswordResetForm
244 return _PasswordResetForm
245
245
246
246
247 def RepoForm(localizer, edit=False, old_data=None, repo_groups=None,
247 def RepoForm(localizer, edit=False, old_data=None, repo_groups=None,
248 landing_revs=None, allow_disabled=False):
248 landing_revs=None, allow_disabled=False):
249 _ = localizer
249 _ = localizer
250 old_data = old_data or {}
250 old_data = old_data or {}
251 repo_groups = repo_groups or []
251 repo_groups = repo_groups or []
252 landing_revs = landing_revs or []
252 landing_revs = landing_revs or []
253 supported_backends = BACKENDS.keys()
253 supported_backends = BACKENDS.keys()
254
254
255 class _RepoForm(formencode.Schema):
255 class _RepoForm(formencode.Schema):
256 allow_extra_fields = True
256 allow_extra_fields = True
257 filter_extra_fields = False
257 filter_extra_fields = False
258 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
258 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
259 v.SlugifyName(localizer), v.CannotHaveGitSuffix(localizer))
259 v.SlugifyName(localizer), v.CannotHaveGitSuffix(localizer))
260 repo_group = All(v.CanWriteGroup(localizer, old_data),
260 repo_group = All(v.CanWriteGroup(localizer, old_data),
261 v.OneOf(repo_groups, hideList=True))
261 v.OneOf(repo_groups, hideList=True))
262 repo_type = v.OneOf(supported_backends, required=False,
262 repo_type = v.OneOf(supported_backends, required=False,
263 if_missing=old_data.get('repo_type'))
263 if_missing=old_data.get('repo_type'))
264 repo_description = v.UnicodeString(strip=True, min=1, not_empty=False)
264 repo_description = v.UnicodeString(strip=True, min=1, not_empty=False)
265 repo_private = v.StringBoolean(if_missing=False)
265 repo_private = v.StringBoolean(if_missing=False)
266 repo_landing_rev = v.OneOf(landing_revs, hideList=True)
266 repo_landing_rev = v.OneOf(landing_revs, hideList=True)
267 repo_copy_permissions = v.StringBoolean(if_missing=False)
267 repo_copy_permissions = v.StringBoolean(if_missing=False)
268 clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
268 clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
269
269
270 repo_enable_statistics = v.StringBoolean(if_missing=False)
270 repo_enable_statistics = v.StringBoolean(if_missing=False)
271 repo_enable_downloads = v.StringBoolean(if_missing=False)
271 repo_enable_downloads = v.StringBoolean(if_missing=False)
272 repo_enable_locking = v.StringBoolean(if_missing=False)
272 repo_enable_locking = v.StringBoolean(if_missing=False)
273
273
274 if edit:
274 if edit:
275 # this is repo owner
275 # this is repo owner
276 user = All(
276 user = All(
277 v.UnicodeString(not_empty=True),
277 v.UnicodeString(not_empty=True),
278 v.ValidRepoUser(localizer, allow_disabled))
278 v.ValidRepoUser(localizer, allow_disabled))
279 clone_uri_change = v.UnicodeString(
279 clone_uri_change = v.UnicodeString(
280 not_empty=False, if_missing=v.Missing)
280 not_empty=False, if_missing=v.Missing)
281
281
282 chained_validators = [v.ValidCloneUri(localizer),
282 chained_validators = [v.ValidCloneUri(localizer),
283 v.ValidRepoName(localizer, edit, old_data)]
283 v.ValidRepoName(localizer, edit, old_data)]
284 return _RepoForm
284 return _RepoForm
285
285
286
286
287 def RepoPermsForm(localizer):
287 def RepoPermsForm(localizer):
288 _ = localizer
288 _ = localizer
289
289
290 class _RepoPermsForm(formencode.Schema):
290 class _RepoPermsForm(formencode.Schema):
291 allow_extra_fields = True
291 allow_extra_fields = True
292 filter_extra_fields = False
292 filter_extra_fields = False
293 chained_validators = [v.ValidPerms(localizer, type_='repo')]
293 chained_validators = [v.ValidPerms(localizer, type_='repo')]
294 return _RepoPermsForm
294 return _RepoPermsForm
295
295
296
296
297 def RepoGroupPermsForm(localizer, valid_recursive_choices):
297 def RepoGroupPermsForm(localizer, valid_recursive_choices):
298 _ = localizer
298 _ = localizer
299
299
300 class _RepoGroupPermsForm(formencode.Schema):
300 class _RepoGroupPermsForm(formencode.Schema):
301 allow_extra_fields = True
301 allow_extra_fields = True
302 filter_extra_fields = False
302 filter_extra_fields = False
303 recursive = v.OneOf(valid_recursive_choices)
303 recursive = v.OneOf(valid_recursive_choices)
304 chained_validators = [v.ValidPerms(localizer, type_='repo_group')]
304 chained_validators = [v.ValidPerms(localizer, type_='repo_group')]
305 return _RepoGroupPermsForm
305 return _RepoGroupPermsForm
306
306
307
307
308 def UserGroupPermsForm(localizer):
308 def UserGroupPermsForm(localizer):
309 _ = localizer
309 _ = localizer
310
310
311 class _UserPermsForm(formencode.Schema):
311 class _UserPermsForm(formencode.Schema):
312 allow_extra_fields = True
312 allow_extra_fields = True
313 filter_extra_fields = False
313 filter_extra_fields = False
314 chained_validators = [v.ValidPerms(localizer, type_='user_group')]
314 chained_validators = [v.ValidPerms(localizer, type_='user_group')]
315 return _UserPermsForm
315 return _UserPermsForm
316
316
317
317
318 def RepoFieldForm(localizer):
318 def RepoFieldForm(localizer):
319 _ = localizer
319 _ = localizer
320
320
321 class _RepoFieldForm(formencode.Schema):
321 class _RepoFieldForm(formencode.Schema):
322 filter_extra_fields = True
322 filter_extra_fields = True
323 allow_extra_fields = True
323 allow_extra_fields = True
324
324
325 new_field_key = All(v.FieldKey(localizer),
325 new_field_key = All(v.FieldKey(localizer),
326 v.UnicodeString(strip=True, min=3, not_empty=True))
326 v.UnicodeString(strip=True, min=3, not_empty=True))
327 new_field_value = v.UnicodeString(not_empty=False, if_missing=u'')
327 new_field_value = v.UnicodeString(not_empty=False, if_missing=u'')
328 new_field_type = v.OneOf(['str', 'unicode', 'list', 'tuple'],
328 new_field_type = v.OneOf(['str', 'unicode', 'list', 'tuple'],
329 if_missing='str')
329 if_missing='str')
330 new_field_label = v.UnicodeString(not_empty=False)
330 new_field_label = v.UnicodeString(not_empty=False)
331 new_field_desc = v.UnicodeString(not_empty=False)
331 new_field_desc = v.UnicodeString(not_empty=False)
332 return _RepoFieldForm
332 return _RepoFieldForm
333
333
334
334
335 def RepoForkForm(localizer, edit=False, old_data=None,
335 def RepoForkForm(localizer, edit=False, old_data=None,
336 supported_backends=BACKENDS.keys(), repo_groups=None,
336 supported_backends=BACKENDS.keys(), repo_groups=None,
337 landing_revs=None):
337 landing_revs=None):
338 _ = localizer
338 _ = localizer
339 old_data = old_data or {}
339 old_data = old_data or {}
340 repo_groups = repo_groups or []
340 repo_groups = repo_groups or []
341 landing_revs = landing_revs or []
341 landing_revs = landing_revs or []
342
342
343 class _RepoForkForm(formencode.Schema):
343 class _RepoForkForm(formencode.Schema):
344 allow_extra_fields = True
344 allow_extra_fields = True
345 filter_extra_fields = False
345 filter_extra_fields = False
346 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
346 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
347 v.SlugifyName(localizer))
347 v.SlugifyName(localizer))
348 repo_group = All(v.CanWriteGroup(localizer, ),
348 repo_group = All(v.CanWriteGroup(localizer, ),
349 v.OneOf(repo_groups, hideList=True))
349 v.OneOf(repo_groups, hideList=True))
350 repo_type = All(v.ValidForkType(localizer, old_data), v.OneOf(supported_backends))
350 repo_type = All(v.ValidForkType(localizer, old_data), v.OneOf(supported_backends))
351 description = v.UnicodeString(strip=True, min=1, not_empty=True)
351 description = v.UnicodeString(strip=True, min=1, not_empty=True)
352 private = v.StringBoolean(if_missing=False)
352 private = v.StringBoolean(if_missing=False)
353 copy_permissions = v.StringBoolean(if_missing=False)
353 copy_permissions = v.StringBoolean(if_missing=False)
354 fork_parent_id = v.UnicodeString()
354 fork_parent_id = v.UnicodeString()
355 chained_validators = [v.ValidForkName(localizer, edit, old_data)]
355 chained_validators = [v.ValidForkName(localizer, edit, old_data)]
356 landing_rev = v.OneOf(landing_revs, hideList=True)
356 landing_rev = v.OneOf(landing_revs, hideList=True)
357 return _RepoForkForm
357 return _RepoForkForm
358
358
359
359
360 def ApplicationSettingsForm(localizer):
360 def ApplicationSettingsForm(localizer):
361 _ = localizer
361 _ = localizer
362
362
363 class _ApplicationSettingsForm(formencode.Schema):
363 class _ApplicationSettingsForm(formencode.Schema):
364 allow_extra_fields = True
364 allow_extra_fields = True
365 filter_extra_fields = False
365 filter_extra_fields = False
366 rhodecode_title = v.UnicodeString(strip=True, max=40, not_empty=False)
366 rhodecode_title = v.UnicodeString(strip=True, max=40, not_empty=False)
367 rhodecode_realm = v.UnicodeString(strip=True, min=1, not_empty=True)
367 rhodecode_realm = v.UnicodeString(strip=True, min=1, not_empty=True)
368 rhodecode_pre_code = v.UnicodeString(strip=True, min=1, not_empty=False)
368 rhodecode_pre_code = v.UnicodeString(strip=True, min=1, not_empty=False)
369 rhodecode_post_code = v.UnicodeString(strip=True, min=1, not_empty=False)
369 rhodecode_post_code = v.UnicodeString(strip=True, min=1, not_empty=False)
370 rhodecode_captcha_public_key = v.UnicodeString(strip=True, min=1, not_empty=False)
370 rhodecode_captcha_public_key = v.UnicodeString(strip=True, min=1, not_empty=False)
371 rhodecode_captcha_private_key = v.UnicodeString(strip=True, min=1, not_empty=False)
371 rhodecode_captcha_private_key = v.UnicodeString(strip=True, min=1, not_empty=False)
372 rhodecode_create_personal_repo_group = v.StringBoolean(if_missing=False)
372 rhodecode_create_personal_repo_group = v.StringBoolean(if_missing=False)
373 rhodecode_personal_repo_group_pattern = v.UnicodeString(strip=True, min=1, not_empty=False)
373 rhodecode_personal_repo_group_pattern = v.UnicodeString(strip=True, min=1, not_empty=False)
374 return _ApplicationSettingsForm
374 return _ApplicationSettingsForm
375
375
376
376
377 def ApplicationVisualisationForm(localizer):
377 def ApplicationVisualisationForm(localizer):
378 from rhodecode.model.db import Repository
378 _ = localizer
379 _ = localizer
379
380
380 class _ApplicationVisualisationForm(formencode.Schema):
381 class _ApplicationVisualisationForm(formencode.Schema):
381 allow_extra_fields = True
382 allow_extra_fields = True
382 filter_extra_fields = False
383 filter_extra_fields = False
383 rhodecode_show_public_icon = v.StringBoolean(if_missing=False)
384 rhodecode_show_public_icon = v.StringBoolean(if_missing=False)
384 rhodecode_show_private_icon = v.StringBoolean(if_missing=False)
385 rhodecode_show_private_icon = v.StringBoolean(if_missing=False)
385 rhodecode_stylify_metatags = v.StringBoolean(if_missing=False)
386 rhodecode_stylify_metatags = v.StringBoolean(if_missing=False)
386
387
387 rhodecode_repository_fields = v.StringBoolean(if_missing=False)
388 rhodecode_repository_fields = v.StringBoolean(if_missing=False)
388 rhodecode_lightweight_journal = v.StringBoolean(if_missing=False)
389 rhodecode_lightweight_journal = v.StringBoolean(if_missing=False)
389 rhodecode_dashboard_items = v.Int(min=5, not_empty=True)
390 rhodecode_dashboard_items = v.Int(min=5, not_empty=True)
390 rhodecode_admin_grid_items = v.Int(min=5, not_empty=True)
391 rhodecode_admin_grid_items = v.Int(min=5, not_empty=True)
391 rhodecode_show_version = v.StringBoolean(if_missing=False)
392 rhodecode_show_version = v.StringBoolean(if_missing=False)
392 rhodecode_use_gravatar = v.StringBoolean(if_missing=False)
393 rhodecode_use_gravatar = v.StringBoolean(if_missing=False)
393 rhodecode_markup_renderer = v.OneOf(['markdown', 'rst'])
394 rhodecode_markup_renderer = v.OneOf(['markdown', 'rst'])
394 rhodecode_gravatar_url = v.UnicodeString(min=3)
395 rhodecode_gravatar_url = v.UnicodeString(min=3)
395 rhodecode_clone_uri_tmpl = v.UnicodeString(min=3)
396 rhodecode_clone_uri_tmpl = v.UnicodeString(not_empty=False, if_empty=Repository.DEFAULT_CLONE_URI)
396 rhodecode_clone_uri_ssh_tmpl = v.UnicodeString(min=3)
397 rhodecode_clone_uri_ssh_tmpl = v.UnicodeString(not_empty=False, if_empty=Repository.DEFAULT_CLONE_URI_SSH)
397 rhodecode_support_url = v.UnicodeString()
398 rhodecode_support_url = v.UnicodeString()
398 rhodecode_show_revision_number = v.StringBoolean(if_missing=False)
399 rhodecode_show_revision_number = v.StringBoolean(if_missing=False)
399 rhodecode_show_sha_length = v.Int(min=4, not_empty=True)
400 rhodecode_show_sha_length = v.Int(min=4, not_empty=True)
400 return _ApplicationVisualisationForm
401 return _ApplicationVisualisationForm
401
402
402
403
403 class _BaseVcsSettingsForm(formencode.Schema):
404 class _BaseVcsSettingsForm(formencode.Schema):
404
405
405 allow_extra_fields = True
406 allow_extra_fields = True
406 filter_extra_fields = False
407 filter_extra_fields = False
407 hooks_changegroup_repo_size = v.StringBoolean(if_missing=False)
408 hooks_changegroup_repo_size = v.StringBoolean(if_missing=False)
408 hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
409 hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
409 hooks_outgoing_pull_logger = v.StringBoolean(if_missing=False)
410 hooks_outgoing_pull_logger = v.StringBoolean(if_missing=False)
410
411
411 # PR/Code-review
412 # PR/Code-review
412 rhodecode_pr_merge_enabled = v.StringBoolean(if_missing=False)
413 rhodecode_pr_merge_enabled = v.StringBoolean(if_missing=False)
413 rhodecode_use_outdated_comments = v.StringBoolean(if_missing=False)
414 rhodecode_use_outdated_comments = v.StringBoolean(if_missing=False)
414
415
415 # hg
416 # hg
416 extensions_largefiles = v.StringBoolean(if_missing=False)
417 extensions_largefiles = v.StringBoolean(if_missing=False)
417 extensions_evolve = v.StringBoolean(if_missing=False)
418 extensions_evolve = v.StringBoolean(if_missing=False)
418 phases_publish = v.StringBoolean(if_missing=False)
419 phases_publish = v.StringBoolean(if_missing=False)
419
420
420 rhodecode_hg_use_rebase_for_merging = v.StringBoolean(if_missing=False)
421 rhodecode_hg_use_rebase_for_merging = v.StringBoolean(if_missing=False)
421 rhodecode_hg_close_branch_before_merging = v.StringBoolean(if_missing=False)
422 rhodecode_hg_close_branch_before_merging = v.StringBoolean(if_missing=False)
422
423
423 # git
424 # git
424 vcs_git_lfs_enabled = v.StringBoolean(if_missing=False)
425 vcs_git_lfs_enabled = v.StringBoolean(if_missing=False)
425 rhodecode_git_use_rebase_for_merging = v.StringBoolean(if_missing=False)
426 rhodecode_git_use_rebase_for_merging = v.StringBoolean(if_missing=False)
426 rhodecode_git_close_branch_before_merging = v.StringBoolean(if_missing=False)
427 rhodecode_git_close_branch_before_merging = v.StringBoolean(if_missing=False)
427
428
428 # svn
429 # svn
429 vcs_svn_proxy_http_requests_enabled = v.StringBoolean(if_missing=False)
430 vcs_svn_proxy_http_requests_enabled = v.StringBoolean(if_missing=False)
430 vcs_svn_proxy_http_server_url = v.UnicodeString(strip=True, if_missing=None)
431 vcs_svn_proxy_http_server_url = v.UnicodeString(strip=True, if_missing=None)
431
432
432
433
433 def ApplicationUiSettingsForm(localizer):
434 def ApplicationUiSettingsForm(localizer):
434 _ = localizer
435 _ = localizer
435
436
436 class _ApplicationUiSettingsForm(_BaseVcsSettingsForm):
437 class _ApplicationUiSettingsForm(_BaseVcsSettingsForm):
437 web_push_ssl = v.StringBoolean(if_missing=False)
438 web_push_ssl = v.StringBoolean(if_missing=False)
438 paths_root_path = All(
439 paths_root_path = All(
439 v.ValidPath(localizer),
440 v.ValidPath(localizer),
440 v.UnicodeString(strip=True, min=1, not_empty=True)
441 v.UnicodeString(strip=True, min=1, not_empty=True)
441 )
442 )
442 largefiles_usercache = All(
443 largefiles_usercache = All(
443 v.ValidPath(localizer),
444 v.ValidPath(localizer),
444 v.UnicodeString(strip=True, min=2, not_empty=True))
445 v.UnicodeString(strip=True, min=2, not_empty=True))
445 vcs_git_lfs_store_location = All(
446 vcs_git_lfs_store_location = All(
446 v.ValidPath(localizer),
447 v.ValidPath(localizer),
447 v.UnicodeString(strip=True, min=2, not_empty=True))
448 v.UnicodeString(strip=True, min=2, not_empty=True))
448 extensions_hgsubversion = v.StringBoolean(if_missing=False)
449 extensions_hgsubversion = v.StringBoolean(if_missing=False)
449 extensions_hggit = v.StringBoolean(if_missing=False)
450 extensions_hggit = v.StringBoolean(if_missing=False)
450 new_svn_branch = v.ValidSvnPattern(localizer, section='vcs_svn_branch')
451 new_svn_branch = v.ValidSvnPattern(localizer, section='vcs_svn_branch')
451 new_svn_tag = v.ValidSvnPattern(localizer, section='vcs_svn_tag')
452 new_svn_tag = v.ValidSvnPattern(localizer, section='vcs_svn_tag')
452 return _ApplicationUiSettingsForm
453 return _ApplicationUiSettingsForm
453
454
454
455
455 def RepoVcsSettingsForm(localizer, repo_name):
456 def RepoVcsSettingsForm(localizer, repo_name):
456 _ = localizer
457 _ = localizer
457
458
458 class _RepoVcsSettingsForm(_BaseVcsSettingsForm):
459 class _RepoVcsSettingsForm(_BaseVcsSettingsForm):
459 inherit_global_settings = v.StringBoolean(if_missing=False)
460 inherit_global_settings = v.StringBoolean(if_missing=False)
460 new_svn_branch = v.ValidSvnPattern(localizer,
461 new_svn_branch = v.ValidSvnPattern(localizer,
461 section='vcs_svn_branch', repo_name=repo_name)
462 section='vcs_svn_branch', repo_name=repo_name)
462 new_svn_tag = v.ValidSvnPattern(localizer,
463 new_svn_tag = v.ValidSvnPattern(localizer,
463 section='vcs_svn_tag', repo_name=repo_name)
464 section='vcs_svn_tag', repo_name=repo_name)
464 return _RepoVcsSettingsForm
465 return _RepoVcsSettingsForm
465
466
466
467
467 def LabsSettingsForm(localizer):
468 def LabsSettingsForm(localizer):
468 _ = localizer
469 _ = localizer
469
470
470 class _LabSettingsForm(formencode.Schema):
471 class _LabSettingsForm(formencode.Schema):
471 allow_extra_fields = True
472 allow_extra_fields = True
472 filter_extra_fields = False
473 filter_extra_fields = False
473 return _LabSettingsForm
474 return _LabSettingsForm
474
475
475
476
476 def ApplicationPermissionsForm(
477 def ApplicationPermissionsForm(
477 localizer, register_choices, password_reset_choices,
478 localizer, register_choices, password_reset_choices,
478 extern_activate_choices):
479 extern_activate_choices):
479 _ = localizer
480 _ = localizer
480
481
481 class _DefaultPermissionsForm(formencode.Schema):
482 class _DefaultPermissionsForm(formencode.Schema):
482 allow_extra_fields = True
483 allow_extra_fields = True
483 filter_extra_fields = True
484 filter_extra_fields = True
484
485
485 anonymous = v.StringBoolean(if_missing=False)
486 anonymous = v.StringBoolean(if_missing=False)
486 default_register = v.OneOf(register_choices)
487 default_register = v.OneOf(register_choices)
487 default_register_message = v.UnicodeString()
488 default_register_message = v.UnicodeString()
488 default_password_reset = v.OneOf(password_reset_choices)
489 default_password_reset = v.OneOf(password_reset_choices)
489 default_extern_activate = v.OneOf(extern_activate_choices)
490 default_extern_activate = v.OneOf(extern_activate_choices)
490 return _DefaultPermissionsForm
491 return _DefaultPermissionsForm
491
492
492
493
493 def ObjectPermissionsForm(localizer, repo_perms_choices, group_perms_choices,
494 def ObjectPermissionsForm(localizer, repo_perms_choices, group_perms_choices,
494 user_group_perms_choices):
495 user_group_perms_choices):
495 _ = localizer
496 _ = localizer
496
497
497 class _ObjectPermissionsForm(formencode.Schema):
498 class _ObjectPermissionsForm(formencode.Schema):
498 allow_extra_fields = True
499 allow_extra_fields = True
499 filter_extra_fields = True
500 filter_extra_fields = True
500 overwrite_default_repo = v.StringBoolean(if_missing=False)
501 overwrite_default_repo = v.StringBoolean(if_missing=False)
501 overwrite_default_group = v.StringBoolean(if_missing=False)
502 overwrite_default_group = v.StringBoolean(if_missing=False)
502 overwrite_default_user_group = v.StringBoolean(if_missing=False)
503 overwrite_default_user_group = v.StringBoolean(if_missing=False)
503 default_repo_perm = v.OneOf(repo_perms_choices)
504 default_repo_perm = v.OneOf(repo_perms_choices)
504 default_group_perm = v.OneOf(group_perms_choices)
505 default_group_perm = v.OneOf(group_perms_choices)
505 default_user_group_perm = v.OneOf(user_group_perms_choices)
506 default_user_group_perm = v.OneOf(user_group_perms_choices)
506 return _ObjectPermissionsForm
507 return _ObjectPermissionsForm
507
508
508
509
509 def UserPermissionsForm(localizer, create_choices, create_on_write_choices,
510 def UserPermissionsForm(localizer, create_choices, create_on_write_choices,
510 repo_group_create_choices, user_group_create_choices,
511 repo_group_create_choices, user_group_create_choices,
511 fork_choices, inherit_default_permissions_choices):
512 fork_choices, inherit_default_permissions_choices):
512 _ = localizer
513 _ = localizer
513
514
514 class _DefaultPermissionsForm(formencode.Schema):
515 class _DefaultPermissionsForm(formencode.Schema):
515 allow_extra_fields = True
516 allow_extra_fields = True
516 filter_extra_fields = True
517 filter_extra_fields = True
517
518
518 anonymous = v.StringBoolean(if_missing=False)
519 anonymous = v.StringBoolean(if_missing=False)
519
520
520 default_repo_create = v.OneOf(create_choices)
521 default_repo_create = v.OneOf(create_choices)
521 default_repo_create_on_write = v.OneOf(create_on_write_choices)
522 default_repo_create_on_write = v.OneOf(create_on_write_choices)
522 default_user_group_create = v.OneOf(user_group_create_choices)
523 default_user_group_create = v.OneOf(user_group_create_choices)
523 default_repo_group_create = v.OneOf(repo_group_create_choices)
524 default_repo_group_create = v.OneOf(repo_group_create_choices)
524 default_fork_create = v.OneOf(fork_choices)
525 default_fork_create = v.OneOf(fork_choices)
525 default_inherit_default_permissions = v.OneOf(inherit_default_permissions_choices)
526 default_inherit_default_permissions = v.OneOf(inherit_default_permissions_choices)
526 return _DefaultPermissionsForm
527 return _DefaultPermissionsForm
527
528
528
529
529 def UserIndividualPermissionsForm(localizer):
530 def UserIndividualPermissionsForm(localizer):
530 _ = localizer
531 _ = localizer
531
532
532 class _DefaultPermissionsForm(formencode.Schema):
533 class _DefaultPermissionsForm(formencode.Schema):
533 allow_extra_fields = True
534 allow_extra_fields = True
534 filter_extra_fields = True
535 filter_extra_fields = True
535
536
536 inherit_default_permissions = v.StringBoolean(if_missing=False)
537 inherit_default_permissions = v.StringBoolean(if_missing=False)
537 return _DefaultPermissionsForm
538 return _DefaultPermissionsForm
538
539
539
540
540 def DefaultsForm(localizer, edit=False, old_data=None, supported_backends=BACKENDS.keys()):
541 def DefaultsForm(localizer, edit=False, old_data=None, supported_backends=BACKENDS.keys()):
541 _ = localizer
542 _ = localizer
542 old_data = old_data or {}
543 old_data = old_data or {}
543
544
544 class _DefaultsForm(formencode.Schema):
545 class _DefaultsForm(formencode.Schema):
545 allow_extra_fields = True
546 allow_extra_fields = True
546 filter_extra_fields = True
547 filter_extra_fields = True
547 default_repo_type = v.OneOf(supported_backends)
548 default_repo_type = v.OneOf(supported_backends)
548 default_repo_private = v.StringBoolean(if_missing=False)
549 default_repo_private = v.StringBoolean(if_missing=False)
549 default_repo_enable_statistics = v.StringBoolean(if_missing=False)
550 default_repo_enable_statistics = v.StringBoolean(if_missing=False)
550 default_repo_enable_downloads = v.StringBoolean(if_missing=False)
551 default_repo_enable_downloads = v.StringBoolean(if_missing=False)
551 default_repo_enable_locking = v.StringBoolean(if_missing=False)
552 default_repo_enable_locking = v.StringBoolean(if_missing=False)
552 return _DefaultsForm
553 return _DefaultsForm
553
554
554
555
555 def AuthSettingsForm(localizer):
556 def AuthSettingsForm(localizer):
556 _ = localizer
557 _ = localizer
557
558
558 class _AuthSettingsForm(formencode.Schema):
559 class _AuthSettingsForm(formencode.Schema):
559 allow_extra_fields = True
560 allow_extra_fields = True
560 filter_extra_fields = True
561 filter_extra_fields = True
561 auth_plugins = All(v.ValidAuthPlugins(localizer),
562 auth_plugins = All(v.ValidAuthPlugins(localizer),
562 v.UniqueListFromString(localizer)(not_empty=True))
563 v.UniqueListFromString(localizer)(not_empty=True))
563 return _AuthSettingsForm
564 return _AuthSettingsForm
564
565
565
566
566 def UserExtraEmailForm(localizer):
567 def UserExtraEmailForm(localizer):
567 _ = localizer
568 _ = localizer
568
569
569 class _UserExtraEmailForm(formencode.Schema):
570 class _UserExtraEmailForm(formencode.Schema):
570 email = All(v.UniqSystemEmail(localizer), v.Email(not_empty=True))
571 email = All(v.UniqSystemEmail(localizer), v.Email(not_empty=True))
571 return _UserExtraEmailForm
572 return _UserExtraEmailForm
572
573
573
574
574 def UserExtraIpForm(localizer):
575 def UserExtraIpForm(localizer):
575 _ = localizer
576 _ = localizer
576
577
577 class _UserExtraIpForm(formencode.Schema):
578 class _UserExtraIpForm(formencode.Schema):
578 ip = v.ValidIp(localizer)(not_empty=True)
579 ip = v.ValidIp(localizer)(not_empty=True)
579 return _UserExtraIpForm
580 return _UserExtraIpForm
580
581
581
582
582 def PullRequestForm(localizer, repo_id):
583 def PullRequestForm(localizer, repo_id):
583 _ = localizer
584 _ = localizer
584
585
585 class ReviewerForm(formencode.Schema):
586 class ReviewerForm(formencode.Schema):
586 user_id = v.Int(not_empty=True)
587 user_id = v.Int(not_empty=True)
587 reasons = All()
588 reasons = All()
588 rules = All(v.UniqueList(localizer, convert=int)())
589 rules = All(v.UniqueList(localizer, convert=int)())
589 mandatory = v.StringBoolean()
590 mandatory = v.StringBoolean()
590
591
591 class _PullRequestForm(formencode.Schema):
592 class _PullRequestForm(formencode.Schema):
592 allow_extra_fields = True
593 allow_extra_fields = True
593 filter_extra_fields = True
594 filter_extra_fields = True
594
595
595 common_ancestor = v.UnicodeString(strip=True, required=True)
596 common_ancestor = v.UnicodeString(strip=True, required=True)
596 source_repo = v.UnicodeString(strip=True, required=True)
597 source_repo = v.UnicodeString(strip=True, required=True)
597 source_ref = v.UnicodeString(strip=True, required=True)
598 source_ref = v.UnicodeString(strip=True, required=True)
598 target_repo = v.UnicodeString(strip=True, required=True)
599 target_repo = v.UnicodeString(strip=True, required=True)
599 target_ref = v.UnicodeString(strip=True, required=True)
600 target_ref = v.UnicodeString(strip=True, required=True)
600 revisions = All(#v.NotReviewedRevisions(localizer, repo_id)(),
601 revisions = All(#v.NotReviewedRevisions(localizer, repo_id)(),
601 v.UniqueList(localizer)(not_empty=True))
602 v.UniqueList(localizer)(not_empty=True))
602 review_members = formencode.ForEach(ReviewerForm())
603 review_members = formencode.ForEach(ReviewerForm())
603 pullrequest_title = v.UnicodeString(strip=True, required=True, min=3, max=255)
604 pullrequest_title = v.UnicodeString(strip=True, required=True, min=3, max=255)
604 pullrequest_desc = v.UnicodeString(strip=True, required=False)
605 pullrequest_desc = v.UnicodeString(strip=True, required=False)
605
606
606 return _PullRequestForm
607 return _PullRequestForm
607
608
608
609
609 def IssueTrackerPatternsForm(localizer):
610 def IssueTrackerPatternsForm(localizer):
610 _ = localizer
611 _ = localizer
611
612
612 class _IssueTrackerPatternsForm(formencode.Schema):
613 class _IssueTrackerPatternsForm(formencode.Schema):
613 allow_extra_fields = True
614 allow_extra_fields = True
614 filter_extra_fields = False
615 filter_extra_fields = False
615 chained_validators = [v.ValidPattern(localizer)]
616 chained_validators = [v.ValidPattern(localizer)]
616 return _IssueTrackerPatternsForm
617 return _IssueTrackerPatternsForm
General Comments 0
You need to be logged in to leave comments. Login now