diff --git a/bin/addons/__init__.py b/bin/addons/__init__.py index b1b140159c1..82761d647bd 100644 --- a/bin/addons/__init__.py +++ b/bin/addons/__init__.py @@ -640,10 +640,20 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs): def load_test(cr, module_name, id_map, mode): cr.commit() - try: - _load_data(cr, module_name, id_map, mode, 'test') - finally: - cr.rollback() + if not tools.config.options['test-disable']: + try: + _load_data(cr, module_name, id_map, mode, 'test') + except Exception, e: + if tools.config.options['test-continue']: + logger.notifyChannel('ERROR', netsvc.LOG_TEST, e) + pass + else: + raise + finally: + if tools.config.options['test-rollback']: + cr.rollback() + else: + cr.commit() def _load_data(cr, module_name, id_map, mode, kind): noupdate = (kind == 'demo') @@ -757,6 +767,15 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs): return has_updates def load_modules(db, force_demo=False, status=None, update_module=False): + + def check_module_name(cr, mods, state): + for mod in mods: + id = modobj.search(cr, 1, ['&', ('state', '=', state), ('name', '=', mod)]) + if id: + getattr(modobj, states[state])(cr, 1, id) + elif mod != 'all': + logger.notifyChannel('init', netsvc.LOG_WARNING, 'module %s: invalid module name!' % (mod)) + if not status: status = {} cr = db.cursor() @@ -787,21 +806,16 @@ def load_modules(db, force_demo=False, status=None, update_module=False): return if update_module: modobj = pool.get('ir.module.module') + states = {'installed': 'button_upgrade', 'uninstalled': 'button_install'} logger.notifyChannel('init', netsvc.LOG_INFO, 'updating modules list') if ('base' in tools.config['init']) or ('base' in tools.config['update']): modobj.update_list(cr, 1) mods = [k for k in tools.config['init'] if tools.config['init'][k]] - if mods: - ids = modobj.search(cr, 1, ['&', ('state', '=', 'uninstalled'), ('name', 'in', mods)]) - if ids: - modobj.button_install(cr, 1, ids) + check_module_name(cr, mods, 'uninstalled') mods = [k for k in tools.config['update'] if tools.config['update'][k]] - if mods: - ids = modobj.search(cr, 1, ['&', ('state', '=', 'installed'), ('name', 'in', mods)]) - if ids: - modobj.button_upgrade(cr, 1, ids) + check_module_name(cr, mods, 'installed') cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base')) diff --git a/bin/addons/base/i18n/ca.po b/bin/addons/base/i18n/ca.po index e64daf5a6e9..79d255c529b 100644 --- a/bin/addons/base/i18n/ca.po +++ b/bin/addons/base/i18n/ca.po @@ -7,14 +7,14 @@ 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-02-07 05:09+0000\n" +"PO-Revision-Date: 2010-05-02 05:54+0000\n" "Last-Translator: Jordi Esteve - http://www.zikzakmedia.com " "\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-04-17 03:49+0000\n" +"X-Launchpad-Export-Date: 2010-05-03 04:02+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: base @@ -109,7 +109,7 @@ msgid "" msgstr "" "Escolliu entre la \"Interfície simplificada\" o \"Interfície estesa\".\n" "Si esteu examinant o utilitzant OpenERP per la primera vegada,\n" -"us suggerim per utilitzar la interfície simplificada, que té menys\n" +"us suggerim que utilitzeu la interfície simplificada, que té menys\n" "opcions i camps però és més fàcil d'entendre. Més tard podreu\n" "canviar a la vista estesa.\n" " " @@ -388,8 +388,8 @@ msgid "" "If you check this, then the second time the user prints with same attachment " "name, it returns the previous report." msgstr "" -"Si marca aquesta opció, quan l'usuari imprimeixi el mateix nom d'adjunt per " -"segona vegada, tornarà l'informe anterior." +"Si marqueu aquesta opció, quan l'usuari imprimeixi el mateix nom d'adjunt " +"per segona vegada, obtindrá l'informe anterior." #. module: base #: help:res.lang,iso_code:0 @@ -433,7 +433,7 @@ msgid "" "The ISO country code in two chars.\n" "You can use this field for quick search." msgstr "" -"EL codi ISO del país en dos caràcters.\n" +"EL codi ISO del país de dos caràcters.\n" "Podeu utilitzar aquest camp per la cerca ràpida." #. module: base @@ -474,7 +474,7 @@ msgstr "Interfície estesa" #: code:addons/base/ir/ir_model.py:0 #, python-format msgid "Custom fields must have a name that starts with 'x_' !" -msgstr "Els camps personalitzats han de tenir un nom que comença con 'x_'!" +msgstr "Els camps personalitzats han de tenir un nom que comenci amb 'x_'!" #. module: base #: help:ir.actions.server,action_id:0 @@ -913,7 +913,7 @@ msgstr "STOCK_MISSING_IMAGE" #. module: base #: view:res.users:0 msgid "Define New Users" -msgstr "Defineix nous usuaris" +msgstr "Definiu nous usuaris" #. module: base #: selection:ir.ui.menu,icon:0 @@ -1489,7 +1489,7 @@ msgstr "Menú" #. module: base #: field:res.currency,rate:0 msgid "Current Rate" -msgstr "Tasa" +msgstr "Taxa" #. module: base #: selection:module.lang.install,init,lang:0 @@ -3124,7 +3124,7 @@ msgid "" "any." msgstr "" "L'usuari intern que s'encarrega de comunicar-se amb aquesta empresa, si " -"n'hi ha." +"n'hi hagués." #. module: base #: field:res.partner,parent_id:0 @@ -5073,8 +5073,8 @@ msgstr "Islàndia" #: view:res.users:0 msgid "Roles are used to defined available actions, provided by workflows." msgstr "" -"Els rols s'utilitzen per definir les accions disponibles, de les que " -"proveeixen els fluxos." +"Els rols s'utilitzen per definir les accions disponibles dins d'un flux de " +"treball." #. module: base #: model:res.country,name:base.de @@ -5437,7 +5437,7 @@ msgstr "Dia de l'any: %(doy)s" #. module: base #: model:res.country,name:base.nt msgid "Neutral Zone" -msgstr "Zona Neutral" +msgstr "Zona neutral" #. module: base #: view:ir.model:0 @@ -5828,7 +5828,7 @@ msgstr "Companyia per defecte per objecte" #. module: base #: view:ir.actions.configuration.wizard:0 msgid "Next Configuration Step" -msgstr "Següent pas configuració" +msgstr "Següent pas de la configuració" #. module: base #: field:res.groups,comment:0 @@ -6645,8 +6645,8 @@ msgid "" "Access all the fields related to the current object using expression in " "double brackets, i.e. [[ object.partner_id.name ]]" msgstr "" -"Accedeix a tots els camps relacionats amb l'objecte actual mitjançant una " -"expressió en claudàtors dobles, per exemple [[ object.partner_id.name ]]" +"Podeu accedir a tots els camps relacionats amb l'objecte actual mitjançant " +"una expressió en claudàtors dobles, per exemple [[ object.partner_id.name ]]" #. module: base #: field:res.request.history,body:0 @@ -8088,7 +8088,7 @@ msgstr "" #. module: base #: wizard_view:module.lang.install,init:0 msgid "Choose a language to install:" -msgstr "Selecciona un idioma per instal·lar:" +msgstr "Seleccioneu un idioma a instal·lar:" #. module: base #: model:res.country,name:base.lk diff --git a/bin/addons/base/i18n/es.po b/bin/addons/base/i18n/es.po index 2303ddf769a..5524104bb92 100644 --- a/bin/addons/base/i18n/es.po +++ b/bin/addons/base/i18n/es.po @@ -7,14 +7,14 @@ 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-02-07 05:11+0000\n" +"PO-Revision-Date: 2010-05-02 05:52+0000\n" "Last-Translator: Jordi Esteve - http://www.zikzakmedia.com " "\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-04-17 03:52+0000\n" +"X-Launchpad-Export-Date: 2010-05-03 04:03+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: base @@ -389,7 +389,7 @@ msgid "" "name, it returns the previous report." msgstr "" "Si marca esta opción, cuando el usuario imprima el mismo nombre de adjunto " -"por segunda vez, devolverá el informe anterior." +"por segunda vez, obtendrá el informe anterior." #. module: base #: help:res.lang,iso_code:0 @@ -434,8 +434,8 @@ msgid "" "The ISO country code in two chars.\n" "You can use this field for quick search." msgstr "" -"EL código ISO del país en dos caracteres.\n" -"Puede usar este campo para la búsqueda rápida." +"EL código ISO del país de dos caracteres.\n" +"Puede utilizar este campo para la búsqueda rápida." #. module: base #: selection:workflow.activity,join_mode:0 @@ -3127,7 +3127,8 @@ msgid "" "The internal user that is in charge of communicating with this partner if " "any." msgstr "" -"El usuario interno que se encarga de comunicarse con esta empresa si hay." +"El usuario interno que se encarga de comunicarse con esta empresa, si los " +"hubiera." #. module: base #: field:res.partner,parent_id:0 @@ -5076,8 +5077,8 @@ msgstr "Islandia" #: view:res.users:0 msgid "Roles are used to defined available actions, provided by workflows." msgstr "" -"Los roles se utilizan para definir las acciones disponibles, que son " -"proporcionadas por los flujos." +"Los roles se utilizan para definir las acciones disponibles dentro de un " +"flujo de trabajo." #. module: base #: model:res.country,name:base.de @@ -5830,7 +5831,7 @@ msgstr "Compañía por defecto por objeto" #. module: base #: view:ir.actions.configuration.wizard:0 msgid "Next Configuration Step" -msgstr "Siguiente paso configuración" +msgstr "Siguiente paso de la configuración" #. module: base #: field:res.groups,comment:0 diff --git a/bin/addons/base/i18n/hr.po b/bin/addons/base/i18n/hr.po index 744feae054f..5d0cf33b263 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-04-26 04:29+0000\n" +"PO-Revision-Date: 2010-05-03 14:18+0000\n" "Last-Translator: goranc \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-04-27 03:37+0000\n" +"X-Launchpad-Export-Date: 2010-05-05 03:47+0000\n" "X-Generator: Launchpad (build Unknown)\n" "Language: hr\n" diff --git a/bin/addons/base/i18n/it.po b/bin/addons/base/i18n/it.po index 253250b3ac1..a07603c3142 100644 --- a/bin/addons/base/i18n/it.po +++ b/bin/addons/base/i18n/it.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-03-31 05:14+0000\n" -"Last-Translator: OpenERP Administrators \n" +"PO-Revision-Date: 2010-04-29 04:41+0000\n" +"Last-Translator: eLBati - albatos.com \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-04-17 03:51+0000\n" +"X-Launchpad-Export-Date: 2010-04-30 03:50+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: base @@ -422,7 +422,7 @@ msgstr "Colombia" #. module: base #: view:ir.module.module:0 msgid "Schedule Upgrade" -msgstr "Aggiornamento Programmazione" +msgstr "Pianifica l'aggiornamento" #. module: base #: field:ir.actions.report.custom,report_id:0 diff --git a/bin/addons/base/i18n/ja.po b/bin/addons/base/i18n/ja.po index c24430cf716..915a0dbb692 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-04-26 04:24+0000\n" +"PO-Revision-Date: 2010-05-03 14:46+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-04-27 03:37+0000\n" +"X-Launchpad-Export-Date: 2010-05-05 03:47+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 1f14d2aa331..471b33dab46 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-04-26 04:22+0000\n" +"PO-Revision-Date: 2010-05-03 14:48+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-04-27 03:37+0000\n" +"X-Launchpad-Export-Date: 2010-05-05 03:47+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 bcaa2d7cd5b..6badbbdeaac 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-04-26 04:19+0000\n" +"PO-Revision-Date: 2010-05-03 14:29+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-04-27 03:37+0000\n" +"X-Launchpad-Export-Date: 2010-05-05 03:47+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 7bed00336e1..106f1cfe8d3 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-04-26 04:28+0000\n" +"PO-Revision-Date: 2010-05-03 14:47+0000\n" "Last-Translator: OpenERP Administrators \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-04-27 03:37+0000\n" +"X-Launchpad-Export-Date: 2010-05-05 03:47+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 7eaa78c8a3a..d260a8a1e75 100644 --- a/bin/addons/base/ir/ir.xml +++ b/bin/addons/base/ir/ir.xml @@ -1147,67 +1147,51 @@ - + Record rules - ir.rule.group + ir.rule form
- - - - - -
- + Record rules - ir.rule.group + ir.rule tree - - - - - - Rule Definition - ir.rule - form - -
- - - - - - - -
- - - Rules - ir.rule - tree - - - @@ -1215,22 +1199,20 @@ + Record Rules - ir.rule.group + ir.rule form - + - + Property multi-company - - ['|',('company_id','child_of',user.company_id.id),('company_id','=',False)] - diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index a9eab3ea3da..dd5cbc833b4 100644 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -191,7 +191,7 @@ class act_window(osv.osv): return s.encode('utf8') return s for act in self.browse(cr, uid, ids): - fields_from_fields_get = self.pool.get(act.res_model).fields_get(cr, uid) + fields_from_fields_get = self.pool.get(act.res_model).fields_get(cr, uid, context=context) search_view_id = False if act.search_view_id: search_view_id = act.search_view_id.id diff --git a/bin/addons/base/ir/ir_model.py b/bin/addons/base/ir/ir_model.py index 670fb420bd2..f6412e85b75 100644 --- a/bin/addons/base/ir/ir_model.py +++ b/bin/addons/base/ir/ir_model.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 logging @@ -80,7 +80,7 @@ class ir_model(osv.osv): if context: context.pop('__last_update', None) return super(ir_model,self).write(cr, user, ids, vals, context) - + def create(self, cr, user, vals, context=None): if context and context.get('manual',False): vals['state']='manual' @@ -226,7 +226,7 @@ class ir_model_fields(osv.osv): 'domain': fields.char('Domain', size=256), 'groups': fields.many2many('res.groups', 'ir_model_fields_group_rel', 'field_id', 'group_id', 'Groups'), 'view_load': fields.boolean('View Auto-Load'), - 'selectable': fields.boolean('Selectable'), + 'selectable': fields.boolean('Selectable'), } _rec_name='field_description' _defaults = { @@ -278,7 +278,7 @@ class ir_model_fields(osv.osv): self.pool.get(vals['model'])._auto_init(cr, ctx) return res - + ir_model_fields() class ir_model_access(osv.osv): @@ -378,6 +378,7 @@ class ir_model_access(osv.osv): 'create': _('You can not create this kind of document! (%s)'), 'unlink': _('You can not delete this document! (%s)'), } + raise except_orm(_('AccessError'), msgs[mode] % model_name ) return r diff --git a/bin/addons/base/ir/ir_rule.py b/bin/addons/base/ir/ir_rule.py index c4165d1bc93..de465fa8025 100644 --- a/bin/addons/base/ir/ir_rule.py +++ b/bin/addons/base/ir/ir_rule.py @@ -23,154 +23,121 @@ from osv import fields,osv import time import tools - -class ir_rule_group(osv.osv): - _name = 'ir.rule.group' - - _columns = { - 'name': fields.char('Name', size=128, select=1), - 'model_id': fields.many2one('ir.model', 'Object',select=1, required=True), - 'global': fields.boolean('Global', select=1, help="Make the rule global, otherwise it needs to be put on a group"), - 'rules': fields.one2many('ir.rule', 'rule_group', 'Tests', help="The rule is satisfied if at least one test is True"), - 'groups': fields.many2many('res.groups', 'group_rule_group_rel', 'rule_group_id', 'group_id', 'Groups'), - 'users': fields.many2many('res.users', 'user_rule_group_rel', 'rule_group_id', 'user_id', 'Users'), - } - - _order = 'model_id, global DESC' - - _defaults={ - 'global': lambda *a: True, - } - -ir_rule_group() - - class ir_rule(osv.osv): _name = 'ir.rule' - _rec_name = 'field_id' - - def _operand(self,cr,uid,context): - - def get(object, level=3, recur=None, root_tech='', root=''): - res = [] - if not recur: - recur = [] - fields = self.pool.get(object).fields_get(cr,uid) - key = fields.keys() - key.sort() - for k in key: - - if fields[k]['type'] in ('many2one'): - res.append((root_tech+'.'+k+'.id', - root+'/'+fields[k]['string'])) - - elif fields[k]['type'] in ('many2many', 'one2many'): - res.append(('\',\'.join(map(lambda x: str(x.id), '+root_tech+'.'+k+'))', - root+'/'+fields[k]['string'])) - - else: - res.append((root_tech+'.'+k, - root+'/'+fields[k]['string'])) - - if (fields[k]['type'] in recur) and (level>0): - res.extend(get(fields[k]['relation'], level-1, - recur, root_tech+'.'+k, root+'/'+fields[k]['string'])) - - return res - - res = [("False", "False"), ("True", "True"), ("user.id", "User")] - res += get('res.users', level=1, - recur=['many2one'], root_tech='user', root='User') - return res def _domain_force_get(self, cr, uid, ids, field_name, arg, context={}): res = {} for rule in self.browse(cr, uid, ids, context): eval_user_data = {'user': self.pool.get('res.users').browse(cr, 1, uid), 'time':time} - - if rule.domain_force: - res[rule.id] = eval(rule.domain_force, eval_user_data) - else: - if rule.operand and rule.operand.startswith('user.') and rule.operand.count('.') > 1: - #Need to check user.field.field1.field2(if field is False,it will break the chain) - op = rule.operand[5:] - rule.operand = rule.operand[:5+len(op[:op.find('.')])] +' and '+ rule.operand + ' or False' - if rule.operator in ('in', 'child_of'): - dom = eval("[('%s', '%s', [%s])]" % (rule.field_id.name, rule.operator, - eval(rule.operand,eval_user_data)), eval_user_data) - else: - dom = eval("[('%s', '%s', %s)]" % (rule.field_id.name, rule.operator, - rule.operand), eval_user_data) - res[rule.id] = dom + res[rule.id] = eval(rule.domain_force, eval_user_data) return res + def _get_value(self, cr, uid, ids, field_name, arg, context={}): + res = {} + for rule in self.browse(cr, uid, ids, context): + if not rule.groups: + res[rule.id] = True + else: + res[rule.id] = False + return res + + def _check_model_obj(self, cr, uid, ids, context={}): + model_obj = self.pool.get('ir.model') + for rule in self.browse(cr, uid, ids, context): + model = model_obj.browse(cr, uid, rule.model_id.id, context).model + obj = self.pool.get(model) + if isinstance(obj, osv.osv_memory): + return False + return True + _columns = { - 'field_id': fields.many2one('ir.model.fields', 'Field',domain= "[('model_id','=', parent.model_id)]", select=1), - 'operator':fields.selection((('=', '='), ('<>', '<>'), ('<=', '<='), ('>=', '>='), ('in', 'in'), ('child_of', 'child_of')), 'Operator'), - 'operand':fields.selection(_operand,'Operand', size=64), - 'rule_group': fields.many2one('ir.rule.group', 'Group', select=2, required=True, ondelete="cascade"), - 'domain_force': fields.char('Force Domain', size=250), + 'name': fields.char('Name', size=128, select=1), + 'model_id': fields.many2one('ir.model', 'Object',select=1, required=True), + 'global': fields.function(_get_value, method=True, string='Global', type='boolean', store=True, help="If no group is specified the rule is global and applied to everyone"), + 'groups': fields.many2many('res.groups', 'rule_group_rel', 'rule_group_id', 'group_id', 'Groups'), + 'domain_force': fields.char('Domain', size=250), 'domain': fields.function(_domain_force_get, method=True, string='Domain', type='char', size=250), - 'perm_read': fields.boolean('Read Access'), - 'perm_write': fields.boolean('Write Access'), - 'perm_create': fields.boolean('Create Access'), - 'perm_unlink': fields.boolean('Delete Access') + 'perm_read': fields.boolean('Apply For Read'), + 'perm_write': fields.boolean('Apply For Write'), + 'perm_create': fields.boolean('Apply For Create'), + 'perm_unlink': fields.boolean('Apply For Delete') } + + _order = 'model_id DESC' + _defaults = { - 'perm_read': lambda *a: True, - 'perm_write': lambda *a: True, - 'perm_create': lambda *a: True, - 'perm_unlink': lambda *a: True, + 'perm_read': True, + 'perm_write': True, + 'perm_create': True, + 'perm_unlink': True, + 'global': True, } _sql_constraints = [ - ('no_access_rights', 'CHECK (perm_read!=False or perm_write!=False or perm_create!=False or perm_unlink!=False)', 'Rule must have atleast one checked access right'), + ('no_access_rights', 'CHECK (perm_read!=False or perm_write!=False or perm_create!=False or perm_unlink!=False)', 'Rule must have at least one checked access right'), + ] + _constraints = [ + (_check_model_obj, 'Rules are not supported for osv_memory objects !', ['model_id']) ] - def onchange_all(self, cr, uid, ids, field_id, operator, operand): - if not (field_id or operator or operand): - return {} + def domain_create(self, cr, uid, rule_ids): + dom = ['&'] * (len(rule_ids)-1) + for rule in self.browse(cr, uid, rule_ids): + dom += rule.domain + return dom + + @tools.cache() + def _compute_domain(self, cr, uid, model_name, mode="read"): + group_rule = {} + global_rules = [] - def domain_get(self, cr, uid, model_name, mode='read', context={}): if uid == 1: - return [], [], ['"'+self.pool.get(model_name)._table+'"'] - + return None cr.execute("""SELECT r.id FROM ir_rule r - JOIN (ir_rule_group g - JOIN ir_model m ON (g.model_id = m.id)) - ON (g.id = r.rule_group) + JOIN ir_model m ON (r.model_id = m.id) WHERE m.model = %s AND r.perm_""" + mode + """ - AND (g.id IN (SELECT rule_group_id FROM group_rule_group_rel g_rel + AND (r.id IN (SELECT rule_group_id FROM rule_group_rel g_rel JOIN res_groups_users_rel u_rel ON (g_rel.group_id = u_rel.gid) - WHERE u_rel.uid = %s) OR g.global)""", (model_name, uid)) + WHERE u_rel.uid = %s) OR r.global)""", (model_name, uid)) ids = map(lambda x: x[0], cr.fetchall()) - dom = [] for rule in self.browse(cr, uid, ids): - dom += rule.domain - d1,d2,tables = self.pool.get(model_name)._where_calc(cr, uid, dom, active_test=False) - return d1, d2, tables - domain_get = tools.cache()(domain_get) + for group in rule.groups: + group_rule.setdefault(group.id, []).append(rule.id) + if not rule.groups: + global_rules.append(rule.id) + dom = self.domain_create(cr, uid, global_rules) + dom += ['|'] * (len(group_rule)-1) + for value in group_rule.values(): + dom += self.domain_create(cr, uid, value) + return dom + + def domain_get(self, cr, uid, model_name, mode='read', context={}): + dom = self._compute_domain(cr, uid, model_name, mode=mode) + if dom: + return self.pool.get(model_name)._where_calc(cr, uid, dom, active_test=False) + return [], [], ['"'+self.pool.get(model_name)._table+'"'] def unlink(self, cr, uid, ids, context=None): res = super(ir_rule, self).unlink(cr, uid, ids, context=context) - # Restart the cache on the domain_get method of ir.rule - self.domain_get.clear_cache(cr.dbname) + # Restart the cache on the _compute_domain method of ir.rule + self._compute_domain.clear_cache(cr.dbname) return res def create(self, cr, user, vals, context=None): res = super(ir_rule, self).create(cr, user, vals, context=context) - # Restart the cache on the domain_get method of ir.rule - self.domain_get.clear_cache(cr.dbname) + # Restart the cache on the _compute_domain method of ir.rule + self._compute_domain.clear_cache(cr.dbname) return res def write(self, cr, uid, ids, vals, context=None): if not context: context={} res = super(ir_rule, self).write(cr, uid, ids, vals, context=context) - # Restart the cache on the domain_get method - self.domain_get.clear_cache(cr.dbname) + # Restart the cache on the _compute_domain method + self._compute_domain.clear_cache(cr.dbname) return res ir_rule() diff --git a/bin/addons/base/res/country.py b/bin/addons/base/res/country.py index 272b0257a49..99e12a96f78 100644 --- a/bin/addons/base/res/country.py +++ b/bin/addons/base/res/country.py @@ -86,7 +86,7 @@ class CountryState(osv.osv): args = [] if not context: context = {} - ids = self.search(cr, user, [('code', '=', name)] + args, limit=limit, + ids = self.search(cr, user, [('code', 'ilike', name)] + args, limit=limit, context=context) if not ids: ids = self.search(cr, user, [('name', operator, name)] + args, diff --git a/bin/addons/base/res/res_user.py b/bin/addons/base/res/res_user.py index ff61b9ec6fa..fe67848de6a 100644 --- a/bin/addons/base/res/res_user.py +++ b/bin/addons/base/res/res_user.py @@ -34,7 +34,7 @@ class groups(osv.osv): _columns = { 'name': fields.char('Group Name', size=64, required=True), 'model_access': fields.one2many('ir.model.access', 'group_id', 'Access Controls'), - 'rule_groups': fields.many2many('ir.rule.group', 'group_rule_group_rel', + 'rule_groups': fields.many2many('ir.rule', 'rule_group_rel', 'group_id', 'rule_group_id', 'Rules', domain="[('global', '<>', True)]"), 'menu_access': fields.many2many('ir.ui.menu', 'ir_ui_menu_group_rel', 'gid', 'menu_id', 'Access Menu'), 'comment' : fields.text('Comment',size=250), @@ -47,7 +47,7 @@ class groups(osv.osv): group_name = self.read(cr, uid, [id], ['name'])[0]['name'] default.update({'name': group_name +' (copy)'}) return super(groups, self).copy(cr, uid, id, default, context) - + def write(self, cr, uid, ids, vals, context=None): if 'name' in vals: if vals['name'].startswith('-'): @@ -185,7 +185,6 @@ class users(osv.osv): 'menu_id': fields.many2one('ir.actions.actions', 'Menu Action'), 'groups_id': fields.many2many('res.groups', 'res_groups_users_rel', 'uid', 'gid', 'Groups'), 'roles_id': fields.many2many('res.roles', 'res_roles_users_rel', 'uid', 'rid', 'Roles'), - 'rules_id': fields.many2many('ir.rule.group', 'user_rule_group_rel', 'user_id', 'rule_group_id', 'Rules'), 'company_id': fields.many2one('res.company', 'Company', required=True, help="The company this user is currently working for."), 'company_ids':fields.many2many('res.company','res_company_users_rel','user_id','cid','Companies'), diff --git a/bin/addons/base/security/base_security.xml b/bin/addons/base/security/base_security.xml index ca1f33aa23e..1059cf4da37 100644 --- a/bin/addons/base/security/base_security.xml +++ b/bin/addons/base/security/base_security.xml @@ -72,37 +72,24 @@ - + res.partner.address company - - - - [('company_id','child_of',[user.company_id.id])] - + res.partner company - - - - [('company_id','child_of',[user.company_id.id])] - - + Multi_company_default company - - - - [('company_id','child_of',[user.company_id.id])] diff --git a/bin/addons/base/security/ir.model.access.csv b/bin/addons/base/security/ir.model.access.csv index bc291af8b33..cf0f73a5cc9 100644 --- a/bin/addons/base/security/ir.model.access.csv +++ b/bin/addons/base/security/ir.model.access.csv @@ -23,9 +23,7 @@ "access_ir_report_custom_group_system","ir_report_custom group_system","model_ir_report_custom",,1,0,0,0 "access_ir_report_custom_fields_group_system","ir_report_custom_fields group_system","model_ir_report_custom_fields",,1,0,0,0 "access_ir_rule_group_user","ir_rule group_user","model_ir_rule",,1,0,0,0 -"access_ir_rule_group_group_user","ir_rule_group group_user","model_ir_rule_group",,1,0,0,0 "access_ir_rule_group_erp_manager","ir_rule group_erp_manager","model_ir_rule","group_erp_manager",1,1,1,1 -"access_ir_rule_group_group_erp_manager","ir_rule_group group_erp_manager","model_ir_rule_group","group_erp_manager",1,1,1,1 "access_ir_sequence_group_user","ir_sequence group_user","model_ir_sequence",,1,1,1,1 "access_ir_sequence_type_group_user","ir_sequence_type group_user","model_ir_sequence_type",,1,0,0,0 "access_ir_translation_group_system","ir_translation group_system","model_ir_translation",,1,1,1,1 diff --git a/bin/addons/module_graph.py b/bin/addons/module_graph.py index edd7f6f947e..3eda4299c74 100755 --- a/bin/addons/module_graph.py +++ b/bin/addons/module_graph.py @@ -26,6 +26,17 @@ import os import sys import glob +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 = os.path.join(module, filename) + if os.path.isfile(description_file): + return eval(file(description_file).read()) + + return {} + if len(sys.argv) == 2 and (sys.argv[1] in ['-h', '--help']): print >>sys.stderr, 'Usage: module_graph.py [module1 module2 module3]\n\tWhen no module is specified, all modules in current directory are used' sys.exit(1) @@ -41,7 +52,7 @@ print 'digraph G {' while len(modules): f = modules.pop(0) done.append(f) - info = addons.load_information_from_description_file(f) + info = load_information_from_description_file(f) if info.get('installable', True): for name in info['depends']: if name not in done+modules: diff --git a/bin/osv/fields.py b/bin/osv/fields.py index 35ff1667418..71faa9898a5 100644 --- a/bin/osv/fields.py +++ b/bin/osv/fields.py @@ -656,6 +656,11 @@ class function(_column): self._symbol_f = float._symbol_f self._symbol_set = float._symbol_set + if type == 'boolean': + self._symbol_c = boolean._symbol_c + self._symbol_f = boolean._symbol_f + self._symbol_set = boolean._symbol_set + def digits_change(self, cr): if self.digits_compute: t = self.digits_compute(cr) diff --git a/bin/osv/orm.py b/bin/osv/orm.py index 062c0bc6f3a..c5019c729ed 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -1139,6 +1139,25 @@ class orm_template(object): return s.encode('utf8') return s + # return True if node can be displayed to current user + def check_group(node): + if node.get('groups'): + groups = node.get('groups').split(',') + can_see = False + access_pool = self.pool.get('ir.model.access') + for group in groups: + can_see = can_see or access_pool.check_groups(cr, user, group) + if can_see: + break + if not can_see: + node.set('invisible', '1') + if 'attrs' in node.attrib: + del(node.attrib['attrs']) #avoid making field visible later + del(node.attrib['groups']) + return can_see + else: + return True + if node.tag in ('field', 'node', 'arrow'): if node.get('object'): attrs = {} @@ -1185,15 +1204,18 @@ class orm_template(object): } attrs = {'views': views} if node.get('widget') and node.get('widget') == 'selection': + if not check_group(node): + attrs['selection'] = [] # We can not use the 'string' domain has it is defined according to the record ! - dom = [] - if column._domain and not isinstance(column._domain, (str, unicode)): - dom = column._domain - dom += eval(node.get('domain','[]'), {'uid':user, 'time':time}) - context.update(eval(node.get('context','{}'))) - attrs['selection'] = self.pool.get(relation).name_search(cr, user, '', dom, context=context,limit=None) - if (node.get('required') and not int(node.get('required'))) or not column.required: - attrs['selection'].append((False,'')) + else: + dom = [] + if column._domain and not isinstance(column._domain, (str, unicode)): + dom = column._domain + dom += eval(node.get('domain','[]'), {'uid':user, 'time':time}) + context.update(eval(node.get('context','{}'))) + attrs['selection'] = self.pool.get(relation)._name_search(cr, user, '', dom, context=context, limit=None, name_get_uid=1) + if (node.get('required') and not int(node.get('required'))) or not column.required: + attrs['selection'].append((False,'')) fields[node.get('name')] = attrs elif node.tag in ('form', 'tree'): @@ -1207,15 +1229,7 @@ class orm_template(object): fields[node.get(additional_field)] = {} if 'groups' in node.attrib: - if node.get('groups'): - groups = node.get('groups').split(',') - readonly = False - access_pool = self.pool.get('ir.model.access') - for group in groups: - readonly = readonly or access_pool.check_groups(cr, user, group) - if not readonly: - node.set('invisible', '1') - del(node.attrib['groups']) + check_group(node) # translate view if ('lang' in context) and not result: @@ -1725,6 +1739,7 @@ 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 = [] @@ -1754,6 +1769,7 @@ 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: @@ -1772,6 +1788,7 @@ class orm_memory(orm_template): return id_new 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 @@ -1923,6 +1940,7 @@ 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] @@ -3225,7 +3243,7 @@ class orm(orm_template): """ if not context: context = {} - self.pool.get('ir.model.access').check(cr, user, self._name, 'create') + self.pool.get('ir.model.access').check(cr, user, self._name, 'create', context=context) default = [] @@ -3282,7 +3300,7 @@ class orm(orm_template): record_id = tocreate[table].pop('id', None) - if record_id is None: + if record_id is None or not record_id: record_id = self.pool.get(table).create(cr, user, tocreate[table], context=context) else: self.pool.get(table).write(cr, user, [record_id], tocreate[table], context=context) @@ -3649,6 +3667,20 @@ class orm(orm_template): return [(r['id'], tools.ustr(r[self._rec_name])) for r in self.read(cr, user, ids, [self._rec_name], context, load='_classic_write')] + # private implementation of name_search, allows passing a dedicated user for the name_get part to + # solve some access rights issues + def _name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=100, name_get_uid=None): + if not args: + args = [] + if not context: + context = {} + args = args[:] + if name: + args += [(self._rec_name, operator, name)] + ids = self.search(cr, user, args, limit=limit, context=context) + res = self.name_get(cr, name_get_uid or user, ids, context) + return res + def name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=100): """ @@ -3664,16 +3696,7 @@ class orm(orm_template): This method is equivalent of search() on name + name_get() """ - if not args: - args = [] - if not context: - context = {} - args = args[:] - if name: - args += [(self._rec_name, operator, name)] - ids = self.search(cr, user, args, limit=limit, context=context) - res = self.name_get(cr, user, ids, context) - return res + return self._name_search(cr, user, name, args, operator, context, limit) def copy_data(self, cr, uid, id, default=None, context=None): """ diff --git a/bin/tools/config.py b/bin/tools/config.py index 8f1f1ca55ea..a92948b8af0 100644 --- a/bin/tools/config.py +++ b/bin/tools/config.py @@ -82,6 +82,9 @@ class configmanager(object): 'login_message': False, 'list_db' : True, 'timezone' : False, # to override the default TZ + 'test-disable' : False, + 'test-rollback' : True, + 'test-continue' : False } self.misc = {} @@ -134,7 +137,17 @@ class configmanager(object): default="server.pkey", help="specify the private key file for the SSL connection") parser.add_option_group(group) - + + # Testing Group + group = optparse.OptionGroup(parser, "Testing Configuration") + group.add_option("--test-disable", action="store_true", dest="test_disable", + default=False, help="Disable loading test files.") + group.add_option("--test-no-rollback", action="store_false", dest="test_rollback", + default=True, help="Don't rollback after running test.") + group.add_option("--test-continue", action="store_true", dest="test_continue", + default=False, help="Display exception but then test should continue.") + parser.add_option_group(group) + # Logging Group group = optparse.OptionGroup(parser, "Logging Configuration") group.add_option("--logfile", dest="logfile", help="file where the server log will be stored") @@ -274,6 +287,9 @@ class configmanager(object): self.options['init'] = opt.init and dict.fromkeys(opt.init.split(','), 1) or {} self.options["demo"] = not opt.without_demo and self.options['init'] or {} + self.options["test-disable"] = opt.test_disable + self.options["test-rollback"] = opt.test_rollback + self.options["test-continue"] = opt.test_continue self.options['update'] = opt.update and dict.fromkeys(opt.update.split(','), 1) or {} self.options['translate_modules'] = opt.translate_modules and map(lambda m: m.strip(), opt.translate_modules.split(',')) or ['all'] diff --git a/bin/tools/yaml_import.py b/bin/tools/yaml_import.py index 90bece88ee4..108a5ff0d32 100644 --- a/bin/tools/yaml_import.py +++ b/bin/tools/yaml_import.py @@ -254,38 +254,48 @@ class YamlInterpreter(object): b = bool(value) else: b = default - return b - - def process_record(self, node): - record, fields = node.items()[0] - - self.validate_xml_id(record.id) - if self.isnoupdate(record) and self.mode != 'init': - id = self.pool.get('ir.model.data')._update_dummy(self.cr, self.uid, record.model, self.module, record.id) - # check if the resource already existed at the last update - if id: - self.id_map[record] = int(id) - return None - else: - if not self._coerce_bool(record.forcecreate): - return None + return b + def create_osv_memory_record(self, record, fields): model = self.get_model(record.model) record_dict = self._create_record(model, fields) - self.logger.debug("RECORD_DICT %s" % record_dict) - id = self.pool.get('ir.model.data')._update(self.cr, self.uid, record.model, \ - self.module, record_dict, record.id, noupdate=self.isnoupdate(record), mode=self.mode) - self.id_map[record.id] = int(id) - if config.get('import_partial', False): - self.cr.commit() - + id_new=model.create(self.cr, self.uid, record_dict, context=self.context) + self.id_map[record.id] = int(id_new) + return record_dict + + def process_record(self, node): + import osv + record, fields = node.items()[0] + model = self.get_model(record.model) + if isinstance(model, osv.osv.osv_memory): + record_dict=self.create_osv_memory_record(record, fields) + else: + self.validate_xml_id(record.id) + if self.isnoupdate(record) and self.mode != 'init': + id = self.pool.get('ir.model.data')._update_dummy(self.cr, self.uid, record.model, self.module, record.id) + # check if the resource already existed at the last update + if id: + self.id_map[record] = int(id) + return None + else: + if not self._coerce_bool(record.forcecreate): + return None + + record_dict = self._create_record(model, fields) + self.logger.debug("RECORD_DICT %s" % record_dict) + id = self.pool.get('ir.model.data')._update(self.cr, self.uid, record.model, \ + self.module, record_dict, record.id, noupdate=self.isnoupdate(record), mode=self.mode) + self.id_map[record.id] = int(id) + if config.get('import_partial'): + self.cr.commit() + def _create_record(self, model, fields): record_dict = {} for field_name, expression in fields.items(): field_value = self._eval_field(model, field_name, expression) record_dict[field_name] = field_value - return record_dict - + return record_dict + def process_ref(self, node, column=None): if node.search: if node.model: @@ -307,10 +317,10 @@ class YamlInterpreter(object): else: value = None return value - + def process_eval(self, node): return eval(node.expression, self.eval_context) - + def _eval_field(self, model, field_name, expression): # TODO this should be refactored as something like model.get_field() in bin/osv if field_name in model._columns: @@ -390,6 +400,10 @@ class YamlInterpreter(object): uid = workflow.uid else: uid = self.uid + self.cr.execute('select distinct signal from wkf_transition') + signals=[x['signal'] for x in self.cr.dictfetchall()] + if workflow.action not in signals: + raise YamlImportException('Incorrect action %s. No such action defined' % workflow.action) wf_service = netsvc.LocalService("workflow") wf_service.trg_validate(uid, workflow.model, id, workflow.action, self.cr) @@ -528,15 +542,19 @@ class YamlInterpreter(object): 'tree_but_open', 'Menuitem', [('ir.ui.menu', int(parent_id))], action, True, True, xml_id=node.id) def process_act_window(self, node): + assert getattr(node, 'id'), "Attribute %s of act_window is empty !" % ('id',) + assert getattr(node, 'name'), "Attribute %s of act_window is empty !" % ('name',) + assert getattr(node, 'res_model'), "Attribute %s of act_window is empty !" % ('res_model',) self.validate_xml_id(node.id) view_id = False if node.view: view_id = self.get_id(node.view) - context = eval(node.context, self.eval_context) - + if not node.context: + node.context={} + context = eval(str(node.context), self.eval_context) values = { 'name': node.name, - 'type': type or 'ir.actions.act_window', + 'type': node.type or 'ir.actions.act_window', 'view_id': view_id, 'domain': node.domain, 'context': context, @@ -566,13 +584,17 @@ class YamlInterpreter(object): # TODO add remove ir.model.data def process_delete(self, node): - if len(node.search): - ids = self.pool.get(node.model).search(self.cr, self.uid, eval(node.search, self.eval_context)) + assert getattr(node, 'model'), "Attribute %s of delete tag is empty !" % ('model',) + if self.pool.get(node.model): + if len(node.search): + ids = self.pool.get(node.model).search(self.cr, self.uid, eval(node.search, self.eval_context)) + else: + ids = [self.get_id(node.id)] + if len(ids): + self.pool.get(node.model).unlink(self.cr, self.uid, ids) + self.pool.get('ir.model.data')._unlink(self.cr, self.uid, node.model, ids) else: - ids = [self.get_id(node.id)] - if len(ids): - self.pool.get(node.model).unlink(self.cr, self.uid, ids) - self.pool.get('ir.model.data')._unlink(self.cr, self.uid, node.model, ids) + self.logger.log(logging.TEST, "Record not deleted.") def process_url(self, node): self.validate_xml_id(node.id) @@ -649,6 +671,8 @@ class YamlInterpreter(object): """ Processes a Yaml string. Custom tags are interpreted by 'process_' instance methods. """ + yaml_tag.add_constructors() + is_preceded_by_comment = False for node in yaml.load(yaml_string): is_preceded_by_comment = self._log(node, is_preceded_by_comment) diff --git a/bin/tools/yaml_tag.py b/bin/tools/yaml_tag.py index cdc892d9b80..817f7d55a3c 100644 --- a/bin/tools/yaml_tag.py +++ b/bin/tools/yaml_tag.py @@ -48,9 +48,7 @@ class Workflow(YamlTag): super(Workflow, self).__init__(**kwargs) class ActWindow(YamlTag): - def __init__(self, model, action, **kwargs): - self.model = model - self.action = action + def __init__(self, **kwargs): super(ActWindow, self).__init__(**kwargs) class Function(YamlTag): @@ -67,10 +65,7 @@ class Report(YamlTag): super(Report, self).__init__(**kwargs) class Delete(YamlTag): - def __init__(self, model, id, search, **kwargs): - self.model = model - self.id = id - self.search = search + def __init__(self, **kwargs): super(Delete, self).__init__(**kwargs) class Context(YamlTag): @@ -156,17 +151,19 @@ def ir_set_constructor(loader, node): # Registers constructors for custom tags. # Constructors are actually defined globally: do not redefined them in another # class/file/package. This means that module recorder need import this file. -yaml.add_constructor(u"!assert", assert_constructor) -yaml.add_constructor(u"!record", record_constructor) -yaml.add_constructor(u"!python", python_constructor) -yaml.add_constructor(u"!menuitem", menuitem_constructor) -yaml.add_constructor(u"!workflow", workflow_constructor) -yaml.add_constructor(u"!act_window", act_window_constructor) -yaml.add_constructor(u"!function", function_constructor) -yaml.add_constructor(u"!report", report_constructor) -yaml.add_constructor(u"!context", context_constructor) -yaml.add_constructor(u"!delete", delete_constructor) -yaml.add_constructor(u"!url", url_constructor) -yaml.add_constructor(u"!eval", eval_constructor) -yaml.add_multi_constructor(u"!ref", ref_constructor) -yaml.add_constructor(u"!ir_set", ir_set_constructor) +def add_constructors(): + yaml.add_constructor(u"!assert", assert_constructor) + yaml.add_constructor(u"!record", record_constructor) + yaml.add_constructor(u"!python", python_constructor) + yaml.add_constructor(u"!menuitem", menuitem_constructor) + yaml.add_constructor(u"!workflow", workflow_constructor) + yaml.add_constructor(u"!act_window", act_window_constructor) + yaml.add_constructor(u"!function", function_constructor) + yaml.add_constructor(u"!report", report_constructor) + yaml.add_constructor(u"!context", context_constructor) + yaml.add_constructor(u"!delete", delete_constructor) + yaml.add_constructor(u"!url", url_constructor) + yaml.add_constructor(u"!eval", eval_constructor) + yaml.add_multi_constructor(u"!ref", ref_constructor) + yaml.add_constructor(u"!ir_set", ir_set_constructor) +add_constructors() \ No newline at end of file