Merge commit 'origin/master' into xrg (5.0.3 official)

Conflicts:
	bin/netsvc.py
	bin/tools/config.py
	bin/workflow/instance.py

bzr revid: p_christ@hol.gr-20090823100210-2py390qp3hym8jlp
This commit is contained in:
P. Christeas 2009-08-23 13:02:10 +03:00
commit 8cbe393b52
18 changed files with 560 additions and 60 deletions

43
Makefile Normal file
View File

@ -0,0 +1,43 @@
# -*- makefile -*-
addons-path := bin/addons/
root-path := bin/
port := 8069
net_port := 8070
module := base
database := terp
language := fr_FR
i18n-import := bin/addons/base/i18n/fr_FR.po
interrogation_file := bin/addons/quality_integration_server/base_quality_interrogation.py
login := admin
password := admin
start:
python $(interrogation_file) start-server --root-path=$(root-path) --addons-path=$(addons-path) --port=$(port)
create-db:
python $(interrogation_file) create-db --database=$(database) --root-path=$(root-path) --addons-path=$(addons-path) --port=$(port) --login=$(login) --password=$(password)
drop-db:
python $(interrogation_file) drop-db --database=$(database) --root-path=$(root-path) --addons-path=$(addons-path) --port=$(port)
install-module:
python $(interrogation_file) install-module --modules=$(module) --database=$(database) --root-path=$(root-path) --addons-path=$(addons-path) --port=$(port) --login=$(login) --password=$(password)
upgrade-module:
python $(interrogation_file) upgrade-module --modules=$(module) --database=$(database) --root-path=$(root-path) --addons-path=$(addons-path) --port=$(port) --login=$(login) --password=$(password)
install-translation:
python $(interrogation_file) install-translation --database=$(database) --translate-in=$(i18n-import) --port=$(port) --login=$(login) --password=$(password) --root-path=$(root-path) --addons-path=$(addons-path)
version:
python bin/openerp-server.py --version
check-quality:
python $(interrogation_file) check-quality --database=$(database) --modules=$(module) --port=$(port) --login=$(login) --password=$(password) --addons-path=$(addons-path) --root-path=$(root-path)

View File

@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: OpenERP
Version: 5.0.1
Version: 5.0.3
Author: Tiny.be
Author-email: fp at tiny be
Maintainer: Tiny.be

View File

@ -22,6 +22,7 @@
import time
from osv import fields,osv
import pooler
class ir_sequence_type(osv.osv):
_name = 'ir.sequence.type'
@ -69,13 +70,12 @@ class ir_sequence(osv.osv):
'sec': time.strftime('%S'),
}
def get_id(self, cr, uid, sequence_id, test='id=%s', context={}):
def get_id(self, cr, uid, sequence_id, test='id=%s', context=None):
try:
cr.execute('lock table ir_sequence')
cr.execute('select id,number_next,number_increment,prefix,suffix,padding from ir_sequence where '+test+' and active=True', (sequence_id,))
cr.execute('SELECT id, number_next, prefix, suffix, padding FROM ir_sequence WHERE '+test+' AND active=%s FOR UPDATE', (sequence_id, True))
res = cr.dictfetchone()
if res:
cr.execute('update ir_sequence set number_next=number_next+number_increment where id=%s and active=True', (res['id'],))
cr.execute('UPDATE ir_sequence SET number_next=number_next+number_increment WHERE id=%s AND active=%s', (res['id'], True))
if res['number_next']:
return self._process(res['prefix']) + '%%0%sd' % res['padding'] % res['number_next'] + self._process(res['suffix'])
else:

View File

@ -325,7 +325,10 @@ class res_partner_address(osv.osv):
if context.get('contact_display', 'contact')=='partner':
ids = self.search(cr, user, [('partner_id',operator,name)], limit=limit, context=context)
else:
ids = self.search(cr, user, [('zip','=',name)] + args, limit=limit, context=context)
if not name:
ids = self.search(cr, user, args, limit=limit, context=context)
else:
ids = self.search(cr, user, [('zip','=',name)] + args, limit=limit, context=context)
if not ids:
ids = self.search(cr, user, [('city',operator,name)] + args, limit=limit, context=context)
if name:

View File

@ -0,0 +1,311 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import xmlrpclib
import ConfigParser
import optparse
import sys
import thread
import threading
import os
import time
import pickle
import base64
import socket
admin_passwd = 'admin'
waittime = 10
def start_server(root_path, port, addons_path):
if root_path:
root_path += '/'
os.system('python2.5 '+root_path+'openerp-server.py --pidfile=openerp.pid --port=%s --no-netrpc --addons-path=%s' %(str(port),addons_path))
def clean():
if os.path.isfile('openerp.pid'):
ps = open('openerp.pid')
if ps:
pid = int(ps.read())
ps.close()
if pid:
os.kill(pid,9)
def execute(connector, method, *args):
res = False
try:
res = getattr(connector,method)(*args)
except socket.error,e:
if e.args[0] == 111:
print 'Please wait %d sec to start server....'%(waittime)
time.sleep(waittime)
res = execute(connector, method, *args)
else:
raise e
return res
def login(uri, dbname, user, pwd):
conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/common')
uid = execute(conn,'login',dbname, user, pwd)
return uid
def import_translate(uri, user, pwd, dbname, translate_in):
uid = login(uri, dbname, user, pwd)
if uid:
conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
wiz_id = execute(conn,'create',dbname, uid, pwd, 'module.lang.import')
for trans_in in translate_in:
lang,ext = os.path.splitext(trans_in.split('/')[-1])
state = 'init'
datas = {'form':{}}
while state!='end':
res = execute(conn,'execute',dbname, uid, pwd, wiz_id, datas, state, {})
if 'datas' in res:
datas['form'].update( res['datas'].get('form',{}) )
if res['type']=='form':
for field in res['fields'].keys():
datas['form'][field] = res['fields'][field].get('value', False)
state = res['state'][-1][0]
trans_obj = open(trans_in)
datas['form'].update({
'name': lang,
'code': lang,
'data' : base64.encodestring(trans_obj.read())
})
trans_obj.close()
elif res['type']=='action':
state = res['state']
def check_quality(uri, user, pwd, dbname, modules):
uid = login(uri, dbname, user, pwd)
if uid:
conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
qualityresult = {}
final = {}
test_detail = {}
for module in modules:
quality_result = execute(conn,'execute', dbname, uid, pwd,'module.quality.check','check_quality',module)
detail_html = ''
html = '''<html><html><html><html><body><a name="TOP"></a>'''
html +="<h1> Module : %s </h1>"%(quality_result['name'])
html += "<h2> Final score : %s</h2>"%(quality_result['final_score'])
html += "<oi>"
for x,y,detail in quality_result['check_detail_ids']:
if detail.get('detail') != '':
test = detail.get('name')
score = round(float(detail.get('score',0)),2)
html += "<li><a href=\"#%s\">%s (%.2f)</a></li>"%(test,test,score)
detail_html +="<a name=\"%s\"><h3>%s (Score : %s)</h3>%s</a>"%(test,test,score,detail.get('detail'))
detail_html +='''<a href="#TOP">Go to Top</a>'''
test_detail[test] = (score,detail.get('detail',''))
html += "</oi>%s</body></html></html></html></html></html>"%(detail_html)
final[quality_result['name']] = (quality_result['final_score'],html,test_detail)
fp = open('quality_log.pck','wb')
pck_obj = pickle.dump(final,fp)
fp.close()
print "LOG PATH%s"%(os.path.realpath('quality_log.pck'))
return final
else:
print 'Login Failed...'
clean()
sys.exit(1)
def wait(id,url=''):
progress=0.0
sock2 = xmlrpclib.ServerProxy(url+'/db')
while not progress==1.0:
progress,users = execute(sock2,'get_progress',admin_passwd, id)
return True
def create_db(uri, dbname, user='admin', pwd='admin', lang='en_US'):
conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/db')
obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
wiz_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
login_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/common')
db_list = execute(conn, 'list')
if dbname not in db_list:
id = execute(conn,'create',admin_passwd, dbname, True, lang)
wait(id,uri)
uid = login_conn.login(dbname, user, pwd)
wiz_id = execute(wiz_conn,'create', dbname, uid, user, 'base_setup.base_setup')
state = 'init'
datas = {'form':{}}
while state!='config':
res = execute(wiz_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {})
if state=='init':
datas['form'].update( res['datas'] )
if res['type']=='form':
for field in res['fields'].keys():
datas['form'][field] = datas['form'].get(field,False)
state = res['state'][-1][0]
datas['form'].update({
'profile': -1
})
elif res['type']=='state':
state = res['state']
res = execute(wiz_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {})
install_module(uri, dbname, ['base_module_quality'],user,pwd)
return True
def drop_db(uri, dbname):
conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/db')
db_list = execute(conn,'list')
if dbname in db_list:
execute(conn, 'drop', admin_passwd, dbname)
return True
def install_module(uri, dbname, modules, user='admin', pwd='admin'):
uid = login(uri, dbname, user, pwd)
if uid:
obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
wizard_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
module_ids = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'search', [('name','in',modules)])
execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'button_install', module_ids)
wiz_id = execute(wizard_conn, 'create', dbname, uid, pwd, 'module.upgrade.simple')
state = 'init'
datas = {}
#while state!='menu':
while state!='end':
res = execute(wizard_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {})
if state == 'init':
state = 'start'
elif state == 'start':
state = 'end'
return True
def upgrade_module(uri, dbname, modules, user='admin', pwd='admin'):
uid = login(uri, dbname, user, pwd)
if uid:
obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object')
wizard_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard')
module_ids = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'search', [('name','in',modules)])
execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'button_upgrade', module_ids)
wiz_id = execute(wizard_conn, 'create', dbname, uid, pwd, 'module.upgrade.simple')
state = 'init'
datas = {}
#while state!='menu':
while state!='end':
res = execute(wizard_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {})
if state == 'init':
state = 'start'
elif state == 'start':
state = 'end'
return True
usage = """%prog command [options]
Basic Commands:
start-server Start Server
create-db Create new database
drop-db Drop database
install-module Install module
upgrade-module Upgrade module
install-translation Install translation file
check-quality Calculate quality and dump quality result into quality_log.pck using pickle
"""
parser = optparse.OptionParser(usage)
parser.add_option("--modules", dest="modules",
help="specify modules to install or check quality")
parser.add_option("--addons-path", dest="addons_path", help="specify the addons path")
parser.add_option("--root-path", dest="root_path", help="specify the root path")
parser.add_option("-p", "--port", dest="port", help="specify the TCP port", type="int")
parser.add_option("-d", "--database", dest="db_name", help="specify the database name")
parser.add_option("--login", dest="login", help="specify the User Login")
parser.add_option("--password", dest="pwd", help="specify the User Password")
parser.add_option("--translate-in", dest="translate_in",
help="specify .po files to import translation terms")
(opt, args) = parser.parse_args()
if len(args) != 1:
parser.error("incorrect number of arguments")
command = args[0]
if command not in ('start-server','create-db','drop-db','install-module','upgrade-module','check-quality','install-translation'):
parser.error("incorrect command")
def die(cond, msg):
if cond:
print msg
sys.exit(1)
die(opt.modules and (not opt.db_name),
"the modules option cannot be used without the database (-d) option")
die(opt.translate_in and (not opt.db_name),
"the translate-in option cannot be used without the database (-d) option")
options = {
'addons-path' : opt.addons_path or 'addons',
'root-path' : opt.root_path or '',
'translate-in': opt.translate_in,
'port' : opt.port or 8069,
'database': opt.db_name or 'terp',
'modules' : opt.modules or [],
'login' : opt.login or 'admin',
'pwd' : opt.pwd or '',
}
options['modules'] = opt.modules and map(lambda m: m.strip(), opt.modules.split(',')) or []
options['translate_in'] = opt.translate_in and map(lambda m: m.strip(), opt.translate_in.split(',')) or []
uri = 'http://localhost:' + str(options['port'])
server_thread = threading.Thread(target=start_server,
args=(options['root-path'], options['port'], options['addons-path']))
try:
server_thread.start()
if command == 'create-db':
create_db(uri, options['database'], options['login'], options['pwd'])
if command == 'drop-db':
drop_db(uri, options['database'])
if command == 'install-module':
install_module(uri, options['database'], options['modules'], options['login'], options['pwd'])
if command == 'upgrade-module':
upgrade_module(uri, options['database'], options['modules'], options['login'], options['pwd'])
if command == 'check-quality':
check_quality(uri, options['login'], options['pwd'], options['database'], options['modules'])
if command == 'install-translation':
import_translate(uri, options['login'], options['pwd'], options['database'], options['translate_in'])
clean()
sys.exit(0)
except xmlrpclib.Fault, e:
print e.faultString
clean()
sys.exit(1)
except Exception, e:
print e
clean()
sys.exit(1)

View File

@ -180,10 +180,11 @@ class Logger(object):
msg = tools.exception_to_unicode(msg)
try:
msg = tools.ustr(msg).strip()
if level in (LOG_ERROR,LOG_CRITICAL) and tools.config.get_misc('debug','env_info',True):
msg = common().get_server_environment() + msg
result = tools.ustr(msg).strip().split('\n')
result = msg.split('\n')
except UnicodeDecodeError:
result = msg.strip().split('\n')
try:

View File

@ -103,14 +103,23 @@ class expression(object):
left, operator, right = e
working_table = table
if left in table._inherit_fields:
working_table = table.pool.get(table._inherit_fields[left][0])
if working_table not in self.__tables.values():
self.__joins.append(('%s.%s=%s.%s' % (working_table._table, 'id', table._table, table._inherits[working_table._name]), working_table._table))
self.__tables[i] = working_table
main_table = table
fargs = left.split('.', 1)
index = i
if left in table._inherit_fields:
while True:
field = main_table._columns.get(fargs[0], False)
if field:
working_table = main_table
self.__tables[i] = working_table
break
working_table = main_table.pool.get(main_table._inherit_fields[left][0])
if working_table not in self.__tables.values():
self.__joins.append(('%s.%s=%s.%s' % (working_table._table, 'id', main_table._table, main_table._inherits[working_table._name]), working_table._table))
self.__tables[index] = working_table
index += 1
main_table = working_table
field = working_table._columns.get(fargs[0], False)
if not field:
if left == 'id' and operator == 'child_of':

View File

@ -53,6 +53,7 @@ def _symbol_set(symb):
class _column(object):
_classic_read = True
_classic_write = True
_prefetch = True
_properties = False
_type = 'unknown'
_obj = None
@ -196,6 +197,7 @@ class binary(_column):
_symbol_get = lambda self, x: x and str(x)
_classic_read = False
_prefetch = False
def __init__(self, string='unknown', filters=None, **args):
_column.__init__(self, string=string, **args)
@ -350,6 +352,7 @@ class many2one(_column):
class one2many(_column):
_classic_read = False
_classic_write = False
_prefetch = False
_type = 'one2many'
def __init__(self, obj, fields_id, string='unknown', limit=None, **args):
@ -426,11 +429,13 @@ class one2many(_column):
return res
def set(self, cr, obj, id, field, values, user=None, context=None):
result = []
if not context:
context = {}
if self._context:
context = context.copy()
context.update(self._context)
context['no_store_function'] = True
if not values:
return
_table = obj.pool.get(self._obj)._table
@ -438,7 +443,8 @@ class one2many(_column):
for act in values:
if act[0] == 0:
act[2][self._fields_id] = id
obj.create(cr, user, act[2], context=context)
id_new = obj.create(cr, user, act[2], context=context)
result += obj._store_get_values(cr, user, [id_new], act[2].keys(), context)
elif act[0] == 1:
obj.write(cr, user, [act[1]], act[2], context=context)
elif act[0] == 2:
@ -455,6 +461,7 @@ class one2many(_column):
cr.execute('select id from '+_table+' where '+self._fields_id+'=%s and id not in ('+','.join(map(str, ids2))+')', (id,))
ids3 = map(lambda x:x[0], cr.fetchall())
obj.write(cr, user, ids3, {self._fields_id:False}, context=context or {})
return result
def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like'):
return obj.pool.get(self._obj).name_search(cr, uid, value, self._domain, offset, limit)
@ -472,6 +479,7 @@ class one2many(_column):
class many2many(_column):
_classic_read = False
_classic_write = False
_prefetch = False
_type = 'many2many'
def __init__(self, obj, rel, id1, id2, string='unknown', limit=None, **args):
@ -582,6 +590,7 @@ class many2many(_column):
class function(_column):
_classic_read = False
_classic_write = False
_prefetch = False
_type = 'function'
_properties = True

View File

@ -174,7 +174,7 @@ class browse_record(object):
return None
# if the field is a classic one or a many2one, we'll fetch all classic and many2one fields
if col._classic_write:
if col._prefetch:
# gen the list of "local" (ie not inherited) fields which are classic or many2one
ffields = filter(lambda x: x[1]._classic_write, self._table._columns.items())
# gen the list of inherited fields
@ -673,7 +673,7 @@ class orm_template(object):
if fields_def[field[len(prefix)]]['type'] == 'integer':
res = line[i] and int(line[i])
elif fields_def[field[len(prefix)]]['type'] == 'boolean':
res = line[i] and bool(line[i])
res = line[i].lower() not in ('0', 'false', 'off')
elif fields_def[field[len(prefix)]]['type'] == 'float':
res = line[i] and float(line[i])
elif fields_def[field[len(prefix)]]['type'] == 'selection':
@ -1444,10 +1444,10 @@ class orm_memory(orm_template):
self._validate(cr, user, [id_new], context)
wf_service = netsvc.LocalService("workflow")
wf_service.trg_write(user, self._name, id_new, cr)
self.vaccum(cr, user)
return id_new
def create(self, cr, user, vals, context=None):
self.vaccum(cr, user)
self.next_id += 1
id_new = self.next_id
default = []
@ -1471,7 +1471,6 @@ class orm_memory(orm_template):
self._validate(cr, user, [id_new], context)
wf_service = netsvc.LocalService("workflow")
wf_service.trg_create(user, self._name, id_new, cr)
self.vaccum(cr, user)
return id_new
def default_get(self, cr, uid, fields_list, context=None):
@ -2056,7 +2055,9 @@ class orm(orm_template):
self._inherits_reload_src()
def fields_get(self, cr, user, fields=None, context=None):
read_access = self.pool.get('ir.model.access').check(cr, user, self._name, 'write', raise_exception=False, context=context)
ira = self.pool.get('ir.model.access')
read_access = ira.check(cr, user, self._name, 'write', raise_exception=False, context=context) or \
ira.check(cr, user, self._name, 'create', raise_exception=False, context=context)
return super(orm, self).fields_get(cr, user, fields, context, read_access)
def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
@ -2361,6 +2362,7 @@ class orm(orm_template):
if not edit:
vals.pop(field)
if not context:
context = {}
if not ids:
@ -2372,6 +2374,7 @@ class orm(orm_template):
self.pool.get('ir.model.access').check(cr, user, self._name, 'write', context=context)
upd0 = []
upd1 = []
upd_todo = []
@ -2448,6 +2451,7 @@ class orm(orm_template):
src_trans = self.pool.get(self._name).read(cr,user,ids,[f])
self.pool.get('ir.translation')._set_ids(cr, user, self._name+','+f, 'model', context['lang'], ids, vals[f], src_trans[0][f])
# call the 'set' method of fields which are not classic_write
upd_todo.sort(lambda x, y: self._columns[x].priority-self._columns[y].priority)
@ -2549,12 +2553,12 @@ class orm(orm_template):
for (t, c) in self._inherits.items():
if c in vals:
avoid_table.append(t)
for f in self._columns.keys(): # + self._inherit_fields.keys():
if not f in vals:
for f in self._columns.keys():
if (not f in vals) and (not isinstance(self._columns[f], fields.property)):
default.append(f)
for f in self._inherit_fields.keys():
if (not f in vals) and (self._inherit_fields[f][0] not in avoid_table):
if (not f in vals) and (self._inherit_fields[f][0] not in avoid_table) and (not isinstance(self._inherit_fields[f][2], fields.property)):
default.append(f)
if len(default):
@ -2563,7 +2567,6 @@ class orm(orm_template):
if dv in self._columns and self._columns[dv]._type == 'many2many':
if default_values[dv] and isinstance(default_values[dv][0], (int, long)):
default_values[dv] = [(6, 0, default_values[dv])]
vals.update(default_values)
tocreate = {}
@ -2666,13 +2669,19 @@ class orm(orm_template):
if c[0].startswith('default_'):
del rel_context[c[0]]
result = []
for field in upd_todo:
self._columns[field].set(cr, self, id_new, field, vals[field], user, rel_context)
result += self._columns[field].set(cr, self, id_new, field, vals[field], user, rel_context) or []
self._validate(cr, user, [id_new], context)
result = self._store_get_values(cr, user, [id_new], vals.keys(), context)
for order, object, ids, fields in result:
self.pool.get(object)._store_set_values(cr, user, ids, fields, context)
if not context.get('no_store_function', False):
result += self._store_get_values(cr, user, [id_new], vals.keys(), context)
result.sort()
done = []
for order, object, ids, fields2 in result:
if not (object, ids, fields2) in done:
self.pool.get(object)._store_set_values(cr, user, ids, fields2, context)
done.append((object, ids, fields2))
wf_service = netsvc.LocalService("workflow")
wf_service.trg_create(user, self._name, id_new, cr)
@ -2682,6 +2691,15 @@ class orm(orm_template):
result = {}
fncts = self.pool._store_function.get(self._name, [])
for fnct in range(len(fncts)):
if fncts[fnct][3]:
ok = False
for f in (fields or []):
if f in fncts[fnct][3]:
ok = True
break
if not ok:
continue
result.setdefault(fncts[fnct][0], {})
ids2 = fncts[fnct][2](self,cr, uid, ids, context)
for id in filter(None, ids2):

View File

@ -22,7 +22,7 @@
##############################################################################
name = 'openerp-server'
version = '5.0.3-bzr'
version = '5.0.3'
major_version = '5.0'
description = 'OpenERP Server'
long_desc = '''\

View File

@ -240,7 +240,7 @@ class document(object):
txt = str(datas[atr['value']])
else:
txt = datas[atr['value']]
el.append(txt)
el.text = txt
else:
for el_cld in node:
parse_result_tree(el_cld, el, datas)

View File

@ -51,7 +51,7 @@ class report_printscreen_list(report_int):
return result
def _parse_string(self, view):
dom = etree.XML(unicode(view, 'utf-8').encode('utf-8'))
dom = etree.XML(view)
return self._parse_node(dom)
def create(self, cr, uid, ids, datas, context=None):
@ -139,7 +139,7 @@ class report_printscreen_list(report_int):
for f in fields_order:
field = etree.Element("field")
field.text = fields[f]['string'] or ''
field.text = tools.ustr(fields[f]['string'] or '')
header.append(field)
new_doc.append(header)
@ -148,12 +148,12 @@ class report_printscreen_list(report_int):
count = len(fields_order)
for i in range(0,count):
tsum.append(0)
for line in results:
node_line = etree.Element("row")
count = -1
for f in fields_order:
float_flag = 0
count += 1
if fields[f]['type']=='many2one' and line[f]:
@ -170,7 +170,9 @@ class report_printscreen_list(report_int):
if fields[f]['type'] == 'float' and line[f]:
precision=(('digits' in fields[f]) and fields[f]['digits'][1]) or 2
line[f]='%.2f'%(line[f])
prec ='%.' + str(precision) +'f'
line[f]=prec%(line[f])
float_flag = 1
if fields[f]['type'] == 'date' and line[f]:
format = str(locale.nl_langinfo(locale.D_FMT).replace('%y', '%Y'))
@ -195,8 +197,12 @@ class report_printscreen_list(report_int):
col.set('tree','no')
if line[f] != None:
col.text = tools.ustr(line[f] or '')
if float_flag:
col.set('tree','float')
if temp[count] == 1:
tsum[count] = float(tsum[count]) + float(line[f]);
else:
col.text = '/'
node_line.append(col)
@ -210,16 +216,18 @@ class report_printscreen_list(report_int):
col.set('tree','no')
if tsum[f] != None:
if tsum[f] >= 0.01 :
total = '%.2f'%(tsum[f])
txt = str(total or '')
else :
txt = str(tsum[f] or '')
prec = '%.' + str(tools.config['price_accuracy']) + 'f'
total = prec%(tsum[f])
txt = str(total or '')
col.set('tree','float')
else:
txt = str(tsum[f] or '')
else:
txt = '/'
if f == 0:
txt ='Total'
col.text = txt
col.text = tools.ustr(txt or '')
node_line.append(col)
lines.append(node_line)

View File

@ -236,7 +236,8 @@ class _rml_canvas(object):
self.canvas.setTitle(self.title)
def _textual(self, node, x=0, y=0):
rc = utils._process_text(self, node.text.encode('utf-8') or '')
text = node.text and node.text.encode('utf-8') or ''
rc = utils._process_text(self, text)
for n in node:
if n.tag == 'seq':
from reportlab.lib.sequencer import getSequencer

View File

@ -189,7 +189,7 @@ class rml_parse(object):
return newtag, attrs
def format(self, text, oldtag=None):
return text
return text.strip()
def removeParentNode(self, tag=None):
raise Exception('Skip')
@ -420,12 +420,14 @@ class report_sxw(report_rml, preprocess.report):
return s.getvalue(), results[0][1]
return self.create_single_pdf(cr, uid, ids, data, report_xml, context)
def create_single_pdf(self, cr, uid, ids, data, report_xml, context={}):
def create_single_pdf(self, cr, uid, ids, data, report_xml, context=None):
if not context:
context={}
logo = None
context = context.copy()
title = report_xml.name
rml = report_xml.report_rml_content
rml_parser = self.parser(cr, uid, self.name2, context)
rml_parser = self.parser(cr, uid, self.name2, context=context)
objs = self.getObjects(cr, uid, ids, context)
rml_parser.set_context(objs, data, ids, report_xml.report_type)
processed_rml = self.preprocess_rml(etree.XML(rml),report_xml.report_type)
@ -437,7 +439,9 @@ class report_sxw(report_rml, preprocess.report):
pdf = create_doc(etree.tostring(processed_rml),rml_parser.localcontext,logo,title.encode('utf8'))
return (pdf, report_xml.report_type)
def create_single_odt(self, cr, uid, ids, data, report_xml, context={}):
def create_single_odt(self, cr, uid, ids, data, report_xml, context=None):
if not context:
context={}
context = context.copy()
report_type = report_xml.report_type
context['parents'] = sxw_parents
@ -447,7 +451,7 @@ class report_sxw(report_rml, preprocess.report):
meta = sxw_z.read('meta.xml')
sxw_z.close()
rml_parser = self.parser(cr, uid, self.name2, context)
rml_parser = self.parser(cr, uid, self.name2, context=context)
rml_parser.parents = sxw_parents
rml_parser.tag = sxw_tag
objs = self.getObjects(cr, uid, ids, context)
@ -514,7 +518,7 @@ class report_sxw(report_rml, preprocess.report):
if report_xml.header:
#Add corporate header/footer
rml = tools.file_open(os.path.join('base', 'report', 'corporate_%s_header.xml' % report_type)).read()
rml_parser = self.parser(cr, uid, self.name2, context)
rml_parser = self.parser(cr, uid, self.name2, context=context)
rml_parser.parents = sxw_parents
rml_parser.tag = sxw_tag
objs = self.getObjects(cr, uid, ids, context)
@ -532,13 +536,15 @@ class report_sxw(report_rml, preprocess.report):
sxw_io.close()
return (final_op, report_type)
def create_single_html2html(self, cr, uid, ids, data, report_xml, context={}):
def create_single_html2html(self, cr, uid, ids, data, report_xml, context=None):
if not context:
context = {}
context = context.copy()
report_type = 'html'
context['parents'] = html_parents
html = report_xml.report_rml_content
html_parser = self.parser(cr, uid, self.name2, context)
html_parser = self.parser(cr, uid, self.name2, context=context)
html_parser.parents = html_parents
html_parser.tag = sxw_tag
objs = self.getObjects(cr, uid, ids, context)

View File

@ -612,9 +612,16 @@ class cache(object):
"""
def to_tuple(d):
i = d.items()
i.sort(key=lambda (x,y): x)
return tuple(i)
pairs = d.items()
pairs.sort(key=lambda (k,v): k)
for i, (k, v) in enumerate(pairs):
if isinstance(v, dict):
pairs[i] = (k, to_tuple(v))
if isinstance(v, (list, set)):
pairs[i] = (k, tuple(v))
elif not is_hashable(v):
pairs[i] = (k, repr(v))
return tuple(pairs)
if not self.multi:
key = (('dbname', dbname),) + to_tuple(kwargs2)
@ -631,12 +638,6 @@ class cache(object):
kwargs2 = self.fun_default_values.copy()
kwargs2.update(kwargs)
kwargs2.update(dict(zip(self.fun_arg_names, args[self.skiparg-2:])))
for k in kwargs2:
if isinstance(kwargs2[k], (list, dict, set)):
kwargs2[k] = tuple(kwargs2[k])
elif not is_hashable(kwargs2[k]):
kwargs2[k] = repr(kwargs2[k])
return kwargs2
def clear(self, dbname, *args, **kwargs):

View File

@ -344,8 +344,9 @@ def trans_export(lang, modules, buffer, format, dbname=None):
tmpmoddir = join(tmpdir, mod, 'i18n')
os.makedirs(tmpmoddir)
pofilename = (newlang and mod or lang) + ".po" + (newlang and 't' or '')
buf = open(join(tmpmoddir, pofilename), 'w')
buf = file(join(tmpmoddir, pofilename), 'w')
_process('po', [mod], modrows, buf, lang, newlang)
buf.close()
tar = tarfile.open(fileobj=buffer, mode='w|gz')
tar.add(tmpdir, '')

View File

@ -43,7 +43,7 @@ def delete(cr, ident):
def validate(cr, inst_id, ident, signal, force_running=False):
cr.execute("select * from wkf_workitem where inst_id=%s", (inst_id,))
stack = None
stack = []
for witem in cr.dictfetchall():
stack = []
workitem.process(cr, witem, ident, signal, force_running, stack=stack)

View File

@ -1,8 +1,85 @@
2009-08-21: 5.0.2
=================
Bugfixes (server)
-----------------
* Not linked to a bug report:
* set_alarm: removed unwanted comment
* report engine: context argument was passed at a wrong position. Now it's passed as a named argument.
* fields_get check access aginst write or create access
* Not allowing only white spaces text to be printed
* sequences: avoid an sql error when locking table...
* report engine: fixed a bug when the xml tag is empty
* bin/workflow: 'stack' variable was not initialized when sql query returned an empty set.
* security issue: avoid access to inactive users
* security issue: avoid access with 'None' password (Thanks to P. Christeas for the bug report)
* avoid a bug when look in stack when translate code strings
* https://launchpad.net/bugs/415257
* import of boolean fields in csv files.
* https://launchpad.net/bugs/415014
* correct translation tgz archive creation
* https://launchpad.net/bugs/362280
* https://launchpad.net/bugs/416883
* Print screen unicode-decode error solved
* https://launchpad.net/bugs/400378
* partner address search
* https://launchpad.net/bugs/415972
* do not get next sequence in its own cursor
* https://launchpad.net/bugs/413484
* Print Screen : was not considering field names with superscripted,subscripted characters(ex.m²)
* https://launchpad.net/bugs/406945
* import of boolean fields in csv files.
* https://launchpad.net/bugs/413586
* bug in cache system that altered some arguments passed to cached function
* https://launchpad.net/bugs/413594
* logger: convert the message in unicode before concatenate it with server environment
* https://launchpad.net/bugs/348217
* Secure option on config file
Improvements (server)
---------------------
* Makefile and quality_integration_server module for Integration server
* Speed impprovement: 2x faster for flow: sale -> invoice -> payment
* Speed improvement in creation of records (4 time faster on partners)
Bugfixes (addons)
-----------------
* Not linked to a bug report:
* Purchase :copy method was not setting stock moves to be null for PO lines
* Module:account Fix keyerror in general_ledger report
* Access rules stock / worker
* mrp: fr_FR.po file had a duplicate message definition
* https://launchpad.net/bugs/413699
* https://launchpad.net/bugs/415014
* report_task: regenerate translations files
* https://launchpad.net/bugs/397100
* improving commit on report
* https://launchpad.net/bugs/416296
* Base_setup : Country passed in values only if filled
* https://launchpad.net/bugs/415218
* report_task : report_task_user_pipeline_open was having no uniqueness
Improvements (addons)
---------------------
* POS: improved the point_of_sale receipt
2009-08-12: 5.0.2
=================
Bugfixes (server)
-----------------
* Not Linked to a bug report:
* ensure sys is imported
* pass the context to check method of 'ir.model.access'
@ -130,6 +207,7 @@ Bugfixes (server)
Improvements (server)
---------------------
* Logger notification improved
* update po(t) files
* new method that allow the server to return a message that will be display on login page
@ -146,6 +224,7 @@ Improvements (server)
Bugfixes (addons)
-----------------
* Not linked to a bug report:
* DMS directory not translatable + translations improvement
* Project : Searching active=no was failing, corrected
@ -339,6 +418,7 @@ Bugfixes (addons)
Improvements (addons)
---------------------
* update po(t) files
* Module:account Api changes def _refund_cleanup_lines(self, lines): added cr,uid arguments
* pyflakes test display result improve on base_module_quality
@ -381,37 +461,46 @@ Improvements (addons)
2009-05-26: 5.0.1
=================
TODO
2009-02-12: 5.0.0-3
===================
TODO
2009-02-08: 5.0.0-2
===================
TODO
2009-02-06: 5.0.0
=================
TODO
2009-01-03: 5.0.0-rc3
=====================
TODO
2008-12-22: 5.0.0-rc2
=====================
TODO
2008-12-01: 5.0.0-rc1.1
=======================
TODO
2008-11-28: 5.0.0-rc1
=====================
TODO
2008-11-03: 5.0.0-alpha
=======================
TODO