(
)
diff --git a/openerp/addons/base/tests/test_base.py b/openerp/addons/base/tests/test_base.py
index 9b6ec4708ac..20382737529 100644
--- a/openerp/addons/base/tests/test_base.py
+++ b/openerp/addons/base/tests/test_base.py
@@ -8,6 +8,7 @@ class test_base(common.TransactionCase):
def setUp(self):
super(test_base,self).setUp()
self.res_partner = self.registry('res.partner')
+ self.res_users = self.registry('res.users')
# samples use effective TLDs from the Mozilla public suffix
# list at http://publicsuffix.org
@@ -282,6 +283,21 @@ class test_base(common.TransactionCase):
p0.refresh()
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):
def setUp(self):
diff --git a/openerp/http.py b/openerp/http.py
index 18a8215263d..c8c1bed24eb 100644
--- a/openerp/http.py
+++ b/openerp/http.py
@@ -208,7 +208,7 @@ class WebRequest(object):
args = (request,) + args
# Correct exception handling and concurency retry
@service_model.check
- def checked_call(dbname, *a, **kw):
+ def checked_call(___dbname, *a, **kw):
return self.func(*a, **kw)
# FIXME: code and rollback management could be cleaned
@@ -832,6 +832,40 @@ class OpenERPSession(werkzeug.contrib.sessions.Session):
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):
if random.random() < 0.001:
# we keep session one week
@@ -973,9 +1007,12 @@ class Root(object):
def setup_db(self, httprequest):
db = httprequest.session.db
# Check if session.db is legit
- if db and db not in db_filter([db], httprequest=httprequest):
- httprequest.session.logout()
- db = None
+ if db:
+ if db not in db_filter([db], httprequest=httprequest):
+ _logger.warn("Logged into database '%s', but dbfilter "
+ "rejects it; logging session out.", db)
+ httprequest.session.logout()
+ db = None
if not db:
httprequest.session.db = db_monodb(httprequest)
diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py
index e187d5d5c81..6ac65125620 100644
--- a/openerp/osv/orm.py
+++ b/openerp/osv/orm.py
@@ -2293,12 +2293,12 @@ class BaseModel(object):
f for f in fields
if f not in ('id', 'sequence')
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:
group_operator = fget[f].get('group_operator', 'sum')
if 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)
gb = groupby and (' GROUP BY ' + qualified_groupby_field) or ''
diff --git a/openerp/release.py b/openerp/release.py
index 1ad35340496..8670ef50abc 100644
--- a/openerp/release.py
+++ b/openerp/release.py
@@ -30,7 +30,7 @@ RELEASE_LEVELS_DISPLAY = {ALPHA: ALPHA,
# 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,'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 '')
serie = major_version = '.'.join(map(str, version_info[:2]))
diff --git a/openerp/service/model.py b/openerp/service/model.py
index a2c2dff90c5..d65cbd77333 100644
--- a/openerp/service/model.py
+++ b/openerp/service/model.py
@@ -40,9 +40,10 @@ def dispatch(method, params):
def check(f):
@wraps(f)
- def wrapper(dbname, *args, **kwargs):
+ def wrapper(___dbname, *args, **kwargs):
""" 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):
# We try to do the same as the _(), but without the frame
diff --git a/openerp/tools/safe_eval.py b/openerp/tools/safe_eval.py
index 7c2fee54183..b64b401a71c 100644
--- a/openerp/tools/safe_eval.py
+++ b/openerp/tools/safe_eval.py
@@ -67,7 +67,8 @@ _SAFE_OPCODES = _EXPR_OPCODES.union(set(opmap[x] for x in [
'LOAD_NAME', 'CALL_FUNCTION', 'COMPARE_OP', 'LOAD_ATTR',
'STORE_NAME', 'GET_ITER', 'FOR_ITER', 'LIST_APPEND', 'DELETE_NAME',
'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 :
'JUMP_IF_FALSE_OR_POP', 'JUMP_IF_TRUE_OR_POP', 'POP_JUMP_IF_FALSE',
'POP_JUMP_IF_TRUE', 'SETUP_EXCEPT', 'END_FINALLY'
diff --git a/openerp/tools/translate.py b/openerp/tools/translate.py
index c14244abd56..58eefc92df4 100644
--- a/openerp/tools/translate.py
+++ b/openerp/tools/translate.py
@@ -172,7 +172,7 @@ class GettextAlias(object):
cr = getattr(s, 'cr', None)
if not cr and allow_create:
db = self._get_db()
- if db:
+ if db is not None:
cr = db.cursor()
is_new_cr = True
return cr, is_new_cr
diff --git a/openerpcommand/run_tests.py b/openerpcommand/run_tests.py
index 3e9fec5030c..7e23f3edee3 100644
--- a/openerpcommand/run_tests.py
+++ b/openerpcommand/run_tests.py
@@ -101,11 +101,11 @@ def run(args):
import openerp
config = openerp.tools.config
+ config.load()
+
config['db_name'] = args.database
if args.port:
config['xmlrpc_port'] = int(args.port)
- config['admin_passwd'] = 'admin'
- config['db_password'] = 'a2aevl8w' # TODO from .openerpserverrc
if args.addons:
args.addons = args.addons.replace(':',',').split(',')