def test_kwargs_passing(self, method, bot, monkeypatch):
        """
        This essentially makes sure that get_relevant_kwargs doesn't pass kwargs that are not
        accepted by the selected method.
        """

        signature = inspect.signature(getattr(bot, method))
        expected_kwargs = {
            name: True
            for name, param in signature.parameters.items()
        }
        kwargs = expected_kwargs.copy()
        kwargs['dummy'] = 'this_should_not_be_passed'

        def make_assertion(**_kwargs):
            self.test_flag = _kwargs == expected_kwargs

        # we're a bit tricky here, because otherwise monkeypatch would fiddle with the signature
        CACHED_SIGNATURES['make_assertion'] = signature

        monkeypatch.setattr(bot, method, make_assertion)
        send_by_kwargs(bot, kwargs)
        assert self.test_flag

        self.test_flag = False
        send_by_kwargs(bot, **kwargs)
        assert self.test_flag
    def test_defaults_handling(self, method, timeout, bot, monkeypatch):
        def make_assertion(**kwargs):
            if timeout is None:
                self.test_flag = 'timeout' not in kwargs
            else:
                self.test_flag = kwargs.get('timeout', None) == 5

        signature = inspect.signature(getattr(bot, method))
        kwargs = {
            name: True
            for name, param in signature.parameters.items()
            if param.default == inspect.Parameter.empty
            # special casing for some methods where the required arguments are not clear
            # due to the fact that we made them optional in order to allow passing e.g. a Venue
            # directly
            or name in
            ['latitude', 'longitude', 'address', 'phone_number', 'first_name']
        }
        if timeout is not None:
            kwargs['timeout'] = 5

        # we're a bit tricky here, because otherwise monkeypatch would fiddle with the signature
        CACHED_SIGNATURES['make_assertion'] = signature

        monkeypatch.setattr(bot, method, make_assertion)
        send_by_kwargs(bot, kwargs)
        assert self.test_flag

        self.test_flag = False
        send_by_kwargs(bot, **kwargs)
        assert self.test_flag
    def test_method_raises_exception(self, bot, monkeypatch):
        def mock(**_kw):
            raise TelegramError()

        signature = inspect.signature(bot.send_message)
        CACHED_SIGNATURES['mock'] = signature
        monkeypatch.setattr(bot, 'send_message', mock)
        with pytest.raises(RuntimeError,
                           match="Selected method 'mock', but it raised"):
            send_by_kwargs(bot, chat_id=123, text='Hi')
    def test_kwarg_mixing(self, bot, monkeypatch, kwargs, _kwargs):
        expected_kwargs = {'chat_id': 123, 'text': 'Hello there'}

        def make_assertion(**kw):
            self.test_flag = kw == expected_kwargs

        signature = inspect.signature(bot.send_message)
        CACHED_SIGNATURES['make_assertion'] = signature
        monkeypatch.setattr(bot, 'send_message', make_assertion)
        send_by_kwargs(bot, kwargs, **_kwargs)
        assert self.test_flag
    def test_fallback_behavior(self, monkeypatch, bot):
        def make_assertion(**kwargs):
            self.test_flag = True

        signature = inspect.signature(bot.send_dice)
        CACHED_SIGNATURES['make_assertion'] = signature
        monkeypatch.setattr(bot, 'send_dice', make_assertion)
        send_by_kwargs(bot, {'chat_id': 1})
        assert self.test_flag

        with pytest.raises(RuntimeError, match='Could not find a bot method'):
            send_by_kwargs(bot, {})
    def test_correct_selection(self, method, args, bot):
        if method == 'send_dice':
            pytest.skip('send_dice only has one required parameter anyway')

        kwargs = {args[0]: args[0]}

        with pytest.raises(
                KeyError,
                match=f"Selected method '{method}', but the required parameter"
        ):
            send_by_kwargs(bot, kwargs)

        with pytest.raises(
                KeyError,
                match=f"Selected method '{method}', but the required parameter"
        ):
            send_by_kwargs(bot, **kwargs)