[MERGE] trunk

bzr revid: qdp-launchpad@openerp.com-20121005115057-am34fqwxopdgkh3y
This commit is contained in:
Quentin (OpenERP) 2012-10-05 13:50:57 +02:00
commit 9d678d1fd1
3 changed files with 40 additions and 36 deletions

View File

@ -557,7 +557,9 @@ class ir_model_access(osv.osv):
model_name = model
# TransientModel records have no access rights, only an implicit access rule
if self.pool.get(model_name).is_transient():
if not self.pool.get(model_name):
_logger.error('Missing model %s' % (model_name, ))
elif self.pool.get(model_name).is_transient():
return True
# We check if a specific rule exists

View File

@ -265,7 +265,7 @@ class ir_ui_menu(osv.osv):
}
if menu.action and menu.action.type in ('ir.actions.act_window','ir.actions.client') and menu.action.res_model:
obj = self.pool.get(menu.action.res_model)
if obj._needaction:
if obj and obj._needaction:
if menu.action.type=='ir.actions.act_window':
dom = menu.action.domain and eval(menu.action.domain, {'uid': uid}) or []
else:

View File

@ -51,6 +51,7 @@ import pickle
import re
import simplejson
import time
import traceback
import types
from lxml import etree
@ -371,8 +372,10 @@ class browse_record(object):
else:
return attr
else:
error_msg = "Field '%s' does not exist in object '%s'" % (name, self)
error_msg = "Field '%s' does not exist in object '%s'" % (name, self)
self.__logger.warning(error_msg)
if self.__logger.isEnabledFor(logging.DEBUG):
self.__logger.debug(''.join(traceback.format_stack()))
raise KeyError(error_msg)
# if the field is a classic one or a many2one, we'll fetch all classic and many2one fields
@ -709,7 +712,7 @@ class BaseModel(object):
def log(self, cr, uid, id, message, secondary=False, context=None):
return _logger.warning("log() is deprecated. Please use OpenChatter notification system instead of the res.log mechanism.")
def view_init(self, cr, uid, fields_list, context=None):
"""Override this method to do specific things when a view on the object is opened."""
pass
@ -899,7 +902,7 @@ class BaseModel(object):
# If new class defines a constraint with
# same function name, we let it override
# the old one.
new[c2] = c
exist = True
break
@ -1593,7 +1596,7 @@ class BaseModel(object):
def user_has_groups(self, cr, uid, groups, context=None):
"""Return true if the user is at least member of one of the groups
in groups_str. Typically used to resolve ``groups`` attribute
in view and model definitions.
in view and model definitions.
:param str groups: comma-separated list of fully-qualified group
external IDs, e.g.: ``base.group_user,base.group_system``
@ -1636,7 +1639,7 @@ class BaseModel(object):
the field should be completely removed from the view, as it is
completely unavailable for non-members
:return: True if field should be included in the result of fields_view_get
:return: True if field should be included in the result of fields_view_get
"""
if node.tag == 'field' and node.get('name') in self._all_columns:
column = self._all_columns[node.get('name')].column
@ -1911,7 +1914,7 @@ class BaseModel(object):
def _get_default_calendar_view(self, cr, user, context=None):
""" Generates a default calendar view by trying to infer
calendar fields from a number of pre-set attribute names
:param cr: database cursor
:param int user: user id
:param dict context: connection context
@ -1990,7 +1993,7 @@ class BaseModel(object):
def raise_view_error(error_msg, child_view_id):
view, child_view = self.pool.get('ir.ui.view').browse(cr, user, [view_id, child_view_id], context)
error_msg = error_msg % {'parent_xml_id': view.xml_id}
error_msg = error_msg % {'parent_xml_id': view.xml_id}
raise AttributeError("View definition error for inherited view '%s' on model '%s': %s"
% (child_view.xml_id, self._name, error_msg))
@ -2026,7 +2029,7 @@ class BaseModel(object):
if all(node.get(attr) == spec.get(attr) \
for attr in spec.attrib
if attr not in ('position','version')):
# Version spec should match parent's root element's version
# Version spec should match parent's root element's version
if spec.get('version') and spec.get('version') != source.get('version'):
return None
return node
@ -2100,7 +2103,7 @@ class BaseModel(object):
raise_view_error("Mismatching view API version for element '%s': %r vs %r in parent view '%%(parent_xml_id)s'" % \
(tag, spec.get('version'), source.get('version')), inherit_id)
raise_view_error("Element '%s' not found in parent view '%%(parent_xml_id)s'" % tag, inherit_id)
return source
def apply_view_inheritance(cr, user, source, inherit_id):
@ -2315,7 +2318,7 @@ class BaseModel(object):
or ``'='``.
:param int limit: optional max number of records to return
:rtype: list
:return: list of pairs ``(id,text_repr)`` for all matching records.
:return: list of pairs ``(id,text_repr)`` for all matching records.
"""
return self._name_search(cr, user, name, args, operator, context, limit)
@ -2445,7 +2448,7 @@ class BaseModel(object):
# This is useful to implement kanban views for instance, where all columns
# should be displayed even if they don't contain any record.
# Grab the list of all groups that should be displayed, including all present groups
# Grab the list of all groups that should be displayed, including all present groups
present_group_ids = [x[groupby][0] for x in read_group_result if x[groupby]]
all_groups,folded = self._group_by_full[groupby](self, cr, uid, present_group_ids, domain,
read_group_order=read_group_order,
@ -2821,28 +2824,28 @@ class BaseModel(object):
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
# 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
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
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'",
@ -2964,14 +2967,14 @@ class BaseModel(object):
('numeric', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]),
('float8', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]),
]
if f_pg_type == 'varchar' and f._type == 'char' and f_pg_size < f.size:
if f_pg_type == 'varchar' and f._type == 'char' and ((f.size is None and f_pg_size) or f_pg_size < f.size):
cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k))
cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, pg_varchar(f.size)))
cr.execute('UPDATE "%s" SET "%s"=temp_change_size::%s' % (self._table, k, pg_varchar(f.size)))
cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,))
cr.commit()
_schema.debug("Table '%s': column '%s' (type varchar) changed size from %s to %s",
self._table, k, f_pg_size, f.size)
self._table, k, f_pg_size or 'unlimited', f.size or 'unlimited')
for c in casts:
if (f_pg_type==c[0]) and (f._type==c[1]):
if f_pg_type != f_obj_type:
@ -3204,8 +3207,7 @@ class BaseModel(object):
# attlen is the number of bytes necessary to represent the type when
# the type has a fixed size. If the type has a varying size attlen is
# -1 and atttypmod is the size limit + 4, or -1 if there is no limit.
# Thus the query can return a negative size for a unlimited varchar.
cr.execute("SELECT c.relname,a.attname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,t.typname,CASE WHEN a.attlen=-1 THEN a.atttypmod-4 ELSE a.attlen END as size " \
cr.execute("SELECT c.relname,a.attname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,t.typname,CASE WHEN a.attlen=-1 THEN (CASE WHEN a.atttypmod=-1 THEN 0 ELSE a.atttypmod-4 END) ELSE a.attlen END as size " \
"FROM pg_class c,pg_attribute a,pg_type t " \
"WHERE c.relname=%s " \
"AND c.oid=a.attrelid " \
@ -3215,7 +3217,7 @@ class BaseModel(object):
def _o2m_raise_on_missing_reference(self, cr, f):
# TODO this check should be a method on fields.one2many.
other = self.pool.get(f._obj)
if other:
# TODO the condition could use fields_get_keys().
@ -3732,7 +3734,7 @@ class BaseModel(object):
the length of `ids`, and raise an appropriate exception if it does not.
"""
if cr.rowcount != len(ids):
# Attempt to distinguish record rule restriction vs deleted records,
# Attempt to distinguish record rule restriction vs deleted records,
# to provide a more specific error message
cr.execute('SELECT id FROM ' + self._table + ' WHERE id IN %s', (tuple(ids),))
if cr.rowcount != len(ids):
@ -3787,13 +3789,13 @@ class BaseModel(object):
self._check_record_rules_result_count(cr, uid, sub_ids, operation, context=context)
def _workflow_trigger(self, cr, uid, ids, trigger, context=None):
"""Call given workflow trigger as a result of a CRUD operation"""
"""Call given workflow trigger as a result of a CRUD operation"""
wf_service = netsvc.LocalService("workflow")
for res_id in ids:
getattr(wf_service, trigger)(uid, self._name, res_id, cr)
def _workflow_signal(self, cr, uid, ids, signal, context=None):
"""Send given workflow signal"""
"""Send given workflow signal"""
wf_service = netsvc.LocalService("workflow")
for res_id in ids:
wf_service.trg_validate(uid, self._name, res_id, signal, cr)
@ -3824,7 +3826,7 @@ class BaseModel(object):
self.check_access_rights(cr, uid, 'unlink')
ir_property = self.pool.get('ir.property')
# Check if the records are used as default properties.
domain = [('res_id', '=', False),
('value_reference', 'in', ['%s,%s' % (self._name, i) for i in ids]),
@ -4952,7 +4954,7 @@ class BaseModel(object):
:return: map of ids to their fully qualified XML ID,
defaulting to an empty string when there's none
(to be usable as a function field),
(to be usable as a function field),
e.g.::
{ 'id': 'module.ext_id',