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