[MERGE] forward port of branch 7.0 up to revid 5270 chs@openerp.com-20140403084524-9rb174osjrbmhgwc
bzr revid: chs@openerp.com-20140402083506-w4cywcf0kxxx9xmk bzr revid: chs@openerp.com-20140312174526-a5rhh83g0fw8djuc bzr revid: chs@openerp.com-20140318105837-53vsx5g7fm517cuc bzr revid: dle@openerp.com-20140326092548-bu4bqinhvco8j5wj bzr revid: chs@openerp.com-20140402092735-3a23yjl169vvt0iv bzr revid: chs@openerp.com-20140402112825-ky8rcb3p467ikitc bzr revid: chs@openerp.com-20140403084808-slnj7uis17kwi9js
This commit is contained in:
commit
1c3ee251f0
|
@ -296,7 +296,12 @@ instance.web.Session.include( /** @lends instance.web.Session# */{
|
|||
for(var i=0; i<cookies.length; ++i) {
|
||||
var cookie = cookies[i].replace(/^\s*/, '');
|
||||
if(cookie.indexOf(nameEQ) === 0) {
|
||||
return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length)));
|
||||
try {
|
||||
return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length)));
|
||||
} catch(err) {
|
||||
// wrong cookie, delete it
|
||||
this.set_cookie(name, '', -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -50,15 +50,21 @@ class change_password_wizard(osv.TransientModel):
|
|||
|
||||
def change_password_button(self, cr, uid, id, context=None):
|
||||
wizard = self.browse(cr, uid, id, context=context)[0]
|
||||
user_ids = []
|
||||
for user in wizard.user_ids:
|
||||
user_ids.append(user.id)
|
||||
self.pool.get('change.password.user').change_password_button(cr, uid, user_ids, context=context)
|
||||
need_reload = any(uid == user.user_id.id for user in wizard.user_ids)
|
||||
line_ids = [user.id for user in wizard.user_ids]
|
||||
|
||||
self.pool.get('change.password.user').change_password_button(cr, uid, line_ids, context=context)
|
||||
# don't keep temporary password copies in the database longer than necessary
|
||||
self.pool.get('change.password.user').write(cr, uid, user_ids, {'new_passwd': False})
|
||||
return {
|
||||
'type': 'ir.actions.act_window_close',
|
||||
}
|
||||
self.pool.get('change.password.user').write(cr, uid, line_ids, {'new_passwd': False}, context=context)
|
||||
|
||||
if need_reload:
|
||||
return {
|
||||
'type': 'ir.actions.client',
|
||||
'tag': 'reload'
|
||||
}
|
||||
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
|
||||
class change_password_user(osv.TransientModel):
|
||||
"""
|
||||
|
|
|
@ -439,5 +439,18 @@ class test_expression(common.TransactionCase):
|
|||
partner_parent_id_col._auto_join = False
|
||||
state_country_id_col._auto_join = False
|
||||
|
||||
def test_translate_search(self):
|
||||
Country = self.registry('res.country')
|
||||
be = self.ref('base.be')
|
||||
domains = [
|
||||
[('name', '=', 'Belgium')],
|
||||
[('name', 'ilike', 'Belgi')],
|
||||
[('name', 'in', ['Belgium', 'Care Bears'])],
|
||||
]
|
||||
|
||||
for domain in domains:
|
||||
ids = Country.search(self.cr, self.uid, domain)
|
||||
self.assertListEqual([be], ids)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest2.main()
|
||||
|
|
|
@ -107,8 +107,15 @@ def run_test_file(dbname, test_file):
|
|||
registry = openerp.modules.registry.RegistryManager.new(dbname, update_module=config['init'] or config['update'])
|
||||
cr = registry.db.cursor()
|
||||
_logger.info('loading test file %s', test_file)
|
||||
openerp.tools.convert_yaml_import(cr, 'base', file(test_file), 'test', {}, 'test', True)
|
||||
cr.rollback()
|
||||
openerp.tools.convert_yaml_import(cr, 'base', file(test_file), 'test', {}, 'init')
|
||||
|
||||
if config['test_commit']:
|
||||
_logger.info('test %s has been commited', test_file)
|
||||
cr.commit()
|
||||
else:
|
||||
_logger.info('test %s has been rollbacked', test_file)
|
||||
cr.rollback()
|
||||
|
||||
cr.close()
|
||||
except Exception:
|
||||
_logger.exception('Failed to initialize database `%s` and run test file `%s`.', dbname, test_file)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2012 OpenERP SA (<http://www.openerp.com>)
|
||||
# Copyright (C) 2004-2014 OpenERP SA (<http://www.openerp.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -89,7 +89,13 @@ class ColoredFormatter(DBFormatter):
|
|||
record.levelname = COLOR_PATTERN % (30 + fg_color, 40 + bg_color, record.levelname)
|
||||
return DBFormatter.format(self, record)
|
||||
|
||||
_logger_init = False
|
||||
def init_logger():
|
||||
global _logger_init
|
||||
if _logger_init:
|
||||
return
|
||||
_logger_init = True
|
||||
|
||||
from tools.translate import resetlocale
|
||||
resetlocale()
|
||||
|
||||
|
@ -137,6 +143,8 @@ def init_logger():
|
|||
formatter = DBFormatter(format)
|
||||
handler.setFormatter(formatter)
|
||||
|
||||
logging.getLogger().addHandler(handler)
|
||||
|
||||
# Configure handlers
|
||||
pseudo_config = PSEUDOCONFIG_MAPPER.get(tools.config['log_level'], [])
|
||||
|
||||
|
@ -147,11 +155,7 @@ def init_logger():
|
|||
loggername, level = logconfig_item.split(':')
|
||||
level = getattr(logging, level, logging.INFO)
|
||||
logger = logging.getLogger(loggername)
|
||||
logger.handlers = []
|
||||
logger.setLevel(level)
|
||||
logger.addHandler(handler)
|
||||
if loggername != '':
|
||||
logger.propagate = False
|
||||
|
||||
for logconfig_item in logging_configurations:
|
||||
_logger.debug('logger level set: "%s"', logconfig_item)
|
||||
|
|
|
@ -1019,6 +1019,7 @@ class expression(object):
|
|||
push(create_substitution_leaf(leaf, (left, operator, right), working_model))
|
||||
|
||||
elif field.translate and right:
|
||||
field = left
|
||||
need_wildcard = operator in ('like', 'ilike', 'not like', 'not ilike')
|
||||
sql_operator = {'=like': 'like', '=ilike': 'ilike'}.get(operator, operator)
|
||||
if need_wildcard:
|
||||
|
@ -1030,33 +1031,40 @@ class expression(object):
|
|||
sql_operator = sql_operator[4:] if sql_operator[:3] == 'not' else '='
|
||||
inselect_operator = 'not inselect'
|
||||
|
||||
subselect = '( SELECT res_id' \
|
||||
' FROM ir_translation' \
|
||||
' WHERE name = %s' \
|
||||
' AND lang = %s' \
|
||||
' AND type = %s'
|
||||
instr = ' %s'
|
||||
#Covering in,not in operators with operands (%s,%s) ,etc.
|
||||
if sql_operator == 'in':
|
||||
instr = ','.join(['%s'] * len(right))
|
||||
subselect += ' AND value ' + sql_operator + ' ' + " (" + instr + ")" \
|
||||
') UNION (' \
|
||||
' SELECT id' \
|
||||
' FROM "' + working_model._table + '"' \
|
||||
' WHERE "' + left + '" ' + sql_operator + ' ' + " (" + instr + "))"
|
||||
else:
|
||||
subselect += ' AND value ' + sql_operator + instr + \
|
||||
') UNION (' \
|
||||
' SELECT id' \
|
||||
' FROM "' + working_model._table + '"' \
|
||||
' WHERE "' + left + '" ' + sql_operator + instr + ")"
|
||||
trans_left = 'value'
|
||||
left = '"%s"' % (left,)
|
||||
instr = '%s'
|
||||
|
||||
params = [working_model._name + ',' + left,
|
||||
context.get('lang', False) or 'en_US',
|
||||
'model',
|
||||
right,
|
||||
right,
|
||||
]
|
||||
if self.has_unaccent and sql_operator.endswith('like'):
|
||||
assert isinstance(right, basestring)
|
||||
trans_left = 'unaccent(value)'
|
||||
left = 'unaccent(%s)' % (left,)
|
||||
instr = 'unaccent(%s)'
|
||||
elif sql_operator == 'in':
|
||||
# params will be flatten by to_sql() => expand the placeholders
|
||||
instr = '(%s)' % ', '.join(['%s'] * len(right))
|
||||
|
||||
subselect = """(SELECT res_id
|
||||
FROM ir_translation
|
||||
WHERE name = %s
|
||||
AND lang = %s
|
||||
AND type = %s
|
||||
AND {trans_left} {operator} {right}
|
||||
) UNION (
|
||||
SELECT id
|
||||
FROM "{table}"
|
||||
WHERE {left} {operator} {right}
|
||||
)
|
||||
""".format(trans_left=trans_left, operator=sql_operator,
|
||||
right=instr, table=working_model._table, left=left)
|
||||
|
||||
params = (
|
||||
working_model._name + ',' + field,
|
||||
context.get('lang') or 'en_US',
|
||||
'model',
|
||||
right,
|
||||
right,
|
||||
)
|
||||
push(create_substitution_leaf(leaf, ('id', inselect_operator, (subselect, params)), working_model))
|
||||
|
||||
else:
|
||||
|
@ -1175,7 +1183,7 @@ class expression(object):
|
|||
|
||||
if left in model._columns:
|
||||
format = need_wildcard and '%s' or model._columns[left]._symbol_set[0]
|
||||
if self.has_unaccent and sql_operator in ('ilike', 'not ilike'):
|
||||
if self.has_unaccent and sql_operator.endswith('like'):
|
||||
query = '(unaccent(%s."%s") %s unaccent(%s))' % (table_alias, left, sql_operator, format)
|
||||
else:
|
||||
query = '(%s."%s" %s %s)' % (table_alias, left, sql_operator, format)
|
||||
|
|
|
@ -602,7 +602,10 @@ class one2many(_column):
|
|||
else:
|
||||
cr.execute('update '+_table+' set '+self._fields_id+'=null where id=%s', (act[1],))
|
||||
elif act[0] == 4:
|
||||
cr.execute("select 1 from {0} where id=%s and {1}=%s".format(_table, self._fields_id), (act[1], id))
|
||||
# table of the field (parent_model in case of inherit)
|
||||
field_model = self._fields_id in obj.pool[self._obj]._columns and self._obj or obj.pool[self._obj]._all_columns[self._fields_id].parent_model
|
||||
field_table = obj.pool[field_model]._table
|
||||
cr.execute("select 1 from {0} where id=%s and {1}=%s".format(field_table, self._fields_id), (act[1], id))
|
||||
if not cr.fetchone():
|
||||
# Must use write() to recompute parent_store structure if needed and check access rules
|
||||
obj.write(cr, user, [act[1]], {self._fields_id:id}, context=context or {})
|
||||
|
|
|
@ -3256,7 +3256,7 @@ class BaseModel(object):
|
|||
msg = "Table '%s': dropping index for column '%s' of type '%s' as it is not required anymore"
|
||||
_schema.debug(msg, self._table, k, f._type)
|
||||
|
||||
if isinstance(f, fields.many2one):
|
||||
if isinstance(f, fields.many2one) or (isinstance(f, fields.function) and f._type == 'many2one' and f.store):
|
||||
dest_model = self.pool[f._obj]
|
||||
if dest_model._table != 'ir_actions':
|
||||
self._m2o_fix_foreign_key(cr, self._table, k, dest_model, f.ondelete)
|
||||
|
@ -3291,7 +3291,7 @@ class BaseModel(object):
|
|||
todo_end.append((order, self._update_store, (f, k)))
|
||||
|
||||
# and add constraints if needed
|
||||
if isinstance(f, fields.many2one):
|
||||
if isinstance(f, fields.many2one) or (isinstance(f, fields.function) and f._type == 'many2one' and f.store):
|
||||
if f._obj not in self.pool:
|
||||
raise except_orm('Programming Error', 'There is no reference available for %s' % (f._obj,))
|
||||
dest_model = self.pool[f._obj]
|
||||
|
|
|
@ -85,50 +85,30 @@ def _open_image(filename, path=None):
|
|||
class NumberedCanvas(canvas.Canvas):
|
||||
def __init__(self, *args, **kwargs):
|
||||
canvas.Canvas.__init__(self, *args, **kwargs)
|
||||
self._codes = []
|
||||
self._flag=False
|
||||
self._pageCount=0
|
||||
self._currentPage =0
|
||||
self._pageCounter=0
|
||||
self.pages={}
|
||||
self._saved_page_states = []
|
||||
|
||||
def showPage(self):
|
||||
self._currentPage +=1
|
||||
if not self._flag:
|
||||
self._pageCount += 1
|
||||
else:
|
||||
self.pages.update({self._currentPage:self._pageCount})
|
||||
self._codes.append({'code': self._code, 'stack': self._codeStack})
|
||||
self._saved_page_states.append(dict(self.__dict__))
|
||||
self._startPage()
|
||||
self._flag=False
|
||||
|
||||
def pageCount(self):
|
||||
if self.pages.get(self._pageCounter,False):
|
||||
self._pageNumber=0
|
||||
self._pageCounter +=1
|
||||
key=self._pageCounter
|
||||
if not self.pages.get(key,False):
|
||||
while not self.pages.get(key,False):
|
||||
key += 1
|
||||
def save(self):
|
||||
"""add page info to each page (page x of y)"""
|
||||
for state in self._saved_page_states:
|
||||
self.__dict__.update(state)
|
||||
self.draw_page_number()
|
||||
canvas.Canvas.showPage(self)
|
||||
canvas.Canvas.save(self)
|
||||
|
||||
def draw_page_number(self):
|
||||
page_count = len(self._saved_page_states)
|
||||
self.setFont("Helvetica", 8)
|
||||
self.drawRightString((self._pagesize[0]-30), (self._pagesize[1]-40),
|
||||
" %(this)i / %(total)i" % {
|
||||
'this': self._pageNumber+1,
|
||||
'total': self.pages.get(key,False),
|
||||
'total': page_count,
|
||||
}
|
||||
)
|
||||
|
||||
def save(self):
|
||||
"""add page info to each page (page x of y)"""
|
||||
# reset page counter
|
||||
self._pageNumber = 0
|
||||
for code in self._codes:
|
||||
self._code = code['code']
|
||||
self._codeStack = code['stack']
|
||||
self.pageCount()
|
||||
canvas.Canvas.showPage(self)
|
||||
# self.restoreState()
|
||||
self._doc.SaveToFile(self._filename, self)
|
||||
|
||||
class PageCount(platypus.Flowable):
|
||||
def __init__(self, story_count=0):
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
# OPENERP_DATABASE=yy PYTHONPATH=../:. unit2 test_ir_sequence
|
||||
# This assume an existing database.
|
||||
import psycopg2
|
||||
import psycopg2.errorcodes
|
||||
import unittest2
|
||||
|
||||
import openerp
|
||||
|
@ -111,11 +112,11 @@ class test_ir_sequence_no_gap(unittest2.TestCase):
|
|||
cr0 = cursor()
|
||||
cr1 = cursor()
|
||||
cr1._default_log_exceptions = False # Prevent logging a traceback
|
||||
msg_re = '^could not obtain lock on row in relation "ir_sequence"$'
|
||||
with self.assertRaisesRegexp(psycopg2.OperationalError, msg_re):
|
||||
with self.assertRaises(psycopg2.OperationalError) as e:
|
||||
n0 = registry('ir.sequence').next_by_code(cr0, ADMIN_USER_ID, 'test_sequence_type_2', {})
|
||||
assert n0
|
||||
n1 = registry('ir.sequence').next_by_code(cr1, ADMIN_USER_ID, 'test_sequence_type_2', {})
|
||||
self.assertEqual(e.exception.pgcode, psycopg2.errorcodes.LOCK_NOT_AVAILABLE, msg="postgresql returned an incorrect errcode")
|
||||
cr0.close()
|
||||
cr1.close()
|
||||
|
||||
|
|
Loading…
Reference in New Issue