Beispiel #1
0
def load(
    project_path: Union[Path, str, None] = None,
    name: Optional[str] = None,
    raise_if_loaded: bool = True,
) -> "Project":
    """Loads a project and instantiates various related objects.

    Args:
        project_path: Path of the project to load. If None, will attempt to
                      locate a project using check_for_project()
        name: Name to assign to the project. If None, the name is generated
              from the name of the project folder

    Returns a Project object.
    """
    # checks
    if project_path is None:
        project_path = check_for_project(".")
        if project_path is not None and project_path != Path(".").absolute():
            warnings.warn(
                f"Loaded project has a root folder of '{project_path}' "
                "which is different from the current working directory",
                BrownieEnvironmentWarning,
            )
    else:
        project_path = Path(project_path)
        if project_path.resolve() != check_for_project(project_path):
            packages_path = _get_data_folder().joinpath("packages")
            if not project_path.is_absolute() and packages_path.joinpath(
                    project_path).exists():
                project_path = packages_path.joinpath(project_path)
            else:
                project_path = None

    if project_path is None:
        raise ProjectNotFound("Could not find Brownie project")

    project_path = Path(project_path).resolve()
    if name is None:
        name = project_path.name
        if not name.lower().endswith("project"):
            name += " project"
        if not name[0].isalpha():
            raise BadProjectName(
                "Project must start with an alphabetic character")
        name = "".join(i for i in name.title() if i.isalnum())

    for loaded_project in _loaded_projects:
        if loaded_project._name == name:
            if raise_if_loaded:
                raise ProjectAlreadyLoaded(
                    "There is already a project loaded with this name")
            return loaded_project

    # paths
    _create_folders(project_path)
    _add_to_sys_path(project_path)

    # load sources and build
    return Project(name, project_path)
Beispiel #2
0
def _get_path(path_str: str) -> Tuple[Path, Optional[Project]]:
    # Returns path to a python module
    path = Path(path_str).with_suffix(".py")

    if not get_loaded_projects():
        if not path.exists():
            raise FileNotFoundError(f"Cannot find {path_str}")
        return path.resolve(), None

    if not path.is_absolute():
        for project in get_loaded_projects():
            if path.parts[:1] == (project._structure["scripts"],):
                script_path = project._path.joinpath(path)
            else:
                script_path = project._path.joinpath(project._structure["scripts"]).joinpath(path)
            if script_path.exists():
                return script_path.resolve(), project
        raise FileNotFoundError(f"Cannot find {path_str}")

    if not path.exists():
        raise FileNotFoundError(f"Cannot find {path_str}")

    try:
        project = next(i for i in get_loaded_projects() if path_str.startswith(i._path.as_posix()))
    except StopIteration:
        raise ProjectNotFound(f"{path_str} is not part of an active project")

    return path.resolve(), project
Beispiel #3
0
def load(project_path: Union[Path, str, None] = None,
         name: Optional[str] = None) -> "Project":
    """Loads a project and instantiates various related objects.

    Args:
        project_path: Path of the project to load. If None, will attempt to
                      locate a project using check_for_project()
        name: Name to assign to the project. If None, the name is generated
              from the name of the project folder

    Returns a Project object.
    """
    # checks
    if project_path is None:
        project_path = check_for_project(".")
    if not project_path or not _get_project_config_path(Path(project_path)):
        raise ProjectNotFound("Could not find Brownie project")

    project_path = Path(project_path).resolve()
    if name is None:
        name = project_path.name
        if not name.lower().endswith("project"):
            name += " project"
        name = "".join(i for i in name.title() if i.isalpha())
    if next((True for i in _loaded_projects if i._name == name), False):
        raise ProjectAlreadyLoaded(
            "There is already a project loaded with this name")

    # paths
    _create_folders(project_path)
    _add_to_sys_path(project_path)

    # load sources and build
    return Project(name, project_path)
Beispiel #4
0
def close(raises=True):
    '''Closes the active project.'''
    if not CONFIG['folders']['project']:
        if not raises:
            return
        raise ProjectNotFound("No Brownie project currently open.")

    # clear sources, build, coverage
    sources.clear()
    build.clear()
    coverage.clear()

    # remove objects from namespace
    for name in sys.modules['brownie.project'].__all__.copy():
        if name == "__brownie_import_all__":
            continue
        del sys.modules['brownie.project'].__dict__[name]
        if '__brownie_import_all__' in sys.modules['__main__'].__dict__:
            del sys.modules['__main__'].__dict__[name]
    sys.modules['brownie.project'].__all__ = ['__brownie_import_all__']

    # clear paths
    try:
        sys.path.remove(CONFIG['folders']['project'])
    except ValueError:
        pass
    CONFIG['folders']['project'] = None
Beispiel #5
0
    def close(self, raises=True):
        '''Removes pointers to the project's ContractContainer objects and this object.'''
        if not self._active:
            if not raises:
                return
            raise ProjectNotFound("Project is not currently loaded.")

        # remove objects from namespace
        for dict_ in self._namespaces:
            for key in [
                    k for k, v in dict_.items()
                    if v == self or (k in self and v == self[k])
            ]:
                del dict_[key]

        name = self._name
        del sys.modules[f'brownie.project.{name}']
        sys.modules['brownie.project'].__all__.remove(name)
        sys.modules['brownie.project'].__console_dir__.remove(name)
        self._active = False
        _loaded_projects.remove(self)

        # clear paths
        try:
            sys.path.remove(self._project_path)
        except ValueError:
            pass
Beispiel #6
0
def run(
    script_path: str,
    method_name: str = "main",
    args: Optional[Tuple] = None,
    kwargs: Optional[Dict] = None,
    project: Any = None,
) -> None:
    """Loads a project script and runs a method in it.

    script_path: path of script to load
    method_name: name of method to run
    args: method args
    kwargs: method kwargs
    project: (deprecated)

    Returns: return value from called method
    """
    if args is None:
        args = tuple()
    if kwargs is None:
        kwargs = {}

    if not get_loaded_projects():
        raise ProjectNotFound("Cannot run a script without an active project")

    script, project = _get_path(script_path)

    # temporarily add project objects to the main namespace, so the script can import them
    brownie: Any = sys.modules["brownie"]
    brownie_dict = brownie.__dict__.copy()
    brownie_all = brownie.__all__.copy()
    brownie.__dict__.update(project)
    brownie.__all__.extend(project.__all__)

    try:
        script = script.absolute().relative_to(project._path)
        module = _import_from_path(script)

        name = module.__name__
        if not hasattr(module, method_name):
            raise AttributeError(
                f"Module '{name}' has no method '{method_name}'")
        print(
            f"\nRunning '{color['module']}{name}{color}.{color['callable']}{method_name}{color}'..."
        )
        return getattr(module, method_name)(*args, **kwargs)
    finally:
        # cleanup namespace
        brownie.__dict__.clear()
        brownie.__dict__.update(brownie_dict)
        brownie.__all__ = brownie_all
Beispiel #7
0
def load(project_path=None):
    '''Loads a project and instantiates various related objects.

    Args:
        project_path: Path of the project to load. If None, will attempt to
                      locate a project using check_for_project()

    Returns a list of ContractContainer objects.
    '''
    # checks
    if CONFIG['folders']['project']:
        raise ProjectAlreadyLoaded(
            f"Project already loaded at {CONFIG['folders']['project']}")
    if project_path is None:
        project_path = check_for_project('.')
    if not project_path or not Path(project_path).joinpath(
            "brownie-config.json").exists():
        raise ProjectNotFound("Could not find Brownie project")

    # paths
    project_path = Path(project_path).resolve()
    _create_folders(project_path)
    _add_to_sys_path(project_path)

    # load config
    load_project_config(project_path)
    CONFIG['solc']['version'] = compiler.set_solc_version(
        CONFIG['solc']['version'])

    # load sources and build
    sources.load(project_path)
    build.load(project_path)

    # compare build, erase as needed
    changed_paths = _get_changed_contracts()

    # compile sources, update build
    build_json = sources.compile_paths(changed_paths,
                                       optimize=CONFIG['solc']['optimize'],
                                       runs=CONFIG['solc']['runs'],
                                       minify=CONFIG['solc']['minify_source'])
    for data in build_json.values():
        build.add(data)

    # create objects, add to namespace
    return _create_objects()
Beispiel #8
0
def run(
    script_path: str,
    method_name: str = "main",
    args: Optional[Tuple] = None,
    kwargs: Optional[Dict] = None,
    project: Any = None,
) -> None:
    """Loads a project script and runs a method in it.

    script_path: path of script to load
    method_name: name of method to run
    args: method args
    kwargs: method kwargs
    project: (deprecated)

    Returns: return value from called method
    """
    if args is None:
        args = tuple()
    if kwargs is None:
        kwargs = {}

    if not get_loaded_projects():
        raise ProjectNotFound("Cannot run a script without an active project")

    script, project = _get_path(script_path)

    # temporarily add project objects to the main namespace, so the script can import them
    project._add_to_main_namespace()

    try:
        script = script.absolute().relative_to(project._path)
        module = _import_from_path(script)

        name = module.__name__
        if not hasattr(module, method_name):
            raise AttributeError(f"Module '{name}' has no method '{method_name}'")
        print(
            f"\nRunning '{color('bright blue')}{name}{color}."
            f"{color('bright cyan')}{method_name}{color}'..."
        )
        return getattr(module, method_name)(*args, **kwargs)
    finally:
        # cleanup namespace
        project._remove_from_main_namespace()
Beispiel #9
0
def load(project_path: Union[Path, str, None] = None,
         name: Optional[str] = None) -> "Project":
    """Loads a project and instantiates various related objects.

    Args:
        project_path: Path of the project to load. If None, will attempt to
                      locate a project using check_for_project()
        name: Name to assign to the project. If None, the name is generated
              from the name of the project folder

    Returns a Project object.
    """
    # checks
    if project_path is None:
        project_path = check_for_project(".")
        if project_path is not None and project_path != Path(".").absolute():
            warnings.warn(
                f"Loaded project has a root folder of '{project_path}' "
                "which is different from the current working directory",
                BrownieEnvironmentWarning,
            )

    elif Path(project_path).resolve() != check_for_project(project_path):
        project_path = None
    if project_path is None:
        raise ProjectNotFound("Could not find Brownie project")

    project_path = Path(project_path).resolve()
    if name is None:
        name = project_path.name
        if not name.lower().endswith("project"):
            name += " project"
        name = "".join(i for i in name.title() if i.isalpha())
    if next((True for i in _loaded_projects if i._name == name), False):
        raise ProjectAlreadyLoaded(
            "There is already a project loaded with this name")

    # paths
    _create_folders(project_path)
    _add_to_sys_path(project_path)

    # load sources and build
    return Project(name, project_path)
Beispiel #10
0
    def close(self, raises: bool = True) -> None:
        """Removes pointers to the project's ContractContainer objects and this object."""
        if not self._active:
            if not raises:
                return
            raise ProjectNotFound("Project is not currently loaded.")

        # remove objects from namespace
        for dict_ in self._namespaces:
            for key in [
                    k for k, v in dict_.items() if v == self or
                (k in self and v == self[k])  # type: ignore
            ]:
                del dict_[key]

        # remove contracts
        for contract in [
                x for v in self._containers.values() for x in v._contracts
        ]:
            _remove_contract(contract)
        for container in self._containers.values():
            container._contracts.clear()
        self._containers.clear()

        # undo black-magic
        self._remove_from_main_namespace()
        name = self._name
        del sys.modules[f"brownie.project.{name}"]
        sys.modules["brownie.project"].__all__.remove(name)  # type: ignore
        sys.modules["brownie.project"].__console_dir__.remove(
            name)  # type: ignore
        self._active = False
        _loaded_projects.remove(self)

        # clear paths
        try:
            sys.path.remove(str(self._path))
        except ValueError:
            pass
Beispiel #11
0
def _get_path(path_str: str) -> Tuple[Path, Project]:
    # Returns path to a python module
    path = Path(path_str).with_suffix(".py")

    if not path.is_absolute():
        if path.parts[0] != "scripts":
            path = Path("scripts").joinpath(path)
        for project in get_loaded_projects():
            if project._path.joinpath(path).exists():
                path = project._path.joinpath(path)
                return path, project
        raise FileNotFoundError(f"Cannot find {path_str}")

    if not path.exists():
        raise FileNotFoundError(f"Cannot find {path_str}")

    try:
        project = next(i for i in get_loaded_projects()
                       if path_str.startswith(i._path.as_posix()))
    except StopIteration:
        raise ProjectNotFound(f"{path_str} is not part of an active project")

    return path, project