##// END OF EJS Templates
core: dropped usage of configobj entirely
super-admin -
r4975:0b11b7dc default
parent child Browse files
Show More
@@ -1,426 +1,428 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 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 Helpers for fixture generation
22 Helpers for fixture generation
23 """
23 """
24
24
25 import os
25 import os
26 import time
26 import time
27 import tempfile
27 import tempfile
28 import shutil
28 import shutil
29
29 import configparser
30 import configobj
31
30
32 from rhodecode.model.settings import SettingsModel
31 from rhodecode.model.settings import SettingsModel
33 from rhodecode.tests import *
32 from rhodecode.tests import *
34 from rhodecode.model.db import Repository, User, RepoGroup, UserGroup, Gist, UserEmailMap
33 from rhodecode.model.db import Repository, User, RepoGroup, UserGroup, Gist, UserEmailMap
35 from rhodecode.model.meta import Session
34 from rhodecode.model.meta import Session
36 from rhodecode.model.repo import RepoModel
35 from rhodecode.model.repo import RepoModel
37 from rhodecode.model.user import UserModel
36 from rhodecode.model.user import UserModel
38 from rhodecode.model.repo_group import RepoGroupModel
37 from rhodecode.model.repo_group import RepoGroupModel
39 from rhodecode.model.user_group import UserGroupModel
38 from rhodecode.model.user_group import UserGroupModel
40 from rhodecode.model.gist import GistModel
39 from rhodecode.model.gist import GistModel
41 from rhodecode.model.auth_token import AuthTokenModel
40 from rhodecode.model.auth_token import AuthTokenModel
42 from rhodecode.model.scm import ScmModel
41 from rhodecode.model.scm import ScmModel
43 from rhodecode.authentication.plugins.auth_rhodecode import \
42 from rhodecode.authentication.plugins.auth_rhodecode import \
44 RhodeCodeAuthPlugin
43 RhodeCodeAuthPlugin
45
44
46 dn = os.path.dirname
45 dn = os.path.dirname
47 FIXTURES = os.path.join(dn(dn(os.path.abspath(__file__))), 'tests', 'fixtures')
46 FIXTURES = os.path.join(dn(dn(os.path.abspath(__file__))), 'tests', 'fixtures')
48
47
49
48
50 def error_function(*args, **kwargs):
49 def error_function(*args, **kwargs):
51 raise Exception('Total Crash !')
50 raise Exception('Total Crash !')
52
51
53
52
54 class TestINI(object):
53 class TestINI(object):
55 """
54 """
56 Allows to create a new test.ini file as a copy of existing one with edited
55 Allows to create a new test.ini file as a copy of existing one with edited
57 data. Example usage::
56 data. Example usage::
58
57
59 with TestINI('test.ini', [{'section':{'key':val'}]) as new_test_ini_path:
58 with TestINI('test.ini', [{'section':{'key':val'}]) as new_test_ini_path:
60 print('paster server %s' % new_test_ini)
59 print('paster server %s' % new_test_ini)
61 """
60 """
62
61
63 def __init__(self, ini_file_path, ini_params, new_file_prefix='DEFAULT',
62 def __init__(self, ini_file_path, ini_params, new_file_prefix='DEFAULT',
64 destroy=True, dir=None):
63 destroy=True, dir=None):
65 self.ini_file_path = ini_file_path
64 self.ini_file_path = ini_file_path
66 self.ini_params = ini_params
65 self.ini_params = ini_params
67 self.new_path = None
66 self.new_path = None
68 self.new_path_prefix = new_file_prefix
67 self.new_path_prefix = new_file_prefix
69 self._destroy = destroy
68 self._destroy = destroy
70 self._dir = dir
69 self._dir = dir
71
70
72 def __enter__(self):
71 def __enter__(self):
73 return self.create()
72 return self.create()
74
73
75 def __exit__(self, exc_type, exc_val, exc_tb):
74 def __exit__(self, exc_type, exc_val, exc_tb):
76 self.destroy()
75 self.destroy()
77
76
78 def create(self):
77 def create(self):
79 config = configobj.ConfigObj(
78 parser = configparser.ConfigParser()
80 self.ini_file_path, file_error=True, write_empty_values=True)
79 parser.read(self.ini_file_path)
81
80
82 for data in self.ini_params:
81 for data in self.ini_params:
83 section, ini_params = data.items()[0]
82 section, ini_params = list(data.items())[0]
83
84 for key, val in ini_params.items():
84 for key, val in ini_params.items():
85 config[section][key] = val
85 parser[section][key] = str(val)
86
86 with tempfile.NamedTemporaryFile(
87 with tempfile.NamedTemporaryFile(
88 mode='w',
87 prefix=self.new_path_prefix, suffix='.ini', dir=self._dir,
89 prefix=self.new_path_prefix, suffix='.ini', dir=self._dir,
88 delete=False) as new_ini_file:
90 delete=False) as new_ini_file:
89 config.write(new_ini_file)
91 parser.write(new_ini_file)
90 self.new_path = new_ini_file.name
92 self.new_path = new_ini_file.name
91
93
92 return self.new_path
94 return self.new_path
93
95
94 def destroy(self):
96 def destroy(self):
95 if self._destroy:
97 if self._destroy:
96 os.remove(self.new_path)
98 os.remove(self.new_path)
97
99
98
100
99 class Fixture(object):
101 class Fixture(object):
100
102
101 def anon_access(self, status):
103 def anon_access(self, status):
102 """
104 """
103 Context process for disabling anonymous access. use like:
105 Context process for disabling anonymous access. use like:
104 fixture = Fixture()
106 fixture = Fixture()
105 with fixture.anon_access(False):
107 with fixture.anon_access(False):
106 #tests
108 #tests
107
109
108 after this block anon access will be set to `not status`
110 after this block anon access will be set to `not status`
109 """
111 """
110
112
111 class context(object):
113 class context(object):
112 def __enter__(self):
114 def __enter__(self):
113 anon = User.get_default_user()
115 anon = User.get_default_user()
114 anon.active = status
116 anon.active = status
115 Session().add(anon)
117 Session().add(anon)
116 Session().commit()
118 Session().commit()
117 time.sleep(1.5) # must sleep for cache (1s to expire)
119 time.sleep(1.5) # must sleep for cache (1s to expire)
118
120
119 def __exit__(self, exc_type, exc_val, exc_tb):
121 def __exit__(self, exc_type, exc_val, exc_tb):
120 anon = User.get_default_user()
122 anon = User.get_default_user()
121 anon.active = not status
123 anon.active = not status
122 Session().add(anon)
124 Session().add(anon)
123 Session().commit()
125 Session().commit()
124
126
125 return context()
127 return context()
126
128
127 def auth_restriction(self, registry, auth_restriction):
129 def auth_restriction(self, registry, auth_restriction):
128 """
130 """
129 Context process for changing the builtin rhodecode plugin auth restrictions.
131 Context process for changing the builtin rhodecode plugin auth restrictions.
130 Use like:
132 Use like:
131 fixture = Fixture()
133 fixture = Fixture()
132 with fixture.auth_restriction('super_admin'):
134 with fixture.auth_restriction('super_admin'):
133 #tests
135 #tests
134
136
135 after this block auth restriction will be taken off
137 after this block auth restriction will be taken off
136 """
138 """
137
139
138 class context(object):
140 class context(object):
139 def _get_plugin(self):
141 def _get_plugin(self):
140 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
142 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
141 plugin = RhodeCodeAuthPlugin(plugin_id)
143 plugin = RhodeCodeAuthPlugin(plugin_id)
142 return plugin
144 return plugin
143
145
144 def __enter__(self):
146 def __enter__(self):
145
147
146 plugin = self._get_plugin()
148 plugin = self._get_plugin()
147 plugin.create_or_update_setting('auth_restriction', auth_restriction)
149 plugin.create_or_update_setting('auth_restriction', auth_restriction)
148 Session().commit()
150 Session().commit()
149 SettingsModel().invalidate_settings_cache()
151 SettingsModel().invalidate_settings_cache()
150
152
151 def __exit__(self, exc_type, exc_val, exc_tb):
153 def __exit__(self, exc_type, exc_val, exc_tb):
152
154
153 plugin = self._get_plugin()
155 plugin = self._get_plugin()
154 plugin.create_or_update_setting(
156 plugin.create_or_update_setting(
155 'auth_restriction', RhodeCodeAuthPlugin.AUTH_RESTRICTION_NONE)
157 'auth_restriction', RhodeCodeAuthPlugin.AUTH_RESTRICTION_NONE)
156 Session().commit()
158 Session().commit()
157 SettingsModel().invalidate_settings_cache()
159 SettingsModel().invalidate_settings_cache()
158
160
159 return context()
161 return context()
160
162
161 def scope_restriction(self, registry, scope_restriction):
163 def scope_restriction(self, registry, scope_restriction):
162 """
164 """
163 Context process for changing the builtin rhodecode plugin scope restrictions.
165 Context process for changing the builtin rhodecode plugin scope restrictions.
164 Use like:
166 Use like:
165 fixture = Fixture()
167 fixture = Fixture()
166 with fixture.scope_restriction('scope_http'):
168 with fixture.scope_restriction('scope_http'):
167 #tests
169 #tests
168
170
169 after this block scope restriction will be taken off
171 after this block scope restriction will be taken off
170 """
172 """
171
173
172 class context(object):
174 class context(object):
173 def _get_plugin(self):
175 def _get_plugin(self):
174 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
176 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
175 plugin = RhodeCodeAuthPlugin(plugin_id)
177 plugin = RhodeCodeAuthPlugin(plugin_id)
176 return plugin
178 return plugin
177
179
178 def __enter__(self):
180 def __enter__(self):
179 plugin = self._get_plugin()
181 plugin = self._get_plugin()
180 plugin.create_or_update_setting('scope_restriction', scope_restriction)
182 plugin.create_or_update_setting('scope_restriction', scope_restriction)
181 Session().commit()
183 Session().commit()
182 SettingsModel().invalidate_settings_cache()
184 SettingsModel().invalidate_settings_cache()
183
185
184 def __exit__(self, exc_type, exc_val, exc_tb):
186 def __exit__(self, exc_type, exc_val, exc_tb):
185 plugin = self._get_plugin()
187 plugin = self._get_plugin()
186 plugin.create_or_update_setting(
188 plugin.create_or_update_setting(
187 'scope_restriction', RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_ALL)
189 'scope_restriction', RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_ALL)
188 Session().commit()
190 Session().commit()
189 SettingsModel().invalidate_settings_cache()
191 SettingsModel().invalidate_settings_cache()
190
192
191 return context()
193 return context()
192
194
193 def _get_repo_create_params(self, **custom):
195 def _get_repo_create_params(self, **custom):
194 repo_type = custom.get('repo_type') or 'hg'
196 repo_type = custom.get('repo_type') or 'hg'
195
197
196 default_landing_ref, landing_ref_lbl = ScmModel.backend_landing_ref(repo_type)
198 default_landing_ref, landing_ref_lbl = ScmModel.backend_landing_ref(repo_type)
197
199
198 defs = {
200 defs = {
199 'repo_name': None,
201 'repo_name': None,
200 'repo_type': repo_type,
202 'repo_type': repo_type,
201 'clone_uri': '',
203 'clone_uri': '',
202 'push_uri': '',
204 'push_uri': '',
203 'repo_group': '-1',
205 'repo_group': '-1',
204 'repo_description': 'DESC',
206 'repo_description': 'DESC',
205 'repo_private': False,
207 'repo_private': False,
206 'repo_landing_commit_ref': default_landing_ref,
208 'repo_landing_commit_ref': default_landing_ref,
207 'repo_copy_permissions': False,
209 'repo_copy_permissions': False,
208 'repo_state': Repository.STATE_CREATED,
210 'repo_state': Repository.STATE_CREATED,
209 }
211 }
210 defs.update(custom)
212 defs.update(custom)
211 if 'repo_name_full' not in custom:
213 if 'repo_name_full' not in custom:
212 defs.update({'repo_name_full': defs['repo_name']})
214 defs.update({'repo_name_full': defs['repo_name']})
213
215
214 # fix the repo name if passed as repo_name_full
216 # fix the repo name if passed as repo_name_full
215 if defs['repo_name']:
217 if defs['repo_name']:
216 defs['repo_name'] = defs['repo_name'].split('/')[-1]
218 defs['repo_name'] = defs['repo_name'].split('/')[-1]
217
219
218 return defs
220 return defs
219
221
220 def _get_group_create_params(self, **custom):
222 def _get_group_create_params(self, **custom):
221 defs = {
223 defs = {
222 'group_name': None,
224 'group_name': None,
223 'group_description': 'DESC',
225 'group_description': 'DESC',
224 'perm_updates': [],
226 'perm_updates': [],
225 'perm_additions': [],
227 'perm_additions': [],
226 'perm_deletions': [],
228 'perm_deletions': [],
227 'group_parent_id': -1,
229 'group_parent_id': -1,
228 'enable_locking': False,
230 'enable_locking': False,
229 'recursive': False,
231 'recursive': False,
230 }
232 }
231 defs.update(custom)
233 defs.update(custom)
232
234
233 return defs
235 return defs
234
236
235 def _get_user_create_params(self, name, **custom):
237 def _get_user_create_params(self, name, **custom):
236 defs = {
238 defs = {
237 'username': name,
239 'username': name,
238 'password': 'qweqwe',
240 'password': 'qweqwe',
239 'email': '%s+test@rhodecode.org' % name,
241 'email': '%s+test@rhodecode.org' % name,
240 'firstname': 'TestUser',
242 'firstname': 'TestUser',
241 'lastname': 'Test',
243 'lastname': 'Test',
242 'description': 'test description',
244 'description': 'test description',
243 'active': True,
245 'active': True,
244 'admin': False,
246 'admin': False,
245 'extern_type': 'rhodecode',
247 'extern_type': 'rhodecode',
246 'extern_name': None,
248 'extern_name': None,
247 }
249 }
248 defs.update(custom)
250 defs.update(custom)
249
251
250 return defs
252 return defs
251
253
252 def _get_user_group_create_params(self, name, **custom):
254 def _get_user_group_create_params(self, name, **custom):
253 defs = {
255 defs = {
254 'users_group_name': name,
256 'users_group_name': name,
255 'user_group_description': 'DESC',
257 'user_group_description': 'DESC',
256 'users_group_active': True,
258 'users_group_active': True,
257 'user_group_data': {},
259 'user_group_data': {},
258 }
260 }
259 defs.update(custom)
261 defs.update(custom)
260
262
261 return defs
263 return defs
262
264
263 def create_repo(self, name, **kwargs):
265 def create_repo(self, name, **kwargs):
264 repo_group = kwargs.get('repo_group')
266 repo_group = kwargs.get('repo_group')
265 if isinstance(repo_group, RepoGroup):
267 if isinstance(repo_group, RepoGroup):
266 kwargs['repo_group'] = repo_group.group_id
268 kwargs['repo_group'] = repo_group.group_id
267 name = name.split(Repository.NAME_SEP)[-1]
269 name = name.split(Repository.NAME_SEP)[-1]
268 name = Repository.NAME_SEP.join((repo_group.group_name, name))
270 name = Repository.NAME_SEP.join((repo_group.group_name, name))
269
271
270 if 'skip_if_exists' in kwargs:
272 if 'skip_if_exists' in kwargs:
271 del kwargs['skip_if_exists']
273 del kwargs['skip_if_exists']
272 r = Repository.get_by_repo_name(name)
274 r = Repository.get_by_repo_name(name)
273 if r:
275 if r:
274 return r
276 return r
275
277
276 form_data = self._get_repo_create_params(repo_name=name, **kwargs)
278 form_data = self._get_repo_create_params(repo_name=name, **kwargs)
277 cur_user = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN)
279 cur_user = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN)
278 RepoModel().create(form_data, cur_user)
280 RepoModel().create(form_data, cur_user)
279 Session().commit()
281 Session().commit()
280 repo = Repository.get_by_repo_name(name)
282 repo = Repository.get_by_repo_name(name)
281 assert repo
283 assert repo
282 return repo
284 return repo
283
285
284 def create_fork(self, repo_to_fork, fork_name, **kwargs):
286 def create_fork(self, repo_to_fork, fork_name, **kwargs):
285 repo_to_fork = Repository.get_by_repo_name(repo_to_fork)
287 repo_to_fork = Repository.get_by_repo_name(repo_to_fork)
286
288
287 form_data = self._get_repo_create_params(
289 form_data = self._get_repo_create_params(
288 repo_name=fork_name,
290 repo_name=fork_name,
289 fork_parent_id=repo_to_fork.repo_id,
291 fork_parent_id=repo_to_fork.repo_id,
290 repo_type=repo_to_fork.repo_type,
292 repo_type=repo_to_fork.repo_type,
291 **kwargs)
293 **kwargs)
292
294
293 #TODO: fix it !!
295 #TODO: fix it !!
294 form_data['description'] = form_data['repo_description']
296 form_data['description'] = form_data['repo_description']
295 form_data['private'] = form_data['repo_private']
297 form_data['private'] = form_data['repo_private']
296 form_data['landing_rev'] = form_data['repo_landing_commit_ref']
298 form_data['landing_rev'] = form_data['repo_landing_commit_ref']
297
299
298 owner = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN)
300 owner = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN)
299 RepoModel().create_fork(form_data, cur_user=owner)
301 RepoModel().create_fork(form_data, cur_user=owner)
300 Session().commit()
302 Session().commit()
301 r = Repository.get_by_repo_name(fork_name)
303 r = Repository.get_by_repo_name(fork_name)
302 assert r
304 assert r
303 return r
305 return r
304
306
305 def destroy_repo(self, repo_name, **kwargs):
307 def destroy_repo(self, repo_name, **kwargs):
306 RepoModel().delete(repo_name, pull_requests='delete', **kwargs)
308 RepoModel().delete(repo_name, pull_requests='delete', **kwargs)
307 Session().commit()
309 Session().commit()
308
310
309 def destroy_repo_on_filesystem(self, repo_name):
311 def destroy_repo_on_filesystem(self, repo_name):
310 rm_path = os.path.join(RepoModel().repos_path, repo_name)
312 rm_path = os.path.join(RepoModel().repos_path, repo_name)
311 if os.path.isdir(rm_path):
313 if os.path.isdir(rm_path):
312 shutil.rmtree(rm_path)
314 shutil.rmtree(rm_path)
313
315
314 def create_repo_group(self, name, **kwargs):
316 def create_repo_group(self, name, **kwargs):
315 if 'skip_if_exists' in kwargs:
317 if 'skip_if_exists' in kwargs:
316 del kwargs['skip_if_exists']
318 del kwargs['skip_if_exists']
317 gr = RepoGroup.get_by_group_name(group_name=name)
319 gr = RepoGroup.get_by_group_name(group_name=name)
318 if gr:
320 if gr:
319 return gr
321 return gr
320 form_data = self._get_group_create_params(group_name=name, **kwargs)
322 form_data = self._get_group_create_params(group_name=name, **kwargs)
321 owner = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN)
323 owner = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN)
322 gr = RepoGroupModel().create(
324 gr = RepoGroupModel().create(
323 group_name=form_data['group_name'],
325 group_name=form_data['group_name'],
324 group_description=form_data['group_name'],
326 group_description=form_data['group_name'],
325 owner=owner)
327 owner=owner)
326 Session().commit()
328 Session().commit()
327 gr = RepoGroup.get_by_group_name(gr.group_name)
329 gr = RepoGroup.get_by_group_name(gr.group_name)
328 return gr
330 return gr
329
331
330 def destroy_repo_group(self, repogroupid):
332 def destroy_repo_group(self, repogroupid):
331 RepoGroupModel().delete(repogroupid)
333 RepoGroupModel().delete(repogroupid)
332 Session().commit()
334 Session().commit()
333
335
334 def create_user(self, name, **kwargs):
336 def create_user(self, name, **kwargs):
335 if 'skip_if_exists' in kwargs:
337 if 'skip_if_exists' in kwargs:
336 del kwargs['skip_if_exists']
338 del kwargs['skip_if_exists']
337 user = User.get_by_username(name)
339 user = User.get_by_username(name)
338 if user:
340 if user:
339 return user
341 return user
340 form_data = self._get_user_create_params(name, **kwargs)
342 form_data = self._get_user_create_params(name, **kwargs)
341 user = UserModel().create(form_data)
343 user = UserModel().create(form_data)
342
344
343 # create token for user
345 # create token for user
344 AuthTokenModel().create(
346 AuthTokenModel().create(
345 user=user, description=u'TEST_USER_TOKEN')
347 user=user, description=u'TEST_USER_TOKEN')
346
348
347 Session().commit()
349 Session().commit()
348 user = User.get_by_username(user.username)
350 user = User.get_by_username(user.username)
349 return user
351 return user
350
352
351 def destroy_user(self, userid):
353 def destroy_user(self, userid):
352 UserModel().delete(userid)
354 UserModel().delete(userid)
353 Session().commit()
355 Session().commit()
354
356
355 def create_additional_user_email(self, user, email):
357 def create_additional_user_email(self, user, email):
356 uem = UserEmailMap()
358 uem = UserEmailMap()
357 uem.user = user
359 uem.user = user
358 uem.email = email
360 uem.email = email
359 Session().add(uem)
361 Session().add(uem)
360 return uem
362 return uem
361
363
362 def destroy_users(self, userid_iter):
364 def destroy_users(self, userid_iter):
363 for user_id in userid_iter:
365 for user_id in userid_iter:
364 if User.get_by_username(user_id):
366 if User.get_by_username(user_id):
365 UserModel().delete(user_id)
367 UserModel().delete(user_id)
366 Session().commit()
368 Session().commit()
367
369
368 def create_user_group(self, name, **kwargs):
370 def create_user_group(self, name, **kwargs):
369 if 'skip_if_exists' in kwargs:
371 if 'skip_if_exists' in kwargs:
370 del kwargs['skip_if_exists']
372 del kwargs['skip_if_exists']
371 gr = UserGroup.get_by_group_name(group_name=name)
373 gr = UserGroup.get_by_group_name(group_name=name)
372 if gr:
374 if gr:
373 return gr
375 return gr
374 # map active flag to the real attribute. For API consistency of fixtures
376 # map active flag to the real attribute. For API consistency of fixtures
375 if 'active' in kwargs:
377 if 'active' in kwargs:
376 kwargs['users_group_active'] = kwargs['active']
378 kwargs['users_group_active'] = kwargs['active']
377 del kwargs['active']
379 del kwargs['active']
378 form_data = self._get_user_group_create_params(name, **kwargs)
380 form_data = self._get_user_group_create_params(name, **kwargs)
379 owner = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN)
381 owner = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN)
380 user_group = UserGroupModel().create(
382 user_group = UserGroupModel().create(
381 name=form_data['users_group_name'],
383 name=form_data['users_group_name'],
382 description=form_data['user_group_description'],
384 description=form_data['user_group_description'],
383 owner=owner, active=form_data['users_group_active'],
385 owner=owner, active=form_data['users_group_active'],
384 group_data=form_data['user_group_data'])
386 group_data=form_data['user_group_data'])
385 Session().commit()
387 Session().commit()
386 user_group = UserGroup.get_by_group_name(user_group.users_group_name)
388 user_group = UserGroup.get_by_group_name(user_group.users_group_name)
387 return user_group
389 return user_group
388
390
389 def destroy_user_group(self, usergroupid):
391 def destroy_user_group(self, usergroupid):
390 UserGroupModel().delete(user_group=usergroupid, force=True)
392 UserGroupModel().delete(user_group=usergroupid, force=True)
391 Session().commit()
393 Session().commit()
392
394
393 def create_gist(self, **kwargs):
395 def create_gist(self, **kwargs):
394 form_data = {
396 form_data = {
395 'description': 'new-gist',
397 'description': 'new-gist',
396 'owner': TEST_USER_ADMIN_LOGIN,
398 'owner': TEST_USER_ADMIN_LOGIN,
397 'gist_type': GistModel.cls.GIST_PUBLIC,
399 'gist_type': GistModel.cls.GIST_PUBLIC,
398 'lifetime': -1,
400 'lifetime': -1,
399 'acl_level': Gist.ACL_LEVEL_PUBLIC,
401 'acl_level': Gist.ACL_LEVEL_PUBLIC,
400 'gist_mapping': {'filename1.txt': {'content': 'hello world'},}
402 'gist_mapping': {'filename1.txt': {'content': 'hello world'},}
401 }
403 }
402 form_data.update(kwargs)
404 form_data.update(kwargs)
403 gist = GistModel().create(
405 gist = GistModel().create(
404 description=form_data['description'], owner=form_data['owner'],
406 description=form_data['description'], owner=form_data['owner'],
405 gist_mapping=form_data['gist_mapping'], gist_type=form_data['gist_type'],
407 gist_mapping=form_data['gist_mapping'], gist_type=form_data['gist_type'],
406 lifetime=form_data['lifetime'], gist_acl_level=form_data['acl_level']
408 lifetime=form_data['lifetime'], gist_acl_level=form_data['acl_level']
407 )
409 )
408 Session().commit()
410 Session().commit()
409 return gist
411 return gist
410
412
411 def destroy_gists(self, gistid=None):
413 def destroy_gists(self, gistid=None):
412 for g in GistModel.cls.get_all():
414 for g in GistModel.cls.get_all():
413 if gistid:
415 if gistid:
414 if gistid == g.gist_access_id:
416 if gistid == g.gist_access_id:
415 GistModel().delete(g)
417 GistModel().delete(g)
416 else:
418 else:
417 GistModel().delete(g)
419 GistModel().delete(g)
418 Session().commit()
420 Session().commit()
419
421
420 def load_resource(self, resource_name, strip=False):
422 def load_resource(self, resource_name, strip=False):
421 with open(os.path.join(FIXTURES, resource_name)) as f:
423 with open(os.path.join(FIXTURES, resource_name)) as f:
422 source = f.read()
424 source = f.read()
423 if strip:
425 if strip:
424 source = source.strip()
426 source = source.strip()
425
427
426 return source
428 return source
@@ -1,200 +1,201 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 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 import os
22 import os
23 import time
23 import time
24 import tempfile
24 import tempfile
25 import pytest
25 import pytest
26 import subprocess
26 import subprocess
27 import configobj
28 import logging
27 import logging
29 from urllib.request import urlopen
28 from urllib.request import urlopen
30 from urllib.error import URLError
29 from urllib.error import URLError
31 import configparser
30 import configparser
32
31
33
32
34 from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS
33 from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS
35 from rhodecode.tests.utils import is_url_reachable
34 from rhodecode.tests.utils import is_url_reachable
36
35
37 log = logging.getLogger(__name__)
36 log = logging.getLogger(__name__)
38
37
39
38
40 def get_port(pyramid_config):
39 def get_port(pyramid_config):
41 config = configparser.ConfigParser()
40 config = configparser.ConfigParser()
42 config.read(pyramid_config)
41 config.read(pyramid_config)
43 return config.get('server:main', 'port')
42 return config.get('server:main', 'port')
44
43
45
44
46 def get_host_url(pyramid_config):
45 def get_host_url(pyramid_config):
47 """Construct the host url using the port in the test configuration."""
46 """Construct the host url using the port in the test configuration."""
48 return '127.0.0.1:%s' % get_port(pyramid_config)
47 port = get_port(pyramid_config)
48 return f'127.0.0.1:{port}'
49
49
50
50
51 def assert_no_running_instance(url):
51 def assert_no_running_instance(url):
52 if is_url_reachable(url):
52 if is_url_reachable(url):
53 print("Hint: Usually this means another instance of server "
53 print(f"Hint: Usually this means another instance of server "
54 "is running in the background at %s." % url)
54 f"is running in the background at {url}.")
55 pytest.fail(
55 pytest.fail(f"Port is not free at {url}, cannot start server at")
56 "Port is not free at %s, cannot start server at" % url)
57
56
58
57
59 class ServerBase(object):
58 class ServerBase(object):
60 _args = []
59 _args = []
61 log_file_name = 'NOT_DEFINED.log'
60 log_file_name = 'NOT_DEFINED.log'
62 status_url_tmpl = 'http://{host}:{port}'
61 status_url_tmpl = 'http://{host}:{port}'
63
62
64 def __init__(self, config_file, log_file):
63 def __init__(self, config_file, log_file):
65 self.config_file = config_file
64 self.config_file = config_file
66 config_data = configobj.ConfigObj(config_file)
65 config = configparser.ConfigParser()
67 self._config = config_data['server:main']
66 config.read(config_file)
67
68 self._config = {k: v for k, v in config['server:main'].items()}
68
69
69 self._args = []
70 self._args = []
70 self.log_file = log_file or os.path.join(
71 self.log_file = log_file or os.path.join(
71 tempfile.gettempdir(), self.log_file_name)
72 tempfile.gettempdir(), self.log_file_name)
72 self.process = None
73 self.process = None
73 self.server_out = None
74 self.server_out = None
74 log.info("Using the {} configuration:{}".format(
75 log.info("Using the {} configuration:{}".format(
75 self.__class__.__name__, config_file))
76 self.__class__.__name__, config_file))
76
77
77 if not os.path.isfile(config_file):
78 if not os.path.isfile(config_file):
78 raise RuntimeError('Failed to get config at {}'.format(config_file))
79 raise RuntimeError(f'Failed to get config at {config_file}')
79
80
80 @property
81 @property
81 def command(self):
82 def command(self):
82 return ' '.join(self._args)
83 return ' '.join(self._args)
83
84
84 @property
85 @property
85 def http_url(self):
86 def http_url(self):
86 template = 'http://{host}:{port}/'
87 template = 'http://{host}:{port}/'
87 return template.format(**self._config)
88 return template.format(**self._config)
88
89
89 def host_url(self):
90 def host_url(self):
90 return 'http://' + get_host_url(self.config_file)
91 return 'http://' + get_host_url(self.config_file)
91
92
92 def get_rc_log(self):
93 def get_rc_log(self):
93 with open(self.log_file) as f:
94 with open(self.log_file) as f:
94 return f.read()
95 return f.read()
95
96
96 def wait_until_ready(self, timeout=30):
97 def wait_until_ready(self, timeout=30):
97 host = self._config['host']
98 host = self._config['host']
98 port = self._config['port']
99 port = self._config['port']
99 status_url = self.status_url_tmpl.format(host=host, port=port)
100 status_url = self.status_url_tmpl.format(host=host, port=port)
100 start = time.time()
101 start = time.time()
101
102
102 while time.time() - start < timeout:
103 while time.time() - start < timeout:
103 try:
104 try:
104 urlopen(status_url)
105 urlopen(status_url)
105 break
106 break
106 except URLError:
107 except URLError:
107 time.sleep(0.2)
108 time.sleep(0.2)
108 else:
109 else:
109 pytest.fail(
110 pytest.fail(
110 "Starting the {} failed or took more than {} "
111 "Starting the {} failed or took more than {} "
111 "seconds. cmd: `{}`".format(
112 "seconds. cmd: `{}`".format(
112 self.__class__.__name__, timeout, self.command))
113 self.__class__.__name__, timeout, self.command))
113
114
114 log.info('Server of {} ready at url {}'.format(
115 log.info('Server of {} ready at url {}'.format(
115 self.__class__.__name__, status_url))
116 self.__class__.__name__, status_url))
116
117
117 def shutdown(self):
118 def shutdown(self):
118 self.process.kill()
119 self.process.kill()
119 self.server_out.flush()
120 self.server_out.flush()
120 self.server_out.close()
121 self.server_out.close()
121
122
122 def get_log_file_with_port(self):
123 def get_log_file_with_port(self):
123 log_file = list(self.log_file.partition('.log'))
124 log_file = list(self.log_file.partition('.log'))
124 log_file.insert(1, get_port(self.config_file))
125 log_file.insert(1, get_port(self.config_file))
125 log_file = ''.join(log_file)
126 log_file = ''.join(log_file)
126 return log_file
127 return log_file
127
128
128
129
129 class RcVCSServer(ServerBase):
130 class RcVCSServer(ServerBase):
130 """
131 """
131 Represents a running VCSServer instance.
132 Represents a running VCSServer instance.
132 """
133 """
133
134
134 log_file_name = 'rc-vcsserver.log'
135 log_file_name = 'rc-vcsserver.log'
135 status_url_tmpl = 'http://{host}:{port}/status'
136 status_url_tmpl = 'http://{host}:{port}/status'
136
137
137 def __init__(self, config_file, log_file=None):
138 def __init__(self, config_file, log_file=None):
138 super(RcVCSServer, self).__init__(config_file, log_file)
139 super(RcVCSServer, self).__init__(config_file, log_file)
139 self._args = ['gunicorn', '--paste', self.config_file]
140 self._args = ['gunicorn', '--paste', self.config_file]
140
141
141 def start(self):
142 def start(self):
142 env = os.environ.copy()
143 env = os.environ.copy()
143
144
144 self.log_file = self.get_log_file_with_port()
145 self.log_file = self.get_log_file_with_port()
145 self.server_out = open(self.log_file, 'w')
146 self.server_out = open(self.log_file, 'w')
146
147
147 host_url = self.host_url()
148 host_url = self.host_url()
148 assert_no_running_instance(host_url)
149 assert_no_running_instance(host_url)
149
150
150 log.info('rhodecode-vcsserver start command: {}'.format(' '.join(self._args)))
151 log.info('rhodecode-vcsserver start command: {}'.format(' '.join(self._args)))
151 log.info('rhodecode-vcsserver starting at: {}'.format(host_url))
152 log.info('rhodecode-vcsserver starting at: {}'.format(host_url))
152 log.info('rhodecode-vcsserver command: {}'.format(self.command))
153 log.info('rhodecode-vcsserver command: {}'.format(self.command))
153 log.info('rhodecode-vcsserver logfile: {}'.format(self.log_file))
154 log.info('rhodecode-vcsserver logfile: {}'.format(self.log_file))
154
155
155 self.process = subprocess.Popen(
156 self.process = subprocess.Popen(
156 self._args, bufsize=0, env=env,
157 self._args, bufsize=0, env=env,
157 stdout=self.server_out, stderr=self.server_out)
158 stdout=self.server_out, stderr=self.server_out)
158
159
159
160
160 class RcWebServer(ServerBase):
161 class RcWebServer(ServerBase):
161 """
162 """
162 Represents a running RCE web server used as a test fixture.
163 Represents a running RCE web server used as a test fixture.
163 """
164 """
164
165
165 log_file_name = 'rc-web.log'
166 log_file_name = 'rc-web.log'
166 status_url_tmpl = 'http://{host}:{port}/_admin/ops/ping'
167 status_url_tmpl = 'http://{host}:{port}/_admin/ops/ping'
167
168
168 def __init__(self, config_file, log_file=None):
169 def __init__(self, config_file, log_file=None):
169 super(RcWebServer, self).__init__(config_file, log_file)
170 super(RcWebServer, self).__init__(config_file, log_file)
170 self._args = [
171 self._args = [
171 'gunicorn', '--worker-class', 'gevent', '--paste', config_file]
172 'gunicorn', '--worker-class', 'gevent', '--paste', config_file]
172
173
173 def start(self):
174 def start(self):
174 env = os.environ.copy()
175 env = os.environ.copy()
175 env['RC_NO_TMP_PATH'] = '1'
176 env['RC_NO_TMP_PATH'] = '1'
176
177
177 self.log_file = self.get_log_file_with_port()
178 self.log_file = self.get_log_file_with_port()
178 self.server_out = open(self.log_file, 'w')
179 self.server_out = open(self.log_file, 'w')
179
180
180 host_url = self.host_url()
181 host_url = self.host_url()
181 assert_no_running_instance(host_url)
182 assert_no_running_instance(host_url)
182
183
183 log.info('rhodecode-web starting at: {}'.format(host_url))
184 log.info('rhodecode-web starting at: {}'.format(host_url))
184 log.info('rhodecode-web command: {}'.format(self.command))
185 log.info('rhodecode-web command: {}'.format(self.command))
185 log.info('rhodecode-web logfile: {}'.format(self.log_file))
186 log.info('rhodecode-web logfile: {}'.format(self.log_file))
186
187
187 self.process = subprocess.Popen(
188 self.process = subprocess.Popen(
188 self._args, bufsize=0, env=env,
189 self._args, bufsize=0, env=env,
189 stdout=self.server_out, stderr=self.server_out)
190 stdout=self.server_out, stderr=self.server_out)
190
191
191 def repo_clone_url(self, repo_name, **kwargs):
192 def repo_clone_url(self, repo_name, **kwargs):
192 params = {
193 params = {
193 'user': TEST_USER_ADMIN_LOGIN,
194 'user': TEST_USER_ADMIN_LOGIN,
194 'passwd': TEST_USER_ADMIN_PASS,
195 'passwd': TEST_USER_ADMIN_PASS,
195 'host': get_host_url(self.config_file),
196 'host': get_host_url(self.config_file),
196 'cloned_repo': repo_name,
197 'cloned_repo': repo_name,
197 }
198 }
198 params.update(**kwargs)
199 params.update(**kwargs)
199 _url = 'http://%(user)s:%(passwd)s@%(host)s/%(cloned_repo)s' % params
200 _url = 'http://%(user)s:%(passwd)s@%(host)s/%(cloned_repo)s' % params
200 return _url
201 return _url
@@ -1,208 +1,208 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 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 # Import early to make sure things are patched up properly
21 # Import early to make sure things are patched up properly
22 from setuptools import setup, find_packages
22 from setuptools import setup, find_packages
23
23
24 import os
24 import os
25 import re
25 import re
26 import sys
26 import sys
27 import pkgutil
27 import pkgutil
28 import platform
28 import platform
29 import codecs
29 import codecs
30
30
31 import pip
31 import pip
32
32
33 pip_major_version = int(pip.__version__.split(".")[0])
33 pip_major_version = int(pip.__version__.split(".")[0])
34 if pip_major_version >= 20:
34 if pip_major_version >= 20:
35 from pip._internal.req import parse_requirements
35 from pip._internal.req import parse_requirements
36 from pip._internal.network.session import PipSession
36 from pip._internal.network.session import PipSession
37 elif pip_major_version >= 10:
37 elif pip_major_version >= 10:
38 from pip._internal.req import parse_requirements
38 from pip._internal.req import parse_requirements
39 from pip._internal.download import PipSession
39 from pip._internal.download import PipSession
40 else:
40 else:
41 from pip.req import parse_requirements
41 from pip.req import parse_requirements
42 from pip.download import PipSession
42 from pip.download import PipSession
43
43
44
44
45 def get_package_name(req_object):
45 def get_package_name(req_object):
46 package_name = None
46 package_name = None
47 try:
47 try:
48 from pip._internal.req.constructors import install_req_from_parsed_requirement
48 from pip._internal.req.constructors import install_req_from_parsed_requirement
49 except ImportError:
49 except ImportError:
50 install_req_from_parsed_requirement = None
50 install_req_from_parsed_requirement = None
51
51
52 # In 20.1 of pip, the requirements object changed
52 # In 20.1 of pip, the requirements object changed
53 if hasattr(req_object, 'req'):
53 if hasattr(req_object, 'req'):
54 package_name = req_object.req.name
54 package_name = req_object.req.name
55
55
56 if package_name is None:
56 if package_name is None:
57 if install_req_from_parsed_requirement:
57 if install_req_from_parsed_requirement:
58 package = install_req_from_parsed_requirement(req_object)
58 package = install_req_from_parsed_requirement(req_object)
59 package_name = package.req.name
59 package_name = package.req.name
60
60
61 if package_name is None:
61 if package_name is None:
62 # fallback for older pip
62 # fallback for older pip
63 package_name = re.split('===|<=|!=|==|>=|~=|<|>', req_object.requirement)[0]
63 package_name = re.split('===|<=|!=|==|>=|~=|<|>', req_object.requirement)[0]
64
64
65 return package_name
65 return package_name
66
66
67
67
68 if sys.version_info < (3, 10):
68 if sys.version_info < (3, 10):
69 raise Exception('RhodeCode requires Python 3.10 or later')
69 raise Exception('RhodeCode requires Python 3.10 or later')
70
70
71 here = os.path.abspath(os.path.dirname(__file__))
71 here = os.path.abspath(os.path.dirname(__file__))
72
72
73 # defines current platform
73 # defines current platform
74 __platform__ = platform.system()
74 __platform__ = platform.system()
75 __license__ = 'AGPLv3, and Commercial License'
75 __license__ = 'AGPLv3, and Commercial License'
76 __author__ = 'RhodeCode GmbH'
76 __author__ = 'RhodeCode GmbH'
77 __url__ = 'https://code.rhodecode.com'
77 __url__ = 'https://code.rhodecode.com'
78 is_windows = __platform__ in ('Windows',)
78 is_windows = __platform__ in ('Windows',)
79
79
80
80
81 def _get_requirements(req_filename, exclude=None, extras=None):
81 def _get_requirements(req_filename, exclude=None, extras=None):
82 extras = extras or []
82 extras = extras or []
83 exclude = exclude or []
83 exclude = exclude or []
84
84
85 try:
85 try:
86 parsed = parse_requirements(
86 parsed = parse_requirements(
87 os.path.join(here, req_filename), session=PipSession())
87 os.path.join(here, req_filename), session=PipSession())
88 except TypeError:
88 except TypeError:
89 # try pip < 6.0.0, that doesn't support session
89 # try pip < 6.0.0, that doesn't support session
90 parsed = parse_requirements(os.path.join(here, req_filename))
90 parsed = parse_requirements(os.path.join(here, req_filename))
91
91
92 requirements = []
92 requirements = []
93 for int_req in parsed:
93 for int_req in parsed:
94 req_name = get_package_name(int_req)
94 req_name = get_package_name(int_req)
95 if req_name not in exclude:
95 if req_name not in exclude:
96 requirements.append(req_name)
96 requirements.append(req_name)
97 return requirements + extras
97 return requirements + extras
98
98
99
99
100 # requirements extract
100 # requirements extract
101 setup_requirements = ['PasteScript']
101 setup_requirements = ['PasteScript']
102 install_requirements = _get_requirements(
102 install_requirements = _get_requirements(
103 'requirements.txt', exclude=['setuptools', 'entrypoints'])
103 'requirements.txt', exclude=['setuptools', 'entrypoints'])
104 test_requirements = _get_requirements(
104 test_requirements = _get_requirements(
105 'requirements_test.txt', extras=['configobj'])
105 'requirements_test.txt')
106
106
107
107
108 def get_version():
108 def get_version():
109 version = pkgutil.get_data('rhodecode', 'VERSION')
109 version = pkgutil.get_data('rhodecode', 'VERSION')
110 return version.decode().strip()
110 return version.decode().strip()
111
111
112
112
113 # additional files that goes into package itself
113 # additional files that goes into package itself
114 package_data = {
114 package_data = {
115 '': ['*.txt', '*.rst'],
115 '': ['*.txt', '*.rst'],
116 'configs': ['*.ini'],
116 'configs': ['*.ini'],
117 'rhodecode': ['VERSION', 'i18n/*/LC_MESSAGES/*.mo', ],
117 'rhodecode': ['VERSION', 'i18n/*/LC_MESSAGES/*.mo', ],
118 }
118 }
119
119
120 description = 'Source Code Management Platform'
120 description = 'Source Code Management Platform'
121 keywords = ' '.join([
121 keywords = ' '.join([
122 'rhodecode', 'mercurial', 'git', 'svn',
122 'rhodecode', 'mercurial', 'git', 'svn',
123 'code review',
123 'code review',
124 'repo groups', 'ldap', 'repository management', 'hgweb',
124 'repo groups', 'ldap', 'repository management', 'hgweb',
125 'hgwebdir', 'gitweb', 'serving hgweb',
125 'hgwebdir', 'gitweb', 'serving hgweb',
126 ])
126 ])
127
127
128
128
129 # README/DESCRIPTION generation
129 # README/DESCRIPTION generation
130 readme_file = 'README.rst'
130 readme_file = 'README.rst'
131 changelog_file = 'CHANGES.rst'
131 changelog_file = 'CHANGES.rst'
132 try:
132 try:
133 long_description = codecs.open(readme_file).read() + '\n\n' + \
133 long_description = codecs.open(readme_file).read() + '\n\n' + \
134 codecs.open(changelog_file).read()
134 codecs.open(changelog_file).read()
135 except IOError as err:
135 except IOError as err:
136 sys.stderr.write(
136 sys.stderr.write(
137 "[WARNING] Cannot find file specified as long_description (%s)\n "
137 "[WARNING] Cannot find file specified as long_description (%s)\n "
138 "or changelog (%s) skipping that file" % (readme_file, changelog_file))
138 "or changelog (%s) skipping that file" % (readme_file, changelog_file))
139 long_description = description
139 long_description = description
140
140
141
141
142 setup(
142 setup(
143 name='rhodecode-enterprise-ce',
143 name='rhodecode-enterprise-ce',
144 version=get_version(),
144 version=get_version(),
145 description=description,
145 description=description,
146 long_description=long_description,
146 long_description=long_description,
147 keywords=keywords,
147 keywords=keywords,
148 license=__license__,
148 license=__license__,
149 author=__author__,
149 author=__author__,
150 author_email='support@rhodecode.com',
150 author_email='support@rhodecode.com',
151 url=__url__,
151 url=__url__,
152 setup_requires=setup_requirements,
152 setup_requires=setup_requirements,
153 install_requires=install_requirements,
153 install_requires=install_requirements,
154 tests_require=test_requirements,
154 tests_require=test_requirements,
155 zip_safe=False,
155 zip_safe=False,
156 packages=find_packages(exclude=["docs", "tests*"]),
156 packages=find_packages(exclude=["docs", "tests*"]),
157 package_data=package_data,
157 package_data=package_data,
158 include_package_data=True,
158 include_package_data=True,
159 classifiers=[
159 classifiers=[
160 'Development Status :: 6 - Mature',
160 'Development Status :: 6 - Mature',
161 'Environment :: Web Environment',
161 'Environment :: Web Environment',
162 'Intended Audience :: Developers',
162 'Intended Audience :: Developers',
163 'Operating System :: OS Independent',
163 'Operating System :: OS Independent',
164 'Topic :: Software Development :: Version Control',
164 'Topic :: Software Development :: Version Control',
165 'License :: OSI Approved :: Affero GNU General Public License v3 or later (AGPLv3+)',
165 'License :: OSI Approved :: Affero GNU General Public License v3 or later (AGPLv3+)',
166 'Programming Language :: Python :: 3.10',
166 'Programming Language :: Python :: 3.10',
167 ],
167 ],
168 message_extractors={
168 message_extractors={
169 'rhodecode': [
169 'rhodecode': [
170 ('**.py', 'python', None),
170 ('**.py', 'python', None),
171 ('**.js', 'javascript', None),
171 ('**.js', 'javascript', None),
172 ('templates/**.mako', 'mako', {'input_encoding': 'utf-8'}),
172 ('templates/**.mako', 'mako', {'input_encoding': 'utf-8'}),
173 ('templates/**.html', 'mako', {'input_encoding': 'utf-8'}),
173 ('templates/**.html', 'mako', {'input_encoding': 'utf-8'}),
174 ('public/**', 'ignore', None),
174 ('public/**', 'ignore', None),
175 ]
175 ]
176 },
176 },
177 paster_plugins=['PasteScript'],
177 paster_plugins=['PasteScript'],
178 entry_points={
178 entry_points={
179 'paste.app_factory': [
179 'paste.app_factory': [
180 'main=rhodecode.config.middleware:make_pyramid_app',
180 'main=rhodecode.config.middleware:make_pyramid_app',
181 ],
181 ],
182 'paste.global_paster_command': [
182 'paste.global_paster_command': [
183 'ishell=rhodecode.lib.paster_commands.ishell:Command',
183 'ishell=rhodecode.lib.paster_commands.ishell:Command',
184 'upgrade-db=rhodecode.lib.paster_commands.upgrade_db:UpgradeDb',
184 'upgrade-db=rhodecode.lib.paster_commands.upgrade_db:UpgradeDb',
185
185
186 'setup-rhodecode=rhodecode.lib.paster_commands.deprecated.setup_rhodecode:Command',
186 'setup-rhodecode=rhodecode.lib.paster_commands.deprecated.setup_rhodecode:Command',
187 'celeryd=rhodecode.lib.paster_commands.deprecated.celeryd:Command',
187 'celeryd=rhodecode.lib.paster_commands.deprecated.celeryd:Command',
188 ],
188 ],
189 'pyramid.pshell_runner': [
189 'pyramid.pshell_runner': [
190 'ipython = rhodecode.lib.pyramid_shell:ipython_shell_runner',
190 'ipython = rhodecode.lib.pyramid_shell:ipython_shell_runner',
191 ],
191 ],
192 'pytest11': [
192 'pytest11': [
193 'pylons=rhodecode.tests.pylons_plugin',
193 'pylons=rhodecode.tests.pylons_plugin',
194 'enterprise=rhodecode.tests.plugin',
194 'enterprise=rhodecode.tests.plugin',
195 ],
195 ],
196 'console_scripts': [
196 'console_scripts': [
197 'rc-setup-app=rhodecode.lib.rc_commands.setup_rc:main',
197 'rc-setup-app=rhodecode.lib.rc_commands.setup_rc:main',
198 'rc-upgrade-db=rhodecode.lib.rc_commands.upgrade_db:main',
198 'rc-upgrade-db=rhodecode.lib.rc_commands.upgrade_db:main',
199 'rc-ishell=rhodecode.lib.rc_commands.ishell:main',
199 'rc-ishell=rhodecode.lib.rc_commands.ishell:main',
200 'rc-add-artifact=rhodecode.lib.rc_commands.add_artifact:main',
200 'rc-add-artifact=rhodecode.lib.rc_commands.add_artifact:main',
201 'rc-ssh-wrapper=rhodecode.apps.ssh_support.lib.ssh_wrapper:main',
201 'rc-ssh-wrapper=rhodecode.apps.ssh_support.lib.ssh_wrapper:main',
202 ],
202 ],
203 'beaker.backends': [
203 'beaker.backends': [
204 'memorylru_base=rhodecode.lib.memory_lru_dict:MemoryLRUNamespaceManagerBase',
204 'memorylru_base=rhodecode.lib.memory_lru_dict:MemoryLRUNamespaceManagerBase',
205 'memorylru_debug=rhodecode.lib.memory_lru_dict:MemoryLRUNamespaceManagerDebug'
205 'memorylru_debug=rhodecode.lib.memory_lru_dict:MemoryLRUNamespaceManagerDebug'
206 ]
206 ]
207 },
207 },
208 )
208 )
General Comments 0
You need to be logged in to leave comments. Login now