diff --git a/bin/addons/__init__.py b/bin/addons/__init__.py index f7e291953d9..6cccbb938f0 100644 --- a/bin/addons/__init__.py +++ b/bin/addons/__init__.py @@ -33,8 +33,6 @@ import pooler import netsvc -from osv import fields -import addons import zipfile import release @@ -88,8 +86,7 @@ class Graph(dict): ## Then we get the values from the database cr.execute('SELECT name, id, state, demo AS dbdemo, latest_version AS installed_version' ' FROM ir_module_module' - ' WHERE name in (%s)' % (','.join(['%s'] * len(self))), - additional_data.keys() + ' WHERE name IN %s',(tuple(additional_data),) ) ## and we update the default values with values from the database @@ -304,7 +301,7 @@ def load_information_from_description_file(module): :param module: The name of the module (sale, purchase, ...) """ for filename in ['__openerp__.py', '__terp__.py']: - description_file = addons.get_module_resource(module, filename) + description_file = get_module_resource(module, filename) if os.path.isfile(description_file): return eval(tools.file_open(description_file).read()) @@ -729,10 +726,10 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs): load_demo_xml(cr, m, idref, mode) load_demo(cr, m, idref, mode) cr.execute('update ir_module_module set demo=%s where id=%s', (True, mid)) - + # launch tests only in demo mode, as most tests will depend # on demo data. Other tests can be added into the regular - # 'data' section, but should probably not alter the data, + # 'data' section, but should probably not alter the data, # as there is no rollback. load_test(cr, m, idref, mode) @@ -824,8 +821,8 @@ def load_modules(db, force_demo=False, status=None, update_module=False): while True: loop_guardrail += 1 if loop_guardrail > 100: - raise ProgrammingError() - cr.execute("SELECT name from ir_module_module WHERE state in (%s)" % ','.join(['%s']*len(STATES_TO_LOAD)), STATES_TO_LOAD) + raise ValueError('Possible recursive module tree detected, aborting.') + cr.execute("SELECT name from ir_module_module WHERE state IN %s" ,(tuple(STATES_TO_LOAD),)) module_list = [name for (name,) in cr.fetchall() if name not in graph] if not module_list: @@ -841,9 +838,19 @@ def load_modules(db, force_demo=False, status=None, update_module=False): has_updates = has_updates or r if has_updates: - cr.execute("""select model,name from ir_model where id not in (select model_id from ir_model_access)""") + cr.execute("""select model,name from ir_model where id NOT IN (select distinct model_id from ir_model_access)""") for (model, name) in cr.fetchall(): - logger.notifyChannel('init', netsvc.LOG_WARNING, 'object %s (%s) has no access rules!' % (model, name)) + model_obj = pool.get(model) + if not isinstance(model_obj, osv.osv.osv_memory): + logger.notifyChannel('init', netsvc.LOG_WARNING, 'object %s (%s) has no access rules!' % (model, name)) + + # Temporary warning while we remove access rights on osv_memory objects, as they have + # been replaced by owner-only access rights + cr.execute("""select distinct mod.model, mod.name from ir_model_access acc, ir_model mod where acc.model_id = mod.id""") + for (model, name) in cr.fetchall(): + model_obj = pool.get(model) + if isinstance(model_obj, osv.osv.osv_memory): + logger.notifyChannel('init', netsvc.LOG_WARNING, 'In-memory object %s (%s) should not have explicit access rules!' % (model, name)) cr.execute("SELECT model from ir_model") for (model,) in cr.fetchall(): @@ -878,11 +885,11 @@ def load_modules(db, force_demo=False, status=None, update_module=False): cr.execute('''delete from ir_ui_menu where - (id not in (select parent_id from ir_ui_menu where parent_id is not null)) + (id not IN (select parent_id from ir_ui_menu where parent_id is not null)) and - (id not in (select res_id from ir_values where model='ir.ui.menu')) + (id not IN (select res_id from ir_values where model='ir.ui.menu')) and - (id not in (select res_id from ir_model_data where model='ir.ui.menu'))''') + (id not IN (select res_id from ir_model_data where model='ir.ui.menu'))''') cr.commit() if not cr.rowcount: break diff --git a/bin/addons/base/base_menu.xml b/bin/addons/base/base_menu.xml index 3989ca3641a..9d49728c437 100644 --- a/bin/addons/base/base_menu.xml +++ b/bin/addons/base/base_menu.xml @@ -2,6 +2,7 @@ + diff --git a/bin/addons/base/i18n/hr.po b/bin/addons/base/i18n/hr.po index 58051891d3b..07f6e3952ea 100644 --- a/bin/addons/base/i18n/hr.po +++ b/bin/addons/base/i18n/hr.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.4\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2009-12-18 08:39+0000\n" -"PO-Revision-Date: 2010-06-23 04:21+0000\n" +"PO-Revision-Date: 2010-06-24 04:19+0000\n" "Last-Translator: Goran Kliska \n" "Language-Team: openerp-translators\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2010-06-24 03:46+0000\n" +"X-Launchpad-Export-Date: 2010-06-25 03:46+0000\n" "X-Generator: Launchpad (build Unknown)\n" "Language: hr\n" diff --git a/bin/addons/base/i18n/ja.po b/bin/addons/base/i18n/ja.po index 1734aa0f31c..bb86f22ba98 100644 --- a/bin/addons/base/i18n/ja.po +++ b/bin/addons/base/i18n/ja.po @@ -8,13 +8,13 @@ msgstr "" "Project-Id-Version: openobject-server\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2009-12-18 08:39+0000\n" -"PO-Revision-Date: 2010-06-23 04:19+0000\n" +"PO-Revision-Date: 2010-06-24 04:17+0000\n" "Last-Translator: Harry (Open ERP) \n" "Language-Team: Japanese \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2010-06-24 03:45+0000\n" +"X-Launchpad-Export-Date: 2010-06-25 03:45+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: base diff --git a/bin/addons/base/i18n/sv.po b/bin/addons/base/i18n/sv.po index a7a9f80856d..22b23babb23 100644 --- a/bin/addons/base/i18n/sv.po +++ b/bin/addons/base/i18n/sv.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.0\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2009-12-18 08:39+0000\n" -"PO-Revision-Date: 2010-06-23 04:18+0000\n" +"PO-Revision-Date: 2010-06-24 04:21+0000\n" "Last-Translator: Anders Wallenquist \n" "Language-Team: <>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2010-06-24 03:46+0000\n" +"X-Launchpad-Export-Date: 2010-06-25 03:46+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: base diff --git a/bin/addons/base/i18n/uk.po b/bin/addons/base/i18n/uk.po index 59e1a67d5c5..c22b356c310 100644 --- a/bin/addons/base/i18n/uk.po +++ b/bin/addons/base/i18n/uk.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.0\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2009-12-18 08:39+0000\n" -"PO-Revision-Date: 2010-06-23 04:22+0000\n" +"PO-Revision-Date: 2010-06-24 04:16+0000\n" "Last-Translator: Fabien (Open ERP) \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2010-06-24 03:46+0000\n" +"X-Launchpad-Export-Date: 2010-06-25 03:46+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: base diff --git a/bin/addons/base/i18n/zh_CN.po b/bin/addons/base/i18n/zh_CN.po index e580212a6f1..3a8295b9a7b 100644 --- a/bin/addons/base/i18n/zh_CN.po +++ b/bin/addons/base/i18n/zh_CN.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.4\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2009-12-18 08:39+0000\n" -"PO-Revision-Date: 2010-06-23 04:19+0000\n" +"PO-Revision-Date: 2010-06-24 04:21+0000\n" "Last-Translator: Eleanor Chen \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2010-06-24 03:46+0000\n" +"X-Launchpad-Export-Date: 2010-06-25 03:46+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: base diff --git a/bin/addons/base/ir/ir.xml b/bin/addons/base/ir/ir.xml index d5be9539a0a..2949107ccff 100644 --- a/bin/addons/base/ir/ir.xml +++ b/bin/addons/base/ir/ir.xml @@ -814,6 +814,7 @@ + diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index 6d90d0416f3..97fedcf88dc 100644 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -159,16 +159,6 @@ class act_window(osv.osv): (_check_model, 'Invalid model name in the action definition.', ['res_model','src_model']) ] - def get_filters(self, cr, uid, model): - cr.execute('SELECT id FROM ir_act_window a WHERE a.id not in (SELECT act_id FROM ir_act_window_user_rel) AND a.res_model=\''+model+'\' and a.filter=\'1\';') - all_ids = cr.fetchall() - filter_ids = map(lambda x:x[0],all_ids) - act_ids = self.search(cr,uid,[('res_model','=',model),('filter','=',1),('default_user_ids','in',(','.join(map(str,[uid,])),))]) - act_ids += filter_ids - act_ids = list(set(act_ids)) - my_acts = self.read(cr, uid, act_ids, ['name', 'domain','context']) - return my_acts - def _views_get_fnc(self, cr, uid, ids, name, arg, context={}): res={} for act in self.browse(cr, uid, ids): @@ -381,7 +371,7 @@ class actions_server(osv.osv): def _select_signals(self, cr, uid, context={}): cr.execute("SELECT distinct w.osv, t.signal FROM wkf w, wkf_activity a, wkf_transition t \ WHERE w.id = a.wkf_id AND t.act_from = a.id OR t.act_to = a.id AND t.signal!='' \ - AND t.signal not in (null, NULL)") + AND t.signal NOT IN (null, NULL)") result = cr.fetchall() or [] res = [] for rs in result: diff --git a/bin/addons/base/ir/ir_attachment.py b/bin/addons/base/ir/ir_attachment.py index 4ca585a92a4..981c6091ceb 100644 --- a/bin/addons/base/ir/ir_attachment.py +++ b/bin/addons/base/ir/ir_attachment.py @@ -30,7 +30,7 @@ class ir_attachment(osv.osv): ima = self.pool.get('ir.model.access') if isinstance(ids, (int, long)): ids = [ids] - cr.execute('select distinct res_model from ir_attachment where id = ANY (%s)', (ids,)) + cr.execute('select distinct res_model from ir_attachment where id IN %s', (tuple(ids),)) for obj in cr.fetchall(): if obj[0]: ima.check(cr, uid, obj[0], mode, context=context) @@ -84,7 +84,7 @@ class ir_attachment(osv.osv): dataobj = self.pool.get('ir.model.data') data_id = dataobj._get_id(cr, 1, 'base', 'action_attachment') res_id = dataobj.browse(cr, uid, data_id, context).res_id - return self.pool.get('ir.actions.act_window').read(cr, uid, res_id, [], context) + return self.pool.get('ir.actions.act_window').read(cr, uid, res_id, [], context) def _name_get_resname(self, cr, uid, ids, object,method, context): data = {} diff --git a/bin/addons/base/ir/ir_filters.py b/bin/addons/base/ir/ir_filters.py index 44dd335f34d..172b178dddf 100644 --- a/bin/addons/base/ir/ir_filters.py +++ b/bin/addons/base/ir/ir_filters.py @@ -27,17 +27,22 @@ class ir_filters(osv.osv): ''' _name = 'ir.filters' _description = 'Filters' - + def _list_all_models(self, cr, uid, context=None): cr.execute("SELECT model, name from ir_model") return cr.fetchall() + def get_filters(self, cr, uid, model): + act_ids = self.search(cr,uid,[('model_id','=',model),('user_id','=',uid)]) + my_acts = self.read(cr, uid, act_ids, ['name', 'domain','context']) + return my_acts + _columns = { - 'name': fields.char('Action Name', size=64, translate=True, required=True), - 'user_id':fields.many2one('res.users', 'User', help='False means for every user'), - 'domain': fields.char('Domain Value', size=250, required=True), - 'context': fields.char('Context Value', size=250, required=True), - 'model_id': fields.selection(_list_all_models, 'Model', required=True), + 'name': fields.char('Action Name', size=64, translate=True, required=True), + 'user_id':fields.many2one('res.users', 'User', help='False means for every user'), + 'domain': fields.char('Domain Value', size=250, required=True), + 'context': fields.char('Context Value', size=250, required=True), + 'model_id': fields.selection(_list_all_models, 'Model', required=True), } ir_filters() diff --git a/bin/addons/base/ir/ir_model.py b/bin/addons/base/ir/ir_model.py index f13d8e188fe..eb6959a2d79 100644 --- a/bin/addons/base/ir/ir_model.py +++ b/bin/addons/base/ir/ir_model.py @@ -44,6 +44,25 @@ class ir_model(osv.osv): _name = 'ir.model' _description = "Objects" _rec_name = 'name' + + def _is_osv_memory(self, cr, uid, ids, field_name, arg, context=None): + models = self.browse(cr, uid, ids, context=context) + res = dict.fromkeys(ids) + for model in models: + res[model.id] = isinstance(self.pool.get(model.model), osv.osv_memory) + return res + + def _search_osv_memory(self, cr, uid, model, name, domain, context=None): + if not domain: + return [] + field, operator, value = domain[0] + if operator not in ['=', '!=']: + raise osv.except_osv('Invalid search criterions','The osv_memory field can only be compared with = and != operator.') + value = bool(value) if operator == '=' else not bool(value) + all_model_ids = self.search(cr, uid, [], context=context) + is_osv_mem = self._is_osv_memory(cr, uid, all_model_ids, 'osv_memory', arg=None, context=context) + return [('id', 'in', [id for id in is_osv_mem if bool(is_osv_mem[id]) == value])] + _columns = { 'name': fields.char('Object Name', size=64, translate=True, required=True), 'model': fields.char('Object', size=64, required=True, select=1), @@ -51,6 +70,9 @@ class ir_model(osv.osv): 'field_id': fields.one2many('ir.model.fields', 'model_id', 'Fields', required=True), 'state': fields.selection([('manual','Custom Object'),('base','Base Object')],'Manually Created',readonly=True), 'access_ids': fields.one2many('ir.model.access', 'model_id', 'Access'), + 'osv_memory': fields.function(_is_osv_memory, method=True, string='In-memory model', type='boolean', + fnct_search=_search_osv_memory, + help="Indicates whether this object model lives in memory only, i.e. is not persisted (osv.osv_memory)") } _defaults = { 'model': lambda *a: 'x_', @@ -81,7 +103,7 @@ class ir_model(osv.osv): def unlink(self, cr, user, ids, context=None): for model in self.browse(cr, user, ids, context): - if model.state <> 'manual': + if model.state != 'manual': raise except_orm(_('Error'), _("You can not remove the model '%s' !") %(model.name,)) res = super(ir_model, self).unlink(cr, user, ids, context) pooler.restart_pool(cr.dbname) @@ -300,7 +322,7 @@ class ir_model_access(osv.osv): _name = 'ir.model.access' _columns = { 'name': fields.char('Name', size=64, required=True), - 'model_id': fields.many2one('ir.model', 'Object', required=True), + 'model_id': fields.many2one('ir.model', 'Object', required=True, domain=[('osv_memory','=', False)]), 'group_id': fields.many2one('res.groups', 'Group', ondelete='cascade'), 'perm_read': fields.boolean('Read Access'), 'perm_write': fields.boolean('Write Access'), @@ -314,7 +336,7 @@ class ir_model_access(osv.osv): if not grouparr: return False - cr.execute("select 1 from res_groups_users_rel where uid=%s and gid in(select res_id from ir_model_data where module=%s and name=%s)", (uid, grouparr[0], grouparr[1],)) + cr.execute("select 1 from res_groups_users_rel where uid=%s and gid IN (select res_id from ir_model_data where module=%s and name=%s)", (uid, grouparr[0], grouparr[1],)) return bool(cr.fetchone()) def check_group(self, cr, uid, model, mode, group_ids): @@ -605,13 +627,13 @@ class ir_model_data(osv.osv): return True modules = list(modules) module_in = ",".join(["%s"] * len(modules)) - cr.execute('select id,name,model,res_id,module from ir_model_data where module in (' + module_in + ') and noupdate=%s', modules + [False]) + cr.execute('select id,name,model,res_id,module from ir_model_data where module IN (' + module_in + ') and noupdate=%s', modules + [False]) wkf_todo = [] for (id, name, model, res_id,module) in cr.fetchall(): if (module,name) not in self.loads: self.unlink_mark[(model,res_id)] = id if model=='workflow.activity': - cr.execute('select res_type,res_id from wkf_instance where id in (select inst_id from wkf_workitem where act_id=%s)', (res_id,)) + cr.execute('select res_type,res_id from wkf_instance where id IN (select inst_id from wkf_workitem where act_id=%s)', (res_id,)) wkf_todo.extend(cr.fetchall()) cr.execute("update wkf_transition set condition='True', role_id=NULL, signal=NULL,act_to=act_from,act_from=%s where act_to=%s", (res_id,res_id)) cr.execute("delete from wkf_transition where act_to=%s", (res_id,)) diff --git a/bin/addons/base/ir/ir_translation.py b/bin/addons/base/ir/ir_translation.py index 8e575b6b242..9a01f74870d 100644 --- a/bin/addons/base/ir/ir_translation.py +++ b/bin/addons/base/ir/ir_translation.py @@ -88,8 +88,8 @@ class ir_translation(osv.osv): 'where lang=%s ' \ 'and type=%s ' \ 'and name=%s ' \ - 'and res_id in ('+','.join(map(str, ids))+')', - (lang,tt,name)) + 'and res_id IN %s', + (lang,tt,name,tuple(ids))) for res_id, value in cr.fetchall(): translations[res_id] = value return translations @@ -107,8 +107,8 @@ class ir_translation(osv.osv): 'where lang=%s ' \ 'and type=%s ' \ 'and name=%s ' \ - 'and res_id in ('+','.join(map(str, ids))+')', - (lang,tt,name)) + 'and res_id IN %s', + (lang,tt,name,tuple(ids),)) cr.commit() for id in ids: self.create(cr, uid, { @@ -152,7 +152,7 @@ class ir_translation(osv.osv): ids = super(ir_translation, self).create(cursor, user, vals, context=context) for trans_obj in self.read(cursor, user, [ids], ['name','type','res_id','src','lang'], context=context): self._get_source.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], source=trans_obj['src']) - self._get_ids.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], context.get('lang','en_US'), [trans_obj['res_id']]) + self._get_ids.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], [trans_obj['res_id']]) return ids def write(self, cursor, user, ids, vals, context=None): @@ -161,7 +161,7 @@ class ir_translation(osv.osv): result = super(ir_translation, self).write(cursor, user, ids, vals, context=context) for trans_obj in self.read(cursor, user, ids, ['name','type','res_id','src','lang'], context=context): self._get_source.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], source=trans_obj['src']) - self._get_ids.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], context.get('lang','en_US'), [trans_obj['res_id']]) + self._get_ids.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], [trans_obj['res_id']]) return result def unlink(self, cursor, user, ids, context=None): @@ -169,7 +169,7 @@ class ir_translation(osv.osv): context = {} for trans_obj in self.read(cursor, user, ids, ['name','type','res_id','src','lang'], context=context): self._get_source.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], source=trans_obj['src']) - self._get_ids.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], context.get('lang','en_US'), [trans_obj['res_id']]) + self._get_ids.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], [trans_obj['res_id']]) result = super(ir_translation, self).unlink(cursor, user, ids, context=context) return result diff --git a/bin/addons/base/ir/ir_ui_menu.py b/bin/addons/base/ir/ir_ui_menu.py index d7d08fb2c69..3e75a3f2593 100644 --- a/bin/addons/base/ir/ir_ui_menu.py +++ b/bin/addons/base/ir/ir_ui_menu.py @@ -67,6 +67,25 @@ class ir_ui_menu(osv.osv): # radical but this doesn't frequently happen self._cache = {} + def create_shortcut(self, cr, uid, values, context={}): + dataobj = self.pool.get('ir.model.data') + menu_id = dataobj._get_id(cr, uid, 'base', 'menu_administration_shortcut', context) + shortcut_menu_id = int(dataobj.read(cr, uid, menu_id, ['res_id'], context)['res_id']) + action_id = self.pool.get('ir.actions.act_window').create(cr, uid, values, context) + menu_data = {'name':values['name'], + 'sequence':10, + 'action':'ir.actions.act_window,'+str(action_id), + 'parent_id':shortcut_menu_id, + 'icon':'STOCK_JUSTIFY_FILL'} + menu_id = self.pool.get('ir.ui.menu').create(cr, uid, menu_data) + sc_data= {'name':values['name'], 'sequence': 1,'res_id': menu_id } + sc_menu_id = self.pool.get('ir.ui.view_sc').create(cr, uid, sc_data, context) + + user_groups = set(self.pool.get('res.users').read(cr, 1, uid, ['groups_id'])['groups_id']) + key = (cr.dbname, shortcut_menu_id, tuple(user_groups)) + self._cache[key] = True + return True + def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False): diff --git a/bin/addons/base/ir/ir_values.py b/bin/addons/base/ir/ir_values.py index 7299b45e29a..13bfee9d192 100644 --- a/bin/addons/base/ir/ir_values.py +++ b/bin/addons/base/ir/ir_values.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). # @@ -15,7 +15,7 @@ # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see . # ############################################################################## @@ -161,54 +161,33 @@ class ir_values(osv.osv): else: res_id=False - where1 = ['key=%s','model=%s'] - where2 = [key,str(m)] - where_opt = [] + where = ['key=%s','model=%s'] + params = [key, str(m)] if key2: - where1.append('key2=%s') - where2.append(key2[:200]) + where.append('key2=%s') + params.append(key2[:200]) else: - dest = where1 - if not key2_req or meta: - dest=where_opt - dest.append('key2 is null') - + if key2_req and not meta: + where.append('key2 is null') if res_id_req and (models[-1][0]==m): if res_id: - where1.append('res_id=%d' % (res_id,)) + where.append('res_id=%s') + params.append(res_id) else: - where1.append('(res_id is NULL)') + where.append('(res_id is NULL)') elif res_id: if (models[-1][0]==m): - where1.append('(res_id=%d or (res_id is null))' % (res_id,)) - where_opt.append('res_id=%d' % (res_id,)) + where.append('(res_id=%s or (res_id is null))') + params.append(res_id) else: - where1.append('res_id=%d' % (res_id,)) - -# if not without_user: - where_opt.append('user_id=%d' % (uid,)) - - result = [] - ok = True - result_ids = {} - while ok: - if not where_opt: - cr.execute('select id,name,value,object,meta, key from ir_values where ' +\ - ' and '.join(where1)+' and user_id is null', where2) - else: - cr.execute('select id,name,value,object,meta, key from ir_values where ' +\ - ' and '.join(where1+where_opt), where2) - for rec in cr.fetchall(): - if rec[0] in result_ids: - continue - if rec[2]: - result.append(rec) - result_ids[rec[0]] = True - if len(where_opt): - where_opt.pop() - else: - ok = False + where.append('res_id=%s') + params.append(res_id) + where.append('(user_id=%s or (user_id IS NULL))') + params.append(uid) + clause = ' and '.join(where) + cr.execute('select id,name,value,object,meta, key from ir_values where ' + clause, params) + result = cr.fetchall() if result: break @@ -250,16 +229,14 @@ class ir_values(osv.osv): res2 = res[:] for r in res: if type(r[2])==type({}) and 'type' in r[2]: - if r[2]['type'] in ('ir.actions.report.xml','ir.actions.act_window','ir.actions.wizard'): - if r[2].has_key('groups_id'): - groups = r[2]['groups_id'] - if len(groups) > 0: - cr.execute("SELECT count(*) FROM res_groups_users_rel WHERE gid = ANY(%s) AND uid=%s",(groups, uid)) - gr_ids = cr.fetchall() - if not gr_ids[0][0] > 0: - res2.remove(r) - if r[1]=='Menuitem' and not res2: - raise osv.except_osv('Error !','You do not have the permission to perform this operation !!!') + groups = r[2].get('groups_id') + if groups: + cr.execute('SELECT COUNT(1) FROM res_groups_users_rel WHERE gid IN %s AND uid=%s',(tuple(groups), uid)) + cnt = cr.fetchone()[0] + if cnt: + res2.remove(r) + if r[1] == 'Menuitem' and not res2: + raise osv.except_osv('Error !','You do not have the permission to perform this operation !!!') return res2 ir_values() diff --git a/bin/addons/base/ir/workflow/print_instance.py b/bin/addons/base/ir/workflow/print_instance.py index eee0706b935..259fe51d41a 100644 --- a/bin/addons/base/ir/workflow/print_instance.py +++ b/bin/addons/base/ir/workflow/print_instance.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). # @@ -15,7 +15,7 @@ # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see . # ############################################################################## @@ -23,7 +23,7 @@ import time, os import netsvc import report,pooler,tools - +from operator import itemgetter def graph_get(cr, graph, wkf_ids, nested=False, workitem={}): import pydot @@ -56,7 +56,8 @@ def graph_get(cr, graph, wkf_ids, nested=False, workitem={}): graph.add_node(pydot.Node(n['id'], **args)) actfrom[n['id']] = (n['id'],{}) actto[n['id']] = (n['id'],{}) - cr.execute('select * from wkf_transition where act_from in ('+','.join(map(lambda x: str(x['id']),nodes))+')') + node_ids = tuple(map(itemgetter('id'), nodes)) + cr.execute('select * from wkf_transition where act_from IN %s', (node_ids,)) transitions = cr.dictfetchall() for t in transitions: if not t['act_to'] in activities: diff --git a/bin/addons/base/module/module.py b/bin/addons/base/module/module.py index 609cbcc6ae0..ce52f8b1515 100644 --- a/bin/addons/base/module/module.py +++ b/bin/addons/base/module/module.py @@ -45,7 +45,14 @@ class module_category(osv.osv): _description = "Module Category" def _module_nbr(self,cr,uid, ids, prop, unknow_none,context): - cr.execute('select category_id,count(*) from ir_module_module where category_id in ('+','.join(map(str, ids))+') or category_id in (select id from ir_module_category where parent_id in ('+','.join(map(str, ids))+')) group by category_id') + cr.execute('SELECT category_id, COUNT(*) \ + FROM ir_module_module \ + WHERE category_id IN %(ids)s \ + OR category_id IN (SELECT id \ + FROM ir_module_category \ + WHERE parent_id IN %(ids)s) \ + GROUP BY category_id', {'ids': tuple(ids)} + ) result = dict(cr.fetchall()) for id in ids: cr.execute('select id from ir_module_category where parent_id=%s', (id,)) diff --git a/bin/addons/base/res/partner/partner.py b/bin/addons/base/res/partner/partner.py index 3a12868fb91..98f13d9ee6c 100644 --- a/bin/addons/base/res/partner/partner.py +++ b/bin/addons/base/res/partner/partner.py @@ -55,7 +55,7 @@ class res_partner_category(osv.osv): def _check_recursion(self, cr, uid, ids): level = 100 while len(ids): - cr.execute('select distinct parent_id from res_partner_category where id in ('+','.join(map(str, ids))+')') + cr.execute('select distinct parent_id from res_partner_category where id IN %s',(tuple(ids),)) ids = filter(None, map(lambda x:x[0], cr.fetchall())) if not level: return False @@ -226,7 +226,7 @@ class res_partner(osv.osv): return True def address_get(self, cr, uid, ids, adr_pref=['default']): - cr.execute('select type,id from res_partner_address where partner_id in ('+','.join(map(str,map(int, ids)))+')') + cr.execute('select type,id from res_partner_address where partner_id IN %s',(tuple(ids),)) res = cr.fetchall() adr = dict(res) # get the id of the (first) default address if there is one, diff --git a/bin/addons/base/res/partner/partner_view.xml b/bin/addons/base/res/partner/partner_view.xml index cc786ac526a..4c40ae4991a 100644 --- a/bin/addons/base/res/partner/partner_view.xml +++ b/bin/addons/base/res/partner/partner_view.xml @@ -317,10 +317,6 @@ - - - - diff --git a/bin/addons/base/res/res_company.py b/bin/addons/base/res/res_company.py index 4b6ec1dc00a..e2e4d18637f 100644 --- a/bin/addons/base/res/res_company.py +++ b/bin/addons/base/res/res_company.py @@ -179,7 +179,7 @@ class res_company(osv.osv): def _check_recursion(self, cr, uid, ids): level = 100 while len(ids): - cr.execute('select distinct parent_id from res_company where id in ('+','.join(map(str, ids))+')') + cr.execute('select distinct parent_id from res_company where id IN %s',(tuple(ids),)) ids = filter(None, map(lambda x:x[0], cr.fetchall())) if not level: return False diff --git a/bin/addons/base/res/res_config.py b/bin/addons/base/res/res_config.py index 49d96768d6a..c6b9cb9fcad 100644 --- a/bin/addons/base/res/res_config.py +++ b/bin/addons/base/res/res_config.py @@ -77,7 +77,7 @@ class res_config_configurable(osv.osv_memory): todo_obj = todos.browse(cr, uid, active_todos[0], context=None) todo_groups = map(lambda x:x.id, todo_obj.groups_id) if todo_groups: - cr.execute("select 1 from res_groups_users_rel where uid=%s and gid=ANY(%s)",(uid, todo_groups,)) + cr.execute("select 1 from res_groups_users_rel where uid=%s and gid IN %s",(uid, tuple(todo_groups),)) dont_skip_todo = bool(cr.fetchone()) if dont_skip_todo: return todos.browse(cr, uid, active_todos[0], context=None) diff --git a/bin/addons/base/res/res_currency.py b/bin/addons/base/res/res_currency.py index 0e4faa68143..86742dc14ae 100644 --- a/bin/addons/base/res/res_currency.py +++ b/bin/addons/base/res/res_currency.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). # @@ -15,7 +15,7 @@ # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see . # ############################################################################## import time @@ -35,7 +35,7 @@ class res_currency(osv.osv): date=time.strftime('%Y-%m-%d') date= date or time.strftime('%Y-%m-%d') for id in ids: - cr.execute("SELECT currency_id, rate FROM res_currency_rate WHERE currency_id = %s AND name <= '%s' ORDER BY name desc LIMIT 1" % (id, date)) + cr.execute("SELECT currency_id, rate FROM res_currency_rate WHERE currency_id = %s AND name <= %s ORDER BY name desc LIMIT 1" ,(id, date)) if cr.rowcount: id, rate=cr.fetchall()[0] res[id]=rate diff --git a/bin/addons/base/security/ir.model.access.csv b/bin/addons/base/security/ir.model.access.csv index 8f98ef81380..76070c24d71 100644 --- a/bin/addons/base/security/ir.model.access.csv +++ b/bin/addons/base/security/ir.model.access.csv @@ -1,11 +1,11 @@ "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" "access_ir_attachment_all","ir_attachment all","model_ir_attachment",,1,0,0,0 -"access_ir_attachment_group_user","ir_attachment group_user","model_ir_attachment",group_user,1,1,1,1 +"access_ir_attachment_group_user","ir_attachment group_user","model_ir_attachment","group_user",1,1,1,1 "access_ir_cron_group_cron","ir_cron group_cron","model_ir_cron","group_system",1,1,1,1 "access_ir_cron_user","ir_cron user","model_ir_cron","group_user",1,0,0,0 "access_ir_default_group_system","ir_default group_system","model_ir_default",,1,1,1,1 -"access_ir_exports_group_system","ir_exports group_system","model_ir_exports",base.group_user,1,1,1,1 -"access_ir_exports_line_group_system","ir_exports_line group_system","model_ir_exports_line",base.group_user,1,1,1,1 +"access_ir_exports_group_system","ir_exports group_system","model_ir_exports","base.group_user",1,1,1,1 +"access_ir_exports_line_group_system","ir_exports_line group_system","model_ir_exports_line","base.group_user",1,1,1,1 "access_ir_model_group_erp_manager","ir_model group_erp_manager","model_ir_model","group_erp_manager",1,1,1,1 "access_ir_model_access_group_erp_manager","ir_model_access_group_erp_manager","model_ir_model_access","group_erp_manager",1,1,1,1 "access_ir_model_grid_group_erp_manager","ir_model_access_grid_group_erp_manager","model_ir_model_grid","group_erp_manager",1,1,1,1 @@ -43,8 +43,8 @@ "access_wizard_module_lang_export_group_system","wizard_module_lang_export group_system","model_wizard_module_lang_export","group_system",1,1,1,1 "access_res_company_group_erp_manager","res_company group_erp_manager","model_res_company","group_erp_manager",1,1,1,1 "access_res_company_group_user","res_company group_user","model_res_company",,1,0,0,0 -"access_res_config_all","res_config all","model_res_config",group_system,1,1,1,1 -"access_res_config_users_all","res_config_users all","model_res_config_users",group_system,1,1,1,1 +"access_res_config_all","res_config all","model_res_config","group_system",1,1,1,1 +"access_res_config_users_all","res_config_users all","model_res_config_users","group_system",1,1,1,1 "access_res_country_group_all","res_country group_user_all","model_res_country",,1,0,0,0 "access_res_country_state_group_all","res_country_state group_user_all","model_res_country_state",,1,0,0,0 "access_res_country_group_user","res_country group_user","model_res_country","group_partner_manager",1,1,1,1 @@ -77,8 +77,8 @@ "access_res_partner_som_group_partner_manager","res_partner_som group_partner_manager","model_res_partner_som","group_user",1,0,0,0 "access_res_partner_title_group_user","res_partner_title group_user","model_res_partner_title","group_partner_manager",1,1,1,1 "access_res_partner_title_group_partner_manager","res_partner_title group_partner_manager","model_res_partner_title",,1,0,0,0 -"access_res_request_group_user","res_request group_user","model_res_request",base.group_user,1,1,1,1 -"access_res_request_history_group_user","res_request_history group_user","model_res_request_history",base.group_user,1,1,1,1 +"access_res_request_group_user","res_request group_user","model_res_request","base.group_user",1,1,1,1 +"access_res_request_history_group_user","res_request_history group_user","model_res_request_history","base.group_user",1,1,1,1 "access_res_request_group_user_all","res_request group_user all","model_res_request",,1,0,0,0 "access_res_request_history_group_user_all","res_request_history group_user all","model_res_request_history",,1,0,0,0 "access_res_request_link_group_system","res_request_link group_system","model_res_request_link","group_system",1,1,1,1 @@ -123,7 +123,7 @@ "access_res_roles_group_erpmanager","res_roles_group_erp_manager","model_res_roles","group_erp_manager",1,1,1,1 "access_res_config_view_group_erpmanager","res_config_view_erp_manager","model_res_config_view","group_system",1,1,1,1 "access_res_roles_all","res_roles_all","model_res_roles",,1,0,0,0 -"access_res_config_view_all","res_config_view_all","model_res_config_view",group_system,1,0,0,0 +"access_res_config_view_all","res_config_view_all","model_res_config_view","group_system",1,0,0,0 "access_res_bank_group_partner_manager","res_bank_group_partner_manager","model_res_bank","group_partner_manager",1,1,1,1 "access_res_bank_user","res_bank user","model_res_bank","group_user",1,0,0,0 "access_maintenance_group_user","maintenance_contract group_user","model_maintenance_contract","group_system",1,1,1,1 @@ -134,3 +134,4 @@ "access_ir_filter all","ir_filters all","model_ir_filters",,1,0,0,0 "access_ir_filter employee","ir_filters employee","model_ir_filters","group_user",1,1,1,1 "access_res_log all","res_log all","model_res_log",,1,0,1,1 +"access_ir_filters","ir_filters_all","model_ir_filters",,1,1,1,1 diff --git a/bin/openerp-server.py b/bin/openerp-server.py index 0577e76679f..4fbebb84490 100755 --- a/bin/openerp-server.py +++ b/bin/openerp-server.py @@ -176,8 +176,7 @@ def handler(signum, _): logger.notifyChannel('shutdown', netsvc.LOG_INFO, "Shutdown Server! - %s" % ( SIGNALS[signum], )) logger.shutdown() - #sys.exit(0) - os._exit(0) + sys.exit(0) for signum in SIGNALS: signal.signal(signum, handler) diff --git a/bin/osv/expression.py b/bin/osv/expression.py index 4da2a70528a..15e8d86ed2a 100644 --- a/bin/osv/expression.py +++ b/bin/osv/expression.py @@ -29,7 +29,7 @@ class expression(object): parse a domain expression use a real polish notation leafs are still in a ('foo', '=', 'bar') format - For more info: http://christophe-simonis-at-tiny.blogspot.com/2008/08/new-new-domain-notation.html + For more info: http://christophe-simonis-at-tiny.blogspot.com/2008/08/new-new-domain-notation.html """ def _is_operator(self, element): @@ -50,16 +50,15 @@ class expression(object): if op in ['<','>','>=','<=']: cr.execute('SELECT "%s"' \ ' FROM "%s"' \ - ' WHERE "%s" %s %s' % (s, f, w, op, ids[0])) + ' WHERE "%s" %s %%s' % (s, f, w, op), (ids[0],)) res.extend([r[0] for r in cr.fetchall()]) else: for i in range(0, len(ids), cr.IN_MAX): subids = ids[i:i+cr.IN_MAX] cr.execute('SELECT "%s"' \ ' FROM "%s"' \ - ' WHERE "%s" in (%s)' % (s, f, w, ','.join(['%s']*len(subids))), - subids) - res.extend([r[0] for r in cr.fetchall()]) + ' WHERE "%s" IN %%s' % (s, f, w),(tuple(subids),)) + res.extend([r[0] for r in cr.fetchall()]) else: cr.execute('SELECT distinct("%s")' \ ' FROM "%s" where "%s" is not null' % (s, f, s)), @@ -77,6 +76,9 @@ class expression(object): self.__main_table = None # 'root' table. set by parse() self.__DUMMY_LEAF = (1, '=', 1) # a dummy leaf that must not be parsed or sql generated + @property + def exp(self): + return self.__exp[:] def parse(self, cr, uid, table, context): """ transform the leafs of the expression """ @@ -128,7 +130,7 @@ class expression(object): self.__joins.append('%s.%s=%s.%s' % (working_table._table, 'id', main_table._table, main_table._inherits[working_table._name])) self.__all_tables.add(working_table) main_table = working_table - + field = working_table._columns.get(fargs[0], False) if not field: if left == 'id' and operator == 'child_of': @@ -176,20 +178,20 @@ class expression(object): else: dom = _rec_get(ids2, working_table, parent=left) self.__exp = self.__exp[:i] + dom + self.__exp[i+1:] - - else: + + else: call_null = True - + if right: if isinstance(right, basestring): ids2 = [x[0] for x in field_obj.name_search(cr, uid, right, [], operator, context=context, limit=None)] if ids2: - operator = 'in' + operator = 'in' else: if not isinstance(right,list): ids2 = [right] else: - ids2 = right + ids2 = right if not ids2: if operator in ['like','ilike','in','=']: #no result found with given search criteria @@ -204,12 +206,12 @@ class expression(object): if operator in ['not like','not ilike','not in','<>','!=']: o2m_op = 'not in' self.__exp[i] = ('id', o2m_op, self.__execute_recursive_in(cr, field._fields_id, field_obj._table, 'id', ids2, operator, field._type)) - + if call_null: o2m_op = 'not in' if operator in ['not like','not ilike','not in','<>','!=']: - o2m_op = 'in' - self.__exp[i] = ('id', o2m_op, self.__execute_recursive_in(cr, field._fields_id, field_obj._table, 'id', [], operator, field._type) or [0]) + o2m_op = 'in' + self.__exp[i] = ('id', o2m_op, self.__execute_recursive_in(cr, field._fields_id, field_obj._table, 'id', [], operator, field._type) or [0]) elif field._type == 'many2many': #FIXME @@ -244,20 +246,20 @@ class expression(object): #no result found with given search criteria call_null_m2m = False self.__exp[i] = ('id','=',0) - else: + else: call_null_m2m = True operator = 'in' # operator changed because ids are directly related to main object else: call_null_m2m = False - m2m_op = 'in' + m2m_op = 'in' if operator in ['not like','not ilike','not in','<>','!=']: m2m_op = 'not in' - + self.__exp[i] = ('id', m2m_op, self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, res_ids, operator, field._type) or [0]) if call_null_m2m: m2m_op = 'not in' if operator in ['not like','not ilike','not in','<>','!=']: - m2m_op = 'in' + m2m_op = 'in' self.__exp[i] = ('id', m2m_op, self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, [], operator, field._type) or [0]) elif field._type == 'many2one': @@ -289,16 +291,16 @@ class expression(object): # other field type # add the time part to datetime field when it's not there: if field._type == 'datetime' and self.__exp[i][2] and len(self.__exp[i][2]) == 10: - + self.__exp[i] = list(self.__exp[i]) - + if operator in ('>', '>='): self.__exp[i][2] += ' 00:00:00' elif operator in ('<', '<='): self.__exp[i][2] += ' 23:59:59' - + self.__exp[i] = tuple(self.__exp[i]) - + if field.translate: if operator in ('like', 'ilike', 'not like', 'not ilike'): right = '%%%s%%' % right @@ -341,7 +343,7 @@ class expression(object): if leaf == self.__DUMMY_LEAF: return ('(1=1)', []) left, operator, right = leaf - + if operator == 'inselect': query = '(%s.%s in (%s))' % (table._table, left, right[0]) params = right[1] @@ -355,7 +357,7 @@ class expression(object): len_after = len(params) check_nulls = len_after != len_before query = '(1=0)' - + if len_after: if left == 'id': instr = ','.join(['%s'] * len_after) @@ -372,7 +374,7 @@ class expression(object): query = '(%s OR %s.%s IS NULL)' % (query, table._table, left) else: params = [] - + if right == False and (leaf[0] in table._columns) and table._columns[leaf[0]]._type=="boolean" and (operator == '='): query = '(%s.%s IS NULL or %s.%s = false )' % (table._table, left,table._table, left) elif (((right == False) and (type(right)==bool)) or (right is None)) and (operator == '='): diff --git a/bin/osv/fields.py b/bin/osv/fields.py index bc843a3d1b1..28f021d8954 100644 --- a/bin/osv/fields.py +++ b/bin/osv/fields.py @@ -469,7 +469,7 @@ class one2many(_column): elif act[0] == 6: obj.write(cr, user, act[2], {self._fields_id:id}, context=context or {}) ids2 = act[2] or [0] - cr.execute('select id from '+_table+' where '+self._fields_id+'=%s and id <> ALL (%s)', (id,ids2)) + cr.execute('select id from '+_table+' where '+self._fields_id+'=%s and id <> ALL %s', (id,tuple(ids2))) ids3 = map(lambda x:x[0], cr.fetchall()) obj.write(cr, user, ids3, {self._fields_id:False}, context=context or {}) return result @@ -520,13 +520,24 @@ class many2many(_column): if d1: d1 = ' and ' + ' and '.join(d1) else: d1 = '' - - cr.execute('SELECT '+self._rel+'.'+self._id2+','+self._rel+'.'+self._id1+' \ - FROM '+self._rel+' , '+(','.join(tables))+' \ - WHERE '+self._rel+'.'+self._id1+' = ANY (%s) \ - AND '+self._rel+'.'+self._id2+' = '+obj._table+'.id '+d1 - +limit_str+' order by '+obj._table+'.'+obj._order+' offset %s', - [ids,]+d2+[offset]) + query = 'SELECT %(rel)s.%(id2)s, %(rel)s.%(id1)s \ + FROM %(rel)s, %(tbl)s \ + WHERE %(rel)s.%(id1)s in %%s \ + AND %(rel)s.%(id2)s = %(tbl)s.id \ + %(d1)s \ + %(limit)s \ + ORDER BY %(tbl)s.%(order)s \ + OFFSET %(offset)d' \ + % {'rel': self._rel, + 'tbl': obj._table, + 'id1': self._id1, + 'id2': self._id2, + 'd1': d1, + 'limit': limit_str, + 'order': obj._order, + 'offset': offset, + } + cr.execute(query, [tuple(ids)] + d2) for r in cr.fetchall(): res[r[1]].append(r[0]) return res diff --git a/bin/osv/orm.py b/bin/osv/orm.py index d658553bb04..734bd41a3be 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -1538,8 +1538,12 @@ class orm_template(object): view_id = view_ref_res[0] if view_id: - where = (model and (" and model='%s'" % (self._name,))) or '' - cr.execute('SELECT arch,name,field_parent,id,type,inherit_id FROM ir_ui_view WHERE id=%s'+where, (view_id,)) + query = "SELECT arch,name,field_parent,id,type,inherit_id FROM ir_ui_view WHERE id=%s" + params = (view_id,) + if model: + query += " AND model=%s" + params += (self._name,) + cr.execute(query, params) else: cr.execute('''SELECT arch,name,field_parent,id,type,inherit_id @@ -1750,6 +1754,10 @@ class orm_memory(orm_template): self.check_id = 0 cr.execute('delete from wkf_instance where res_type=%s', (self._name,)) + def _check_access(self, uid, object_id, mode): + if uid != 1 and self.datas[object_id]['internal.create_uid'] != uid: + raise except_orm(_('AccessError'), '%s access is only allowed on your own records for osv_memory objects' % mode.capitalize()) + def vaccum(self, cr, uid): self.check_id += 1 if self.check_id % self._check_time: @@ -1770,7 +1778,6 @@ class orm_memory(orm_template): def read(self, cr, user, ids, fields_to_read=None, context=None, load='_classic_read'): if not context: context = {} - self.pool.get('ir.model.access').check(cr, user, self._name, 'read', context=context) if not fields_to_read: fields_to_read = self._columns.keys() result = [] @@ -1781,8 +1788,10 @@ class orm_memory(orm_template): for id in ids: r = {'id': id} for f in fields_to_read: - if id in self.datas: - r[f] = self.datas[id].get(f, False) + record = self.datas.get(id) + if record: + self._check_access(user, id, 'read') + r[f] = record.get(f, False) if r[f] and isinstance(self._columns[f], fields.binary) and context.get('bin_size', False): r[f] = len(r[f]) result.append(r) @@ -1800,7 +1809,6 @@ class orm_memory(orm_template): def write(self, cr, user, ids, vals, context=None): if not ids: return True - self.pool.get('ir.model.access').check(cr, user, self._name, 'write', context=context) vals2 = {} upd_todo = [] for field in vals: @@ -1808,18 +1816,18 @@ class orm_memory(orm_template): vals2[field] = vals[field] else: upd_todo.append(field) - for id_new in ids: - self.datas[id_new].update(vals2) - self.datas[id_new]['internal.date_access'] = time.time() + for object_id in ids: + self._check_access(user, object_id, mode='write') + self.datas[object_id].update(vals2) + self.datas[object_id]['internal.date_access'] = time.time() for field in upd_todo: - self._columns[field].set_memory(cr, self, id_new, field, vals[field], user, context) - self._validate(cr, user, [id_new], context) + self._columns[field].set_memory(cr, self, object_id, field, vals[field], user, context) + self._validate(cr, user, [object_id], context) wf_service = netsvc.LocalService("workflow") - wf_service.trg_write(user, self._name, id_new, cr) - return id_new + wf_service.trg_write(user, self._name, object_id, cr) + return object_id def create(self, cr, user, vals, context=None): - self.pool.get('ir.model.access').check(cr, user, self._name, 'create', context=context) self.vaccum(cr, user) self.next_id += 1 id_new = self.next_id @@ -1838,6 +1846,7 @@ class orm_memory(orm_template): upd_todo.append(field) self.datas[id_new] = vals2 self.datas[id_new]['internal.date_access'] = time.time() + self.datas[id_new]['internal.create_uid'] = user for field in upd_todo: self._columns[field].set_memory(cr, self, id_new, field, vals[field], user, context) @@ -1932,13 +1941,19 @@ class orm_memory(orm_template): import expression e = expression.expression(args) e.parse(cr, user, self, context) - res=e.__dict__['_expression__exp'] + res = e.exp return res or [] def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False): if not context: context = {} + + # implicit filter on current user + if not args: + args = [] + args.insert(0, ('internal.create_uid', '=', user)) + result = self._where_calc(cr, user, args, context=context) if result==[]: return self.datas.keys() @@ -1950,25 +1965,20 @@ class orm_memory(orm_template): if result: for id, data in self.datas.items(): counter=counter+1 - data['id'] = id - if limit and (counter >int(limit)): + data['id'] = id + if limit and (counter > int(limit)): break f = True for arg in result: - if arg[1] =='=': - val =eval('data[arg[0]]'+'==' +' arg[2]', locals()) - elif arg[1] in ['<','>','in','not in','<=','>=','<>']: - val =eval('data[arg[0]]'+arg[1] +' arg[2]', locals()) - elif arg[1] in ['ilike']: - if str(data[arg[0]]).find(str(arg[2]))!=-1: - val= True - else: - val=False + if arg[1] == '=': + val = eval('data[arg[0]]'+'==' +' arg[2]', locals()) + elif arg[1] in ['<','>','in','not in','<=','>=','<>']: + val = eval('data[arg[0]]'+arg[1] +' arg[2]', locals()) + elif arg[1] in ['ilike']: + val = (str(data[arg[0]]).find(str(arg[2]))!=-1) + + f = f and val - if f and val: - f = True - else: - f = False if f: res.append(id) if count: @@ -1976,20 +1986,22 @@ class orm_memory(orm_template): return res or [] def unlink(self, cr, uid, ids, context=None): - self.pool.get('ir.model.access').check(cr, uid, self._name, 'unlink', context=context) for id in ids: - if id in self.datas: - del self.datas[id] + self._check_access(uid, id, 'unlink') + self.datas.pop(id, None) if len(ids): - cr.execute('delete from wkf_instance where res_type=%s and res_id = ANY (%s)', (self._name,ids)) + cr.execute('delete from wkf_instance where res_type=%s and res_id IN %s', (self._name, tuple(ids))) return True def perm_read(self, cr, user, ids, context=None, details=True): result = [] + credentials = self.pool.get('res.users').name_get(cr, user, [user])[0] + create_date = time.strftime('%Y-%m-%d %H:%M:%S') for id in ids: + self._check_access(user, id, 'read') result.append({ - 'create_uid': (user, 'Root'), - 'create_date': time.strftime('%Y-%m-%d %H:%M:%S'), + 'create_uid': credentials, + 'create_date': create_date, 'write_uid': False, 'write_date': False, 'id': id @@ -2193,12 +2205,12 @@ class orm(orm_template): columns += ('id', 'write_uid', 'write_date', 'create_uid', 'create_date') # openerp access columns cr.execute("SELECT a.attname, a.attnotnull" " FROM pg_class c, pg_attribute a" - " WHERE c.relname=%%s" + " WHERE c.relname=%s" " AND c.oid=a.attrelid" - " AND a.attisdropped=%%s" + " AND a.attisdropped=%s" " AND pg_catalog.format_type(a.atttypid, a.atttypmod) NOT IN ('cid', 'tid', 'oid', 'xid')" - " AND a.attname NOT IN (%s)" % ",".join(['%s']*len(columns)), - [self._table, False] + columns) + " AND a.attname NOT IN %s" ,(self._table, False, tuple(columns))), + for column in cr.dictfetchall(): if log: logger.notifyChannel("orm", netsvc.LOG_DEBUG, "column %s is in the table %s but not in the corresponding object %s" % (column['attname'], self._table, self._name)) @@ -2212,9 +2224,9 @@ class orm(orm_template): todo_end = [] self._field_create(cr, context=context) if getattr(self, '_auto', True): - cr.execute("SELECT relname FROM pg_class WHERE relkind in ('r','v') AND relname='%s'" % self._table) + cr.execute("SELECT relname FROM pg_class WHERE relkind IN ('r','v') AND relname=%s" ,( self._table,)) if not cr.rowcount: - cr.execute("CREATE TABLE \"%s\" (id SERIAL NOT NULL, PRIMARY KEY(id)) WITHOUT OIDS" % self._table) + cr.execute('CREATE TABLE "%s" (id SERIAL NOT NULL, PRIMARY KEY(id)) WITHOUT OIDS' % (self._table,)) cr.execute("COMMENT ON TABLE \"%s\" IS '%s'" % (self._table, self._description.replace("'","''"))) create = True cr.commit() @@ -2280,7 +2292,7 @@ class orm(orm_template): if not res: cr.execute('ALTER TABLE "%s" ADD FOREIGN KEY (%s) REFERENCES "%s" ON DELETE SET NULL' % (self._obj, f._fields_id, f._table)) elif isinstance(f, fields.many2many): - cr.execute("SELECT relname FROM pg_class WHERE relkind in ('r','v') AND relname=%s", (f._rel,)) + cr.execute("SELECT relname FROM pg_class WHERE relkind IN ('r','v') AND relname=%s", (f._rel,)) if not cr.dictfetchall(): if not self.pool.get(f._obj): raise except_orm('Programming Error', ('There is no reference available for %s') % (f._obj,)) @@ -2356,7 +2368,7 @@ class orm(orm_template): try: cr.commit() cr.execute('ALTER TABLE "%s" ALTER COLUMN "%s" SET NOT NULL' % (self._table, k)) - except Exception, e: + except Exception: logger.notifyChannel('orm', netsvc.LOG_WARNING, 'WARNING: unable to set column %s of table %s not null !\nTry to re-run: openerp-server.py --update=module\nIf it doesn\'t work, update records and execute manually:\nALTER TABLE %s ALTER COLUMN %s SET NOT NULL' % (k, self._table, self._table, k)) cr.commit() elif len(res)==1: @@ -2427,7 +2439,7 @@ class orm(orm_template): try: cr.execute('ALTER TABLE "%s" ALTER COLUMN "%s" SET NOT NULL' % (self._table, k)) cr.commit() - except Exception, e: + except Exception: logger.notifyChannel('orm', netsvc.LOG_WARNING, 'unable to set a NOT NULL constraint on column %s of the %s table !\nIf you want to have it, you should update the records and execute manually:\nALTER TABLE %s ALTER COLUMN %s SET NOT NULL' % (k, self._table, self._table, k)) cr.commit() elif not f.required and f_pg_notnull == 1: @@ -2472,7 +2484,7 @@ class orm(orm_template): todo_end.append((order, self._update_store, (f, k))) else: - cr.execute("SELECT relname FROM pg_class WHERE relkind in ('r','v') AND relname=%s", (self._table,)) + cr.execute("SELECT relname FROM pg_class WHERE relkind IN ('r','v') AND relname=%s", (self._table,)) create = not bool(cr.fetchone()) cr.commit() # start a new transaction @@ -2481,11 +2493,12 @@ class orm(orm_template): conname = '%s_%s' % (self._table, key) cr.execute("SELECT conname FROM pg_constraint where conname=%s", (conname,)) if not cr.dictfetchall(): + query = 'ALTER TABLE "%s" ADD CONSTRAINT "%s" %s' % (self._table, conname, con,) try: - cr.execute('alter table "%s" add constraint "%s_%s" %s' % (self._table, self._table, key, con,)) + cr.execute(query) cr.commit() except: - logger.notifyChannel('orm', netsvc.LOG_WARNING, 'unable to add \'%s\' constraint on table %s !\n If you want to have it, you should update the records and execute manually:\nALTER table %s ADD CONSTRAINT %s_%s %s' % (con, self._table, self._table, self._table, key, con,)) + logger.notifyChannel('orm', netsvc.LOG_WARNING, 'unable to add \'%s\' constraint on table %s !\n If you want to have it, you should update the records and execute manually:\n%s' % (con, self._table, query)) cr.rollback() if create: @@ -2824,18 +2837,19 @@ class orm(orm_template): return '"%s"' % (f,) fields_pre2 = map(convert_field, fields_pre) order_by = self._parent_order or self._order + select_fields = ','.join(fields_pre2 + ['id']) + query = 'SELECT %s FROM "%s" WHERE id IN %%s' % (select_fields, self._table) + if d1: + query += " AND " + d1 + query += " ORDER BY " + order_by for sub_ids in cr.split_for_in_conditions(ids): if d1: - cr.execute('SELECT %s FROM %s WHERE %s.id IN %%s AND %s ORDER BY %s' % \ - (','.join(fields_pre2 + [self._table + '.id']), ','.join(tables), self._table, ' and '.join(d1), - order_by),[sub_ids,]+d2) + cr.execute(query, [tuple(sub_ids)] + d2) if cr.rowcount != len(sub_ids): raise except_orm(_('AccessError'), _('You try to bypass an access rule while reading (Document type: %s).') % self._description) else: - cr.execute('SELECT %s FROM \"%s\" WHERE id IN %%s ORDER BY %s' % - (','.join(fields_pre2 + ['id']), self._table, - order_by), (sub_ids,)) + cr.execute(query, (tuple(sub_ids),)) res.extend(cr.dictfetchall()) else: res = map(lambda x: {'id': x}, ids) @@ -2922,7 +2936,7 @@ class orm(orm_template): for group in groups: module = group.split(".")[0] grp = group.split(".")[1] - cr.execute("select count(*) from res_groups_users_rel where gid in (select res_id from ir_model_data where name='%s' and module='%s' and model='%s') and uid=%s" % \ + cr.execute("select count(*) from res_groups_users_rel where gid IN (select res_id from ir_model_data where name=%s and module=%s and model=%s) and uid=%s" \ (grp, module, 'res.groups', user)) readonly = cr.fetchall() if readonly[0][0] >= 1: @@ -2968,13 +2982,14 @@ class orm(orm_template): if not ids: return [] fields = '' + uniq = isinstance(ids, (int, long)) + if uniq: + ids = [ids] + fields = 'id' if self._log_access: - fields = ', u.create_uid, u.create_date, u.write_uid, u.write_date' - if isinstance(ids, (int, long)): - ids_str = str(ids) - else: - ids_str = string.join(map(lambda x: str(x), ids), ',') - cr.execute('select u.id'+fields+' from "'+self._table+'" u where u.id in ('+ids_str+')') + fields += ', create_uid, create_date, write_uid, write_date' + query = 'SELECT %s FROM "%s" WHERE id IN %%s' % (fields, self._table) + cr.execute(query, (tuple(ids),)) res = cr.dictfetchall() for r in res: for key in r: @@ -2982,8 +2997,8 @@ class orm(orm_template): if key in ('write_uid', 'create_uid', 'uid') and details: if r[key]: r[key] = self.pool.get('res.users').name_get(cr, user, [r[key]])[0] - if isinstance(ids, (int, long)): - return res[ids] + if uniq: + return res[ids[0]] return res def _check_concurrency(self, cr, ids, context): @@ -3059,20 +3074,15 @@ class orm(orm_template): for oid in ids: wf_service.trg_delete(uid, self._name, oid, cr) - #cr.execute('select * from '+self._table+' where id in ('+str_d+')', ids) - #res = cr.dictfetchall() - #for key in self._inherits: - # ids2 = [x[self._inherits[key]] for x in res] - # self.pool.get(key).unlink(cr, uid, ids2) self.check_access_rule(cr, uid, ids, 'unlink', context=context) for sub_ids in cr.split_for_in_conditions(ids): cr.execute('delete from ' + self._table + ' ' \ - 'where id in %s', (sub_ids,)) + 'where id IN %s', (sub_ids,)) for order, object, store_ids, fields in result_store: if object != self._name: obj = self.pool.get(object) - cr.execute('select id from '+obj._table+' where id in ('+','.join(map(str, store_ids))+')') + cr.execute('select id from '+obj._table+' where id IN %s',(tuple(store_ids),)) rids = map(lambda x: x[0], cr.fetchall()) if rids: obj._store_set_values(cr, uid, rids, fields, context) @@ -3100,7 +3110,7 @@ class orm(orm_template): vals format for relational field type. - + many2many field : + + many2many field : For write operation on a many2many fields a list of tuple is expected. The folowing tuples are accepted: @@ -3138,7 +3148,7 @@ class orm(orm_template): for group in groups: module = group.split(".")[0] grp = group.split(".")[1] - cr.execute("select count(*) from res_groups_users_rel where gid in (select res_id from ir_model_data where name='%s' and module='%s' and model='%s') and uid=%s" % \ + cr.execute("select count(*) from res_groups_users_rel where gid IN (select res_id from ir_model_data where name=%s and module=%s and model=%s) and uid=%s" \ (grp, module, 'res.groups', user)) readonly = cr.fetchall() if readonly[0][0] >= 1: @@ -3229,7 +3239,7 @@ class orm(orm_template): self.check_access_rule(cr, user, ids, 'write', context=context) for sub_ids in cr.split_for_in_conditions(ids): cr.execute('update ' + self._table + ' set ' + ','.join(upd0) + ' ' \ - 'where id in %s', upd1 + [sub_ids]) + 'where id IN %s', upd1 + [sub_ids]) if totranslate: # TODO: optimize @@ -3261,7 +3271,7 @@ class orm(orm_template): nids = [] for sub_ids in cr.split_for_in_conditions(ids): cr.execute('select distinct "'+col+'" from "'+self._table+'" ' \ - 'where id in %s', (sub_ids,)) + 'where id IN %s', (sub_ids,)) nids.extend([x[0] for x in cr.fetchall()]) v = {} @@ -3457,7 +3467,7 @@ class orm(orm_template): for group in groups: module = group.split(".")[0] grp = group.split(".")[1] - cr.execute("select count(*) from res_groups_users_rel where gid in (select res_id from ir_model_data where name='%s' and module='%s' and model='%s') and uid=%s" % \ + cr.execute("select count(*) from res_groups_users_rel where gid IN (select res_id from ir_model_data where name='%s' and module='%s' and model='%s') and uid=%s" % \ (grp, module, 'res.groups', user)) readonly = cr.fetchall() if readonly[0][0] >= 1: @@ -3602,7 +3612,7 @@ class orm(orm_template): field_flag = False field_dict = {} if self._log_access: - cr.execute('select id,write_date from '+self._table+' where id in ('+','.join(map(str, ids))+')') + cr.execute('select id,write_date from '+self._table+' where id IN %s',(tuple(ids),)) res = cr.fetchall() for r in res: if r[1]: @@ -3983,13 +3993,12 @@ class orm(orm_template): if not parent: parent = self._parent_name ids_parent = ids[:] - while len(ids_parent): + query = 'SELECT distinct "%s" FROM "%s" WHERE id IN %%s' % (parent, self._table) + while ids_parent: ids_parent2 = [] for i in range(0, len(ids), cr.IN_MAX): sub_ids_parent = ids_parent[i:i+cr.IN_MAX] - cr.execute('SELECT distinct "'+parent+'"'+ - ' FROM "'+self._table+'" ' \ - 'WHERE id = ANY(%s)',(sub_ids_parent,)) + cr.execute(query, (tuple(sub_ids_parent),)) ids_parent2.extend(filter(None, map(lambda x: x[0], cr.fetchall()))) ids_parent = ids_parent2 for i in ids_parent: diff --git a/bin/report/render/rml2txt/rml2txt.py b/bin/report/render/rml2txt/rml2txt.py index 86362c57535..d4378c0749d 100755 --- a/bin/report/render/rml2txt/rml2txt.py +++ b/bin/report/render/rml2txt/rml2txt.py @@ -33,7 +33,7 @@ Font_size= 10.0 def verbose(text): sys.stderr.write(text+"\n"); -class textbox(): +class textbox(object): """A box containing plain text. It can have an offset, in chars. Lines can be either text strings, or textbox'es, recursively. diff --git a/bin/service/http_server.py b/bin/service/http_server.py index 623cd0364fa..3891d32eb78 100644 --- a/bin/service/http_server.py +++ b/bin/service/http_server.py @@ -260,7 +260,7 @@ class OerpAuthProxy(AuthProxy): if not db: db = handler.get_db_from_path(path) print "Got db:",db - except: + except Exception: if path.startswith('/'): path = path[1:] psp= path.split('/') diff --git a/bin/service/netrpc_server.py b/bin/service/netrpc_server.py index ff1d726b5b0..2a9c831b224 100644 --- a/bin/service/netrpc_server.py +++ b/bin/service/netrpc_server.py @@ -48,7 +48,7 @@ class TinySocketClientThread(threading.Thread, netsvc.OpenERPDispatcher): try: self.socket.shutdown( getattr(socket, 'SHUT_RDWR', 2)) - except: pass + except Exception: pass # That should garbage-collect and close it, too self.sock = None @@ -56,7 +56,7 @@ class TinySocketClientThread(threading.Thread, netsvc.OpenERPDispatcher): self.running = True try: ts = tiny_socket.mysocket(self.sock) - except: + except Exception: self.threads.remove(self) self.running = False return False diff --git a/bin/service/websrv_lib.py b/bin/service/websrv_lib.py index c9576dc1701..3f44b6d8314 100644 --- a/bin/service/websrv_lib.py +++ b/bin/service/websrv_lib.py @@ -370,7 +370,7 @@ class SecureMultiHTTPHandler(MultiHTTPHandler): self.rfile = self.connection.makefile('rb', self.rbufsize) self.wfile = self.connection.makefile('wb', self.wbufsize) self.log_message("Secure %s connection from %s",self.connection.cipher(),self.client_address) - except: + except Exception: self.request.shutdown(socket.SHUT_RDWR) raise @@ -381,7 +381,7 @@ class SecureMultiHTTPHandler(MultiHTTPHandler): MultiHTTPHandler.finish(self) try: self.connection.shutdown(socket.SHUT_RDWR) - except: + except Exception: pass import threading @@ -418,7 +418,7 @@ class ConnThreadingMixIn: if self.verify_request(request, client_address): try: self.process_request(request, client_address) - except: + except Exception: self.handle_error(request, client_address) self.close_request(request) diff --git a/bin/tools/misc.py b/bin/tools/misc.py index 43a283da2a4..5f69a5bdcea 100644 --- a/bin/tools/misc.py +++ b/bin/tools/misc.py @@ -982,14 +982,15 @@ def get_user_companies(cr, user): def _get_company_children(cr, ids): if not ids: return [] - cr.execute('SELECT id FROM res_company WHERE parent_id = ANY (%s)', (ids,)) - res=[x[0] for x in cr.fetchall()] + cr.execute('SELECT id FROM res_company WHERE parent_id IN %s', (tuple(ids),)) + res = [x[0] for x in cr.fetchall()] res.extend(_get_company_children(cr, res)) return res - cr.execute('SELECT comp.id FROM res_company AS comp, res_users AS u WHERE u.id = %s AND comp.id = u.company_id', (user,)) - compids=[cr.fetchone()[0]] - compids.extend(_get_company_children(cr, compids)) - return compids + cr.execute('SELECT company_id FROM res_users WHERE id=%s', (user,)) + user_comp = cr.fetchone()[0] + if not user_comp: + return [] + return [user_comp] + _get_company_children(cr, [user_comp]) def mod10r(number): """ diff --git a/bin/tools/translate.py b/bin/tools/translate.py index 9277bf6924b..7648470edb6 100644 --- a/bin/tools/translate.py +++ b/bin/tools/translate.py @@ -148,7 +148,7 @@ class GettextAlias(object): except: return source - cr.execute('select value from ir_translation where lang=%s and type in (%s,%s) and src=%s', (lang, 'code','sql_constraint', source)) + cr.execute('select value from ir_translation where lang=%s and type IN (%s,%s) and src=%s', (lang, 'code','sql_constraint', source)) res_trans = cr.fetchone() return res_trans and res_trans[0] or source _ = GettextAlias() @@ -446,9 +446,10 @@ def trans_generate(lang, modules, dbname=None): query_param = None if 'all_installed' in modules: query += ' WHERE module IN ( SELECT name FROM ir_module_module WHERE state = \'installed\') ' - elif not 'all' in modules: - query += ' WHERE module IN (%s)' % ','.join(['%s']*len(modules)) - query_param = modules + query_param = None + if 'all' not in modules: + query += ' WHERE module IN %s' + query_param = (tuple(modules),) query += ' ORDER BY module, model, name' cr.execute(query, query_param) @@ -584,7 +585,10 @@ def trans_generate(lang, modules, dbname=None): for constraint in pool.get(model)._constraints: msg = constraint[1] - push_translation(module, 'constraint', model, 0, encode(msg)) + # Check presence of __call__ directly instead of using + # callable() because it will be deprecated as of Python 3.0 + if not hasattr(msg, '__call__'): + push_translation(module, 'constraint', model, 0, encode(msg)) for field_name,field_def in pool.get(model)._columns.items(): if field_def.translate: diff --git a/bin/workflow/instance.py b/bin/workflow/instance.py index e1407fd1455..e530d56dcd2 100644 --- a/bin/workflow/instance.py +++ b/bin/workflow/instance.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). # @@ -15,7 +15,7 @@ # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see . # ############################################################################## @@ -71,7 +71,7 @@ def _update_end(cr, inst_id, ident): act_names = cr.fetchall() cr.execute("update wkf_instance set state='complete' where id=%s", (inst_id,)) cr.execute("update wkf_workitem set state='complete' where subflow_id=%s", (inst_id,)) - cr.execute("select i.id,w.osv,i.res_id from wkf_instance i left join wkf w on (i.wkf_id=w.id) where i.id in (select inst_id from wkf_workitem where subflow_id=%s)", (inst_id,)) + cr.execute("select i.id,w.osv,i.res_id from wkf_instance i left join wkf w on (i.wkf_id=w.id) where i.id IN (select inst_id from wkf_workitem where subflow_id=%s)", (inst_id,)) for i in cr.fetchall(): for act_name in act_names: validate(cr, i[0], (ident[0],i[1],i[2]), 'subflow.'+act_name[0]) diff --git a/bin/workflow/workitem.py b/bin/workflow/workitem.py index 4576f8c5278..bd98e8f67a1 100644 --- a/bin/workflow/workitem.py +++ b/bin/workflow/workitem.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). # @@ -15,7 +15,7 @@ # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see . # ############################################################################## @@ -89,7 +89,7 @@ def _execute(cr, workitem, activity, ident, stack): # signal_todo = [] if (workitem['state']=='active') and activity['signal_send']: - cr.execute("select i.id,w.osv,i.res_id from wkf_instance i left join wkf w on (i.wkf_id=w.id) where i.id in (select inst_id from wkf_workitem where subflow_id=%s)", (workitem['inst_id'],)) + cr.execute("select i.id,w.osv,i.res_id from wkf_instance i left join wkf w on (i.wkf_id=w.id) where i.id IN (select inst_id from wkf_workitem where subflow_id=%s)", (workitem['inst_id'],)) for i in cr.fetchall(): signal_todo.append((i[0], (ident[0],i[1],i[2]), activity['signal_send']))