Esempio n. 1
0
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")
Esempio n. 2
0
 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,
     )
Esempio n. 3
0
    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()
Esempio n. 4
0
    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)