<commit_before># vim: fileencoding=utf-8 et ts=4 sts=4 sw=4 tw=0

from types import GeneratorType

from netcall import RemoteRPCError, RPCTimeoutError, RPCServiceBase


class RPCCallsMixIn(object):

    def setUp(self):
        super(RPCCallsMixIn, self).setUp()

        assert self.tools
        assert self.client
        assert self.service

        self.url = self.urls[0]
        self.service.bind(self.url)
        self.client.connect(self.url)

        self.service.start()


    def assertNotImplementedRemotely(self, func_name):
        err_msg = "NotImplementedError: Unregistered procedure '%s'" % func_name
        with self.assertRaisesRegexp(RemoteRPCError, err_msg):
            self.client.call(func_name)


    def test_netcall_reserved(self):
        # Avoid asking for the special _* GEN names, they raise another exception
        reserved = [n for n in RPCServiceBase._RESERVED if not n.startswith('_')]
        for name in reserved:
            self.assertNotImplementedRemotely(name)

    def test_cannot_register_netcall_reserved(self):
        def dummy():
            pass

        for name in RPCServiceBase._RESERVED:
            with self.assertRaisesRegexp(ValueError, '%s is a reserved function name' % name):
                self.service.register(dummy, name=name)

        self.assertDictEqual(self.service.procedures, {})

        # Avoid asking for the special _* GEN names, they raise another exception
        reserved = [n for n in RPCServiceBase._RESERVED if not n.startswith('_')]
        for name in reserved:
            self.assertNotImplementedRemotely(name)

    def test_cannot_register_object_netcall_reserved(self):
        def dummy():
            pass

        class Dummy(object):
            pass

        toy = Dummy()
        for name in RPCServiceBase._RESERVED:
            setattr(toy, name, dummy)
        self.service.register_object(toy)

        self.assertDictEqual(self.service.procedures, {})

        # Avoid asking for the special _* GEN names, they raise another exception
        reserved = [n for n in RPCServiceBase._RESERVED if not n.startswith('_')]
        for name in reserved:
            self.assertNotImplementedRemotely(name)


    def test_function(self):
        @self.service.register
        def fixture():
            return 'This is a test'

        self.assertEqual(self.client.fixture(), 'This is a test')

    def test_function_named(self):
        @self.service.register(name='work')
        def fixture():
            return 'This is a test'

        self.assertEqual(self.client.work(), 'This is a test')
        self.assertNotImplementedRemotely("fixture")

    def test_function_args(self):
        @self.service.register
        def fn_double_one_arg(arg1):
            return arg1 * 2

        @self.service.register
        def fn_mul_two_args(arg1, arg2):
            return arg1 * arg2

        @self.service.register
        def fn_mul_vargs(*args):
            mul = 1
            for arg in args:
                mul = mul * arg
            return mul

        self.assertEqual(self.client.fn_double_one_arg(7),   14)
        self.assertEqual(self.client.fn_mul_two_args(7, 3),  21)
        self.assertEqual(self.client.fn_mul_vargs(7, 3, 10), 210)

    def test_function_kwargs(self):
        @self.service.register
        def fn_double_one_kwarg(arg1=None):
            return arg1 * 2

        @self.service.register
        def fn_mul_two_kwargs(arg1=None, arg2=None):
            return arg1 * arg2

        @self.service.register
        def fn_mul_vkwargs(**kwargs):
            mul = 1
            for arg in kwargs.values():
                mul = mul * arg
            return mul

        self.assertEqual(self.client.fn_double_one_kwarg(arg1=7), 14)
        self.assertEqual(self.client.fn_mul_two_kwargs(arg1=7, arg2=3), 21)
        self.assertEqual(self.client.fn_mul_vkwargs(arg1=7, arg2=3, arg3=10), 210)

        with self.assertRaisesRegexp(RemoteRPCError, "TypeError: .*() got an unexpected keyword argument 'argNot'"):
            self.client.fn_double_one_kwarg(argNot=7)
        with self.assertRaisesRegexp(RemoteRPCError, "TypeError: .*() got an unexpected keyword argument 'argNot'"):
            self.client.fn_mul_two_kwargs(arg1=7, arg2=3, argNot=17)

    def test_function_args_kwargs(self):
        @self.service.register
        def fn_one_arg_one_kwarg(arg1, arg2=None):
            return arg1 * arg2

        @self.service.register
        def fn_vargs_vkwargs(*args, **kwargs):
            return args[0] * sorted(kwargs.items())[0][1]

        self.assertEqual(self.client.fn_one_arg_one_kwarg(7, arg2=3), 21)
        self.assertEqual(self.client.fn_vargs_vkwargs(7, 5, argA=3, argB=18), 21)


    def test_timeout(self):
        @self.service.register
        def fixture():
            self.tools.sleep(0.2)

        with self.assertRaises(RPCTimeoutError):
            self.client.call('fixture', timeout=0.1)


    def test_object(self):
        toy = ToyObject(12)
        self.service.register_object(toy)

        self.assertEqual(self.client.value(), toy.value())
        self.assertIsNone(self.client.restricted())

    def test_object_private(self):
        toy = ToyObject(12)
        self.service.register_object(toy)

        self.assertNotImplementedRemotely("_private")

    def test_object_restricted(self):
        toy = ToyObject(12)
        self.service.register_object(toy, restricted=['restricted'])

        self.assertNotImplementedRemotely("restricted")

    def test_object_namespace_one_level(self):
        toys = []
        for i, n in enumerate('abc'):
            toys.append(ToyObject(i))
            self.service.register_object(toys[i], namespace=n)<commit_msg>added a test for a missing service (skipped for now)<commit_after># vim: fileencoding=utf-8 et ts=4 sts=4 sw=4 tw=0

from unittest import skip
from types    import GeneratorType

from netcall import RemoteRPCError, RPCTimeoutError, RPCServiceBase


class RPCCallsMixIn(object):

    def setUp(self):
        super(RPCCallsMixIn, self).setUp()

        assert self.tools
        assert self.client
        assert self.service

        self.url = self.urls[0]
        self.service.bind(self.url)
        self.client.connect(self.url)

        self.service.start()


    def assertNotImplementedRemotely(self, func_name):
        err_msg = "NotImplementedError: Unregistered procedure '%s'" % func_name
        with self.assertRaisesRegexp(RemoteRPCError, err_msg):
            self.client.call(func_name)


    def test_netcall_reserved(self):
        # Avoid asking for the special _* GEN names, they raise another exception
        reserved = [n for n in RPCServiceBase._RESERVED if not n.startswith('_')]
        for name in reserved:
            self.assertNotImplementedRemotely(name)

    def test_cannot_register_netcall_reserved(self):
        def dummy():
            pass

        for name in RPCServiceBase._RESERVED:
            with self.assertRaisesRegexp(ValueError, '%s is a reserved function name' % name):
                self.service.register(dummy, name=name)

        self.assertDictEqual(self.service.procedures, {})

        # Avoid asking for the special _* GEN names, they raise another exception
        reserved = [n for n in RPCServiceBase._RESERVED if not n.startswith('_')]
        for name in reserved:
            self.assertNotImplementedRemotely(name)

    def test_cannot_register_object_netcall_reserved(self):
        def dummy():
            pass

        class Dummy(object):
            pass

        toy = Dummy()
        for name in RPCServiceBase._RESERVED:
            setattr(toy, name, dummy)
        self.service.register_object(toy)

        self.assertDictEqual(self.service.procedures, {})

        # Avoid asking for the special _* GEN names, they raise another exception
        reserved = [n for n in RPCServiceBase._RESERVED if not n.startswith('_')]
        for name in reserved:
            self.assertNotImplementedRemotely(name)


    def test_function(self):
        @self.service.register
        def fixture():
            return 'This is a test'

        self.assertEqual(self.client.fixture(), 'This is a test')

    def test_function_named(self):
        @self.service.register(name='work')
        def fixture():
            return 'This is a test'

        self.assertEqual(self.client.work(), 'This is a test')
        self.assertNotImplementedRemotely("fixture")

    def test_function_args(self):
        @self.service.register
        def fn_double_one_arg(arg1):
            return arg1 * 2

        @self.service.register
        def fn_mul_two_args(arg1, arg2):
            return arg1 * arg2

        @self.service.register
        def fn_mul_vargs(*args):
            mul = 1
            for arg in args:
                mul = mul * arg
            return mul

        self.assertEqual(self.client.fn_double_one_arg(7),   14)
        self.assertEqual(self.client.fn_mul_two_args(7, 3),  21)
        self.assertEqual(self.client.fn_mul_vargs(7, 3, 10), 210)

    def test_function_kwargs(self):
        @self.service.register
        def fn_double_one_kwarg(arg1=None):
            return arg1 * 2

        @self.service.register
        def fn_mul_two_kwargs(arg1=None, arg2=None):
            return arg1 * arg2

        @self.service.register
        def fn_mul_vkwargs(**kwargs):
            mul = 1
            for arg in kwargs.values():
                mul = mul * arg
            return mul

        self.assertEqual(self.client.fn_double_one_kwarg(arg1=7), 14)
        self.assertEqual(self.client.fn_mul_two_kwargs(arg1=7, arg2=3), 21)
        self.assertEqual(self.client.fn_mul_vkwargs(arg1=7, arg2=3, arg3=10), 210)

        with self.assertRaisesRegexp(RemoteRPCError, "TypeError: .*() got an unexpected keyword argument 'argNot'"):
            self.client.fn_double_one_kwarg(argNot=7)
        with self.assertRaisesRegexp(RemoteRPCError, "TypeError: .*() got an unexpected keyword argument 'argNot'"):
            self.client.fn_mul_two_kwargs(arg1=7, arg2=3, argNot=17)

    def test_function_args_kwargs(self):
        @self.service.register
        def fn_one_arg_one_kwarg(arg1, arg2=None):
            return arg1 * arg2

        @self.service.register
        def fn_vargs_vkwargs(*args, **kwargs):
            return args[0] * sorted(kwargs.items())[0][1]

        self.assertEqual(self.client.fn_one_arg_one_kwarg(7, arg2=3), 21)
        self.assertEqual(self.client.fn_vargs_vkwargs(7, 5, argA=3, argB=18), 21)


    def test_timeout(self):
        @self.service.register
        def fixture():
            self.tools.sleep(0.2)

        with self.assertRaises(RPCTimeoutError):
            self.client.call('fixture', timeout=0.1)

    @skip('TODO')
    def test_ignore_missing_service(self):
        fail_url = self.extra[0]

        self.client.connect(fail_url)
        self.assertTrue(fail_url in self.client.connected)

        self.service.register(lambda: 123, name='fixture')

        call = lambda: self.client.call('fixture', timeout=0.5)

        self.assertEqual(call(), 123)  # ask existing service
        self.assertEqual(call(), 123)  # skip missing service


    def test_object(self):
        toy = ToyObject(12)
        self.service.register_object(toy)

        self.assertEqual(self.client.value(), toy.value())
        self.assertIsNone(self.client.restricted())

    def test_object_private(self):
        toy = ToyObject(12)
        self.service.register_object(toy)

        self.assertNotImplementedRemotely("_private")

    def test_object_restricted(self):
        toy = ToyObject(12)
        self.service.register_object(toy, restricted=['restricted'])

        self.assertNotImplementedRemotely("restricted")

    def test_object_namespace_one_level(self):
        toys = []
        for i, n in enumerate('abc'):
            toys.append(ToyObject(i))
            self.service.register_object(toys[i], namespace=n)
{'fraction_non_alphanumeric': 0.10032578731935511, 'fraction_numerical': 0.016372901177846462, 'mean_word_length': 2.5139418843557384, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5069168', 'n_tokens_mistral': 3789, 'n_tokens_neox': 3597, 'n_words': 758}