def test_skip_locks_before_reading(self, data_path, cfg_file): """ Here we test that the object constructor waits for a second and raises a Runtime error because it tries to lock the file for reading by default """ yacmap = yacman.YacAttMap(filepath=cfg_file, writable=True) yacman.YacAttMap(filepath=cfg_file, skip_read_lock=True) yacmap.make_readonly()
def test_locks_before_reading_by_default(self, data_path, cfg_file): """ Here we test that the object constructor waits for a second and raises a Runtime error because it tries to lock the file for reading by default """ yacmap = yacman.YacAttMap(filepath=cfg_file, writable=True) with pytest.raises(RuntimeError): yacman.YacAttMap(filepath=cfg_file, wait_max=1) yacmap.make_readonly()
def test_entries_update(self, name, data_path, entry): filepath = make_cfg_file_path(name, data_path) yacmap = yacman.YacAttMap(entries={}) yacmap.test = entry yacmap.write(filepath=filepath) yacmap.make_readonly( ) # need to remove the lock; the next line locks for read yacmapin = yacman.YacAttMap(filepath=filepath, writable=False) assert yacmapin.test == entry os.remove(filepath)
def test_context_manager_saves_updates(self, cfg_file, state): yacmap = yacman.YacAttMap(filepath=cfg_file, writable=state) with yacmap as y: y.testattr = "testval" if not getattr(yacmap[IK], RO_KEY, True): yacmap.make_readonly() yacmap1 = yacman.YacAttMap(filepath=cfg_file, writable=True) assert yacmap1.testattr == "testval" del yacmap1["testattr"] yacmap1.make_readonly()
def load_remote_registry_path(bulker_config, registry_path, filepath=None): cratevars = parse_registry_path(registry_path) if cratevars: # assemble the query string if 'registry_url' in bulker_config.bulker: base_url = bulker_config.bulker.registry_url else: # base_url = "http://big.databio.org/bulker/" base_url = DEFAULT_BASE_URL query = cratevars["crate"] if cratevars["tag"] != "default": query = query + "_" + cratevars["tag"] if not cratevars["namespace"]: cratevars["namespace"] = "bulker" # default namespace query = cratevars["namespace"] + "/" + query # Until we have an API: query = query + ".yaml" if not filepath: filepath = os.path.join(base_url, query) else: _LOGGER.error( "Unable to parse registry path: {}".format(registry_path)) sys.exit(1) if is_url(filepath): _LOGGER.debug("Got URL: {}".format(filepath)) try: #python3 from urllib.request import urlopen from urllib.error import HTTPError except: #python2 from urllib2 import urlopen from urllib2 import URLError as HTTPError try: response = urlopen(filepath) except HTTPError as e: if cratevars: _LOGGER.error( "The requested remote manifest '{}' is not found.".format( filepath)) sys.exit(1) else: raise e data = response.read() # a `bytes` object text = data.decode('utf-8') manifest_lines = yacman.YacAttMap(yamldata=text) else: manifest_lines = yacman.YacAttMap(filepath=filepath) return manifest_lines, cratevars
def test_context_manager_does_not_change_state(self, cfg_file, state): yacmap = yacman.YacAttMap(filepath=cfg_file, writable=state) with yacmap as _: pass is_ro = getattr(yacmap[IK], RO_KEY, None) is_writable = None if is_ro is None else not is_ro assert is_writable == state
def test_init_with_empty_file(self, data_path): a, v = "testattr", "testval" empty_file_path = os.path.join(data_path, "empty_file.yaml") open(empty_file_path, "a").close() y = yacman.YacAttMap(entries={a: v}, filepath=empty_file_path) assert a in y os.remove(empty_file_path)
def test_write_creates_file(self, data_path, list_locks): with pytest.warns(UserWarning): yacmap = yacman.YacAttMap(entries={}, writable=True) yacmap.write(filepath=make_cfg_file_path("writeout.yaml", data_path)) assert os.path.exists(make_lock_path("writeout.yaml", data_path)) assert os.path.exists(make_cfg_file_path("writeout.yaml", data_path)) os.remove(make_cfg_file_path("writeout.yaml", data_path))
def test_validation_fails_in_constructor(self, schema, value): """ test object that does not adhere to the schema guidelines does not pass validation """ with pytest.raises(ValidationError): yacman.YacAttMap(entries={"testattr": value}, schema_source=schema)
def activate_package(self, package_name): """ Activates a compute package. This copies the computing attributes from the configuration file into the `compute` attribute, where the class stores current compute settings. :param str package_name: name for non-resource compute bundle, the name of a subsection in an environment configuration file :return bool: success flag for attempt to establish compute settings """ # Hope that environment & environment compute are present. act_msg = "Activating compute package '{}'".format(package_name) if package_name == "default": _LOGGER.debug(act_msg) else: _LOGGER.info(act_msg) if (package_name and self.compute_packages and package_name in self.compute_packages): # Augment compute, creating it if needed. if self.compute is None: _LOGGER.debug("Creating Project compute") self.compute = yacman.YacAttMap() _LOGGER.debug("Adding entries for package_name '{}'".format( package_name)) self.compute.add_entries(self.compute_packages[package_name]) # Ensure submission template is absolute. This *used to be* handled # at update (so the paths were stored as absolutes in the packages), # but now, it makes more sense to do it here so we can piggyback on # the default update() method and not even have to do that. if not os.path.isabs(self.compute.submission_template): try: self.compute.submission_template = os.path.join( os.path.dirname(self["__internal"].file_path), self.compute.submission_template, ) except AttributeError as e: # Environment and environment compute should at least have been # set as null-valued attributes, so execution here is an error. _LOGGER.error(str(e)) _LOGGER.debug("Submit template set to: {}".format( self.compute.submission_template)) return True else: # Scenario in which environment and environment compute are # both present--but don't evaluate to True--is fairly harmless. _LOGGER.debug( "Can't activate package. compute_packages = {}".format( self.compute_packages)) return False
def test_locking_is_opt_in(self, cfg_file, locked_cfg_file): """ this tests backwards compatibility, in the past the locking system did not exist. Consequently, to make yacman backwards compatible, multiple processes should be able to read and write to the file when no arguments but the intput are specified """ yacman.YacAttMap(filepath=cfg_file) assert not os.path.exists(locked_cfg_file)
def test_make_writable_rereads_source_file(self, cfg_file): """ Test that the the changes made to the cfg by other processes are re-read after the original process is made writable """ yacmap1 = yacman.YacAttMap(filepath=cfg_file, writable=False) yacmap = yacman.YacAttMap(filepath=cfg_file, writable=True) yacmap.test = "test" yacmap.write() yacmap.make_readonly() yacmap1.make_writable(cfg_file) assert yacmap1.test == "test" # remove added entry after the test if "test" in yacmap1: del yacmap1["test"] yacmap1.write() yacmap1.make_readonly()
def reset_active_settings(self): """ Clear out current compute settings. :return bool: success flag """ self.compute = yacman.YacAttMap() return True
def test_float_idx(): data = yacman.YacAttMap(yamldata=yaml_str) # We should be able to access this by string, not by int index. assert (data['2'] == "two") with pytest.raises(KeyError): data[2] del data
def test_validation_in_write(self, cfg_file, schema): """ test object that adheres to the schema guidelines passes validation on write """ y = yacman.YacAttMap(filepath=cfg_file, schema_source=schema, write_validate=True, writable=True) y.write()
def test_warn_on_write_when_not_locked(self, name, data_path, cfg_file, locked_cfg_file): yacmap = yacman.YacAttMap(filepath=cfg_file, writable=True) filename = make_cfg_file_path(name, data_path) f = os.open(filename, os.O_CREAT | os.O_EXCL | os.O_WRONLY) os.close(f) with pytest.warns(UserWarning): yacmap.write(filename) os.remove(filename) assert os.path.exists(make_lock_path(name, data_path)) assert not os.path.exists(locked_cfg_file)
def test_validation_fails_in_write(self, cfg_file, schema, value): """ test object that does not adhere to the schema guidelines does not pass validation on write """ y = yacman.YacAttMap(filepath=cfg_file, schema_source=schema, write_validate=True, writable=True) y["testattr"] = value with pytest.raises(ValidationError): y.write()
def get_adapters(self): """ Get current adapters, if defined. Adapters are sourced from the 'adapters' section in the root of the divvy configuration file and updated with an active compute package-specific set of adapters, if any defined in 'adapters' section under currently active compute package. :return yacman.YacAttMap: current adapters mapping """ adapters = yacman.YacAttMap() if "adapters" in self and self.adapters is not None: adapters.update(self.adapters) if "compute" in self and "adapters" in self.compute: adapters.update(self.compute.adapters) if not adapters: _LOGGER.debug( "No adapters determined in divvy configuration file.") return adapters
def test_bulker_init(): try: shutil.rmtree(DUMMY_CFG_FOLDER) os.mkdir(DUMMY_CFG_FOLDER) os.mkdir(DUMMY_CFG_TEMPLATES) # TODO: Clean up these folders # Why do I have to pre-create these anyway? I guess to test init? os.mkdir(os.path.join(DUMMY_CFG_TEMPLATES, "zsh_start")) os.mkdir(os.path.join(DUMMY_CFG_TEMPLATES, "zsh_start_strict")) except: pass bulker_init(DUMMY_CFG_FILEPATH, DEFAULT_CONFIG_FILEPATH, "docker") bulker_config = yacman.YacAttMap(filepath=DEFAULT_CONFIG_FILEPATH) manifest, cratevars = load_remote_registry_path(bulker_config, "demo", None) # del bulker_config try: shutil.rmtree(DUMMY_CFG_FOLDER) except: pass
def main(): """ Primary workflow """ parser = logmuse.add_logging_options(build_argparser()) args, remaining_args = parser.parse_known_args() logger_kwargs = {"level": args.verbosity, "devmode": args.logdev} logmuse.init_logger(name="yacman", **logger_kwargs) global _LOGGER _LOGGER = logmuse.logger_via_cli(args) _LOGGER.debug("Command given: {}".format(args.command)) if not args.command: parser.print_help() _LOGGER.error("No command given") sys.exit(1) if args.command == "init": bulkercfg = args.config _LOGGER.debug("Initializing bulker configuration") _is_writable(os.path.dirname(bulkercfg), check_exist=False) bulker_init(bulkercfg, DEFAULT_CONFIG_FILEPATH, args.engine) sys.exit(0) bulkercfg = select_bulker_config(args.config) bulker_config = yacman.YacAttMap(filepath=bulkercfg, writable=False) if args.command == "list": # Output header via logger and content via print so the user can # redirect the list from stdout if desired without the header as clutter if args.simple: fmt = "{namespace}/{crate}:{tag}" else: _LOGGER.info("Available crates:") fmt = "{namespace}/{crate}:{tag} -- {path}" if bulker_config.bulker.crates: for namespace, crates in bulker_config.bulker.crates.items(): for crate, tags in crates.items(): for tag, path in tags.items(): print( fmt.format(namespace=namespace, crate=crate, tag=tag, path=path)) else: _LOGGER.info( "No crates available. Use 'bulker load' to load a crate.") sys.exit(1) # For all remaining commands we need a crate identifier _LOGGER.info("Bulker config: {}".format(bulkercfg)) if args.command == "activate": try: cratelist = parse_registry_paths( args.crate_registry_paths, bulker_config.bulker.default_namespace) _LOGGER.debug(cratelist) _LOGGER.info("Activating bulker crate: {}{}".format( args.crate_registry_paths, " (Strict)" if args.strict else "")) bulker_activate(bulker_config, cratelist, echo=args.echo, strict=args.strict, prompt=args.no_prompt) except KeyError as e: parser.print_help(sys.stderr) _LOGGER.error("{} is not an available crate".format(e)) sys.exit(1) except MissingCrateError as e: _LOGGER.error("Missing crate: {}".format(e)) sys.exit(1) except AttributeError as e: _LOGGER.error( "Your bulker config file is outdated, you need to re-initialize it: {}" .format(e)) sys.exit(1) if args.command == "run": try: cratelist = parse_registry_paths(args.crate_registry_paths) _LOGGER.info("Activating crate: {}\n".format( args.crate_registry_paths)) bulker_run(bulker_config, cratelist, args.cmd, strict=args.strict) except KeyError as e: parser.print_help(sys.stderr) _LOGGER.error("{} is not an available crate".format(e)) sys.exit(1) except MissingCrateError as e: _LOGGER.error("Missing crate: {}".format(e)) sys.exit(1) if args.command == "load": bulker_config.make_writable() manifest, cratevars = load_remote_registry_path( bulker_config, args.crate_registry_paths, args.manifest) exe_template_jinja = None build_template_jinja = None shell_template_jinja = None exe_template = mkabs(bulker_config.bulker.executable_template, os.path.dirname(bulker_config._file_path)) build_template = mkabs(bulker_config.bulker.build_template, os.path.dirname(bulker_config._file_path)) try: shell_template = mkabs(bulker_config.bulker.shell_template, os.path.dirname(bulker_config._file_path)) except AttributeError: _LOGGER.error( "You need to re-initialize your bulker config or add a 'shell_template' attribute." ) sys.exit(1) try: assert (os.path.exists(exe_template)) except AssertionError: _LOGGER.error( "Bulker config points to a missing executable template: {}". format(exe_template)) sys.exit(1) with open(exe_template, 'r') as f: # with open(DOCKER_TEMPLATE, 'r') as f: contents = f.read() exe_template_jinja = jinja2.Template(contents) try: assert (os.path.exists(shell_template)) except AssertionError: _LOGGER.error( "Bulker config points to a missing shell template: {}".format( shell_template)) sys.exit(1) with open(shell_template, 'r') as f: # with open(DOCKER_TEMPLATE, 'r') as f: contents = f.read() shell_template_jinja = jinja2.Template(contents) if args.build: try: assert (os.path.exists(build_template)) except AssertionError: _LOGGER.error( "Bulker config points to a missing build template: {}". format(build_template)) sys.exit(1) _LOGGER.info( "Building images with template: {}".format(build_template)) with open(build_template, 'r') as f: contents = f.read() build_template_jinja = jinja2.Template(contents) bulker_load(manifest, cratevars, bulker_config, exe_jinja2_template=exe_template_jinja, shell_jinja2_template=shell_template_jinja, crate_path=args.path, build=build_template_jinja, force=args.force) if args.command == "inspect": if args.crate_registry_paths == "": _LOGGER.error( "No active create. Inspect requires a provided crate, or a currently active create." ) sys.exit(1) manifest, cratevars = load_remote_registry_path( bulker_config, args.crate_registry_paths, None) manifest_name = cratevars['crate'] print("Bulker manifest: {}".format(args.crate_registry_paths)) crate_path = os.path.join(bulker_config.bulker.default_crate_folder, cratevars['namespace'], manifest_name, cratevars['tag']) if not os.path.isabs(crate_path): crate_path = os.path.join(os.path.dirname(bcfg._file_path), crate_path) print("Crate path: {}".format(crate_path)) import glob filenames = glob.glob(os.path.join(crate_path, "*")) available_commands = [ x for x in [os.path.basename(x) for x in filenames] if x[0] != "_" ] print("Available commands: {}".format(available_commands))
def bulker_load(manifest, cratevars, bcfg, exe_jinja2_template, shell_jinja2_template, crate_path=None, build=False, force=False): manifest_name = cratevars['crate'] # We store them in folder: namespace/crate/version if not crate_path: crate_path = os.path.join(bcfg.bulker.default_crate_folder, cratevars['namespace'], manifest_name, cratevars['tag']) if not os.path.isabs(crate_path): crate_path = os.path.join(os.path.dirname(bcfg._file_path), crate_path) _LOGGER.debug("Crate path: {}".format(crate_path)) _LOGGER.debug("cratevars: {}".format(cratevars)) # Update the config file if not bcfg.bulker.crates: bcfg.bulker.crates = {} if not hasattr(bcfg.bulker.crates, cratevars['namespace']): bcfg.bulker.crates[cratevars['namespace']] = yacman.YacAttMap({}) if not hasattr(bcfg.bulker.crates[cratevars['namespace']], cratevars['crate']): bcfg.bulker.crates[cratevars['namespace']][ cratevars['crate']] = yacman.YacAttMap({}) if hasattr(bcfg.bulker.crates[cratevars['namespace']][cratevars['crate']], cratevars['tag']): _LOGGER.debug(bcfg.bulker.crates[cratevars['namespace']][ cratevars['crate']].to_dict()) if not (force or query_yes_no( "That manifest has already been loaded. Overwrite?")): return else: bcfg.bulker.crates[cratevars['namespace']][cratevars['crate']][str( cratevars['tag'])] = crate_path _LOGGER.warning( "Removing all executables in: {}".format(crate_path)) try: shutil.rmtree(crate_path) except: _LOGGER.error( "Error removing crate at {}. Did your crate path change? Remove it manually." .format(crate_path)) else: bcfg.bulker.crates[cratevars['namespace']][cratevars['crate']][str( cratevars['tag'])] = crate_path # Now make the crate # First add any imports mkdir(crate_path, exist_ok=True) if hasattr(manifest.manifest, "imports") and manifest.manifest.imports: for imp in manifest.manifest.imports: imp_cratevars = parse_registry_path(imp) imp_crate_path = os.path.join(bcfg.bulker.default_crate_folder, imp_cratevars['namespace'], imp_cratevars['crate'], imp_cratevars['tag']) if not os.path.isabs(imp_crate_path): imp_crate_path = os.path.join(os.path.dirname(bcfg._file_path), imp_crate_path) if not os.path.exists(imp_crate_path): _LOGGER.error("Can't import crate '{}' from '{}'".format( imp, imp_crate_path)) # Recursively load any non-existant imported crates. imp_manifest, imp_cratevars = load_remote_registry_path( bcfg, imp, None) _LOGGER.debug(imp_manifest) _LOGGER.debug(imp_cratevars) bulker_load(imp_manifest, imp_cratevars, bcfg, exe_jinja2_template, shell_jinja2_template, crate_path=None, build=build, force=force) _LOGGER.info("Importing crate '{}' from '{}'.".format( imp, imp_crate_path)) copy_tree(imp_crate_path, crate_path) # should put this in a function def host_tool_specific_args(bcfg, pkg, hosttool_arg_key): _LOGGER.debug("Arg key: '{}'".format(hosttool_arg_key)) # Here we're parsing the *image*, not the crate registry path. imvars = parse_registry_path_image(pkg['docker_image']) _LOGGER.debug(imvars) try: amap = bcfg.bulker.tool_args[imvars['namespace']][imvars['image']] if imvars['tag'] != 'default' and hasattr(amap, imvars['tag']): string = amap[imvars['tag']][hosttool_arg_key] else: string = amap.default[hosttool_arg_key] _LOGGER.debug(string) return string except: _LOGGER.debug("No host/tool args found.") return "" cmdlist = [] cmd_count = 0 if hasattr(manifest.manifest, "commands") and manifest.manifest.commands: for pkg in manifest.manifest.commands: _LOGGER.debug(pkg) pkg.update(bcfg.bulker) # Add terms from the bulker config pkg = copy.deepcopy( yacman.YacAttMap(pkg)) # (otherwise it's just a dict) # We have to deepcopy it so that changes we make to pkg aren't reflected in bcfg. if pkg.container_engine == "singularity" and "singularity_image_folder" in pkg: pkg["singularity_image"] = os.path.basename( pkg["docker_image"]) pkg["namespace"] = os.path.dirname(pkg["docker_image"]) if os.path.isabs(pkg["singularity_image_folder"]): sif = pkg["singularity_image_folder"] else: sif = os.path.join(os.path.dirname(bcfg._file_path), pkg["singularity_image_folder"]) pkg["singularity_fullpath"] = os.path.join( sif, pkg["namespace"], pkg["singularity_image"]) mkdir(os.path.dirname(pkg["singularity_fullpath"]), exist_ok=True) command = pkg["command"] path = os.path.join(crate_path, command) _LOGGER.debug("Writing {cmd}".format(cmd=path)) cmdlist.append(command) # Add any host-specific tool-specific args hosttool_arg_key = "{engine}_args".format( engine=bcfg.bulker.container_engine) hts = host_tool_specific_args(bcfg, pkg, hosttool_arg_key) _LOGGER.debug("Adding host-tool args: {}".format(hts)) if hasattr(pkg, hosttool_arg_key): pkg[hosttool_arg_key] += " " + hts else: pkg[hosttool_arg_key] = hts # Remove any excluded volumes from the package exclude_vols = host_tool_specific_args(bcfg, pkg, "exclude_volumes") _LOGGER.debug("Volume list: {}".format(pkg["volumes"])) _LOGGER.debug("pkg: {}".format(pkg)) if len(exclude_vols) > 0: for item in exclude_vols: _LOGGER.debug("Excluding volume: '{}'".format(item)) try: pkg["volumes"].remove(item) except: pass _LOGGER.debug("Volume list: {}".format(pkg["volumes"])) else: _LOGGER.debug("No excluded volumes") with open(path, "w") as fh: fh.write(exe_jinja2_template.render(pkg=pkg)) os.chmod(path, 0o755) # shell commands path_shell = os.path.join(crate_path, "_" + command) _LOGGER.debug( "Writing shell command: '{cmd}'".format(cmd=path_shell)) with open(path_shell, "w") as fh: fh.write(shell_jinja2_template.render(pkg=pkg)) os.chmod(path_shell, 0o755) if build: buildscript = build.render(pkg=pkg) x = os.system(buildscript) if x != 0: _LOGGER.error( "------ Error building. Build script used: ------") _LOGGER.error(buildscript) _LOGGER.error( "------------------------------------------------") _LOGGER.info("Container available at: {cmd}".format( cmd=pkg["singularity_fullpath"])) # host commands host_cmdlist = [] if hasattr(manifest.manifest, "host_commands") and manifest.manifest.host_commands: _LOGGER.info("Populating host commands") for cmd in manifest.manifest.host_commands: _LOGGER.debug(cmd) if not is_command_callable(cmd): _LOGGER.warning("Requested host command is not callable and " "therefore not created: '{}'".format(cmd)) continue local_exe = find_executable(cmd) path = os.path.join(crate_path, cmd) host_cmdlist.append(cmd) os.symlink(local_exe, path) # The old way: TODO: REMOVE THIS if False: populated_template = LOCAL_EXE_TEMPLATE.format(cmd=local_exe) with open(path, "w") as fh: fh.write(populated_template) os.chmod(path, 0o755) cmd_count = len(cmdlist) host_cmd_count = len(host_cmdlist) if cmd_count < 1 and host_cmd_count < 1: _LOGGER.error("No commands provided. Crate not created.") os.rmdir(crate_path) crate_path_parent = os.path.dirname(crate_path) if not os.listdir(crate_path_parent): os.rmdir(crate_path_parent) sys.exit(1) rp = "{namespace}/{crate}:{tag}".format(namespace=cratevars['namespace'], crate=cratevars['crate'], tag=cratevars['tag']) _LOGGER.info("Loading manifest: '{rp}'." " Activate with 'bulker activate {rp}'.".format(rp=rp)) if cmd_count > 0: _LOGGER.info("Commands available: {}".format(", ".join(cmdlist))) if host_cmd_count > 0: _LOGGER.info("Host commands available: {}".format( ", ".join(host_cmdlist))) bcfg.write()
def bulker_init(config_path, template_config_path, container_engine=None): """ Initialize a config file. :param str config_path: path to bulker configuration file to create/initialize :param str template_config_path: path to bulker configuration file to copy FROM """ if not config_path: _LOGGER.error("You must specify a file path to initialize.") return if not template_config_path: _LOGGER.error("You must specify a template config file path.") return if not container_engine: check_engines = ["docker", "singularity"] for engine in check_engines: if is_command_callable(engine): _LOGGER.info("Guessing container engine is {}.".format(engine)) container_engine = engine break # it's a priority list, stop at the first found engine if config_path and not (os.path.exists(config_path) and not query_yes_no("Exists. Overwrite?")): # dcc.write(config_path) # Init should *also* write the templates. dest_folder = os.path.dirname(config_path) dest_templates_dir = os.path.join(dest_folder, TEMPLATE_SUBDIR) # templates_subdir = TEMPLATE_SUBDIR copy_tree(os.path.dirname(template_config_path), dest_templates_dir) new_template = os.path.join(dest_folder, os.path.basename(template_config_path)) bulker_config = yacman.YacAttMap(filepath=template_config_path, writable=True) _LOGGER.debug("Engine used: {}".format(container_engine)) bulker_config.bulker.container_engine = container_engine if bulker_config.bulker.container_engine == "docker": bulker_config.bulker.executable_template = os.path.join( TEMPLATE_SUBDIR, DOCKER_EXE_TEMPLATE) bulker_config.bulker.shell_template = os.path.join( TEMPLATE_SUBDIR, DOCKER_SHELL_TEMPLATE) bulker_config.bulker.build_template = os.path.join( TEMPLATE_SUBDIR, DOCKER_BUILD_TEMPLATE) elif bulker_config.bulker.container_engine == "singularity": bulker_config.bulker.executable_template = os.path.join( TEMPLATE_SUBDIR, SINGULARITY_EXE_TEMPLATE) bulker_config.bulker.shell_template = os.path.join( TEMPLATE_SUBDIR, SINGULARITY_SHELL_TEMPLATE) bulker_config.bulker.build_template = os.path.join( TEMPLATE_SUBDIR, SINGULARITY_BUILD_TEMPLATE) bulker_config.bulker.rcfile = os.path.join(TEMPLATE_SUBDIR, RCFILE_TEMPLATE) bulker_config.bulker.rcfile_strict = os.path.join( TEMPLATE_SUBDIR, RCFILE_STRICT_TEMPLATE) bulker_config.write(config_path) # copyfile(template_config_path, new_template) # os.rename(new_template, config_path) _LOGGER.info("Wrote new configuration file: {}".format(config_path)) else: _LOGGER.warning( "Can't initialize, file exists: {} ".format(config_path))
def test_make_writable_changes_filepath(self, cfg_file, name, data_path): yacmap = yacman.YacAttMap(filepath=cfg_file, writable=False) yacmap.make_writable(make_cfg_file_path(name, data_path)) assert getattr(yacmap[IK], FILEPATH_KEY) != cfg_file
def test_make_writable_makes_object_writable(self, cfg_file): yacmap = yacman.YacAttMap(filepath=cfg_file, writable=False) yacmap.make_writable() assert not getattr(yacmap[IK], RO_KEY, True)
def test_make_writable_doesnt_change_already_writable_objects( self, cfg_file): yacmap = yacman.YacAttMap(filepath=cfg_file, writable=True) assert yacmap == yacmap.make_writable()
def test_make_readonly_returns_false_if_nothing_unlocked(self, cfg_file): yacmap = yacman.YacAttMap(filepath=cfg_file, writable=False) assert not yacmap.make_readonly()
def test_make_readonly_removes_lock_and_returns_true( self, cfg_file, list_locks): yacmap = yacman.YacAttMap(filepath=cfg_file, writable=True) assert yacmap.make_readonly() assert len(list_locks) == 0
def test_warnings(self, cfg_file): with pytest.warns(None): yacman.YacAttMap({}, writable=True)
def test_unlock_errors_when_no_filepath_provided(self, cfg_file): yacmap = yacman.YacAttMap({}) with pytest.raises(TypeError): yacmap.make_readonly()
def test_filename_required_when_object_created_from_mapping(self): yacmap = yacman.YacAttMap(entries={}) with pytest.raises(TypeError): yacmap.write()