From 573d02b6a98168bfdd30ea0175aba4e356a58497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 19 Oct 2010 22:17:21 +0200 Subject: [PATCH] Add wizard to proteus --- proteus/__init__.py | 68 ++++++++++++++++++++++++++++++++++++ proteus/config.py | 43 ++++++++++++----------- proteus/tests/test_wizard.py | 41 ++++++++++++++++++++++ 3 files changed, 131 insertions(+), 21 deletions(-) create mode 100644 proteus/tests/test_wizard.py diff --git a/proteus/__init__.py b/proteus/__init__.py index bdb9be5898..4554e60aaa 100644 --- a/proteus/__init__.py +++ b/proteus/__init__.py @@ -552,3 +552,71 @@ class Model(object): res = getattr(self._proxy, 'on_change_with_%s' % field)(args, context) self._set_on_change(field, res) + + +class Wizard(object): + 'Wizard class for Tryton wizards' + + def __init__(self, name, models=None, config=None, context=None): + if models: + assert isinstance(models, ModelList) + + super(Wizard, self).__init__() + self.name = name + self.state = None + self.states = ['init'] + self.form = None + self._config = config or proteus.config.get_config() + self._context = context or {} + self._proxy = self._config.get_proxy(name, type='wizard') + self.id = self._proxy.create(self._config.context) + if models: + self.datas = { + 'model': models[0].__class__.__name__, + 'id': models[0].id, + 'ids': [model.id for model in models] + } + else: + self.datas = {} + self.execute('init') + + def execute(self, state): + assert state in self.states + + if 'form' not in self.datas: + self.datas['form'] = {} + + if self.form: + self.datas['form'].update(self.form._get_values()) + + self.state = state + while self.state != 'end': + ctx = self._context.copy() + ctx.update(self._config.context) + ctx['active_id'] = self.datas.get('id') + ctx['active_ids'] = self.datas.get('ids') + + res = self._proxy.execute(self.id, self.datas, self.state, ctx) + if not res: + break + + if 'datas' in res: + self.datas['form'] = res['datas'] + elif res['type'] == 'form': + self.datas['form'] = {} + + if res['type'] == 'form': + self.states = [x[0] for x in res['state']] + # XXX set context + self.form = Model.get(res['object'])() + self.form._default_set(self.datas['form']) + return + elif res['type'] == 'action': + # TODO run action + self.state = res['state'] + elif res['type'] == 'print': + # TODO run print + self.state = res['state'] + + if self.state == 'end': + self._proxy.delete(self.id, self._config.context) diff --git a/proteus/config.py b/proteus/config.py index 5723f78d3c..2cccbe3048 100644 --- a/proteus/config.py +++ b/proteus/config.py @@ -51,14 +51,14 @@ class _TrytondMethod(object): def __init__(self, name, model, config): super(_TrytondMethod, self).__init__() self._name = name - self._model = model + self._object = model self._config = config def __call__(self, *args): from trytond.cache import Cache from trytond.transaction import Transaction - assert self._name in self._model._rpc + assert self._name in self._object._rpc with Transaction().start(self._config.database_name, self._config.user) as transaction: @@ -69,8 +69,8 @@ class _TrytondMethod(object): transaction.timestamp = context['_timestamp'] del context['_timestamp'] transaction.context = context - res = getattr(self._model, self._name)(*args) - if self._model._rpc[self._name]: + res = getattr(self._object, self._name)(*args) + if self._object._rpc[self._name]: transaction.cursor.commit() Cache.resets(self._config.database_name) return res @@ -78,15 +78,15 @@ class _TrytondMethod(object): class TrytondProxy(object): 'Proxy for function call for trytond' - def __init__(self, name, config): + def __init__(self, name, config, type='model'): super(TrytondProxy, self).__init__() self._config = config - self._model = config.pool.get(name) + self._object = config.pool.get(name, type=type) __init__.__doc__ = object.__init__.__doc__ def __getattr__(self, name): 'Return attribute value' - return _TrytondMethod(name, self._model, self._config) + return _TrytondMethod(name, self._object, self._config) class TrytondConfig(Config): @@ -140,14 +140,14 @@ class TrytondConfig(Config): self.database_name, self._user, self.database_type) __repr__.__doc__ = object.__repr__.__doc__ - def get_proxy(self, name): + def get_proxy(self, name, type='model'): 'Return Proxy class' - return TrytondProxy(name, self) + return TrytondProxy(name, self, type=type) - def get_proxy_methods(self, name): + def get_proxy_methods(self, name, type='model'): 'Return list of methods' - proxy = self.get_proxy(name) - return [x for x in proxy._model._rpc] + proxy = self.get_proxy(name, type=type) + return [x for x in proxy._object._rpc] def set_trytond(database_name, user='admin', database_type='postgresql', language='en_US', password=''): @@ -160,15 +160,15 @@ def set_trytond(database_name, user='admin', database_type='postgresql', class XmlrpcProxy(object): 'Proxy for function call for XML-RPC' - def __init__(self, name, config): + def __init__(self, name, config, type='model'): super(XmlrpcProxy, self).__init__() self._config = config - self._model = getattr(config.server, 'model.%s' % name) + self._object = getattr(config.server, '%s.%s' % (type, name)) __init__.__doc__ = object.__init__.__doc__ def __getattr__(self, name): 'Return attribute value' - return getattr(self._model, name) + return getattr(self._object, name) class XmlrpcConfig(Config): 'Configuration for XML-RPC' @@ -185,16 +185,17 @@ class XmlrpcConfig(Config): return "proteus.config.XmlrpcConfig('%s')" % self.url __repr__.__doc__ = object.__repr__.__doc__ - def get_proxy(self, name): + def get_proxy(self, name, type='model'): 'Return Proxy class' - return XmlrpcProxy(name, self) + return XmlrpcProxy(name, self, type=type) - def get_proxy_methods(self, name): + def get_proxy_methods(self, name, type='model'): 'Return list of methods' - return [x[len('model.%s' % name) + 1:] + object_ = '%s.%s' % (type, name) + return [x[len(object_) + 1:] for x in self.server.system.listMethods() - if x.startswith('model.%s' % name) - and '.' not in x[len('model.%s' % name) + 1:]] + if x.startswith(object_) + and '.' not in x[len(object_) + 1:]] def set_xmlrpc(url): 'Set XML-RPC as backend' diff --git a/proteus/tests/test_wizard.py b/proteus/tests/test_wizard.py new file mode 100644 index 0000000000..4541b8ae4f --- /dev/null +++ b/proteus/tests/test_wizard.py @@ -0,0 +1,41 @@ +#This file is part of Tryton. The COPYRIGHT file at the top level of +#this repository contains the full copyright notices and license terms. +from unittest import TestCase +from proteus import config, Wizard, Model + + +class TestWizard(TestCase): + + def setUp(self): + config.set_trytond(':memory:', database_type='sqlite') + + def test_translation_clean(self): + translation_clean = Wizard('ir.translation.clean') + self.assertEqual(translation_clean.form.__class__.__name__, + 'ir.translation.clean.init') + translation_clean.execute('start') + + def test_translation_export(self): + translation_export = Wizard('ir.translation.export') + translation_export.form.lang = 'en_US' + translation_export.form.module = 'ir' + translation_export.execute('start') + self.assert_(translation_export.form.file) + translation_export.execute('end') + + def test_user_config(self): + User = Model.get('res.user') + + user_config = Wizard('res.user.config') + user_config.execute('user') + user_config.form.name = 'Foo' + user_config.form.login = 'foo' + user_config.execute('add') + self.assertEqual(user_config.form.name, None) + self.assertEqual(user_config.form.login, None) + user_config.form.name = 'Bar' + user_config.form.login = 'bar' + user_config.execute('end') + + self.assert_(User.find([('name', '=', 'Foo')])) + self.assertFalse(User.find([('name', '=', 'Bar')]))