[IMP] use the openerp namespace.
[odoo/odoo.git] / openerp / addons / base_quality_interrogation.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #    
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.     
19 #
20 ##############################################################################
21
22 import xmlrpclib
23 import ConfigParser
24 import optparse
25 import sys
26 import thread
27 import threading
28 import os
29 import time
30 import pickle
31 import base64
32 import socket
33
34 admin_passwd = 'admin'
35 waittime = 10
36 wait_count = 0
37 wait_limit = 12
38
39 def to_decode(s):
40     try:
41         return s.encode('utf-8')
42     except UnicodeError:
43         try:
44             return s.encode('latin')
45         except UnicodeError:
46             try:
47                 return s.decode('ascii')
48             except UnicodeError:
49                 return s
50
51 def start_server(root_path, port, netport, addons_path):
52     os.system('python2.5 %sopenerp-server  --pidfile=openerp.pid  --no-xmlrpcs --xmlrpc-port=%s --netrpc-port=%s --addons-path=%s' %(root_path, str(port),str(netport),addons_path))
53 def clean():
54     if os.path.isfile('openerp.pid'):
55         ps = open('openerp.pid')
56         if ps:
57             pid = int(ps.read())
58             ps.close()
59             if pid:
60                 os.kill(pid,9)
61
62 def execute(connector, method, *args):
63     global wait_count
64     res = False
65     try:
66         res = getattr(connector,method)(*args)
67     except socket.error,e:
68         if e.args[0] == 111:
69             if wait_count > wait_limit:
70                 print "Server is taking too long to start, it has exceeded the maximum limit of %d seconds."%(wait_limit)
71                 clean()
72                 sys.exit(1)
73             print 'Please wait %d sec to start server....'%(waittime)
74             wait_count += 1
75             time.sleep(waittime)
76             res = execute(connector, method, *args)
77         else:
78             raise e
79     wait_count = 0
80     return res
81
82 def login(uri, dbname, user, pwd):
83     conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/common')
84     uid = execute(conn,'login',dbname, user, pwd)
85     return uid
86
87 def import_translate(uri, user, pwd, dbname, translate_in):
88     uid = login(uri, dbname, user, pwd)
89     if uid:
90         conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
91         wiz_id = execute(conn,'create',dbname, uid, pwd, 'base.language.import')
92         for trans_in in translate_in:
93             lang,ext = os.path.splitext(trans_in.split('/')[-1])
94             state = 'init'
95             datas = {'form':{}}
96             while state!='end':
97                 res = execute(conn,'execute',dbname, uid, pwd, wiz_id, datas, state, {})
98                 if 'datas' in res:
99                     datas['form'].update( res['datas'].get('form',{}) )
100                 if res['type']=='form':
101                     for field in res['fields'].keys():
102                         datas['form'][field] = res['fields'][field].get('value', False)
103                     state = res['state'][-1][0]
104                     trans_obj = open(trans_in)
105                     datas['form'].update({
106                         'name': lang,
107                         'code': lang,
108                         'data' : base64.encodestring(trans_obj.read())
109                     })
110                     trans_obj.close()
111                 elif res['type']=='action':
112                     state = res['state']
113
114
115 def check_quality(uri, user, pwd, dbname, modules, quality_logs):
116     uid = login(uri, dbname, user, pwd)
117     quality_logs += 'quality-logs'
118     if uid:
119         conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
120         final = {}
121         for module in modules:
122             qualityresult = {}
123             test_detail = {}
124             quality_result = execute(conn,'execute', dbname, uid, pwd,'module.quality.check','check_quality',module)
125             detail_html = ''
126             html = '''<html><body><a name="TOP"></a>'''
127             html +="<h1> Module: %s </h1>"%(quality_result['name'])
128             html += "<h2> Final score: %s</h2>"%(quality_result['final_score'])
129             html += "<div id='tabs'>"
130             html += "<ul>"
131             for x,y,detail in quality_result['check_detail_ids']:
132                 test = detail.get('name')
133                 msg = detail.get('message','')
134                 score = round(float(detail.get('score',0)),2)
135                 html += "<li><a href=\"#%s\">%s</a></li>"%(test.replace(' ','-'),test)
136                 detail_html +='''<div id=\"%s\"><h3>%s (Score : %s)</h3><font color=red><h5>%s</h5></font>%s</div>'''%(test.replace(' ', '-'), test, score, msg, detail.get('detail', ''))
137                 test_detail[test] = (score,msg,detail.get('detail',''))
138             html += "</ul>"
139             html += "%s"%(detail_html)
140             html += "</div></body></html>"
141             if not os.path.isdir(quality_logs):
142                 os.mkdir(quality_logs)
143             fp = open('%s/%s.html'%(quality_logs,module),'wb')
144             fp.write(to_decode(html))
145             fp.close()
146             #final[quality_result['name']] = (quality_result['final_score'],html,test_detail)
147
148         #fp = open('quality_log.pck','wb')
149         #pck_obj = pickle.dump(final,fp)
150         #fp.close()
151         #print "LOG PATH%s"%(os.path.realpath('quality_log.pck'))
152         return True
153     else:
154         print 'Login Failed...'
155         clean()
156         sys.exit(1)
157
158
159
160 def wait(id,url=''):
161     progress=0.0
162     sock2 = xmlrpclib.ServerProxy(url+'/xmlrpc/db')
163     while not progress==1.0:
164         progress,users = execute(sock2,'get_progress',admin_passwd, id)
165     return True
166
167
168 def create_db(uri, dbname, user='admin', pwd='admin', lang='en_US'):
169     conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/db')
170     obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
171     wiz_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
172     login_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/common')
173     db_list = execute(conn, 'list')
174     if dbname in db_list:
175         drop_db(uri, dbname)
176     id = execute(conn,'create',admin_passwd, dbname, True, lang)
177     wait(id,uri)    
178     install_module(uri, dbname, ['base_module_quality'],user=user,pwd=pwd)
179     return True
180
181 def drop_db(uri, dbname):
182     conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/db')
183     db_list = execute(conn,'list')
184     if dbname in db_list:
185         execute(conn, 'drop', admin_passwd, dbname)
186     return True
187
188 def make_links(uri, uid, dbname, source, destination, module, user, pwd):
189     if module in ('base','quality_integration_server'):
190         return True
191     if os.path.islink(destination + '/' + module):
192         os.unlink(destination + '/' + module)                
193     for path in source:
194         if os.path.isdir(path + '/' + module):
195             os.symlink(path + '/' + module, destination + '/' + module)
196             obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
197             execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'update_list')
198             module_ids = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'search', [('name','=',module)])
199             if len(module_ids):
200                 data = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'read', module_ids[0],['name','dependencies_id'])
201                 dep_datas = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module.dependency', 'read', data['dependencies_id'],['name'])
202                 for dep_data in dep_datas:
203                     make_links(uri, uid, dbname, source, destination, dep_data['name'], user, pwd)
204     return False
205
206 def install_module(uri, dbname, modules, addons='', extra_addons='',  user='admin', pwd='admin'):
207     uid = login(uri, dbname, user, pwd)
208     if extra_addons:
209         extra_addons = extra_addons.split(',')
210     if uid:
211         if addons and extra_addons:
212             for module in modules:
213                 make_links(uri, uid, dbname, extra_addons, addons, module, user, pwd)
214
215         obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
216         wizard_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
217         module_ids = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'search', [('name','in',modules)])
218         execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'button_install', module_ids)
219         wiz_id = execute(wizard_conn, 'create', dbname, uid, pwd, 'module.upgrade.simple')
220         state = 'init'
221         datas = {}
222         #while state!='menu':
223         while state!='end':
224             res = execute(wizard_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {})
225             if state == 'init':
226                 state = 'start'
227             elif state == 'start':
228                 state = 'end'
229     return True
230
231 def upgrade_module(uri, dbname, modules, user='admin', pwd='admin'):
232     uid = login(uri, dbname, user, pwd)
233     if uid:
234         obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
235         wizard_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
236         module_ids = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'search', [('name','in',modules)])
237         execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'button_upgrade', module_ids)
238         wiz_id = execute(wizard_conn, 'create', dbname, uid, pwd, 'module.upgrade.simple')
239         state = 'init'
240         datas = {}
241         #while state!='menu':
242         while state!='end':
243             res = execute(wizard_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {})
244             if state == 'init':
245                 state = 'start'
246             elif state == 'start':
247                 state = 'end'
248
249     return True
250
251
252
253
254
255 usage = """%prog command [options]
256
257 Basic Commands:
258     start-server         Start Server
259     create-db            Create new database
260     drop-db              Drop database
261     install-module       Install module
262     upgrade-module       Upgrade module
263     install-translation  Install translation file
264     check-quality        Calculate quality and dump quality result into quality_log.pck using pickle
265 """
266 parser = optparse.OptionParser(usage)
267 parser.add_option("--modules", dest="modules",
268                      help="specify modules to install or check quality")
269 parser.add_option("--addons-path", dest="addons_path", help="specify the addons path")
270 parser.add_option("--quality-logs", dest="quality_logs", help="specify the path of quality logs files which has to stores")
271 parser.add_option("--root-path", dest="root_path", help="specify the root path")
272 parser.add_option("-p", "--port", dest="port", help="specify the TCP port", type="int")
273 parser.add_option("--net_port", dest="netport",help="specify the TCP port for netrpc")
274 parser.add_option("-d", "--database", dest="db_name", help="specify the database name")
275 parser.add_option("--login", dest="login", help="specify the User Login")
276 parser.add_option("--password", dest="pwd", help="specify the User Password")
277 parser.add_option("--translate-in", dest="translate_in",
278                      help="specify .po files to import translation terms")
279 parser.add_option("--extra-addons", dest="extra_addons",
280                      help="specify extra_addons and trunkCommunity modules path ")
281
282 (opt, args) = parser.parse_args()
283 if len(args) != 1:
284     parser.error("incorrect number of arguments")
285 command = args[0]
286 if command not in ('start-server','create-db','drop-db','install-module','upgrade-module','check-quality','install-translation'):
287     parser.error("incorrect command")
288
289 def die(cond, msg):
290     if cond:
291         print msg
292         sys.exit(1)
293
294 die(opt.modules and (not opt.db_name),
295         "the modules option cannot be used without the database (-d) option")
296
297 die(opt.translate_in and (not opt.db_name),
298         "the translate-in option cannot be used without the database (-d) option")
299
300 options = {
301     'addons-path' : opt.addons_path or 'addons',
302     'quality-logs' : opt.quality_logs or '',
303     'root-path' : opt.root_path or '',
304     'translate-in': [],
305     'port' : opt.port or 8069,
306     'netport':opt.netport or 8070,
307     'database': opt.db_name or 'terp',
308     'modules' : opt.modules or [],
309     'login' : opt.login or 'admin',
310     'pwd' : opt.pwd or '',
311     'extra-addons':opt.extra_addons or []
312 }
313
314 options['modules'] = opt.modules and map(lambda m: m.strip(), opt.modules.split(',')) or []
315 # Hint:i18n-import=purchase:ar_AR.po+sale:fr_FR.po,nl_BE.po
316 if opt.translate_in:
317     translate = opt.translate_in
318     for module_name,po_files in map(lambda x:tuple(x.split(':')),translate.split('+')):
319         for po_file in po_files.split(','):
320             if module_name == 'base':
321                 po_link = '%saddons/%s/i18n/%s'%(options['root-path'],module_name,po_file)
322             else:
323                 po_link = '%s/%s/i18n/%s'%(options['addons-path'], module_name, po_file)
324             options['translate-in'].append(po_link)
325
326 uri = 'http://localhost:' + str(options['port'])
327
328 server_thread = threading.Thread(target=start_server,
329                 args=(options['root-path'], options['port'],options['netport'], options['addons-path']))
330 try:
331     server_thread.start()
332     if command == 'create-db':
333         create_db(uri, options['database'], options['login'], options['pwd'])
334     if command == 'drop-db':
335         drop_db(uri, options['database'])
336     if command == 'install-module':
337         install_module(uri, options['database'], options['modules'],options['addons-path'],options['extra-addons'],options['login'], options['pwd'])
338     if command == 'upgrade-module':
339         upgrade_module(uri, options['database'], options['modules'], options['login'], options['pwd'])
340     if command == 'check-quality':
341         check_quality(uri, options['login'], options['pwd'], options['database'], options['modules'], options['quality-logs'])
342     if command == 'install-translation':
343         import_translate(uri, options['login'], options['pwd'], options['database'], options['translate-in'])
344     clean()
345     sys.exit(0)
346
347 except xmlrpclib.Fault, e:
348     print e.faultString
349     clean()
350     sys.exit(1)
351 except Exception, e:
352     print e
353     clean()
354     sys.exit(1)
355
356 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: