[MERGE] forward port of branch saas-3 up to revid 5060 chs@openerp.com-20140206131116-we6rlic5fu09xh8q
bzr revid: chs@openerp.com-20140206131219-9rpwsfe9vc7uf0cr
This commit is contained in:
commit
9289a2608d
|
@ -13,6 +13,7 @@ from openerp.osv import orm
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
from openerp.tools.misc import DEFAULT_SERVER_DATE_FORMAT,\
|
from openerp.tools.misc import DEFAULT_SERVER_DATE_FORMAT,\
|
||||||
DEFAULT_SERVER_DATETIME_FORMAT
|
DEFAULT_SERVER_DATETIME_FORMAT
|
||||||
|
from openerp.tools import html_sanitize
|
||||||
|
|
||||||
REFERENCING_FIELDS = set([None, 'id', '.id'])
|
REFERENCING_FIELDS = set([None, 'id', '.id'])
|
||||||
def only_ref_fields(record):
|
def only_ref_fields(record):
|
||||||
|
@ -188,7 +189,7 @@ class ir_fields_converter(orm.Model):
|
||||||
|
|
||||||
def _str_id(self, cr, uid, model, column, value, context=None):
|
def _str_id(self, cr, uid, model, column, value, context=None):
|
||||||
return value, []
|
return value, []
|
||||||
_str_to_reference = _str_to_char = _str_to_text = _str_to_binary = _str_id
|
_str_to_reference = _str_to_char = _str_to_text = _str_to_binary = _str_to_html = _str_id
|
||||||
|
|
||||||
def _str_to_date(self, cr, uid, model, column, value, context=None):
|
def _str_to_date(self, cr, uid, model, column, value, context=None):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -337,7 +337,7 @@ class view(osv.osv):
|
||||||
if isinstance(spec, SKIPPED_ELEMENT_TYPES):
|
if isinstance(spec, SKIPPED_ELEMENT_TYPES):
|
||||||
continue
|
continue
|
||||||
if spec.tag == 'data':
|
if spec.tag == 'data':
|
||||||
specs += [ c for c in specs_tree ]
|
specs += [c for c in spec]
|
||||||
continue
|
continue
|
||||||
node = self.locate_node(source, spec)
|
node = self.locate_node(source, spec)
|
||||||
if node is not None:
|
if node is not None:
|
||||||
|
|
|
@ -129,7 +129,7 @@
|
||||||
<form string="Partners" version="7.0">
|
<form string="Partners" version="7.0">
|
||||||
<sheet>
|
<sheet>
|
||||||
<field name="image" widget='image' class="oe_left oe_avatar" options='{"preview_image": "image_medium", "size": [90, 90]}'/>
|
<field name="image" widget='image' class="oe_left oe_avatar" options='{"preview_image": "image_medium", "size": [90, 90]}'/>
|
||||||
<div class="oe_title">
|
<div class="oe_title oe_left">
|
||||||
<div class="oe_edit_only">
|
<div class="oe_edit_only">
|
||||||
<label for="name"/> (
|
<label for="name"/> (
|
||||||
<field name="is_company" on_change="onchange_type(is_company)" class="oe_inline"/> <label for="is_company" string="Is a Company?"/>)
|
<field name="is_company" on_change="onchange_type(is_company)" class="oe_inline"/> <label for="is_company" string="Is a Company?"/>)
|
||||||
|
|
|
@ -8,6 +8,7 @@ class test_base(common.TransactionCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(test_base,self).setUp()
|
super(test_base,self).setUp()
|
||||||
self.res_partner = self.registry('res.partner')
|
self.res_partner = self.registry('res.partner')
|
||||||
|
self.res_users = self.registry('res.users')
|
||||||
|
|
||||||
# samples use effective TLDs from the Mozilla public suffix
|
# samples use effective TLDs from the Mozilla public suffix
|
||||||
# list at http://publicsuffix.org
|
# list at http://publicsuffix.org
|
||||||
|
@ -282,6 +283,21 @@ class test_base(common.TransactionCase):
|
||||||
p0.refresh()
|
p0.refresh()
|
||||||
self.assertEquals(p0.vat, sunhelmvat2, 'Commercial fields must be automatically synced')
|
self.assertEquals(p0.vat, sunhelmvat2, 'Commercial fields must be automatically synced')
|
||||||
|
|
||||||
|
def test_60_read_group(self):
|
||||||
|
cr, uid = self.cr, self.uid
|
||||||
|
for user_data in [
|
||||||
|
{'name': 'Alice', 'login': 'alice', 'color': 1, 'function': 'Friend'},
|
||||||
|
{'name': 'Bob', 'login': 'bob', 'color': 2, 'function': 'Friend'},
|
||||||
|
{'name': 'Eve', 'login': 'eve', 'color': 3, 'function': 'Eavesdropper'},
|
||||||
|
]:
|
||||||
|
self.res_users.create(cr, uid, user_data)
|
||||||
|
|
||||||
|
groups_data = self.res_users.read_group(cr, uid, domain=[('login', 'in', ('alice', 'bob', 'eve'))], fields=['name', 'color', 'function'], groupby='function')
|
||||||
|
self.assertEqual(len(groups_data), 2, "Incorrect number of results when grouping on a field")
|
||||||
|
for group_data in groups_data:
|
||||||
|
self.assertIn('color', group_data, "Aggregated data for the column 'color' is not present in read_group return values")
|
||||||
|
self.assertEqual(group_data['color'], 3, "Incorrect sum for aggregated data for the column 'color'")
|
||||||
|
|
||||||
class test_partner_recursion(common.TransactionCase):
|
class test_partner_recursion(common.TransactionCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
|
@ -208,7 +208,7 @@ class WebRequest(object):
|
||||||
args = (request,) + args
|
args = (request,) + args
|
||||||
# Correct exception handling and concurency retry
|
# Correct exception handling and concurency retry
|
||||||
@service_model.check
|
@service_model.check
|
||||||
def checked_call(dbname, *a, **kw):
|
def checked_call(___dbname, *a, **kw):
|
||||||
return self.func(*a, **kw)
|
return self.func(*a, **kw)
|
||||||
|
|
||||||
# FIXME: code and rollback management could be cleaned
|
# FIXME: code and rollback management could be cleaned
|
||||||
|
@ -832,6 +832,40 @@ class OpenERPSession(werkzeug.contrib.sessions.Session):
|
||||||
|
|
||||||
return Model(self, model)
|
return Model(self, model)
|
||||||
|
|
||||||
|
def save_action(self, action):
|
||||||
|
"""
|
||||||
|
This method store an action object in the session and returns an integer
|
||||||
|
identifying that action. The method get_action() can be used to get
|
||||||
|
back the action.
|
||||||
|
|
||||||
|
:param the_action: The action to save in the session.
|
||||||
|
:type the_action: anything
|
||||||
|
:return: A key identifying the saved action.
|
||||||
|
:rtype: integer
|
||||||
|
"""
|
||||||
|
saved_actions = self.setdefault('saved_actions', {"next": 1, "actions": {}})
|
||||||
|
# we don't allow more than 10 stored actions
|
||||||
|
if len(saved_actions["actions"]) >= 10:
|
||||||
|
del saved_actions["actions"][min(saved_actions["actions"])]
|
||||||
|
key = saved_actions["next"]
|
||||||
|
saved_actions["actions"][key] = action
|
||||||
|
saved_actions["next"] = key + 1
|
||||||
|
self.modified = True
|
||||||
|
return key
|
||||||
|
|
||||||
|
def get_action(self, key):
|
||||||
|
"""
|
||||||
|
Gets back a previously saved action. This method can return None if the action
|
||||||
|
was saved since too much time (this case should be handled in a smart way).
|
||||||
|
|
||||||
|
:param key: The key given by save_action()
|
||||||
|
:type key: integer
|
||||||
|
:return: The saved action or None.
|
||||||
|
:rtype: anything
|
||||||
|
"""
|
||||||
|
saved_actions = self.get('saved_actions', {})
|
||||||
|
return saved_actions.get("actions", {}).get(key)
|
||||||
|
|
||||||
def session_gc(session_store):
|
def session_gc(session_store):
|
||||||
if random.random() < 0.001:
|
if random.random() < 0.001:
|
||||||
# we keep session one week
|
# we keep session one week
|
||||||
|
@ -973,9 +1007,12 @@ class Root(object):
|
||||||
def setup_db(self, httprequest):
|
def setup_db(self, httprequest):
|
||||||
db = httprequest.session.db
|
db = httprequest.session.db
|
||||||
# Check if session.db is legit
|
# Check if session.db is legit
|
||||||
if db and db not in db_filter([db], httprequest=httprequest):
|
if db:
|
||||||
httprequest.session.logout()
|
if db not in db_filter([db], httprequest=httprequest):
|
||||||
db = None
|
_logger.warn("Logged into database '%s', but dbfilter "
|
||||||
|
"rejects it; logging session out.", db)
|
||||||
|
httprequest.session.logout()
|
||||||
|
db = None
|
||||||
|
|
||||||
if not db:
|
if not db:
|
||||||
httprequest.session.db = db_monodb(httprequest)
|
httprequest.session.db = db_monodb(httprequest)
|
||||||
|
|
|
@ -2293,12 +2293,12 @@ class BaseModel(object):
|
||||||
f for f in fields
|
f for f in fields
|
||||||
if f not in ('id', 'sequence')
|
if f not in ('id', 'sequence')
|
||||||
if fget[f]['type'] in ('integer', 'float')
|
if fget[f]['type'] in ('integer', 'float')
|
||||||
if (f in self._columns and getattr(self._columns[f], '_classic_write'))]
|
if (f in self._all_columns and getattr(self._all_columns[f].column, '_classic_write'))]
|
||||||
for f in aggregated_fields:
|
for f in aggregated_fields:
|
||||||
group_operator = fget[f].get('group_operator', 'sum')
|
group_operator = fget[f].get('group_operator', 'sum')
|
||||||
if flist:
|
if flist:
|
||||||
flist += ', '
|
flist += ', '
|
||||||
qualified_field = '"%s"."%s"' % (self._table, f)
|
qualified_field = self._inherits_join_calc(f, query)
|
||||||
flist += "%s(%s) AS %s" % (group_operator, qualified_field, f)
|
flist += "%s(%s) AS %s" % (group_operator, qualified_field, f)
|
||||||
|
|
||||||
gb = groupby and (' GROUP BY ' + qualified_groupby_field) or ''
|
gb = groupby and (' GROUP BY ' + qualified_groupby_field) or ''
|
||||||
|
|
|
@ -30,7 +30,7 @@ RELEASE_LEVELS_DISPLAY = {ALPHA: ALPHA,
|
||||||
# properly comparable using normal operarors, for example:
|
# properly comparable using normal operarors, for example:
|
||||||
# (6,1,0,'beta',0) < (6,1,0,'candidate',1) < (6,1,0,'candidate',2)
|
# (6,1,0,'beta',0) < (6,1,0,'candidate',1) < (6,1,0,'candidate',2)
|
||||||
# (6,1,0,'candidate',2) < (6,1,0,'final',0) < (6,1,2,'final',0)
|
# (6,1,0,'candidate',2) < (6,1,0,'final',0) < (6,1,2,'final',0)
|
||||||
version_info = (8, 0, 0, ALPHA, 1)
|
version_info = (7, 'saas~3', 0, FINAL, 0)
|
||||||
version = '.'.join(map(str, version_info[:2])) + RELEASE_LEVELS_DISPLAY[version_info[3]] + str(version_info[4] or '')
|
version = '.'.join(map(str, version_info[:2])) + RELEASE_LEVELS_DISPLAY[version_info[3]] + str(version_info[4] or '')
|
||||||
serie = major_version = '.'.join(map(str, version_info[:2]))
|
serie = major_version = '.'.join(map(str, version_info[:2]))
|
||||||
|
|
||||||
|
|
|
@ -40,9 +40,10 @@ def dispatch(method, params):
|
||||||
|
|
||||||
def check(f):
|
def check(f):
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
def wrapper(dbname, *args, **kwargs):
|
def wrapper(___dbname, *args, **kwargs):
|
||||||
""" Wraps around OSV functions and normalises a few exceptions
|
""" Wraps around OSV functions and normalises a few exceptions
|
||||||
"""
|
"""
|
||||||
|
dbname = ___dbname # NOTE: this forbid to use "___dbname" as arguments in http routes
|
||||||
|
|
||||||
def tr(src, ttype):
|
def tr(src, ttype):
|
||||||
# We try to do the same as the _(), but without the frame
|
# We try to do the same as the _(), but without the frame
|
||||||
|
|
|
@ -67,7 +67,8 @@ _SAFE_OPCODES = _EXPR_OPCODES.union(set(opmap[x] for x in [
|
||||||
'LOAD_NAME', 'CALL_FUNCTION', 'COMPARE_OP', 'LOAD_ATTR',
|
'LOAD_NAME', 'CALL_FUNCTION', 'COMPARE_OP', 'LOAD_ATTR',
|
||||||
'STORE_NAME', 'GET_ITER', 'FOR_ITER', 'LIST_APPEND', 'DELETE_NAME',
|
'STORE_NAME', 'GET_ITER', 'FOR_ITER', 'LIST_APPEND', 'DELETE_NAME',
|
||||||
'JUMP_FORWARD', 'JUMP_IF_TRUE', 'JUMP_IF_FALSE', 'JUMP_ABSOLUTE',
|
'JUMP_FORWARD', 'JUMP_IF_TRUE', 'JUMP_IF_FALSE', 'JUMP_ABSOLUTE',
|
||||||
'MAKE_FUNCTION', 'SLICE+0', 'SLICE+1', 'SLICE+2', 'SLICE+3',
|
'MAKE_FUNCTION', 'SLICE+0', 'SLICE+1', 'SLICE+2', 'SLICE+3', 'BREAK_LOOP',
|
||||||
|
'CONTINUE_LOOP', 'RAISE_VARARGS',
|
||||||
# New in Python 2.7 - http://bugs.python.org/issue4715 :
|
# New in Python 2.7 - http://bugs.python.org/issue4715 :
|
||||||
'JUMP_IF_FALSE_OR_POP', 'JUMP_IF_TRUE_OR_POP', 'POP_JUMP_IF_FALSE',
|
'JUMP_IF_FALSE_OR_POP', 'JUMP_IF_TRUE_OR_POP', 'POP_JUMP_IF_FALSE',
|
||||||
'POP_JUMP_IF_TRUE', 'SETUP_EXCEPT', 'END_FINALLY'
|
'POP_JUMP_IF_TRUE', 'SETUP_EXCEPT', 'END_FINALLY'
|
||||||
|
|
|
@ -172,7 +172,7 @@ class GettextAlias(object):
|
||||||
cr = getattr(s, 'cr', None)
|
cr = getattr(s, 'cr', None)
|
||||||
if not cr and allow_create:
|
if not cr and allow_create:
|
||||||
db = self._get_db()
|
db = self._get_db()
|
||||||
if db:
|
if db is not None:
|
||||||
cr = db.cursor()
|
cr = db.cursor()
|
||||||
is_new_cr = True
|
is_new_cr = True
|
||||||
return cr, is_new_cr
|
return cr, is_new_cr
|
||||||
|
|
|
@ -101,11 +101,11 @@ def run(args):
|
||||||
import openerp
|
import openerp
|
||||||
|
|
||||||
config = openerp.tools.config
|
config = openerp.tools.config
|
||||||
|
config.load()
|
||||||
|
|
||||||
config['db_name'] = args.database
|
config['db_name'] = args.database
|
||||||
if args.port:
|
if args.port:
|
||||||
config['xmlrpc_port'] = int(args.port)
|
config['xmlrpc_port'] = int(args.port)
|
||||||
config['admin_passwd'] = 'admin'
|
|
||||||
config['db_password'] = 'a2aevl8w' # TODO from .openerpserverrc
|
|
||||||
|
|
||||||
if args.addons:
|
if args.addons:
|
||||||
args.addons = args.addons.replace(':',',').split(',')
|
args.addons = args.addons.replace(':',',').split(',')
|
||||||
|
|
Loading…
Reference in New Issue