def __init__(self, sim=None, params=None): self.sim = sim try: self.name_solver = sim.info.solver.short_name except AttributeError: pass else: self.package = get_solver_package(self.name_solver) self.root = self.get_root() # Check configfile early self.get_configfile() if sim: self.oper = sim.oper self.params = sim.params.output # Same as package name __name__ super().__init__(sim) dict_classes = sim.info.solver.classes.Output.import_classes() # initialize objects for cls_name, Class in dict_classes.items(): # only initialize if Class is not the Output class if not isinstance(self, Class): setattr(self, underscore(cls_name), Class(self)) elif params: # At least initialize params self.params = params.output else: self.params = None logger.warning( "Initializing Output class without sim or params might lead to errors." )
def get_configfile(cls, host=None): """Get path of the Snakemake configuration file for the current machine. All configuration files are stored under ``etc`` sub-package. """ if not host: host = os.getenv("SNIC_RESOURCE", os.getenv("GITHUB_WORKFLOW", gethostname())) root = cls.get_root() configfile = root / "etc" / f"{host}.yml" if not configfile.exists(): logger.warning( "Expected a configuration file describing compilers and flags: " f"{configfile}") configfile = Path(get_asset("default_configfile.yml")) logger.info(f"Using default configuration instead: {configfile}") return configfile
def copy(self, new_dir, force=False): """Copy case files to a new directory. The directory does not have to be present. :param new_dir: A str or Path-like instance pointing to the new directory. :param force: Force copy would overwrite if files already exist. """ # Avoid race conditions! Should be only executed by rank 0. if mpi.rank != 0: return abs_paths = self.get_paths() subpackages = self._get_subpackages() root = self.root def conditional_ignore(src, names): """Ignore if not found in ``abs_paths``.""" src = Path(src) include = abs_paths + [root / subpkg for subpkg in subpackages] exclude = tuple(name for name in names if not any( (src / name) == path for path in include)) logger.debug("".join(( f"- src: {src}", "\n- include:\n", "\n ".join(str(name) for name in include), "\n- exclude:\n", "\n ".join(exclude), "\n----", ))) return exclude new_root = Path(new_dir) try: logger.info("Copying with shutil.copytree ...") copytree_kwargs = dict(src=root, dst=new_root, symlinks=False, ignore=conditional_ignore) # Python 3.8+ shutil.copytree(**copytree_kwargs, dirs_exist_ok=True) except (TypeError, shutil.Error): try: logger.warning( "Python < 3.8: shutil.copytree may not proceed if directories exist." ) # Hoping that new_root has not been created shutil.copytree(**copytree_kwargs) except FileExistsError as e: logger.warning(e) logger.info("Copying with shutil.copy2 ...") # Copy one by one from the scratch if not new_root.exists(): logger.debug(f"Creating {new_root} ...") os.makedirs(new_root, exist_ok=True) for abs_path in abs_paths: rel_path = abs_path.relative_to(root) new_path = new_root / rel_path if not new_path.parent.exists(): os.makedirs(new_path.parent) logger.debug(f"Copying {new_path}") if new_path.exists(): if force: logger.warning( f"{new_path} would be overwritten ...") else: logger.warning( f"{new_path} exists, skipping. Use force=True to overwrite." ) continue shutil.copy2(abs_path, new_path) finally: logger.info(f"Copied: {root} -> {new_root}")