Exemplo n.º 1
0
    def test_instantiate(self):
        "Test instantiate"

        def side_effect(*args, **kwargs):
            self.assertEqual(Transaction().context, {'test': True})
            return DEFAULT

        rpc = RPC(instantiate=0, check_access=True)
        obj = Mock()
        obj.return_value = instance = Mock()
        obj.side_effect = side_effect

        # Integer
        self.assertEqual(
            rpc.convert(obj, 1, {'test': True}),
            ([instance], {}, {'test': True, '_check_access': True}, None))
        obj.assert_called_once_with(1)

        obj.reset_mock()

        # Dictionary
        self.assertEqual(
            rpc.convert(obj, {'foo': 'bar'}, {'test': True}),
            ([instance], {}, {'test': True, '_check_access': True}, None))
        obj.assert_called_once_with(foo='bar')

        obj.reset_mock()
        obj.browse.return_value = instances = Mock()

        # List
        self.assertEqual(
            rpc.convert(obj, [1, 2, 3], {'test': True}),
            ([instances], {}, {'test': True, '_check_access': True}, None))
        obj.browse.assert_called_once_with([1, 2, 3])
Exemplo n.º 2
0
    def test_missing_context(self):
        "Test missing context"
        rpc = RPC()
        with self.assertRaises(ValueError) as cm:
            rpc.convert(None)

        self.assertEqual(str(cm.exception), "Missing context argument")
Exemplo n.º 3
0
    def test_wrong_context_type(self):
        "Test wrong context type"
        rpc = RPC()
        with self.assertRaises(TypeError) as cm:
            rpc.convert(None, context=None)

        self.assertEqual(str(cm.exception), "context must be a dictionary")
Exemplo n.º 4
0
    def test_check_access(self):
        "Test check_access"
        rpc_no_access = RPC(check_access=False)
        self.assertEqual(rpc_no_access.convert(None, {}), ([], {}, {}, None))

        rpc_with_access = RPC(check_access=True)
        self.assertEqual(rpc_with_access.convert(None, {}),
                         ([], {}, {
                             '_check_access': True
                         }, None))
Exemplo n.º 5
0
    def test_instantiate_unique(self):
        "Test instantiate unique"
        rpc = RPC(instantiate=0, unique=True)
        obj = Mock()

        rpc.convert(obj, [1, 2], {})
        obj.browse.assert_called_once_with([1, 2])

        obj.reset_mock()

        with self.assertRaises(ValueError):
            rpc.convert(obj, [1, 1], {})
Exemplo n.º 6
0
    def __call__(self, *args):
        from trytond.cache import Cache
        from trytond.transaction import Transaction
        from trytond.rpc import RPC

        if self._name in self._object.__rpc__:
            rpc = self._object.__rpc__[self._name]
        elif self._name in getattr(self._object, '_buttons', {}):
            rpc = RPC(readonly=False, instantiate=0)
        else:
            raise TypeError('%s is not callable' % self._name)

        with Transaction().start(self._config.database_name,
                self._config.user, readonly=rpc.readonly) as transaction:
            Cache.clean(self._config.database_name)
            args, kwargs, transaction.context, transaction.timestamp = \
                rpc.convert(self._object, *args)
            meth = getattr(self._object, self._name)
            if not hasattr(meth, 'im_self') or meth.im_self:
                result = rpc.result(meth(*args, **kwargs))
            else:
                assert rpc.instantiate == 0
                inst = args.pop(0)
                if hasattr(inst, self._name):
                    result = rpc.result(meth(inst, *args, **kwargs))
                else:
                    result = [rpc.result(meth(i, *args, **kwargs))
                        for i in inst]
            if not rpc.readonly:
                transaction.commit()
            Cache.resets(self._config.database_name)
        return result
Exemplo n.º 7
0
 def test_keyword_argument(self):
     "Test keyword argument"
     rpc = RPC(check_access=False)
     self.assertEqual(rpc.convert(None, 'foo', bar=True, context={}),
                      (['foo'], {
                          'bar': True
                      }, {}, None))
Exemplo n.º 8
0
    def __call__(self, *args):
        from trytond.transaction import Transaction
        from trytond.rpc import RPC

        if self._name in self._object.__rpc__:
            rpc = self._object.__rpc__[self._name]
        elif self._name in getattr(self._object, '_buttons', {}):
            rpc = RPC(readonly=False, instantiate=0)
        else:
            raise TypeError('%s is not callable' % self._name)

        with Transaction().start(self._config.database_name,
                self._config.user, readonly=rpc.readonly) as transaction:
            args, kwargs, transaction.context, transaction.timestamp = \
                rpc.convert(self._object, *args)
            meth = getattr(self._object, self._name)
            if not hasattr(meth, 'im_self') or meth.im_self:
                result = rpc.result(meth(*args, **kwargs))
            else:
                assert rpc.instantiate == 0
                inst = args.pop(0)
                if hasattr(inst, self._name):
                    result = rpc.result(meth(inst, *args, **kwargs))
                else:
                    result = [rpc.result(meth(i, *args, **kwargs))
                        for i in inst]
            if not rpc.readonly:
                transaction.commit()
        return result
Exemplo n.º 9
0
 def test_clean_context(self):
     "Test clean context"
     rpc = RPC(check_access=False)
     self.assertEqual(rpc.convert(None, {
         '_foo': True,
         '_datetime': None
     }), ([], {}, {
         '_datetime': None
     }, None))
Exemplo n.º 10
0
    def test_instantiate_slice(self):
        "Test instantiate with slice"
        rpc = RPC(instantiate=slice(0, 2), check_access=False)
        obj = Mock()
        obj.return_value = instance = Mock()

        self.assertEqual(rpc.convert(obj, 1, 2, {}),
                         ([instance, instance], {}, {}, None))
        obj.assert_has_calls([call(1), call(2)])
Exemplo n.º 11
0
    def __call__(self, *args, **kwargs):
        from trytond.rpc import RPC
        from trytond.tools import is_instance_method
        from trytond.transaction import Transaction
        from trytond.worker import run_task

        if self._name in self._object.__rpc__:
            rpc = self._object.__rpc__[self._name]
        elif self._name in getattr(self._object, '_buttons', {}):
            rpc = RPC(readonly=False, instantiate=0)
        else:
            raise TypeError('%s is not callable' % self._name)

        with Transaction().start(self._config.database_name,
                                 self._config.user,
                                 readonly=rpc.readonly) as transaction:
            args, kwargs, transaction.context, transaction.timestamp = \
                rpc.convert(self._object, *args, **kwargs)
            meth = getattr(self._object, self._name)
            if (rpc.instantiate is None
                    or not is_instance_method(self._object, self._name)):
                result = rpc.result(meth(*args, **kwargs))
            else:
                assert rpc.instantiate == 0
                inst = args.pop(0)
                if hasattr(inst, self._name):
                    result = rpc.result(meth(inst, *args, **kwargs))
                else:
                    result = [
                        rpc.result(meth(i, *args, **kwargs)) for i in inst
                    ]
            transaction.commit()
        while transaction.tasks:
            task_id = transaction.tasks.pop()
            run_task(self._config.database_name, task_id)
        return result
Exemplo n.º 12
0
 def test_timestamp(self):
     "Test context timestamp"
     rpc = RPC(check_access=False)
     self.assertEqual(rpc.convert(None, {'_timestamp': 'test'}),
                      ([], {}, {}, 'test'))
Exemplo n.º 13
0
 def test_simple(self):
     "Test simple"
     rpc = RPC(check_access=False)
     self.assertEqual(rpc.convert(None, 'foo', {}), (['foo'], {}, {}, None))
Exemplo n.º 14
0
def dispatch(host, port, protocol, database_name, user, session, object_type,
        object_name, method, *args, **kwargs):

    if object_type == 'common':
        if method == 'login':
            try:
                database = Database(database_name).connect()
                cursor = database.cursor()
                cursor.close()
            except Exception:
                return False
            res = security.login(database_name, user, session)
            Cache.clean(database_name)
            logger = logging.getLogger('dispatcher')
            msg = res and 'successful login' or 'bad login or password'
            logger.info('%s \'%s\' from %s:%d using %s on database \'%s\''
                % (msg, user, host, port, protocol, database_name))
            Cache.resets(database_name)
            return res or False
        elif method == 'logout':
            name = security.logout(database_name, user, session)
            logger = logging.getLogger('dispatcher')
            logger.info(('logout \'%s\' from %s:%d '
                    'using %s on database \'%s\'')
                % (name, host, port, protocol, database_name))
            return True
        elif method == 'version':
            return VERSION
        elif method == 'timezone_get':
            return CONFIG['timezone']
        elif method == 'list_lang':
            return [
                ('bg_BG', 'Български'),
                ('ca_ES', 'Català'),
                ('cs_CZ', 'Čeština'),
                ('de_DE', 'Deutsch'),
                ('en_US', 'English'),
                ('es_AR', 'Español (Argentina)'),
                ('es_ES', 'Español (España)'),
                ('es_CO', 'Español (Colombia)'),
                ('fr_FR', 'Français'),
                ('lt_LT', 'Lietuvių'),
                ('nl_NL', 'Nederlands'),
                ('ru_RU', 'Russian'),
            ]
        elif method == 'db_exist':
            try:
                database = Database(*args, **kwargs).connect()
                cursor = database.cursor()
                cursor.close(close=True)
                return True
            except Exception:
                return False
        elif method == 'list':
            if CONFIG['prevent_dblist']:
                raise Exception('AccessDenied')
            database = Database().connect()
            try:
                cursor = database.cursor()
                try:
                    res = database.list(cursor)
                finally:
                    cursor.close(close=True)
            except Exception:
                res = []
            return res
        elif method == 'create':
            return create(*args, **kwargs)
        elif method == 'restore':
            return restore(*args, **kwargs)
        elif method == 'drop':
            return drop(*args, **kwargs)
        elif method == 'dump':
            return dump(*args, **kwargs)
        return
    elif object_type == 'system':
        database = Database(database_name).connect()
        database_list = Pool.database_list()
        pool = Pool(database_name)
        if not database_name in database_list:
            pool.init()
        if method == 'listMethods':
            res = []
            for type in ('model', 'wizard', 'report'):
                for object_name, obj in pool.iterobject(type=type):
                    for method in obj.__rpc__:
                        res.append(type + '.' + object_name + '.' + method)
                    if hasattr(obj, '_buttons'):
                        for button in obj._buttons:
                            res.append(type + '.' + object_name + '.' + button)
            return res
        elif method == 'methodSignature':
            return 'signatures not supported'
        elif method == 'methodHelp':
            res = []
            args_list = args[0].split('.')
            object_type = args_list[0]
            object_name = '.'.join(args_list[1:-1])
            method = args_list[-1]
            obj = pool.get(object_name, type=object_type)
            return pydoc.getdoc(getattr(obj, method))

    for count in range(int(CONFIG['retry']), -1, -1):
        try:
            user = security.check(database_name, user, session)
        except DatabaseOperationalError:
            if count:
                continue
            raise
        break

    Cache.clean(database_name)
    database_list = Pool.database_list()
    pool = Pool(database_name)
    if not database_name in database_list:
        with Transaction().start(database_name, user,
                readonly=True) as transaction:
            pool.init()
    obj = pool.get(object_name, type=object_type)

    if method in obj.__rpc__:
        rpc = obj.__rpc__[method]
    elif method in getattr(obj, '_buttons', {}):
        rpc = RPC(readonly=False, instantiate=0)
    else:
        raise UserError('Calling method %s on %s %s is not allowed!'
            % (method, object_type, object_name))

    for count in range(int(CONFIG['retry']), -1, -1):
        with Transaction().start(database_name, user,
                readonly=rpc.readonly) as transaction:
            try:
                args, kwargs, transaction.context, transaction.timestamp = \
                    rpc.convert(obj, *args, **kwargs)
                meth = getattr(obj, method)
                if not hasattr(meth, 'im_self') or meth.im_self:
                    result = rpc.result(meth(*args, **kwargs))
                else:
                    assert rpc.instantiate == 0
                    inst = args.pop(0)
                    if hasattr(inst, method):
                        result = rpc.result(meth(inst, *args, **kwargs))
                    else:
                        result = [rpc.result(meth(i, *args, **kwargs))
                            for i in inst]
                if not rpc.readonly:
                    transaction.cursor.commit()
            except DatabaseOperationalError, exception:
                transaction.cursor.rollback()
                if count and not rpc.readonly:
                    continue
                raise
            except Exception, exception:
                if CONFIG['verbose'] and not isinstance(exception, (
                            NotLogged, ConcurrencyException, UserError,
                            UserWarning)):
                    tb_s = ''.join(traceback.format_exception(*sys.exc_info()))
                    logger = logging.getLogger('dispatcher')
                    logger.error('Exception calling method %s on '
                        '%s %s from %s@%s:%d/%s:\n'
                        % (method, object_type, object_name, user, host, port,
                            database_name) + tb_s)
                transaction.cursor.rollback()
                raise