[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:
Christophe Simonis 2014-02-06 14:12:19 +01:00
commit 9289a2608d
11 changed files with 71 additions and 15 deletions

View File

@ -13,6 +13,7 @@ from openerp.osv import orm
from openerp.tools.translate import _
from openerp.tools.misc import DEFAULT_SERVER_DATE_FORMAT,\
DEFAULT_SERVER_DATETIME_FORMAT
from openerp.tools import html_sanitize
REFERENCING_FIELDS = set([None, 'id', '.id'])
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):
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):
try:

View File

@ -337,7 +337,7 @@ class view(osv.osv):
if isinstance(spec, SKIPPED_ELEMENT_TYPES):
continue
if spec.tag == 'data':
specs += [ c for c in specs_tree ]
specs += [c for c in spec]
continue
node = self.locate_node(source, spec)
if node is not None:

View File

@ -129,7 +129,7 @@
<form string="Partners" version="7.0">
<sheet>
<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">
<label for="name"/> (
<field name="is_company" on_change="onchange_type(is_company)" class="oe_inline"/> <label for="is_company" string="Is a Company?"/>)

View File

@ -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):

View File

@ -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)

View File

@ -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 ''

View File

@ -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]))

View File

@ -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

View File

@ -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'

View File

@ -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

View File

@ -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(',')