##// END OF EJS Templates
Removed config names from whoosh and celery,...
marcink -
r483:a9e50dce celery
parent child Browse files
Show More
@@ -1,33 +1,45 b''
1 # List of modules to import when celery starts.
1 # List of modules to import when celery starts.
2 import sys
2 import sys
3 import os
3 import os
4 import ConfigParser
5
6 PYLONS_CONFIG_NAME = 'test.ini'
7
8 root = os.getcwd()
9 config = ConfigParser.ConfigParser({'here':root})
10 config.read('%s/%s' % (root, PYLONS_CONFIG_NAME))
11 PYLONS_CONFIG = config
12
13
14 print config.items('app:main')
15
4 sys.path.append(os.getcwd())
16 sys.path.append(os.getcwd())
5 CELERY_IMPORTS = ("pylons_app.lib.celerylib.tasks", )
17 CELERY_IMPORTS = ("pylons_app.lib.celerylib.tasks",)
6
18
7 ## Result store settings.
19 ## Result store settings.
8 CELERY_RESULT_BACKEND = "database"
20 CELERY_RESULT_BACKEND = "database"
9 CELERY_RESULT_DBURI = "sqlite:///hg_app.db"
21 CELERY_RESULT_DBURI = "sqlite:///hg_app.db"
10
22
11 BROKER_CONNECTION_MAX_RETRIES = 30
23 BROKER_CONNECTION_MAX_RETRIES = 30
12
24
13 ## Broker settings.
25 ## Broker settings.
14 BROKER_HOST = "localhost"
26 BROKER_HOST = "localhost"
15 BROKER_PORT = 5672
27 BROKER_PORT = 5672
16 BROKER_VHOST = "rabbitmqhost"
28 BROKER_VHOST = "rabbitmqhost"
17 BROKER_USER = "rabbitmq"
29 BROKER_USER = "rabbitmq"
18 BROKER_PASSWORD = "qweqwe"
30 BROKER_PASSWORD = "qweqwe"
19
31
20 ## Worker settings
32 ## Worker settings
21 ## If you're doing mostly I/O you can have more processes,
33 ## If you're doing mostly I/O you can have more processes,
22 ## but if mostly spending CPU, try to keep it close to the
34 ## but if mostly spending CPU, try to keep it close to the
23 ## number of CPUs on your machine. If not set, the number of CPUs/cores
35 ## number of CPUs on your machine. If not set, the number of CPUs/cores
24 ## available will be used.
36 ## available will be used.
25 CELERYD_CONCURRENCY = 2
37 CELERYD_CONCURRENCY = 2
26 # CELERYD_LOG_FILE = "celeryd.log"
38 # CELERYD_LOG_FILE = "celeryd.log"
27 CELERYD_LOG_LEVEL = "DEBUG"
39 CELERYD_LOG_LEVEL = "DEBUG"
28 CELERYD_MAX_TASKS_PER_CHILD = 1
40 CELERYD_MAX_TASKS_PER_CHILD = 1
29
41
30 #CELERY_ALWAYS_EAGER = True
42 #CELERY_ALWAYS_EAGER = True
31 #rabbitmqctl add_user rabbitmq qweqwe
43 #rabbitmqctl add_user rabbitmq qweqwe
32 #rabbitmqctl add_vhost rabbitmqhost
44 #rabbitmqctl add_vhost rabbitmqhost
33 #rabbitmqctl set_permissions -p rabbitmqhost rabbitmq ".*" ".*" ".*" No newline at end of file
45 #rabbitmqctl set_permissions -p rabbitmqhost rabbitmq ".*" ".*" ".*"
@@ -1,215 +1,208 b''
1 from celery.decorators import task
1 from celery.decorators import task
2 from celery.task.sets import subtask
2 from celery.task.sets import subtask
3 from celeryconfig import PYLONS_CONFIG as config
3 from datetime import datetime, timedelta
4 from datetime import datetime, timedelta
4 from os.path import dirname as dn
5 from pylons.i18n.translation import _
5 from pylons.i18n.translation import _
6 from pylons_app.lib.celerylib import run_task
6 from pylons_app.lib.celerylib import run_task
7 from pylons_app.lib.helpers import person
7 from pylons_app.lib.helpers import person
8 from pylons_app.lib.smtp_mailer import SmtpMailer
8 from pylons_app.lib.smtp_mailer import SmtpMailer
9 from pylons_app.lib.utils import OrderedDict
9 from pylons_app.lib.utils import OrderedDict
10 from time import mktime
10 from time import mktime
11 from vcs.backends.hg import MercurialRepository
11 from vcs.backends.hg import MercurialRepository
12 import ConfigParser
13 import calendar
12 import calendar
14 import os
15 import traceback
13 import traceback
16
14
17
18 root = dn(dn(dn(dn(os.path.realpath(__file__)))))
19 config = ConfigParser.ConfigParser({'here':root})
20 config.read('%s/development.ini' % root)
21
22 __all__ = ['whoosh_index', 'get_commits_stats',
15 __all__ = ['whoosh_index', 'get_commits_stats',
23 'reset_user_password', 'send_email']
16 'reset_user_password', 'send_email']
24
17
25 def get_session():
18 def get_session():
26 from sqlalchemy import engine_from_config
19 from sqlalchemy import engine_from_config
27 from sqlalchemy.orm import sessionmaker, scoped_session
20 from sqlalchemy.orm import sessionmaker, scoped_session
28 engine = engine_from_config(dict(config.items('app:main')), 'sqlalchemy.db1.')
21 engine = engine_from_config(dict(config.items('app:main')), 'sqlalchemy.db1.')
29 sa = scoped_session(sessionmaker(bind=engine))
22 sa = scoped_session(sessionmaker(bind=engine))
30 return sa
23 return sa
31
24
32 def get_hg_settings():
25 def get_hg_settings():
33 from pylons_app.model.db import HgAppSettings
26 from pylons_app.model.db import HgAppSettings
34 try:
27 try:
35 sa = get_session()
28 sa = get_session()
36 ret = sa.query(HgAppSettings).all()
29 ret = sa.query(HgAppSettings).all()
37 finally:
30 finally:
38 sa.remove()
31 sa.remove()
39
32
40 if not ret:
33 if not ret:
41 raise Exception('Could not get application settings !')
34 raise Exception('Could not get application settings !')
42 settings = {}
35 settings = {}
43 for each in ret:
36 for each in ret:
44 settings['hg_app_' + each.app_settings_name] = each.app_settings_value
37 settings['hg_app_' + each.app_settings_name] = each.app_settings_value
45
38
46 return settings
39 return settings
47
40
48 def get_hg_ui_settings():
41 def get_hg_ui_settings():
49 from pylons_app.model.db import HgAppUi
42 from pylons_app.model.db import HgAppUi
50 try:
43 try:
51 sa = get_session()
44 sa = get_session()
52 ret = sa.query(HgAppUi).all()
45 ret = sa.query(HgAppUi).all()
53 finally:
46 finally:
54 sa.remove()
47 sa.remove()
55
48
56 if not ret:
49 if not ret:
57 raise Exception('Could not get application ui settings !')
50 raise Exception('Could not get application ui settings !')
58 settings = {}
51 settings = {}
59 for each in ret:
52 for each in ret:
60 k = each.ui_key
53 k = each.ui_key
61 v = each.ui_value
54 v = each.ui_value
62 if k == '/':
55 if k == '/':
63 k = 'root_path'
56 k = 'root_path'
64
57
65 if k.find('.') != -1:
58 if k.find('.') != -1:
66 k = k.replace('.', '_')
59 k = k.replace('.', '_')
67
60
68 if each.ui_section == 'hooks':
61 if each.ui_section == 'hooks':
69 v = each.ui_active
62 v = each.ui_active
70
63
71 settings[each.ui_section + '_' + k] = v
64 settings[each.ui_section + '_' + k] = v
72
65
73 return settings
66 return settings
74
67
75 @task
68 @task
76 def whoosh_index(repo_location, full_index):
69 def whoosh_index(repo_location, full_index):
77 log = whoosh_index.get_logger()
70 log = whoosh_index.get_logger()
78 from pylons_app.lib.indexers import DaemonLock
71 from pylons_app.lib.indexers import DaemonLock
79 from pylons_app.lib.indexers.daemon import WhooshIndexingDaemon, LockHeld
72 from pylons_app.lib.indexers.daemon import WhooshIndexingDaemon, LockHeld
80 try:
73 try:
81 l = DaemonLock()
74 l = DaemonLock()
82 WhooshIndexingDaemon(repo_location=repo_location)\
75 WhooshIndexingDaemon(repo_location=repo_location)\
83 .run(full_index=full_index)
76 .run(full_index=full_index)
84 l.release()
77 l.release()
85 return 'Done'
78 return 'Done'
86 except LockHeld:
79 except LockHeld:
87 log.info('LockHeld')
80 log.info('LockHeld')
88 return 'LockHeld'
81 return 'LockHeld'
89
82
90 @task
83 @task
91 def get_commits_stats(repo):
84 def get_commits_stats(repo):
92 log = get_commits_stats.get_logger()
85 log = get_commits_stats.get_logger()
93 aggregate = OrderedDict()
86 aggregate = OrderedDict()
94 repos_path = get_hg_ui_settings()['paths_root_path'].replace('*','')
87 repos_path = get_hg_ui_settings()['paths_root_path'].replace('*', '')
95 repo = MercurialRepository(repos_path + repo)
88 repo = MercurialRepository(repos_path + repo)
96 #graph range
89 #graph range
97 td = datetime.today() + timedelta(days=1)
90 td = datetime.today() + timedelta(days=1)
98 y, m, d = td.year, td.month, td.day
91 y, m, d = td.year, td.month, td.day
99 ts_min = mktime((y, (td - timedelta(days=calendar.mdays[m])).month,
92 ts_min = mktime((y, (td - timedelta(days=calendar.mdays[m])).month,
100 d, 0, 0, 0, 0, 0, 0,))
93 d, 0, 0, 0, 0, 0, 0,))
101 ts_max = mktime((y, m, d, 0, 0, 0, 0, 0, 0,))
94 ts_max = mktime((y, m, d, 0, 0, 0, 0, 0, 0,))
102
95
103 def author_key_cleaner(k):
96 def author_key_cleaner(k):
104 k = person(k)
97 k = person(k)
105 k = k.replace('"', "'") #for js data compatibilty
98 k = k.replace('"', "'") #for js data compatibilty
106 return k
99 return k
107
100
108 for cs in repo[:200]:#added limit 200 until fix #29 is made
101 for cs in repo[:200]:#added limit 200 until fix #29 is made
109 k = '%s-%s-%s' % (cs.date.timetuple()[0], cs.date.timetuple()[1],
102 k = '%s-%s-%s' % (cs.date.timetuple()[0], cs.date.timetuple()[1],
110 cs.date.timetuple()[2])
103 cs.date.timetuple()[2])
111 timetupple = [int(x) for x in k.split('-')]
104 timetupple = [int(x) for x in k.split('-')]
112 timetupple.extend([0 for _ in xrange(6)])
105 timetupple.extend([0 for _ in xrange(6)])
113 k = mktime(timetupple)
106 k = mktime(timetupple)
114 if aggregate.has_key(author_key_cleaner(cs.author)):
107 if aggregate.has_key(author_key_cleaner(cs.author)):
115 if aggregate[author_key_cleaner(cs.author)].has_key(k):
108 if aggregate[author_key_cleaner(cs.author)].has_key(k):
116 aggregate[author_key_cleaner(cs.author)][k]["commits"] += 1
109 aggregate[author_key_cleaner(cs.author)][k]["commits"] += 1
117 aggregate[author_key_cleaner(cs.author)][k]["added"] += len(cs.added)
110 aggregate[author_key_cleaner(cs.author)][k]["added"] += len(cs.added)
118 aggregate[author_key_cleaner(cs.author)][k]["changed"] += len(cs.changed)
111 aggregate[author_key_cleaner(cs.author)][k]["changed"] += len(cs.changed)
119 aggregate[author_key_cleaner(cs.author)][k]["removed"] += len(cs.removed)
112 aggregate[author_key_cleaner(cs.author)][k]["removed"] += len(cs.removed)
120
113
121 else:
114 else:
122 #aggregate[author_key_cleaner(cs.author)].update(dates_range)
115 #aggregate[author_key_cleaner(cs.author)].update(dates_range)
123 if k >= ts_min and k <= ts_max:
116 if k >= ts_min and k <= ts_max:
124 aggregate[author_key_cleaner(cs.author)][k] = {}
117 aggregate[author_key_cleaner(cs.author)][k] = {}
125 aggregate[author_key_cleaner(cs.author)][k]["commits"] = 1
118 aggregate[author_key_cleaner(cs.author)][k]["commits"] = 1
126 aggregate[author_key_cleaner(cs.author)][k]["added"] = len(cs.added)
119 aggregate[author_key_cleaner(cs.author)][k]["added"] = len(cs.added)
127 aggregate[author_key_cleaner(cs.author)][k]["changed"] = len(cs.changed)
120 aggregate[author_key_cleaner(cs.author)][k]["changed"] = len(cs.changed)
128 aggregate[author_key_cleaner(cs.author)][k]["removed"] = len(cs.removed)
121 aggregate[author_key_cleaner(cs.author)][k]["removed"] = len(cs.removed)
129
122
130 else:
123 else:
131 if k >= ts_min and k <= ts_max:
124 if k >= ts_min and k <= ts_max:
132 aggregate[author_key_cleaner(cs.author)] = OrderedDict()
125 aggregate[author_key_cleaner(cs.author)] = OrderedDict()
133 #aggregate[author_key_cleaner(cs.author)].update(dates_range)
126 #aggregate[author_key_cleaner(cs.author)].update(dates_range)
134 aggregate[author_key_cleaner(cs.author)][k] = {}
127 aggregate[author_key_cleaner(cs.author)][k] = {}
135 aggregate[author_key_cleaner(cs.author)][k]["commits"] = 1
128 aggregate[author_key_cleaner(cs.author)][k]["commits"] = 1
136 aggregate[author_key_cleaner(cs.author)][k]["added"] = len(cs.added)
129 aggregate[author_key_cleaner(cs.author)][k]["added"] = len(cs.added)
137 aggregate[author_key_cleaner(cs.author)][k]["changed"] = len(cs.changed)
130 aggregate[author_key_cleaner(cs.author)][k]["changed"] = len(cs.changed)
138 aggregate[author_key_cleaner(cs.author)][k]["removed"] = len(cs.removed)
131 aggregate[author_key_cleaner(cs.author)][k]["removed"] = len(cs.removed)
139
132
140 d = ''
133 d = ''
141 tmpl0 = u""""%s":%s"""
134 tmpl0 = u""""%s":%s"""
142 tmpl1 = u"""{label:"%s",data:%s,schema:["commits"]},"""
135 tmpl1 = u"""{label:"%s",data:%s,schema:["commits"]},"""
143 for author in aggregate:
136 for author in aggregate:
144
137
145 d += tmpl0 % (author,
138 d += tmpl0 % (author,
146 tmpl1 \
139 tmpl1 \
147 % (author,
140 % (author,
148 [{"time":x,
141 [{"time":x,
149 "commits":aggregate[author][x]['commits'],
142 "commits":aggregate[author][x]['commits'],
150 "added":aggregate[author][x]['added'],
143 "added":aggregate[author][x]['added'],
151 "changed":aggregate[author][x]['changed'],
144 "changed":aggregate[author][x]['changed'],
152 "removed":aggregate[author][x]['removed'],
145 "removed":aggregate[author][x]['removed'],
153 } for x in aggregate[author]]))
146 } for x in aggregate[author]]))
154 if d == '':
147 if d == '':
155 d = '"%s":{label:"%s",data:[[0,1],]}' \
148 d = '"%s":{label:"%s",data:[[0,1],]}' \
156 % (author_key_cleaner(repo.contact),
149 % (author_key_cleaner(repo.contact),
157 author_key_cleaner(repo.contact))
150 author_key_cleaner(repo.contact))
158 return (ts_min, ts_max, d)
151 return (ts_min, ts_max, d)
159
152
160 @task
153 @task
161 def reset_user_password(user_email):
154 def reset_user_password(user_email):
162 log = reset_user_password.get_logger()
155 log = reset_user_password.get_logger()
163 from pylons_app.lib import auth
156 from pylons_app.lib import auth
164 from pylons_app.model.db import User
157 from pylons_app.model.db import User
165
158
166 try:
159 try:
167
160
168 try:
161 try:
169 sa = get_session()
162 sa = get_session()
170 user = sa.query(User).filter(User.email == user_email).scalar()
163 user = sa.query(User).filter(User.email == user_email).scalar()
171 new_passwd = auth.PasswordGenerator().gen_password(8,
164 new_passwd = auth.PasswordGenerator().gen_password(8,
172 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
165 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
173 user.password = auth.get_crypt_password(new_passwd)
166 user.password = auth.get_crypt_password(new_passwd)
174 sa.add(user)
167 sa.add(user)
175 sa.commit()
168 sa.commit()
176 log.info('change password for %s', user_email)
169 log.info('change password for %s', user_email)
177 if new_passwd is None:
170 if new_passwd is None:
178 raise Exception('unable to generate new password')
171 raise Exception('unable to generate new password')
179
172
180 except:
173 except:
181 log.error(traceback.format_exc())
174 log.error(traceback.format_exc())
182 sa.rollback()
175 sa.rollback()
183
176
184 run_task(send_email, user_email,
177 run_task(send_email, user_email,
185 "Your new hg-app password",
178 "Your new hg-app password",
186 'Your new hg-app password:%s' % (new_passwd))
179 'Your new hg-app password:%s' % (new_passwd))
187 log.info('send new password mail to %s', user_email)
180 log.info('send new password mail to %s', user_email)
188
181
189
182
190 except:
183 except:
191 log.error('Failed to update user password')
184 log.error('Failed to update user password')
192 log.error(traceback.format_exc())
185 log.error(traceback.format_exc())
193 return True
186 return True
194
187
195 @task
188 @task
196 def send_email(recipients, subject, body):
189 def send_email(recipients, subject, body):
197 log = send_email.get_logger()
190 log = send_email.get_logger()
198 email_config = dict(config.items('DEFAULT'))
191 email_config = dict(config.items('DEFAULT'))
199 mail_from = email_config.get('app_email_from')
192 mail_from = email_config.get('app_email_from')
200 user = email_config.get('smtp_username')
193 user = email_config.get('smtp_username')
201 passwd = email_config.get('smtp_password')
194 passwd = email_config.get('smtp_password')
202 mail_server = email_config.get('smtp_server')
195 mail_server = email_config.get('smtp_server')
203 mail_port = email_config.get('smtp_port')
196 mail_port = email_config.get('smtp_port')
204 tls = email_config.get('smtp_use_tls')
197 tls = email_config.get('smtp_use_tls')
205 ssl = False
198 ssl = False
206
199
207 try:
200 try:
208 m = SmtpMailer(mail_from, user, passwd, mail_server,
201 m = SmtpMailer(mail_from, user, passwd, mail_server,
209 mail_port, ssl, tls)
202 mail_port, ssl, tls)
210 m.send(recipients, subject, body)
203 m.send(recipients, subject, body)
211 except:
204 except:
212 log.error('Mail sending failed')
205 log.error('Mail sending failed')
213 log.error(traceback.format_exc())
206 log.error(traceback.format_exc())
214 return False
207 return False
215 return True
208 return True
@@ -1,226 +1,238 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # whoosh indexer daemon for hg-app
3 # whoosh indexer daemon for hg-app
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on Jan 26, 2010
21 Created on Jan 26, 2010
22
22
23 @author: marcink
23 @author: marcink
24 A deamon will read from task table and run tasks
24 A deamon will read from task table and run tasks
25 """
25 """
26 import sys
26 import sys
27 import os
27 import os
28 from os.path import dirname as dn
28 from os.path import dirname as dn
29 from os.path import join as jn
29 from os.path import join as jn
30
30
31 #to get the pylons_app import
31 #to get the pylons_app import
32 project_path = dn(dn(dn(dn(os.path.realpath(__file__)))))
32 project_path = dn(dn(dn(dn(os.path.realpath(__file__)))))
33 sys.path.append(project_path)
33 sys.path.append(project_path)
34
34
35 from pidlock import LockHeld, DaemonLock
35 from pidlock import LockHeld, DaemonLock
36 import traceback
37 from pylons_app.config.environment import load_environment
38 from pylons_app.model.hg_model import HgModel
36 from pylons_app.model.hg_model import HgModel
39 from pylons_app.lib.helpers import safe_unicode
37 from pylons_app.lib.helpers import safe_unicode
40 from whoosh.index import create_in, open_dir
38 from whoosh.index import create_in, open_dir
41 from shutil import rmtree
39 from shutil import rmtree
42 from pylons_app.lib.indexers import ANALYZER, INDEX_EXTENSIONS, IDX_LOCATION, \
40 from pylons_app.lib.indexers import INDEX_EXTENSIONS, IDX_LOCATION, SCHEMA, IDX_NAME
43 SCHEMA, IDX_NAME
44
41
45 import logging
42 import logging
46 import logging.config
43
47 logging.config.fileConfig(jn(project_path, 'development.ini'))
48 log = logging.getLogger('whooshIndexer')
44 log = logging.getLogger('whooshIndexer')
45 # create logger
46 log.setLevel(logging.DEBUG)
47
48 # create console handler and set level to debug
49 ch = logging.StreamHandler()
50 ch.setLevel(logging.DEBUG)
51
52 # create formatter
53 formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
54
55 # add formatter to ch
56 ch.setFormatter(formatter)
57
58 # add ch to logger
59 log.addHandler(ch)
49
60
50 def scan_paths(root_location):
61 def scan_paths(root_location):
51 return HgModel.repo_scan('/', root_location, None, True)
62 return HgModel.repo_scan('/', root_location, None, True)
52
63
53 class WhooshIndexingDaemon(object):
64 class WhooshIndexingDaemon(object):
54 """Deamon for atomic jobs"""
65 """Deamon for atomic jobs"""
55
66
56 def __init__(self, indexname='HG_INDEX', repo_location=None):
67 def __init__(self, indexname='HG_INDEX', repo_location=None):
57 self.indexname = indexname
68 self.indexname = indexname
58 self.repo_location = repo_location
69 self.repo_location = repo_location
59 self.initial = False
70 self.initial = False
60 if not os.path.isdir(IDX_LOCATION):
71 if not os.path.isdir(IDX_LOCATION):
61 os.mkdir(IDX_LOCATION)
72 os.mkdir(IDX_LOCATION)
62 log.info('Cannot run incremental index since it does not'
73 log.info('Cannot run incremental index since it does not'
63 ' yet exist running full build')
74 ' yet exist running full build')
64 self.initial = True
75 self.initial = True
65
76
66 def get_paths(self, root_dir):
77 def get_paths(self, root_dir):
67 """recursive walk in root dir and return a set of all path in that dir
78 """recursive walk in root dir and return a set of all path in that dir
68 excluding files in .hg dir"""
79 excluding files in .hg dir"""
69 index_paths_ = set()
80 index_paths_ = set()
70 for path, dirs, files in os.walk(root_dir):
81 for path, dirs, files in os.walk(root_dir):
71 if path.find('.hg') == -1:
82 if path.find('.hg') == -1:
72 for f in files:
83 for f in files:
73 index_paths_.add(jn(path, f))
84 index_paths_.add(jn(path, f))
74
85
75 return index_paths_
86 return index_paths_
76
87
77 def add_doc(self, writer, path, repo):
88 def add_doc(self, writer, path, repo):
78 """Adding doc to writer"""
89 """Adding doc to writer"""
79
90
80 ext = unicode(path.split('/')[-1].split('.')[-1].lower())
91 ext = unicode(path.split('/')[-1].split('.')[-1].lower())
81 #we just index the content of choosen files
92 #we just index the content of choosen files
82 if ext in INDEX_EXTENSIONS:
93 if ext in INDEX_EXTENSIONS:
83 log.debug(' >> %s [WITH CONTENT]' % path)
94 log.debug(' >> %s [WITH CONTENT]' % path)
84 fobj = open(path, 'rb')
95 fobj = open(path, 'rb')
85 content = fobj.read()
96 content = fobj.read()
86 fobj.close()
97 fobj.close()
87 u_content = safe_unicode(content)
98 u_content = safe_unicode(content)
88 else:
99 else:
89 log.debug(' >> %s' % path)
100 log.debug(' >> %s' % path)
90 #just index file name without it's content
101 #just index file name without it's content
91 u_content = u''
102 u_content = u''
92
103
93
104
94
105
95 try:
106 try:
96 os.stat(path)
107 os.stat(path)
97 writer.add_document(owner=unicode(repo.contact),
108 writer.add_document(owner=unicode(repo.contact),
98 repository=u"%s" % repo.name,
109 repository=u"%s" % repo.name,
99 path=u"%s" % path,
110 path=u"%s" % path,
100 content=u_content,
111 content=u_content,
101 modtime=os.path.getmtime(path),
112 modtime=os.path.getmtime(path),
102 extension=ext)
113 extension=ext)
103 except OSError, e:
114 except OSError, e:
104 import errno
115 import errno
105 if e.errno == errno.ENOENT:
116 if e.errno == errno.ENOENT:
106 log.debug('path %s does not exist or is a broken symlink' % path)
117 log.debug('path %s does not exist or is a broken symlink' % path)
107 else:
118 else:
108 raise e
119 raise e
109
120
110
121
111 def build_index(self):
122 def build_index(self):
112 if os.path.exists(IDX_LOCATION):
123 if os.path.exists(IDX_LOCATION):
113 log.debug('removing previos index')
124 log.debug('removing previos index')
114 rmtree(IDX_LOCATION)
125 rmtree(IDX_LOCATION)
115
126
116 if not os.path.exists(IDX_LOCATION):
127 if not os.path.exists(IDX_LOCATION):
117 os.mkdir(IDX_LOCATION)
128 os.mkdir(IDX_LOCATION)
118
129
119 idx = create_in(IDX_LOCATION, SCHEMA, indexname=IDX_NAME)
130 idx = create_in(IDX_LOCATION, SCHEMA, indexname=IDX_NAME)
120 writer = idx.writer()
131 writer = idx.writer()
121
132
122 for cnt, repo in enumerate(scan_paths(self.repo_location).values()):
133 for cnt, repo in enumerate(scan_paths(self.repo_location).values()):
123 log.debug('building index @ %s' % repo.path)
134 log.debug('building index @ %s' % repo.path)
124
135
125 for idx_path in self.get_paths(repo.path):
136 for idx_path in self.get_paths(repo.path):
126 self.add_doc(writer, idx_path, repo)
137 self.add_doc(writer, idx_path, repo)
127 writer.commit(merge=True)
138 writer.commit(merge=True)
128
139
129 log.debug('>>> FINISHED BUILDING INDEX <<<')
140 log.debug('>>> FINISHED BUILDING INDEX <<<')
130
141
131
142
132 def update_index(self):
143 def update_index(self):
133 log.debug('STARTING INCREMENTAL INDEXING UPDATE')
144 log.debug('STARTING INCREMENTAL INDEXING UPDATE')
134
145
135 idx = open_dir(IDX_LOCATION, indexname=self.indexname)
146 idx = open_dir(IDX_LOCATION, indexname=self.indexname)
136 # The set of all paths in the index
147 # The set of all paths in the index
137 indexed_paths = set()
148 indexed_paths = set()
138 # The set of all paths we need to re-index
149 # The set of all paths we need to re-index
139 to_index = set()
150 to_index = set()
140
151
141 reader = idx.reader()
152 reader = idx.reader()
142 writer = idx.writer()
153 writer = idx.writer()
143
154
144 # Loop over the stored fields in the index
155 # Loop over the stored fields in the index
145 for fields in reader.all_stored_fields():
156 for fields in reader.all_stored_fields():
146 indexed_path = fields['path']
157 indexed_path = fields['path']
147 indexed_paths.add(indexed_path)
158 indexed_paths.add(indexed_path)
148
159
149 if not os.path.exists(indexed_path):
160 if not os.path.exists(indexed_path):
150 # This file was deleted since it was indexed
161 # This file was deleted since it was indexed
151 log.debug('removing from index %s' % indexed_path)
162 log.debug('removing from index %s' % indexed_path)
152 writer.delete_by_term('path', indexed_path)
163 writer.delete_by_term('path', indexed_path)
153
164
154 else:
165 else:
155 # Check if this file was changed since it
166 # Check if this file was changed since it
156 # was indexed
167 # was indexed
157 indexed_time = fields['modtime']
168 indexed_time = fields['modtime']
158
169
159 mtime = os.path.getmtime(indexed_path)
170 mtime = os.path.getmtime(indexed_path)
160
171
161 if mtime > indexed_time:
172 if mtime > indexed_time:
162
173
163 # The file has changed, delete it and add it to the list of
174 # The file has changed, delete it and add it to the list of
164 # files to reindex
175 # files to reindex
165 log.debug('adding to reindex list %s' % indexed_path)
176 log.debug('adding to reindex list %s' % indexed_path)
166 writer.delete_by_term('path', indexed_path)
177 writer.delete_by_term('path', indexed_path)
167 to_index.add(indexed_path)
178 to_index.add(indexed_path)
168 #writer.commit()
179 #writer.commit()
169
180
170 # Loop over the files in the filesystem
181 # Loop over the files in the filesystem
171 # Assume we have a function that gathers the filenames of the
182 # Assume we have a function that gathers the filenames of the
172 # documents to be indexed
183 # documents to be indexed
173 for repo in scan_paths(self.repo_location).values():
184 for repo in scan_paths(self.repo_location).values():
174 for path in self.get_paths(repo.path):
185 for path in self.get_paths(repo.path):
175 if path in to_index or path not in indexed_paths:
186 if path in to_index or path not in indexed_paths:
176 # This is either a file that's changed, or a new file
187 # This is either a file that's changed, or a new file
177 # that wasn't indexed before. So index it!
188 # that wasn't indexed before. So index it!
178 self.add_doc(writer, path, repo)
189 self.add_doc(writer, path, repo)
179 log.debug('reindexing %s' % path)
190 log.debug('reindexing %s' % path)
180
191
181 writer.commit(merge=True)
192 writer.commit(merge=True)
182 #idx.optimize()
193 #idx.optimize()
183 log.debug('>>> FINISHED <<<')
194 log.debug('>>> FINISHED <<<')
184
195
185 def run(self, full_index=False):
196 def run(self, full_index=False):
186 """Run daemon"""
197 """Run daemon"""
187 if full_index or self.initial:
198 if full_index or self.initial:
188 self.build_index()
199 self.build_index()
189 else:
200 else:
190 self.update_index()
201 self.update_index()
191
202
192 if __name__ == "__main__":
203 if __name__ == "__main__":
193 arg = sys.argv[1:]
204 arg = sys.argv[1:]
194 if len(arg) != 2:
205 if len(arg) != 2:
195 sys.stderr.write('Please specify indexing type [full|incremental]'
206 sys.stderr.write('Please specify indexing type [full|incremental]'
196 'and path to repositories as script args \n')
207 'and path to repositories as script args \n')
197 sys.exit()
208 sys.exit()
198
209
199
210
200 if arg[0] == 'full':
211 if arg[0] == 'full':
201 full_index = True
212 full_index = True
202 elif arg[0] == 'incremental':
213 elif arg[0] == 'incremental':
203 # False means looking just for changes
214 # False means looking just for changes
204 full_index = False
215 full_index = False
205 else:
216 else:
206 sys.stdout.write('Please use [full|incremental]'
217 sys.stdout.write('Please use [full|incremental]'
207 ' as script first arg \n')
218 ' as script first arg \n')
208 sys.exit()
219 sys.exit()
209
220
210 if not os.path.isdir(arg[1]):
221 if not os.path.isdir(arg[1]):
211 sys.stderr.write('%s is not a valid path \n' % arg[1])
222 sys.stderr.write('%s is not a valid path \n' % arg[1])
212 sys.exit()
223 sys.exit()
213 else:
224 else:
214 if arg[1].endswith('/'):
225 if arg[1].endswith('/'):
215 repo_location = arg[1] + '*'
226 repo_location = arg[1] + '*'
216 else:
227 else:
217 repo_location = arg[1] + '/*'
228 repo_location = arg[1] + '/*'
218
229
219 try:
230 try:
220 l = DaemonLock()
231 l = DaemonLock()
221 WhooshIndexingDaemon(repo_location=repo_location)\
232 WhooshIndexingDaemon(repo_location=repo_location)\
222 .run(full_index=full_index)
233 .run(full_index=full_index)
223 l.release()
234 l.release()
235 reload(logging)
224 except LockHeld:
236 except LockHeld:
225 sys.exit(1)
237 sys.exit(1)
226
238
@@ -1,49 +1,70 b''
1 """Pylons application test package
1 """Pylons application test package
2
2
3 This package assumes the Pylons environment is already loaded, such as
3 This package assumes the Pylons environment is already loaded, such as
4 when this script is imported from the `nosetests --with-pylons=test.ini`
4 when this script is imported from the `nosetests --with-pylons=test.ini`
5 command.
5 command.
6
6
7 This module initializes the application via ``websetup`` (`paster
7 This module initializes the application via ``websetup`` (`paster
8 setup-app`) and provides the base testing objects.
8 setup-app`) and provides the base testing objects.
9 """
9 """
10 from unittest import TestCase
10 from unittest import TestCase
11
11
12 from paste.deploy import loadapp
12 from paste.deploy import loadapp
13 from paste.script.appinstall import SetupCommand
13 from paste.script.appinstall import SetupCommand
14 from pylons import config, url
14 from pylons import config, url
15 from routes.util import URLGenerator
15 from routes.util import URLGenerator
16 from webtest import TestApp
16 from webtest import TestApp
17 import os
17 import os
18 from pylons_app.model import meta
18 from pylons_app.model import meta
19 from pylons_app.lib.indexers import IDX_LOCATION
19 import logging
20 import logging
21 import shutil
20 log = logging.getLogger(__name__)
22 log = logging.getLogger(__name__)
21
23
22 import pylons.test
24 import pylons.test
23
25
24 __all__ = ['environ', 'url', 'TestController']
26 __all__ = ['environ', 'url', 'TestController']
25
27
26 # Invoke websetup with the current config file
28 # Invoke websetup with the current config file
27 #SetupCommand('setup-app').run([pylons.test.pylonsapp.config['__file__']])
29 #SetupCommand('setup-app').run([pylons.test.pylonsapp.config['__file__']])
30 def create_index(repo_location, full_index):
31 from pylons_app.lib.indexers import daemon
32 from pylons_app.lib.indexers.daemon import WhooshIndexingDaemon
33 from pylons_app.lib.indexers.pidlock import DaemonLock, LockHeld
34
35 try:
36 l = DaemonLock()
37 WhooshIndexingDaemon(repo_location=repo_location)\
38 .run(full_index=full_index)
39 l.release()
40 except LockHeld:
41 pass
42
43 if os.path.exists(IDX_LOCATION):
44 shutil.rmtree(IDX_LOCATION)
45
46 create_index('/tmp/*', True)
28
47
29 environ = {}
48 environ = {}
30
49
31 class TestController(TestCase):
50 class TestController(TestCase):
32
51
33 def __init__(self, *args, **kwargs):
52 def __init__(self, *args, **kwargs):
34 wsgiapp = pylons.test.pylonsapp
53 wsgiapp = pylons.test.pylonsapp
35 config = wsgiapp.config
54 config = wsgiapp.config
36 self.app = TestApp(wsgiapp)
55 self.app = TestApp(wsgiapp)
37 url._push_object(URLGenerator(config['routes.map'], environ))
56 url._push_object(URLGenerator(config['routes.map'], environ))
38 self.sa = meta.Session
57 self.sa = meta.Session
58
39 TestCase.__init__(self, *args, **kwargs)
59 TestCase.__init__(self, *args, **kwargs)
40
60
41
61
42 def log_user(self):
62 def log_user(self):
43 response = self.app.post(url(controller='login', action='index'),
63 response = self.app.post(url(controller='login', action='index'),
44 {'username':'test_admin',
64 {'username':'test_admin',
45 'password':'test'})
65 'password':'test'})
46 assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
66 assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
47 assert response.session['hg_app_user'].username == 'test_admin', 'wrong logged in user'
67 assert response.session['hg_app_user'].username == 'test_admin', 'wrong logged in user'
48 return response.follow()
68 return response.follow()
49 No newline at end of file
69
70
@@ -1,139 +1,139 b''
1 from pylons_app.tests import *
1 from pylons_app.tests import *
2 from pylons_app.model.db import User
2 from pylons_app.model.db import User
3 from pylons_app.lib.auth import check_password
3 from pylons_app.lib.auth import check_password
4
4
5
5
6 class TestLoginController(TestController):
6 class TestLoginController(TestController):
7
7
8 def test_index(self):
8 def test_index(self):
9 response = self.app.get(url(controller='login', action='index'))
9 response = self.app.get(url(controller='login', action='index'))
10 assert response.status == '200 OK', 'Wrong response from login page got %s' % response.status
10 assert response.status == '200 OK', 'Wrong response from login page got %s' % response.status
11 # Test response...
11 # Test response...
12
12
13 def test_login_admin_ok(self):
13 def test_login_admin_ok(self):
14 response = self.app.post(url(controller='login', action='index'),
14 response = self.app.post(url(controller='login', action='index'),
15 {'username':'test_admin',
15 {'username':'test_admin',
16 'password':'test'})
16 'password':'test'})
17 assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
17 assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
18 assert response.session['hg_app_user'].username == 'test_admin', 'wrong logged in user'
18 assert response.session['hg_app_user'].username == 'test_admin', 'wrong logged in user'
19 response = response.follow()
19 response = response.follow()
20 assert 'auto description for vcs_test' in response.body
20 assert 'auto description for vcs_test' in response.body
21
21
22 def test_login_regular_ok(self):
22 def test_login_regular_ok(self):
23 response = self.app.post(url(controller='login', action='index'),
23 response = self.app.post(url(controller='login', action='index'),
24 {'username':'test_regular',
24 {'username':'test_regular',
25 'password':'test'})
25 'password':'test'})
26 assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
26 assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
27 assert response.session['hg_app_user'].username == 'test_regular', 'wrong logged in user'
27 assert response.session['hg_app_user'].username == 'test_regular', 'wrong logged in user'
28 response = response.follow()
28 response = response.follow()
29 assert 'auto description for vcs_test' in response.body
29 assert 'auto description for vcs_test' in response.body
30 assert '<a title="Admin" href="/_admin">' not in response.body
30 assert '<a title="Admin" href="/_admin">' not in response.body
31
31
32 def test_login_ok_came_from(self):
32 def test_login_ok_came_from(self):
33 test_came_from = '/_admin/users'
33 test_came_from = '/_admin/users'
34 response = self.app.post(url(controller='login', action='index', came_from=test_came_from),
34 response = self.app.post(url(controller='login', action='index', came_from=test_came_from),
35 {'username':'test_admin',
35 {'username':'test_admin',
36 'password':'test'})
36 'password':'test'})
37 assert response.status == '302 Found', 'Wrong response code from came from redirection'
37 assert response.status == '302 Found', 'Wrong response code from came from redirection'
38 response = response.follow()
38 response = response.follow()
39
39
40 assert response.status == '200 OK', 'Wrong response from login page got %s' % response.status
40 assert response.status == '200 OK', 'Wrong response from login page got %s' % response.status
41 assert 'Users administration' in response.body, 'No proper title in response'
41 assert 'Users administration' in response.body, 'No proper title in response'
42
42
43
43
44 def test_login_wrong(self):
44 def test_login_wrong(self):
45 response = self.app.post(url(controller='login', action='index'),
45 response = self.app.post(url(controller='login', action='index'),
46 {'username':'error',
46 {'username':'error',
47 'password':'test'})
47 'password':'test'})
48 assert response.status == '200 OK', 'Wrong response from login page'
48 assert response.status == '200 OK', 'Wrong response from login page'
49
49
50 assert 'invalid user name' in response.body, 'No error username message in response'
50 assert 'invalid user name' in response.body, 'No error username message in response'
51 assert 'invalid password' in response.body, 'No error password message in response'
51 assert 'invalid password' in response.body, 'No error password message in response'
52
52
53
53
54 def test_register(self):
54 def test_register(self):
55 response = self.app.get(url(controller='login', action='register'))
55 response = self.app.get(url(controller='login', action='register'))
56 assert 'Sign Up to hg-app' in response.body, 'wrong page for user registration'
56 assert 'Sign Up to hg-app' in response.body, 'wrong page for user registration'
57
57
58 def test_register_err_same_username(self):
58 def test_register_err_same_username(self):
59 response = self.app.post(url(controller='login', action='register'),
59 response = self.app.post(url(controller='login', action='register'),
60 {'username':'test_admin',
60 {'username':'test_admin',
61 'password':'test',
61 'password':'test',
62 'email':'goodmail@domain.com',
62 'email':'goodmail@domain.com',
63 'name':'test',
63 'name':'test',
64 'lastname':'test'})
64 'lastname':'test'})
65
65
66 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
66 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
67 assert 'This username already exists' in response.body
67 assert 'This username already exists' in response.body
68
68
69 def test_register_err_wrong_data(self):
69 def test_register_err_wrong_data(self):
70 response = self.app.post(url(controller='login', action='register'),
70 response = self.app.post(url(controller='login', action='register'),
71 {'username':'xs',
71 {'username':'xs',
72 'password':'',
72 'password':'',
73 'email':'goodmailm',
73 'email':'goodmailm',
74 'name':'test',
74 'name':'test',
75 'lastname':'test'})
75 'lastname':'test'})
76
76
77 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
77 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
78 assert 'An email address must contain a single @' in response.body
78 assert 'An email address must contain a single @' in response.body
79 assert 'Enter a value 3 characters long or more' in response.body
79 assert 'Enter a value 3 characters long or more' in response.body
80 assert 'Please enter a value<' in response.body
80 assert 'Please enter a value<' in response.body
81
81
82
82
83
83
84 def test_register_ok(self):
84 def test_register_ok(self):
85 username = 'test_regular4'
85 username = 'test_regular4'
86 password = 'qweqwe'
86 password = 'qweqwe'
87 email = 'marcin@somemail.com'
87 email = 'marcin@test.com'
88 name = 'testname'
88 name = 'testname'
89 lastname = 'testlastname'
89 lastname = 'testlastname'
90
90
91 response = self.app.post(url(controller='login', action='register'),
91 response = self.app.post(url(controller='login', action='register'),
92 {'username':username,
92 {'username':username,
93 'password':password,
93 'password':password,
94 'email':email,
94 'email':email,
95 'name':name,
95 'name':name,
96 'lastname':lastname})
96 'lastname':lastname})
97 print response.body
97 print response.body
98 assert response.status == '302 Found', 'Wrong response from register page got %s' % response.status
98 assert response.status == '302 Found', 'Wrong response from register page got %s' % response.status
99 assert 'You have successfully registered into hg-app' in response.session['flash'][0], 'No flash message about user registration'
99 assert 'You have successfully registered into hg-app' in response.session['flash'][0], 'No flash message about user registration'
100
100
101 ret = self.sa.query(User).filter(User.username == 'test_regular4').one()
101 ret = self.sa.query(User).filter(User.username == 'test_regular4').one()
102 assert ret.username == username , 'field mismatch %s %s' % (ret.username, username)
102 assert ret.username == username , 'field mismatch %s %s' % (ret.username, username)
103 assert check_password(password,ret.password) == True , 'password mismatch'
103 assert check_password(password, ret.password) == True , 'password mismatch'
104 assert ret.email == email , 'field mismatch %s %s' % (ret.email, email)
104 assert ret.email == email , 'field mismatch %s %s' % (ret.email, email)
105 assert ret.name == name , 'field mismatch %s %s' % (ret.name, name)
105 assert ret.name == name , 'field mismatch %s %s' % (ret.name, name)
106 assert ret.lastname == lastname , 'field mismatch %s %s' % (ret.lastname, lastname)
106 assert ret.lastname == lastname , 'field mismatch %s %s' % (ret.lastname, lastname)
107
107
108
108
109 def test_forgot_password_wrong_mail(self):
109 def test_forgot_password_wrong_mail(self):
110 response = self.app.post(url(controller='login', action='password_reset'),
110 response = self.app.post(url(controller='login', action='password_reset'),
111 {'email':'marcin@wrongmail.org',})
111 {'email':'marcin@wrongmail.org', })
112
112
113 assert "That e-mail address doesn't exist" in response.body,'Missing error message about wrong email'
113 assert "That e-mail address doesn't exist" in response.body, 'Missing error message about wrong email'
114
114
115 def test_forgot_password(self):
115 def test_forgot_password(self):
116 response = self.app.get(url(controller='login', action='password_reset'))
116 response = self.app.get(url(controller='login', action='password_reset'))
117 assert response.status == '200 OK', 'Wrong response from login page got %s' % response.status
117 assert response.status == '200 OK', 'Wrong response from login page got %s' % response.status
118
118
119 username = 'test_password_reset_1'
119 username = 'test_password_reset_1'
120 password = 'qweqwe'
120 password = 'qweqwe'
121 email = 'marcin@python-works.com'
121 email = 'marcin@python-works.com'
122 name = 'passwd'
122 name = 'passwd'
123 lastname = 'reset'
123 lastname = 'reset'
124
124
125 response = self.app.post(url(controller='login', action='register'),
125 response = self.app.post(url(controller='login', action='register'),
126 {'username':username,
126 {'username':username,
127 'password':password,
127 'password':password,
128 'email':email,
128 'email':email,
129 'name':name,
129 'name':name,
130 'lastname':lastname})
130 'lastname':lastname})
131 #register new user for email test
131 #register new user for email test
132 response = self.app.post(url(controller='login', action='password_reset'),
132 response = self.app.post(url(controller='login', action='password_reset'),
133 {'email':email,})
133 {'email':email, })
134 print response.session['flash']
134 print response.session['flash']
135 assert 'You have successfully registered into hg-app' in response.session['flash'][0], 'No flash message about user registration'
135 assert 'You have successfully registered into hg-app' in response.session['flash'][0], 'No flash message about user registration'
136 assert 'Your new password was sent' in response.session['flash'][1], 'No flash message about password reset'
136 assert 'Your new password was sent' in response.session['flash'][1], 'No flash message about password reset'
137
137
138
138
139
139
@@ -1,29 +1,38 b''
1 from pylons_app.tests import *
1 from pylons_app.tests import *
2 from pylons_app.lib.indexers import IDX_LOCATION
2 from pylons_app.lib.indexers import IDX_LOCATION
3 import os
3 import os
4 from nose.plugins.skip import SkipTest
4 from nose.plugins.skip import SkipTest
5
5
6 class TestSearchController(TestController):
6 class TestSearchController(TestController):
7
7
8 def test_index(self):
8 def test_index(self):
9 self.log_user()
9 self.log_user()
10 response = self.app.get(url(controller='search', action='index'))
10 response = self.app.get(url(controller='search', action='index'))
11 print response.body
11 print response.body
12 assert 'class="small" id="q" name="q" type="text"' in response.body,'Search box content error'
12 assert 'class="small" id="q" name="q" type="text"' in response.body, 'Search box content error'
13 # Test response...
13 # Test response...
14
14
15 def test_empty_search(self):
15 def test_empty_search(self):
16
16
17 if os.path.isdir(IDX_LOCATION):
17 if os.path.isdir(IDX_LOCATION):
18 raise SkipTest('skipped due to existing index')
18 raise SkipTest('skipped due to existing index')
19 else:
19 else:
20 self.log_user()
20 self.log_user()
21 response = self.app.get(url(controller='search', action='index'),{'q':'vcs_test'})
21 response = self.app.get(url(controller='search', action='index'), {'q':'vcs_test'})
22 assert 'There is no index to search in. Please run whoosh indexer' in response.body,'No error message about empty index'
22 assert 'There is no index to search in. Please run whoosh indexer' in response.body, 'No error message about empty index'
23
23
24 def test_normal_search(self):
24 def test_normal_search(self):
25 self.log_user()
25 self.log_user()
26 response = self.app.get(url(controller='search', action='index'),{'q':'def+repo'})
26 response = self.app.get(url(controller='search', action='index'), {'q':'def repo'})
27 print response.body
27 print response.body
28 assert '9 results' in response.body,'no message about proper search results'
28 assert '10 results' in response.body, 'no message about proper search results'
29 assert 'Permission denied' not in response.body, 'Wrong permissions settings for that repo and user'
29
30
31
32 def test_repo_search(self):
33 self.log_user()
34 response = self.app.get(url(controller='search', action='index'), {'q':'repository:vcs_test def test'})
35 print response.body
36 assert '4 results' in response.body, 'no message about proper search results'
37 assert 'Permission denied' not in response.body, 'Wrong permissions settings for that repo and user'
38
General Comments 0
You need to be logged in to leave comments. Login now