def _load_project_config(project_path: Path) -> None: """Loads configuration settings from a project's brownie-config.yaml""" config_path = project_path.joinpath("brownie-config") config_data = _load_config(config_path) config_vars = _load_project_envvars(project_path) if "dotenv" in config_data: if not isinstance(config_data["dotenv"], str): raise ValueError( f'Invalid value passed to dotenv: {config_data["dotenv"]}') env_path = project_path.joinpath(config_data["dotenv"]) if not env_path.is_file(): raise ValueError( f"Dotenv specified in config but not found at path: {env_path}" ) config_vars.update(dotenv_values(dotenv_path=env_path)) # type: ignore load_dotenv(dotenv_path=env_path) config_data = expand_posix_vars(config_data, config_vars) if not config_data: return if "network" in config_data: warnings.warn( "The `network` field in `brownie-config.yaml` has been deprecated. " "Network settings are now handled via `brownie networks` in the CLI. " f"Remove `network` from {config_path} to silence this warning.", DeprecationWarning, ) del config_data["network"] # Update the network config cmd_settings with project specific cmd_settings if "networks" in config_data and isinstance(config_data["networks"], dict): for network, values in config_data["networks"].items(): if (network != "default" and network in CONFIG.networks.keys() and "cmd_settings" in values and isinstance(values["cmd_settings"], dict)): if "cmd_settings" in CONFIG.networks[network]: _recursive_update(CONFIG.networks[network]["cmd_settings"], values["cmd_settings"]) else: CONFIG.networks[network]["cmd_settings"] = values[ "cmd_settings"] CONFIG.settings._unlock() _recursive_update(CONFIG.settings, config_data) _recursive_update(CONFIG.settings, expand_posix_vars(CONFIG.settings, config_vars)) CONFIG.settings._lock() if "hypothesis" in config_data: _modify_hypothesis_settings(config_data["hypothesis"], "brownie", "brownie-base")
def setUp(self): self.v = str(uuid.uuid4()) self.input = { "non": "b", "simple": "${FOO}", "partial": "the ${FOO}", "number": 1, "bool": True, "nested": { "one": "nest ${FOO}", "super_nested": { "two": "real ${FOO}", "three": "not" }, }, "${A}": "abc", "default_envvar_present": "${FOO:-xyz}", "default_envvar_missing": "${ABC:-bar}", "default_int_present": "${NUM:-42}", "default_int_missing": "${ABC:-42}", "arr": [{ "a": False, "b": False }, { "a": True, "b": "${FOO}" }], } variables = {"FOO": self.v, "NUM": 314} self.res = expand_posix_vars( self.input, variables, )
def __init__(self, name: str, project_path: Path) -> None: self._path: Path = project_path self._envvars = _load_project_envvars(project_path) self._structure = expand_posix_vars( _load_project_structure_config(project_path), self._envvars) self._build_path: Path = project_path.joinpath( self._structure["build"]) self._name = name self._active = False self.load()
def load(self) -> None: """Compiles the project contracts, creates ContractContainer objects and populates the namespace.""" if self._active: raise ProjectAlreadyLoaded("Project is already active") contract_sources = _load_sources(self._path, self._structure["contracts"], False) interface_sources = _load_sources(self._path, self._structure["interfaces"], True) self._sources = Sources(contract_sources, interface_sources) self._build = Build(self._sources) contract_list = self._sources.get_contract_list() for path in list(self._build_path.glob("contracts/*.json")): try: with path.open() as fp: build_json = json.load(fp) except json.JSONDecodeError: build_json = {} if not set(BUILD_KEYS).issubset( build_json) or path.stem not in contract_list: path.unlink() continue if isinstance(build_json["allSourcePaths"], list): # this handles the format change in v1.7.0, it can be removed in a future release path.unlink() test_path = self._build_path.joinpath("tests.json") if test_path.exists(): test_path.unlink() continue if not self._path.joinpath(build_json["sourcePath"]).exists(): path.unlink() continue self._build._add_contract(build_json) interface_hashes = {} interface_list = self._sources.get_interface_list() for path in list(self._build_path.glob("interfaces/*.json")): try: with path.open() as fp: build_json = json.load(fp) except json.JSONDecodeError: build_json = {} if not set(INTERFACE_KEYS).issubset( build_json) or path.stem not in interface_list: path.unlink() continue self._build._add_interface(build_json) interface_hashes[path.stem] = build_json["sha1"] self._compiler_config = expand_posix_vars( _load_project_compiler_config(self._path), self._envvars) # compile updated sources, update build changed = self._get_changed_contracts(interface_hashes) self._compile(changed, self._compiler_config, False) self._compile_interfaces(interface_hashes) self._load_dependency_artifacts() self._create_containers() self._load_deployments() # add project to namespaces, apply import blackmagic name = self._name self.__all__ = list(self._containers) + ["interface"] sys.modules[f"brownie.project.{name}"] = self # type: ignore sys.modules["brownie.project"].__dict__[name] = self sys.modules["brownie.project"].__all__.append(name) # type: ignore sys.modules["brownie.project"].__console_dir__.append( name) # type: ignore self._namespaces = [ sys.modules["__main__"].__dict__, sys.modules["brownie.project"].__dict__, ] # register project for revert and reset _revert_register(self) self._active = True _loaded_projects.append(self)