Exemple #1
0
def test_component_configuration_load_file_not_found():
    """Test Component.load when a file is not found."""
    with mock.patch("builtins.open", side_effect=FileNotFoundError):
        with pytest.raises(FileNotFoundError):
            ComponentConfiguration.load(
                ComponentType.PROTOCOL, mock.MagicMock(spec=Path)
            )
Exemple #2
0
def dummy_contract(request):
    directory = Path(ROOT_DIR, "tests", "data", "dummy_contract")
    configuration = ComponentConfiguration.load(ComponentType.CONTRACT,
                                                directory)
    configuration._directory = directory
    configuration = cast(ContractConfig, configuration)

    if str(configuration.public_id) in contract_registry.specs:
        contract_registry.specs.pop(str(configuration.public_id))

    # load into sys modules
    Contract.from_config(configuration)

    # load into registry
    path = Path(configuration.directory,
                configuration.path_to_contract_interface)
    with open(path, "r") as interface_file:
        contract_interface = json.load(interface_file)

    contract_registry.register(
        id_=str(configuration.public_id),
        entry_point=
        f"{configuration.prefix_import_path}.contract:{configuration.class_name}",
        class_kwargs={"contract_interface": contract_interface},
        contract_config=configuration,
    )
    contract = contract_registry.make(str(configuration.public_id))
    yield contract
    contract_registry.specs.pop(str(configuration.public_id))
    def add_component(
        self,
        component_type: ComponentType,
        directory: PathLike,
        skip_consistency_check: bool = False,
    ) -> "AEABuilder":
        """
        Add a component, given its type and the directory.

        :param component_type: the component type.
        :param directory: the directory path.
        :param skip_consistency_check: if True, the consistency check are skipped.
        :raises AEAException: if a component is already registered with the same component id.
                            | or if there's a missing dependency.
        :return: the AEABuilder
        """
        directory = Path(directory)
        configuration = ComponentConfiguration.load(
            component_type, directory, skip_consistency_check
        )
        self._check_can_add(configuration)
        # update dependency graph
        self._package_dependency_manager.add_component(configuration)
        configuration.directory = directory

        return self
Exemple #4
0
def erc1155_contract():
    """
    Instantiate an ERC1155 contract instance. As a side effect,
    register it to the registry, if not already registered.
    """
    directory = Path(ROOT_DIR, "packages", "fetchai", "contracts", "erc1155")
    configuration = ComponentConfiguration.load(ComponentType.CONTRACT,
                                                directory)
    configuration._directory = directory
    configuration = cast(ContractConfig, configuration)

    if str(configuration.public_id) not in contract_registry.specs:
        # load contract into sys modules
        Contract.from_config(configuration)

        path = Path(configuration.directory,
                    configuration.path_to_contract_interface)
        with open(path, "r") as interface_file:
            contract_interface = json.load(interface_file)

        contract_registry.register(
            id_=str(configuration.public_id),
            entry_point=
            f"{configuration.prefix_import_path}.contract:{configuration.class_name}",
            class_kwargs={"contract_interface": contract_interface},
            contract_config=configuration,
        )

    contract = contract_registry.make(str(configuration.public_id))
    yield contract
Exemple #5
0
def test_from_config_and_registration():
    """Tests the from config method and contract registry registration."""

    directory = Path(ROOT_DIR, "tests", "data", "dummy_contract")
    configuration = ComponentConfiguration.load(ComponentType.CONTRACT, directory)
    configuration._directory = directory
    configuration = cast(ContractConfig, configuration)

    if str(configuration.public_id) in contract_registry.specs:
        contract_registry.specs.pop(str(configuration.public_id))

    contract = Contract.from_config(configuration)
    assert contract is not None
    assert contract.contract_interface is None
    assert contract.configuration == configuration
    assert contract.id == configuration.public_id

    contract_registry.register(
        id_=str(configuration.public_id),
        entry_point=f"{configuration.prefix_import_path}.contract:{configuration.class_name}",
        class_kwargs={"contract_interface": configuration.contract_interfaces},
        contract_config=configuration,
    )

    contract = contract_registry.make(str(configuration.public_id))
    assert contract is not None
    assert contract.configuration == configuration
    assert contract.contract_interface is not None
Exemple #6
0
    def from_dir(cls, directory: str) -> "Contract":
        """
        Load the protocol from a directory.

        :param directory: the directory to the skill package.
        :return: the contract object.
        """
        configuration = cast(
            ContractConfig,
            ComponentConfiguration.load(ComponentType.CONTRACT, Path(directory)),
        )
        configuration._directory = Path(directory)
        return Contract.from_config(configuration)
Exemple #7
0
    def from_dir(cls, directory: str) -> "Skill":
        """
        Load the skill from a directory.

        :param directory: the directory to the skill package.
        :return: the skill object.
        """
        configuration = cast(
            SkillConfig,
            ComponentConfiguration.load(ComponentType.SKILL, Path(directory)),
        )
        configuration._directory = Path(directory)
        return Skill.from_config(configuration)
Exemple #8
0
    def from_dir(cls, directory: str, **kwargs) -> "Protocol":
        """
        Load the protocol from a directory.

        :param directory: the directory to the skill package.
        :return: the protocol object.
        """
        configuration = cast(
            ProtocolConfig,
            ComponentConfiguration.load(ComponentType.PROTOCOL,
                                        Path(directory)),
        )
        configuration.directory = Path(directory)
        return Protocol.from_config(configuration, **kwargs)
Exemple #9
0
    def from_dir(cls, directory: str, identity: Identity,
                 crypto_store: CryptoStore) -> "Connection":
        """
        Load the connection from a directory.

        :param directory: the directory to the connection package.
        :param identity: the identity object.
        :param crypto_store: object to access the connection crypto objects.
        :return: the connection object.
        """
        configuration = cast(
            ConnectionConfig,
            ComponentConfiguration.load(ComponentType.CONNECTION,
                                        Path(directory)),
        )
        configuration.directory = Path(directory)
        return Connection.from_config(configuration, identity, crypto_store)
    def _find_import_order(
        self,
        skill_ids: List[ComponentId],
        aea_project_path: Path,
        skip_consistency_check: bool,
    ) -> List[ComponentId]:
        """Find import order for skills.

        We need to handle skills separately, since skills can depend on each other.

        That is, we need to:
        - load the skill configurations to find the import order
        - detect if there are cycles
        - import skills from the leaves of the dependency graph, by finding a topological ordering.
        """
        # the adjacency list for the dependency graph
        depends_on: Dict[ComponentId, Set[ComponentId]] = defaultdict(set)
        # the adjacency list for the inverse dependency graph
        supports: Dict[ComponentId, Set[ComponentId]] = defaultdict(set)
        # nodes with no incoming edges
        roots = copy(skill_ids)
        for skill_id in skill_ids:
            component_path = self._find_component_directory_from_component_id(
                aea_project_path, skill_id
            )
            configuration = cast(
                SkillConfig,
                ComponentConfiguration.load(
                    skill_id.component_type, component_path, skip_consistency_check
                ),
            )

            if len(configuration.skills) != 0:
                roots.remove(skill_id)

            depends_on[skill_id].update(
                [
                    ComponentId(ComponentType.SKILL, skill)
                    for skill in configuration.skills
                ]
            )
            for dependency in configuration.skills:
                supports[ComponentId(ComponentType.SKILL, dependency)].add(skill_id)

        # find topological order (Kahn's algorithm)
        queue: Deque[ComponentId] = deque()
        order = []
        queue.extend(roots)
        while len(queue) > 0:
            current = queue.pop()
            order.append(current)
            for node in supports[
                current
            ]:  # pragma: nocover # TODO: extract method and test properly
                depends_on[node].discard(current)
                if len(depends_on[node]) == 0:
                    queue.append(node)

        if any(len(edges) > 0 for edges in depends_on.values()):
            raise AEAException("Cannot load skills, there is a cyclic dependency.")

        return order