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, )
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
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
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
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
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
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, )
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
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
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
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}'", )
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
def __init__(self, name, skill_context): Model.__init__(self, name, skill_context) Dialogues.__init__(self, "addr", MagicMock(), Message, Dialogue, role_from_first_message)