Beispiel #1
0
    def __init__(self, **kwargs) -> None:
        """
        Initialize dialogues.

        :return: None
        """
        Model.__init__(self, **kwargs)

        def role_from_first_message(  # pylint: disable=unused-argument
                message: Message, receiver_address: Address) -> Dialogue.Role:
            """Infer the role of the agent from an incoming/outgoing first message

            :param message: an incoming/outgoing first message
            :param receiver_address: the address of the receiving agent
            :return: The role of the agent
            """
            return 1  # type: ignore

        Dialogues.__init__(
            self,
            self_address=self.context.agent_name,
            end_states=[Mock()],  # type: ignore
            message_class=Message,
            dialogue_class=Dialogue,
            role_from_first_message=role_from_first_message,
        )
Beispiel #2
0
    def test_on_register(self):
        """Test the _on_register method of the tac handler, the successful case."""
        # setup
        self.game._phase = Phase.GAME_REGISTRATION

        incoming_message = self.build_incoming_message(
            message_type=TacMessage,
            performative=TacMessage.Performative.REGISTER,
            dialogue_reference=Dialogues.new_self_initiated_dialogue_reference(
            ),
            agent_name=self.agent_name,
        )

        # before
        assert self.game.registration.nb_agents == 0

        # operation
        with patch.object(self.tac_handler.context.logger,
                          "log") as mock_logger:
            self.tac_handler.handle(incoming_message)

        # after
        mock_logger.assert_any_call(logging.INFO,
                                    f"agent registered: '{self.agent_name}'")
        assert self.game.registration.nb_agents == 1
Beispiel #3
0
    def test_on_register_agent_name_already_exists(self):
        """Test the _on_register method of the tac handler where the agent name of the sender is already registered."""
        # setup
        self.game._phase = Phase.GAME_REGISTRATION
        self.game._registration.register_agent("some_address", self.agent_name)

        incoming_message = self.build_incoming_message(
            message_type=TacMessage,
            performative=TacMessage.Performative.REGISTER,
            dialogue_reference=Dialogues.new_self_initiated_dialogue_reference(
            ),
            agent_name=self.agent_name,
        )

        # operation
        with patch.object(self.tac_handler.context.logger,
                          "log") as mock_logger:
            self.tac_handler.handle(incoming_message)

        # after
        mock_logger.assert_any_call(
            logging.WARNING,
            f"agent with this name already registered: '{self.agent_name}'",
        )
        self.assert_quantity_in_outbox(1)
        has_attributes, error_str = self.message_has_attributes(
            actual_message=self.get_message_from_outbox(),
            message_type=TacMessage,
            performative=TacMessage.Performative.TAC_ERROR,
            to=COUNTERPARTY_ADDRESS,
            sender=self.skill.skill_context.agent_address,
            target=incoming_message.message_id,
            error_code=TacMessage.ErrorCode.AGENT_NAME_ALREADY_REGISTERED,
        )
        assert has_attributes, error_str
Beispiel #4
0
    def test_on_register_agent_not_in_whitelist(self):
        """Test the _on_register method of the tac handler where the agent is NOT in the whitelist."""
        # setup
        self.game._phase = Phase.GAME_REGISTRATION
        self.parameters._whitelist = ["some_other_agent", "yet_another_agent"]

        incoming_message = self.build_incoming_message(
            message_type=TacMessage,
            performative=TacMessage.Performative.REGISTER,
            dialogue_reference=Dialogues.new_self_initiated_dialogue_reference(
            ),
            agent_name=self.agent_name,
        )

        # operation
        with patch.object(self.tac_handler.context.logger,
                          "log") as mock_logger:
            self.tac_handler.handle(incoming_message)

        # after
        mock_logger.assert_any_call(
            logging.WARNING,
            f"agent name not in whitelist: '{self.agent_name}'")
        self.assert_quantity_in_outbox(1)
        has_attributes, error_str = self.message_has_attributes(
            actual_message=self.get_message_from_outbox(),
            message_type=TacMessage,
            performative=TacMessage.Performative.TAC_ERROR,
            to=COUNTERPARTY_ADDRESS,
            sender=self.skill.skill_context.agent_address,
            target=incoming_message.message_id,
            error_code=TacMessage.ErrorCode.AGENT_NAME_NOT_IN_WHITELIST,
        )
        assert has_attributes, error_str
Beispiel #5
0
def _try_construct_envelope(
        agent_name: str, dialogues: Dialogues,
        message_class: Type[Message]) -> Optional[Envelope]:
    """Try construct an envelope from user input."""
    envelope = None  # type: Optional[Envelope]
    try:
        performative_str = "bytes"
        performative = message_class.Performative(performative_str)
        click.echo(
            f"Provide message of protocol '{str(message_class.protocol_id)}' for performative {performative_str}:"
        )
        message_escaped = input()  # nosec
        message_escaped = message_escaped.strip()
        if message_escaped == "":
            raise InterruptInputException
        message_decoded = codecs.decode(message_escaped.encode("utf-8"),
                                        "unicode-escape")
        message = message_decoded.encode("utf-8")  # type: Union[str, bytes]
        msg, _ = dialogues.create(
            counterparty=agent_name,
            performative=performative,
            content=message,
        )
        envelope = Envelope(
            to=msg.to,
            sender=msg.sender,
            message=msg,
        )
    except InterruptInputException:
        click.echo("Interrupting input, checking inbox ...")
    except KeyboardInterrupt:
        raise
    except BaseException as e:  # pylint: disable=broad-except # pragma: no cover
        click.echo(e)
    return envelope
Beispiel #6
0
    def test_handle_cfp_is_matching_supply(self):
        """Test the _handle_cfp method of the fipa handler where is_matching_supply is True."""
        # setup
        proposal = Description({
            "ledger_id": "some_ledger_id",
            "price": 100,
            "currency_id": "FET",
            "service_id": "some_service_id",
            "quantity": 1,
            "tx_nonce": "some_tx_nonce",
        })
        terms = "some_terms"
        data = {"data_type": "data"}

        incoming_message = self.build_incoming_message(
            message_type=FipaMessage,
            performative=FipaMessage.Performative.CFP,
            dialogue_reference=Dialogues.new_self_initiated_dialogue_reference(
            ),
            query="some_query",
        )

        # operation
        with patch.object(
                self.strategy,
                "is_matching_supply",
                return_value=True,
        ):
            with patch.object(
                    self.strategy,
                    "generate_proposal_terms_and_data",
                    return_value=(proposal, terms, data),
            ):
                with patch.object(self.fipa_handler.context.logger,
                                  "log") as mock_logger:
                    self.fipa_handler.handle(incoming_message)

        # after
        mock_logger.assert_any_call(
            logging.INFO,
            f"received CFP from sender={COUNTERPARTY_ADDRESS[-5:]}")
        mock_logger.assert_any_call(
            logging.INFO,
            f"sending a PROPOSE with proposal={proposal.values} to sender={COUNTERPARTY_ADDRESS[-5:]}",
        )

        self.assert_quantity_in_outbox(1)

        has_attributes, error_str = self.message_has_attributes(
            actual_message=self.get_message_from_outbox(),
            message_type=FipaMessage,
            performative=FipaMessage.Performative.PROPOSE,
            to=COUNTERPARTY_ADDRESS,
            sender=self.skill.skill_context.agent_address,
            target=incoming_message.message_id,
            proposal=proposal,
        )
        assert has_attributes, error_str
Beispiel #7
0
    def __init__(
        self,
        self_address: Address,
        role_from_first_message: Callable[[Message, Address], Dialogue.Role],
        dialogue_class: Type[TProtocolDialogue] = TProtocolDialogue,
    ) -> None:
        """
        Initialize dialogues.

        :param self_address: the address of the entity for whom dialogues are maintained
        :return: None
        """
        Dialogues.__init__(
            self,
            self_address=self_address,
            end_states=cast(FrozenSet[Dialogue.EndState], self.END_STATES),
            message_class=TProtocolMessage,
            dialogue_class=dialogue_class,
            role_from_first_message=role_from_first_message,
        )
Beispiel #8
0
    def build_incoming_message(
        self,
        message_type: Type[Message],
        performative: Message.Performative,
        dialogue_reference: Optional[Tuple[str, str]] = None,
        message_id: Optional[int] = None,
        target: Optional[int] = None,
        to: Optional[Address] = None,
        sender: Address = COUNTERPARTY_ADDRESS,
        **kwargs,
    ) -> Message:
        """
        Quickly create an incoming message with the provided attributes.

        For any attribute not provided, the corresponding default value in message is used.

        :param message_type: the type of the message
        :param dialogue_reference: the dialogue_reference
        :param message_id: the message_id
        :param target: the target
        :param performative: the performative
        :param to: the 'to' address
        :param sender: the 'sender' address
        :param kwargs: other attributes

        :return: the created incoming message
        """
        message_attributes = dict()  # type: Dict[str, Any]

        default_dialogue_reference = Dialogues.new_self_initiated_dialogue_reference()
        dialogue_reference = (
            default_dialogue_reference
            if dialogue_reference is None
            else dialogue_reference
        )
        message_attributes["dialogue_reference"] = dialogue_reference
        if message_id is not None:
            message_attributes["message_id"] = message_id
        if target is not None:
            message_attributes["target"] = target
        message_attributes["performative"] = performative
        message_attributes.update(kwargs)

        incoming_message = message_type(**message_attributes)
        incoming_message.sender = sender
        incoming_message.to = (
            self.skill.skill_context.agent_address if to is None else to
        )

        return incoming_message
Beispiel #9
0
    def _non_initial_incoming_message_dialogue_reference(
        dialogue: Dialogue,
    ) -> Tuple[str, str]:
        """
        Specifies the dialogue reference of a non-initial incoming message for a dialogue.

        It uses a complete version of the reference in the dialogue if it is incomplete,
        otherwise it uses the reference in the dialogue.

        :param dialogue: the dialogue to which the incoming message is intended
        :return: its dialogue reference
        """
        dialogue_reference = (
            dialogue.dialogue_label.dialogue_reference[0],
            Dialogues._generate_dialogue_nonce()  # pylint: disable=protected-access
            if dialogue.dialogue_label.dialogue_reference[1]
            == Dialogue.UNASSIGNED_DIALOGUE_REFERENCE
            else dialogue.dialogue_label.dialogue_reference[1],
        )
        return dialogue_reference
Beispiel #10
0
    def test_handle_cfp_not_is_matching_supply(self):
        """Test the _handle_cfp method of the fipa handler where is_matching_supply is False."""
        # setup
        incoming_message = self.build_incoming_message(
            message_type=FipaMessage,
            performative=FipaMessage.Performative.CFP,
            dialogue_reference=Dialogues.new_self_initiated_dialogue_reference(
            ),
            query="some_query",
        )

        # operation
        with patch.object(self.strategy,
                          "is_matching_supply",
                          return_value=False):
            with patch.object(self.fipa_handler.context.logger,
                              "log") as mock_logger:
                self.fipa_handler.handle(incoming_message)

        # after
        mock_logger.assert_any_call(
            logging.INFO,
            f"received CFP from sender={COUNTERPARTY_ADDRESS[-5:]}")
        mock_logger.assert_any_call(
            logging.INFO,
            f"declined the CFP from sender={COUNTERPARTY_ADDRESS[-5:]}")

        self.assert_quantity_in_outbox(1)

        has_attributes, error_str = self.message_has_attributes(
            actual_message=self.get_message_from_outbox(),
            message_type=FipaMessage,
            performative=FipaMessage.Performative.DECLINE,
            to=COUNTERPARTY_ADDRESS,
            sender=self.skill.skill_context.agent_address,
            target=incoming_message.message_id,
        )
        assert has_attributes, error_str
Beispiel #11
0
    def test_on_register_not_pre_reg_phase(self):
        """Test the _on_register method of the tac handler where phase is NOT pre_registration."""
        # setup
        self.game._phase = Phase.PRE_GAME

        incoming_message = self.build_incoming_message(
            message_type=TacMessage,
            performative=TacMessage.Performative.REGISTER,
            dialogue_reference=Dialogues.new_self_initiated_dialogue_reference(
            ),
            agent_name=self.agent_name,
        )

        # operation
        with patch.object(self.tac_handler.context.logger,
                          "log") as mock_logger:
            self.tac_handler.handle(incoming_message)

        # after
        mock_logger.assert_any_call(
            logging.WARNING,
            f"received registration outside of game registration phase: '{incoming_message}'",
        )
Beispiel #12
0
    def prepare_skill_dialogue(
        self,
        dialogues: Dialogues,
        messages: Tuple[DialogueMessage, ...],
        counterparty: Address = COUNTERPARTY_ADDRESS,
    ) -> Dialogue:
        """
        Quickly create a dialogue.

        The 'messages' argument is a tuple of DialogueMessages.
        For every DialogueMessage (performative, contents, is_incoming, target):
            - if 'is_incoming' is not provided: for the first message it is assumed False (outgoing),
            for any other message, it is the opposite of the one preceding it.
            - if 'target' is not provided: for the first message it is assumed 0,
            for any other message, it is the index of the message before it in the tuple of messages + 1.

        :param dialogues: a dialogues class
        :param counterparty: the message_id
        :param messages: the dialogue_reference

        :return: the created incoming message
        """
        if len(messages) == 0:
            raise AEAEnforceError("the list of messages must be positive.")

        (
            performative,
            contents,
            message_id,
            is_incoming,
            target,
        ) = self._extract_message_fields(messages[0], index=0, last_is_incoming=True)

        if is_incoming:  # first message from the opponent
            dialogue_reference = dialogues.new_self_initiated_dialogue_reference()
            message = self.build_incoming_message(
                message_type=dialogues.message_class,
                dialogue_reference=dialogue_reference,
                message_id=message_id,
                target=target,
                performative=performative,
                to=self.skill.skill_context.agent_address,
                sender=counterparty,
                **contents,
            )
            dialogue = cast(Dialogue, dialogues.update(message))
            if dialogue is None:
                raise AEAEnforceError(
                    "Cannot update the dialogue with message number {}".format(
                        message_id
                    )
                )
        else:  # first message from self
            _, dialogue = dialogues.create(
                counterparty=counterparty, performative=performative, **contents
            )

        for idx, dialogue_message in enumerate(messages[1:]):
            (
                performative,
                contents,
                message_id,
                is_incoming,
                target,
            ) = self._extract_message_fields(dialogue_message, idx + 1, is_incoming)
            if is_incoming:  # messages from the opponent
                dialogue_reference = self._non_initial_incoming_message_dialogue_reference(
                    dialogue
                )
                message = self.build_incoming_message(
                    message_type=dialogues.message_class,
                    dialogue_reference=dialogue_reference,
                    message_id=message_id,
                    target=target,
                    performative=performative,
                    to=self.skill.skill_context.agent_address,
                    sender=counterparty,
                    **contents,
                )
                dialogue = cast(Dialogue, dialogues.update(message))
                if dialogue is None:
                    raise AEAEnforceError(
                        "Cannot update the dialogue with message number {}".format(
                            message_id
                        )
                    )
            else:  # messages from self
                dialogue.reply(performative=performative, target=target, **contents)

        return dialogue
Beispiel #13
0
 def __init__(self, name, skill_context):
     Model.__init__(self, name, skill_context)
     Dialogues.__init__(self, "addr", MagicMock(), Message, Dialogue,
                        role_from_first_message)