[MERGE] Latest fixes from 6.1
bzr revid: odo@openerp.com-20120314142043-9jpk3dkss1hkvb3q
This commit is contained in:
commit
638a9102c5
|
@ -199,7 +199,7 @@
|
|||
<field name="code">cf</field>
|
||||
</record>
|
||||
<record id="cd" model="res.country">
|
||||
<field name="name">Congo, The Democratic Republic of the</field>
|
||||
<field name="name">Congo, Democratic Republic of the</field>
|
||||
<field name="code">cd</field>
|
||||
</record>
|
||||
<record id="cg" model="res.country">
|
||||
|
|
|
@ -54,11 +54,11 @@ class ir_attachment(osv.osv):
|
|||
ima.check(cr, uid, model, mode)
|
||||
self.pool.get(model).check_access_rule(cr, uid, mids, mode, context=context)
|
||||
|
||||
def search(self, cr, uid, args, offset=0, limit=None, order=None,
|
||||
context=None, count=False):
|
||||
ids = super(ir_attachment, self).search(cr, uid, args, offset=offset,
|
||||
limit=limit, order=order,
|
||||
context=context, count=False)
|
||||
def _search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False, access_rights_uid=None):
|
||||
ids = super(ir_attachment, self)._search(cr, uid, args, offset=offset,
|
||||
limit=limit, order=order,
|
||||
context=context, count=count,
|
||||
access_rights_uid=access_rights_uid)
|
||||
if not ids:
|
||||
if count:
|
||||
return 0
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2011 OpenERP S.A (<http://www.openerp.com>)
|
||||
# Copyright (C) 2011-2012 OpenERP S.A (<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
|
||||
|
@ -232,6 +232,11 @@ class ir_mail_server(osv.osv):
|
|||
|
||||
if user:
|
||||
# Attempt authentication - will raise if AUTH service not supported
|
||||
# The user/password must be converted to bytestrings in order to be usable for
|
||||
# certain hashing schemes, like HMAC.
|
||||
# See also bug #597143 and python issue #5285
|
||||
user = tools.ustr(user).encode('utf-8')
|
||||
password = tools.ustr(password).encode('utf-8')
|
||||
connection.login(user, password)
|
||||
return connection
|
||||
|
||||
|
@ -364,7 +369,6 @@ class ir_mail_server(osv.osv):
|
|||
:param smtp_user: optional SMTP user, if mail_server_id is not passed
|
||||
:param smtp_password: optional SMTP password to use, if mail_server_id is not passed
|
||||
:param smtp_debug: optional SMTP debug flag, if mail_server_id is not passed
|
||||
:param debug: whether to turn on the SMTP level debugging, output to DEBUG log level
|
||||
:return: the Message-ID of the message that was just sent, if successfully sent, otherwise raises
|
||||
MailDeliveryException and logs root cause.
|
||||
"""
|
||||
|
|
|
@ -35,12 +35,14 @@ import pooler
|
|||
_logger = logging.getLogger(__name__)
|
||||
|
||||
def _get_fields_type(self, cr, uid, context=None):
|
||||
# Avoid too many nested `if`s below, as RedHat's Python 2.6
|
||||
# break on it. See bug 939653.
|
||||
return sorted([(k,k) for k,v in fields.__dict__.iteritems()
|
||||
if type(v) == types.TypeType
|
||||
if issubclass(v, fields._column)
|
||||
if v != fields._column
|
||||
if not v._deprecated
|
||||
if not issubclass(v, fields.function)])
|
||||
if type(v) == types.TypeType and \
|
||||
issubclass(v, fields._column) and \
|
||||
v != fields._column and \
|
||||
not v._deprecated and \
|
||||
not issubclass(v, fields.function)])
|
||||
|
||||
def _in_modules(self, cr, uid, ids, field_name, arg, context=None):
|
||||
#pseudo-method used by fields.function in ir.model/ir.model.fields
|
||||
|
|
|
@ -75,7 +75,7 @@ class ir_rule(osv.osv):
|
|||
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=128, select=1),
|
||||
'model_id': fields.many2one('ir.model', 'Object',select=1, required=True),
|
||||
'model_id': fields.many2one('ir.model', 'Object',select=1, required=True, ondelete="cascade"),
|
||||
'global': fields.function(_get_value, string='Global', type='boolean', store=True, help="If no group is specified the rule is global and applied to everyone"),
|
||||
'groups': fields.many2many('res.groups', 'rule_group_rel', 'rule_group_id', 'group_id', 'Groups'),
|
||||
'domain_force': fields.text('Domain'),
|
||||
|
|
|
@ -42,6 +42,9 @@ class base_module_upgrade(osv.osv_memory):
|
|||
@return: New arch of view.
|
||||
"""
|
||||
res = super(base_module_upgrade, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar,submenu=False)
|
||||
if view_type != 'form':
|
||||
return res
|
||||
|
||||
record_id = context and context.get('active_id', False) or False
|
||||
active_model = context.get('active_model')
|
||||
if (not record_id) or (not active_model):
|
||||
|
|
|
@ -151,7 +151,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=
|
|||
_logger.debug('loading %d packages...', len(graph))
|
||||
|
||||
# get db timestamp
|
||||
cr.execute("select now()::timestamp")
|
||||
cr.execute("select (now() at time zone 'UTC')::timestamp")
|
||||
dt_before_load = cr.fetchone()[0]
|
||||
|
||||
# register, instantiate and initialize models for each modules
|
||||
|
|
|
@ -364,7 +364,15 @@ class time(_column):
|
|||
class binary(_column):
|
||||
_type = 'binary'
|
||||
_symbol_c = '%s'
|
||||
_symbol_f = lambda symb: symb and Binary(symb) or None
|
||||
|
||||
# Binary values may be byte strings (python 2.6 byte array), but
|
||||
# the legacy OpenERP convention is to transfer and store binaries
|
||||
# as base64-encoded strings. The base64 string may be provided as a
|
||||
# unicode in some circumstances, hence the str() cast in symbol_f.
|
||||
# This str coercion will only work for pure ASCII unicode strings,
|
||||
# on purpose - non base64 data must be passed as a 8bit byte strings.
|
||||
_symbol_f = lambda symb: symb and Binary(str(symb)) or None
|
||||
|
||||
_symbol_set = (_symbol_c, _symbol_f)
|
||||
_symbol_get = lambda self, x: x and str(x)
|
||||
|
||||
|
|
|
@ -750,7 +750,7 @@ class BaseModel(object):
|
|||
name_id = 'model_'+self._name.replace('.', '_')
|
||||
cr.execute('select * from ir_model_data where name=%s and module=%s', (name_id, context['module']))
|
||||
if not cr.rowcount:
|
||||
cr.execute("INSERT INTO ir_model_data (name,date_init,date_update,module,model,res_id) VALUES (%s, now(), now(), %s, %s, %s)", \
|
||||
cr.execute("INSERT INTO ir_model_data (name,date_init,date_update,module,model,res_id) VALUES (%s, (now() at time zone 'UTC'), (now() at time zone 'UTC'), %s, %s, %s)", \
|
||||
(name_id, context['module'], 'ir.model', model_id)
|
||||
)
|
||||
|
||||
|
@ -816,7 +816,7 @@ class BaseModel(object):
|
|||
cr.execute("select name from ir_model_data where name=%s", (name1,))
|
||||
if cr.fetchone():
|
||||
name1 = name1 + "_" + str(id)
|
||||
cr.execute("INSERT INTO ir_model_data (name,date_init,date_update,module,model,res_id) VALUES (%s, now(), now(), %s, %s, %s)", \
|
||||
cr.execute("INSERT INTO ir_model_data (name,date_init,date_update,module,model,res_id) VALUES (%s, (now() at time zone 'UTC'), (now() at time zone 'UTC'), %s, %s, %s)", \
|
||||
(name1, context['module'], 'ir.model.fields', id)
|
||||
)
|
||||
else:
|
||||
|
@ -872,11 +872,11 @@ class BaseModel(object):
|
|||
|
||||
for parent_name in ((type(parent_names)==list) and parent_names or [parent_names]):
|
||||
parent_model = pool.get(parent_name)
|
||||
if not getattr(cls, '_original_module', None) and name == parent_model._name:
|
||||
cls._original_module = parent_model._original_module
|
||||
if not parent_model:
|
||||
raise TypeError('The model "%s" specifies an unexisting parent class "%s"\n'
|
||||
'You may need to add a dependency on the parent class\' module.' % (name, parent_name))
|
||||
if not getattr(cls, '_original_module', None) and name == parent_model._name:
|
||||
cls._original_module = parent_model._original_module
|
||||
parent_class = parent_model.__class__
|
||||
nattr = {}
|
||||
for s in attributes:
|
||||
|
@ -2690,7 +2690,7 @@ class BaseModel(object):
|
|||
elif val in dict(self._columns[field].selection(self, cr, uid, context=context)):
|
||||
return
|
||||
raise except_orm(_('ValidateError'),
|
||||
_('The value "%s" for the field "%s.%s" is not in the selection') % (value, self._table, field))
|
||||
_('The value "%s" for the field "%s.%s" is not in the selection') % (value, self._table, field))
|
||||
|
||||
def _check_removed_columns(self, cr, log=False):
|
||||
# iterate on the database columns to drop the NOT NULL constraints
|
||||
|
@ -2733,6 +2733,50 @@ class BaseModel(object):
|
|||
_schema.debug("Table '%s': added foreign key '%s' with definition=REFERENCES \"%s\" ON DELETE %s",
|
||||
source_table, source_field, dest_model._table, ondelete)
|
||||
|
||||
def _drop_constraint(self, cr, source_table, constraint_name):
|
||||
cr.execute("ALTER TABLE %s DROP CONSTRAINT %s" % (source_table,constraint_name))
|
||||
|
||||
def _m2o_fix_foreign_key(self, cr, source_table, source_field, dest_model, ondelete):
|
||||
# Find FK constraint(s) currently established for the m2o field,
|
||||
# and see whether they are stale or not
|
||||
cr.execute("""SELECT confdeltype as ondelete_rule, conname as constraint_name,
|
||||
cl2.relname as foreign_table
|
||||
FROM pg_constraint as con, pg_class as cl1, pg_class as cl2,
|
||||
pg_attribute as att1, pg_attribute as att2
|
||||
WHERE con.conrelid = cl1.oid
|
||||
AND cl1.relname = %s
|
||||
AND con.confrelid = cl2.oid
|
||||
AND array_lower(con.conkey, 1) = 1
|
||||
AND con.conkey[1] = att1.attnum
|
||||
AND att1.attrelid = cl1.oid
|
||||
AND att1.attname = %s
|
||||
AND array_lower(con.confkey, 1) = 1
|
||||
AND con.confkey[1] = att2.attnum
|
||||
AND att2.attrelid = cl2.oid
|
||||
AND att2.attname = %s
|
||||
AND con.contype = 'f'""", (source_table, source_field, 'id'))
|
||||
constraints = cr.dictfetchall()
|
||||
if constraints:
|
||||
if len(constraints) == 1:
|
||||
# Is it the right constraint?
|
||||
cons, = constraints
|
||||
if cons['ondelete_rule'] != POSTGRES_CONFDELTYPES.get((ondelete or 'set null').upper(), 'a')\
|
||||
or cons['foreign_table'] != dest_model._table:
|
||||
_schema.debug("Table '%s': dropping obsolete FK constraint: '%s'",
|
||||
source_table, cons['constraint_name'])
|
||||
self._drop_constraint(cr, source_table, cons['constraint_name'])
|
||||
self._m2o_add_foreign_key_checked(source_field, dest_model, ondelete)
|
||||
# else it's all good, nothing to do!
|
||||
else:
|
||||
# Multiple FKs found for the same field, drop them all, and re-create
|
||||
for cons in constraints:
|
||||
_schema.debug("Table '%s': dropping duplicate FK constraints: '%s'",
|
||||
source_table, cons['constraint_name'])
|
||||
self._drop_constraint(cr, source_table, cons['constraint_name'])
|
||||
self._m2o_add_foreign_key_checked(source_field, dest_model, ondelete)
|
||||
|
||||
|
||||
|
||||
def _auto_init(self, cr, context=None):
|
||||
"""
|
||||
|
||||
|
@ -2932,31 +2976,8 @@ class BaseModel(object):
|
|||
|
||||
if isinstance(f, fields.many2one):
|
||||
dest_model = self.pool.get(f._obj)
|
||||
ref = dest_model._table
|
||||
if ref != 'ir_actions':
|
||||
cr.execute('SELECT confdeltype, conname FROM pg_constraint as con, pg_class as cl1, pg_class as cl2, '
|
||||
'pg_attribute as att1, pg_attribute as att2 '
|
||||
'WHERE con.conrelid = cl1.oid '
|
||||
'AND cl1.relname = %s '
|
||||
'AND con.confrelid = cl2.oid '
|
||||
'AND cl2.relname = %s '
|
||||
'AND array_lower(con.conkey, 1) = 1 '
|
||||
'AND con.conkey[1] = att1.attnum '
|
||||
'AND att1.attrelid = cl1.oid '
|
||||
'AND att1.attname = %s '
|
||||
'AND array_lower(con.confkey, 1) = 1 '
|
||||
'AND con.confkey[1] = att2.attnum '
|
||||
'AND att2.attrelid = cl2.oid '
|
||||
'AND att2.attname = %s '
|
||||
"AND con.contype = 'f'", (self._table, ref, k, 'id'))
|
||||
res2 = cr.dictfetchall()
|
||||
if res2:
|
||||
if res2[0]['confdeltype'] != POSTGRES_CONFDELTYPES.get((f.ondelete or 'set null').upper(), 'a'):
|
||||
cr.execute('ALTER TABLE "' + self._table + '" DROP CONSTRAINT "' + res2[0]['conname'] + '"')
|
||||
self._m2o_add_foreign_key_checked(k, dest_model, f.ondelete)
|
||||
cr.commit()
|
||||
_schema.debug("Table '%s': column '%s': XXX",
|
||||
self._table, k)
|
||||
if dest_model._table != 'ir_actions':
|
||||
self._m2o_fix_foreign_key(cr, self._table, k, dest_model, f.ondelete)
|
||||
|
||||
# The field doesn't exist in database. Create it if necessary.
|
||||
else:
|
||||
|
@ -3152,6 +3173,9 @@ class BaseModel(object):
|
|||
_sql_constraints.
|
||||
|
||||
"""
|
||||
def unify_cons_text(txt):
|
||||
return txt.lower().replace(', ',',').replace(' (','(')
|
||||
|
||||
for (key, con, _) in self._sql_constraints:
|
||||
conname = '%s_%s' % (self._table, key)
|
||||
|
||||
|
@ -3181,7 +3205,7 @@ class BaseModel(object):
|
|||
# constraint does not exists:
|
||||
sql_actions['add']['execute'] = True
|
||||
sql_actions['add']['msg_err'] = sql_actions['add']['msg_err'] % (sql_actions['add']['query'], )
|
||||
elif con.lower() not in [item['condef'].lower() for item in existing_constraints]:
|
||||
elif unify_cons_text(con) not in [unify_cons_text(item['condef']) for item in existing_constraints]:
|
||||
# constraint exists but its definition has changed:
|
||||
sql_actions['drop']['execute'] = True
|
||||
sql_actions['drop']['msg_ok'] = sql_actions['drop']['msg_ok'] % (existing_constraints[0]['condef'].lower(), )
|
||||
|
@ -3416,8 +3440,8 @@ class BaseModel(object):
|
|||
return "date_trunc('second', %s) as %s" % (f_qual, f)
|
||||
if f == self.CONCURRENCY_CHECK_FIELD:
|
||||
if self._log_access:
|
||||
return "COALESCE(%s.write_date, %s.create_date, now())::timestamp AS %s" % (self._table, self._table, f,)
|
||||
return "now()::timestamp AS %s" % (f,)
|
||||
return "COALESCE(%s.write_date, %s.create_date, (now() at time zone 'UTC'))::timestamp AS %s" % (self._table, self._table, f,)
|
||||
return "(now() at time zone 'UTC')::timestamp AS %s" % (f,)
|
||||
if isinstance(self._columns[f], fields.binary) and context.get('bin_size', False):
|
||||
return 'length(%s) as "%s"' % (f_qual, f)
|
||||
return f_qual
|
||||
|
@ -3598,7 +3622,7 @@ class BaseModel(object):
|
|||
return
|
||||
if not (context.get(self.CONCURRENCY_CHECK_FIELD) and self._log_access):
|
||||
return
|
||||
check_clause = "(id = %s AND %s < COALESCE(write_date, create_date, now())::timestamp)"
|
||||
check_clause = "(id = %s AND %s < COALESCE(write_date, create_date, (now() at time zone 'UTC'))::timestamp)"
|
||||
for sub_ids in cr.split_for_in_conditions(ids):
|
||||
ids_to_check = []
|
||||
for id in sub_ids:
|
||||
|
@ -3882,7 +3906,7 @@ class BaseModel(object):
|
|||
|
||||
if self._log_access:
|
||||
upd0.append('write_uid=%s')
|
||||
upd0.append('write_date=now()')
|
||||
upd0.append("write_date=(now() at time zone 'UTC')")
|
||||
upd1.append(user)
|
||||
|
||||
if len(upd0):
|
||||
|
@ -4149,7 +4173,7 @@ class BaseModel(object):
|
|||
self._check_selection_field_value(cr, user, field, vals[field], context=context)
|
||||
if self._log_access:
|
||||
upd0 += ',create_uid,create_date'
|
||||
upd1 += ',%s,now()'
|
||||
upd1 += ",%s,(now() at time zone 'UTC')"
|
||||
upd2.append(user)
|
||||
cr.execute('insert into "'+self._table+'" (id'+upd0+") values ("+str(id_new)+upd1+')', tuple(upd2))
|
||||
self.check_access_rule(cr, user, [id_new], 'create', context=context)
|
||||
|
@ -4382,13 +4406,11 @@ class BaseModel(object):
|
|||
domain = domain[:]
|
||||
# if the object has a field named 'active', filter out all inactive
|
||||
# records unless they were explicitely asked for
|
||||
if 'active' in self._columns and (active_test and context.get('active_test', True)):
|
||||
if 'active' in self._all_columns and (active_test and context.get('active_test', True)):
|
||||
if domain:
|
||||
active_in_args = False
|
||||
for a in domain:
|
||||
if a[0] == 'active':
|
||||
active_in_args = True
|
||||
if not active_in_args:
|
||||
# the item[0] trick below works for domain items and '&'/'|'/'!'
|
||||
# operators too
|
||||
if not any(item[0] == 'active' for item in domain):
|
||||
domain.insert(0, ('active', '=', 1))
|
||||
else:
|
||||
domain = [('active', '=', 1)]
|
||||
|
@ -4852,15 +4874,15 @@ class BaseModel(object):
|
|||
def _transient_clean_rows_older_than(self, cr, seconds):
|
||||
assert self._transient, "Model %s is not transient, it cannot be vacuumed!" % self._name
|
||||
cr.execute("SELECT id FROM " + self._table + " WHERE"
|
||||
" COALESCE(write_date, create_date, now())::timestamp <"
|
||||
" (now() - interval %s)", ("%s seconds" % seconds,))
|
||||
" COALESCE(write_date, create_date, (now() at time zone 'UTC'))::timestamp <"
|
||||
" ((now() at time zone 'UTC') - interval %s)", ("%s seconds" % seconds,))
|
||||
ids = [x[0] for x in cr.fetchall()]
|
||||
self.unlink(cr, SUPERUSER_ID, ids)
|
||||
|
||||
def _transient_clean_old_rows(self, cr, count):
|
||||
assert self._transient, "Model %s is not transient, it cannot be vacuumed!" % self._name
|
||||
cr.execute(
|
||||
"SELECT id, COALESCE(write_date, create_date, now())::timestamp"
|
||||
"SELECT id, COALESCE(write_date, create_date, (now() at time zone 'UTC'))::timestamp"
|
||||
" AS t FROM " + self._table +
|
||||
" ORDER BY t LIMIT %s", (count,))
|
||||
ids = [x[0] for x in cr.fetchall()]
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
# Copyright (C) 2010 OpenERP s.a. (<http://openerp.com>).
|
||||
# Copyright (C) 2010-2012 OpenERP s.a. (<http://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
|
||||
|
@ -383,7 +383,7 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
|
|||
|
||||
res = mail_server_pool.send_email(cr, uid or 1, email_msg, mail_server_id=None,
|
||||
smtp_server=smtp_server, smtp_port=smtp_port, smtp_user=smtp_user, smtp_password=smtp_password,
|
||||
smtp_encryption=('ssl' if ssl else None), debug=debug)
|
||||
smtp_encryption=('ssl' if ssl else None), smtp_debug=debug)
|
||||
except Exception:
|
||||
_logger.exception("tools.email_send failed to deliver email")
|
||||
return False
|
||||
|
|
|
@ -20,9 +20,7 @@
|
|||
##############################################################################
|
||||
|
||||
def drop_view_if_exists(cr, viewname):
|
||||
cr.execute("select count(1) from pg_class where relkind=%s and relname=%s", ('v', viewname,))
|
||||
if cr.fetchone()[0]:
|
||||
cr.execute("DROP view %s" % (viewname,))
|
||||
cr.commit()
|
||||
cr.execute("DROP view IF EXISTS %s CASCADE" % (viewname,))
|
||||
cr.commit()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
Loading…
Reference in New Issue