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) )
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
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
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
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)
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)
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)
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