def build_archive(config, interactive=True): narrate("Building the archive") plugins = select_plugins(config, 'archive') if not plugins: raise ConfigError(f"'plugins.archive' not specified, nothing to do.") # Make the archive directory: name = config.get('archive_name', '{host}').format(**PARAMS) workspace = to_path(appdirs.user_data_dir(__slug__), name) archive = to_path(workspace / 'archive') rm(workspace) mkdir(archive) # Apply any 'archive' plugins: for plugin in plugins: subconfigs = config.get('archive', {}).get(plugin.name, []) run_plugin(plugin, config, subconfigs, archive) # Show the user which files were included in the archive. display("The following files were included in the archive:") for root, _, files in os.walk(archive): root = to_path(root).relative_to(archive) for file in files: display(' ', root / file) display() if interactive: input("Is this correct? <Enter> to continue, <Ctrl-C> to cancel: ") return workspace
def test_chmod_gathering(): """change mode of a multiple files""" # setup f1 = to_path('f1') f2 = to_path('f2') touch(f1, f2) # run test for i in range(8): chmod(i, f1, f2) # 0o100000 represents a regular file assert f1.stat().st_mode == 0o100000 + i assert getmod(f1) == i assert f2.stat().st_mode == 0o100000 + i assert getmod(f2) == i chmod(8 * i, f1, f2) assert f1.stat().st_mode == 0o100000 + 8 * i assert getmod(f1) == 8 * i assert f2.stat().st_mode == 0o100000 + 8 * i assert getmod(f2) == 8 * i chmod(8 * 8 * i, f1, f2) assert f1.stat().st_mode == 0o100000 + 8 * 8 * i assert f2.stat().st_mode == 0o100000 + 8 * 8 * i assert getmod(f1) == 8 * 8 * i assert getmod(f2) == 8 * 8 * i # cleanup rm(f1, f2)
def main(): with Inform(notify_if_no_tty=True, version=version) as inform: try: # assure config and log directories exist to_path(CONFIG_DIR).mkdir(parents=True, exist_ok=True) to_path(DATA_DIR).mkdir(parents=True, exist_ok=True) inform.set_logfile(to_path(DATA_DIR, LOG_FILE)) # read command line cmdline = docopt(synopsis, options_first=True, version=version) command = cmdline["<command>"] args = cmdline["<args>"] if cmdline["--quiet"]: inform.quiet = True # find and run command settings = Settings(cmdline) cmd, cmd_name = Command.find(command) cmd.execute(cmd_name, args, settings, cmdline) except KeyboardInterrupt: display("Terminated by user.") except Error as e: e.terminate() except OSError as e: fatal(os_error(e)) done()
def test_ls_abominate(): """recursive list of directory""" # setup mkdir('work') with cd('work'): d1 = to_path('d1') mkdir(d1) d1d1 = to_path('d1/d1') mkdir(d1d1) d1d2 = to_path('d1/d2') mkdir(d1d2) d1d1f1 = to_path('d1/d1/f1') touch(d1d1f1) d1d2f2 = to_path('d1/d2/f2') touch(d1d2f2) # run test paths = ls('.', select='**/*') # check assert set(str(f) for f in paths) == set( ['d1', 'd1/d1', 'd1/d2', 'd1/d1/f1', 'd1/d2/f2'] ) # cleanup rm('work')
def run(cls, command, args, settings, options): # read command line cmdline = docopt(cls.USAGE, argv=[command] + args) mount_point = cmdline['<mount_point>'] if not mount_point: mount_point = settings.value('default_mount_point') if not mount_point: raise Error('must specify directory to use as mount point') mount_point = to_path(mount_point) # run borg try: settings.run_borg( cmd='umount', args=[mount_point], emborg_opts=options, ) try: to_path(mount_point).rmdir() except OSError as e: warn(os_error(e)) except Error as e: if 'busy' in str(e): e.reraise( codicil= f"Try running 'lsof +D {mount_point}' to find culprit.")
def test_ls_abominate(): """recursive list of directory""" # setup mkdir("work") with cd("work"): d1 = to_path("d1") mkdir(d1) d1d1 = to_path("d1/d1") mkdir(d1d1) d1d2 = to_path("d1/d2") mkdir(d1d2) d1d1f1 = to_path("d1/d1/f1") touch(d1d1f1) d1d2f2 = to_path("d1/d2/f2") touch(d1d2f2) # run test paths = ls(".", select="**/*") # check assert set(str(f) for f in paths) == set( ["d1", "d1/d1", "d1/d2", "d1/d1/f1", "d1/d2/f2"]) # cleanup rm("work")
def test_chmod_quisling(): """change mode of a multiple directories""" # setup d1 = to_path('d1') d2 = to_path('d2') mkdir(d1, d2) # run test for i in range(8): chmod(i, [d1, d2]) # 0o040000 represents a directory assert d1.stat().st_mode == 0o040000 + i assert getmod(d1) == i assert d2.stat().st_mode == 0o040000 + i assert getmod(d2) == i chmod(8 * i, d1, d2) assert d1.stat().st_mode == 0o040000 + 8 * i assert getmod(d1) == 8 * i assert d2.stat().st_mode == 0o040000 + 8 * i assert getmod(d2) == 8 * i chmod(8 * 8 * i, d1, d2) assert d1.stat().st_mode == 0o040000 + 8 * 8 * i assert d2.stat().st_mode == 0o040000 + 8 * 8 * i assert getmod(d1) == 8 * 8 * i assert getmod(d2) == 8 * 8 * i # cleanup rm(d1)
def read_confs(self): # read the .conf files in our config directory (except for hosts.conf) for name in "ssh networks locations proxies".split(): conf_file = to_path(CONFIG_DIR, name + ".conf") if conf_file.exists(): settings = PythonFile(conf_file).run() overlap = settings.keys() & self.settings.keys() overlap -= sshconfig_names overlap = [k for k in overlap if not k.startswith("_")] if overlap: warn("conflicting settings:", conjoin(overlap), culprit=conf_file) self.settings.update(settings) self.ssh_config_file = to_path( self.settings.get("CONFIG_FILE", SSH_CONFIG_FILE)) if not self.ssh_config_file.is_absolute(): raise Error( "path to SSH config file should be absolute.", culprit=self.ssh_config_file, ) self.ssh_defaults = self.settings.get("DEFAULTS", "") self.ssh_overrides = self.settings.get("OVERRIDES", "") self.preferred_networks = self.settings.get("PREFERRED_NETWORKS", []) self.locations = self.settings.get("LOCATIONS", {}) self.proxies = self.settings.get("PROXIES", {}) self.available_ciphers = self.settings.get("AVAILABLE_CIPHERS") self.available_macs = self.settings.get("AVAILABLE_MACS") self.available_host_key_algorithms = self.settings.get( "AVAILABLE_HOST_KEY_ALGORITHMS") self.available_kex_algorithms = self.settings.get( "AVAILABLE_KEX_ALGORITHMS")
def test_ls_abominate(): """recursive list of directory""" # setup mkdir('work') with cd('work'): d1 = to_path('d1') mkdir(d1) d1d1 = to_path('d1/d1') mkdir(d1d1) d1d2 = to_path('d1/d2') mkdir(d1d2) d1d1f1 = to_path('d1/d1/f1') touch(d1d1f1) d1d2f2 = to_path('d1/d2/f2') touch(d1d2f2) # run test paths = ls('.', select='**/*') # check assert set(str(f) for f in paths) == set( ['d1', 'd1/d1', 'd1/d2', 'd1/d1/f1', 'd1/d2/f2']) # cleanup rm('work')
def initialize(cls, gpg_path=None, gpg_home=None, armor=None ): from .config import get_setting, override_setting cls.gpg_path = to_path( gpg_path if gpg_path else get_setting('gpg_executable') ) override_setting('gpg_executable', cls.gpg_path) cls.gpg_home = to_path( gpg_home if gpg_home else get_setting('gpg_home') ) override_setting('gpg_home', cls.gpg_home) armor = armor if armor is not None else get_setting('gpg_armor') if armor not in ARMOR_CHOICES: warn( "'%s' is not valid, choose from %s." % ( armor, conjoin(ARMOR_CHOICES) ), culprit=(get_setting('config_file'), 'gpg_armor') ) armor = None cls.armor = armor override_setting('gpg_armor', armor) gpg_args = {} if cls.gpg_path: gpg_args.update({'gpgbinary': str(cls.gpg_path)}) if cls.gpg_home: gpg_args.update({'gnupghome': str(cls.gpg_home)}) cls.gpg = gnupg.GPG(**gpg_args)
def to_path(self, s, resolve=True, culprit=None): """Converts a string to a path.""" p = to_path(s) if resolve: p = to_path(self.working_dir, p) if culprit: if not p.exists(): raise Error(f"{p!s} not found.", culprit=culprit) return p
def test_mv_ground(): """rename nonexistent file""" # setup f1 = to_path('f1') f2 = to_path('f2') # run test with pytest.raises(IOError): mv(f1, f2)
def test_mv_ground(): """rename nonexistent file""" # setup f1 = to_path("f1") f2 = to_path("f2") # run test with pytest.raises(IOError): mv(f1, f2)
def test_cp_ground(): """copy nonexistent file to new file""" # setup f1 = to_path("f1") f2 = to_path("f2") # run test with pytest.raises(IOError): cp(f1, f2)
def test_cp_ground(): """copy nonexistent file to new file""" # setup f1 = to_path('f1') f2 = to_path('f2') # run test with pytest.raises(IOError): cp(f1, f2)
def __enter__(self): # change to working directory working_dir = self.value('working_dir') if not working_dir: working_dir = self.resolve(DEFAULT_WORKING_DIR) self.working_dir = to_path(working_dir) mkdir(self.working_dir) narrate('changing to working_dir:', working_dir) self.starting_dir = cd(self.working_dir).starting_dir # resolve src and dest directories src_dir = self.resolve(self.src_dir) self.src_dir = to_path(src_dir) dest_dir = self.resolve(self.dest_dir) self.dest_dir = to_path(dest_dir) # resolve other files and directories config_dir = self.resolve(CONFIG_DIR) self.config_dir = to_path(config_dir, config_dir) logfile = self.resolve(EMBALM_LOG_FILE) self.logfile = to_path(working_dir, logfile) incr_date_file = self.resolve(INCR_DATE_FILE) self.incr_date_file = to_path(working_dir, incr_date_file) full_date_file = self.resolve(FULL_DATE_FILE) self.full_date_file = to_path(working_dir, full_date_file) restore_dir = self.resolve(RESTORE_DIR) self.restore_dir = to_path(working_dir, restore_dir) archive_dir = self.resolve(ARCHIVE_DIR) self.archive_dir = to_path(working_dir, archive_dir) # perform locking if self.requires_exclusivity: # check for existance of lockfile lockfile = self.lockfile = to_path(working_dir, LOCK_FILE) if lockfile.exists(): raise Error(f'currently running (see {lockfile} for details).') # create lockfile now = arrow.now() pid = os.getpid() lockfile.write_text( dedent(f''' started = {now!s} pid = {pid} ''').lstrip()) # open logfile get_informer().set_logfile(self.logfile) return self
def cleanup(self): if self.vim: self.vim.kill() for each in cull([self.file1, self.file2, self.file3, self.file4]): path = to_path(each) dn = path.parent fn = path.name swpfile = to_path(dn, '.' + fn + '.swp') try: rm(swpfile) except OSError as e: error(os_error(e))
def test_ln_endorse(): """link a nonexistent file""" # setup f1 = to_path('f1') f2 = to_path('f2') # run test ln(f1, f2) # check assert f2.is_symlink() # cleanup rm(f1, f2)
def test_ln_endorse(): """link a nonexistent file""" # setup f1 = to_path("f1") f2 = to_path("f2") # run test ln(f1, f2) # check assert f2.is_symlink() # cleanup rm(f1, f2)
def test_ln_ground(): """link to a pre-existing name""" # setup f1 = to_path('f1') touch(f1) f2 = to_path('f2') touch(f2) # run test with pytest.raises(OSError): ln(f1, f2) # cleanup rm(f1, f2)
def test_rm_ground(): """remove two files""" # setup f1 = to_path('f1') touch(f1) f2 = to_path('f2') touch(f2) # run test rm(f1, f2) # check assert not f1.exists() assert not f2.exists()
def test_ln_ground(): """link to a pre-existing name""" # setup f1 = to_path("f1") touch(f1) f2 = to_path("f2") touch(f2) # run test with pytest.raises(OSError): ln(f1, f2) # cleanup rm(f1, f2)
def test_cp_real_downturn(): """copy existing file (ie: not generated by test_cp_real_downturn) to new file""" # setup f1 = to_path('tests/SRCFILE') f2 = to_path('f2') # run test cp(f1, f2) # check assert f2.is_file() # cleanup rm(f2)
def test_mkdir_endorse(): """make two directories""" # setup d1 = to_path("d1") d2 = to_path("d2") # run test mkdir(d1, d2) # check assert d1.is_dir() assert d2.is_dir() # cleanup rm(d1, d2)
def test_mv_cymbal(): """move two files to a new directory""" # setup f1 = to_path("f1") touch(f1) f2 = to_path("f2") touch(f2) d1 = to_path("d2") # run test with pytest.raises(OSError): mv(f1, f2, d1) # cleanup rm(f1, f2, d1)
def test_cp_downturn(): """copy file to new file""" # setup f1 = to_path('f1') touch(f1) f2 = to_path('f2') # run test cp(f1, f2) # check assert f2.is_file() # cleanup rm(f1, f2)
def test_cp_cymbal(): """copy two files to a new directory""" # setup d1 = to_path('d1') f1 = to_path('f1') touch(f1) f2 = to_path('f2') touch(f2) # run test with pytest.raises(OSError): cp(f1, f2, d1) # cleanup rm(f1, f2, d1)
def test_cartesian_product_negative(): """cartesian product of paths""" # run test paths = cartesian_product( [to_path('A'), to_path('B'), to_path('C')], ['a', 'b', 'c'], 'f' ) # check assert set(str(p) for p in paths) == set([ 'A/a/f', 'A/b/f', 'A/c/f', 'B/a/f', 'B/b/f', 'B/c/f', 'C/a/f', 'C/b/f', 'C/c/f', ])
def test_mv_cymbal(): """move two files to a new directory""" # setup f1 = to_path('f1') touch(f1) f2 = to_path('f2') touch(f2) d1 = to_path('d2') # run test with pytest.raises(OSError): mv(f1, f2, d1) # cleanup rm(f1, f2, d1)
def test_touch_cymbal(): """touch multiple files""" # setup f1 = to_path("f1") f2 = to_path("f2") # run test touch([f1, f2]) # check assert f1.is_file() assert f2.is_file() # cleanup rm(f1, f2)
def test_mkdir_ground(): """make two directories""" # setup d1 = to_path('d1') d2 = to_path('d2') # run test mkdir([d1, d2]) # check assert d1.is_dir() assert d2.is_dir() # cleanup rm(d1, d2)
def test_mv_incense(): """move two files into a nonexistent directory""" # setup d1 = to_path('d1') f1 = to_path('f1') touch(f1) f2 = to_path('f2') touch(f2) # run test with pytest.raises(OSError): mv([f1, f2], d1) # cleanup rm(d1, f1, f2)
def test_touch_ground(): """touch multiple files""" # setup f1 = to_path('f1') f2 = to_path('f2') # run test touch(f1, f2) # check assert f1.is_file() assert f2.is_file() # cleanup rm(f1, f2)
def test_touch_cymbal(): """touch multiple files""" # setup f1 = to_path('f1') f2 = to_path('f2') # run test touch([f1, f2]) # check assert f1.is_file() assert f2.is_file() # cleanup rm(f1, f2)
def test_cp_downturn(): """copy file to new file""" # setup f1 = to_path("f1") touch(f1) f2 = to_path("f2") # run test cp(f1, f2) # check assert f2.is_file() # cleanup rm(f1, f2)
def test_cp_incense(): """copy two files into a nonexistent directory""" # setup d1 = to_path("d1") f1 = to_path("f1") touch(f1) f2 = to_path("f2") touch(f2) # run test with pytest.raises(OSError): cp([f1, f2], d1) # cleanup rm(f1, f2)
def test_cp_cymbal(): """copy two files to a new directory""" # setup d1 = to_path("d1") f1 = to_path("f1") touch(f1) f2 = to_path("f2") touch(f2) # run test with pytest.raises(OSError): cp(f1, f2, d1) # cleanup rm(f1, f2, d1)
def test_lsd_rissole(): """list files""" # setup f1 = to_path('f1') touch(f1) f2 = to_path('f2') touch(f2) # run test files = lsd(f1, f2) # check assert set(str(f) for f in files) == set() # cleanup rm(f1, f2)
def test_mv_ruminate(): """move two files into an existing file""" # setup f1 = to_path('f1') touch(f1) f2 = to_path('f2') touch(f2) f3 = to_path('f2') touch(f3) # run test with pytest.raises(OSError): mv(f1, f2, f3) # cleanup rm(f1, f2, f3)
def test_mv_downturn(): """rename file""" # setup f1 = to_path('f1') touch(f1) f2 = to_path('f2') # run test mv(f1, f2) # check assert f2.is_file() assert not f1.exists() # cleanup rm(f1, f2)
def __init__(self, init=False, gpg_ids=None): # initialize avendesora (these should already be done if called from # main, but it is safe to call them again) read_config() GnuPG.initialize() # check the integrity of avendesora validate_componenets() # create the avendesora data directory if init: self.initialize(gpg_ids, init) terminate() # read the accounts files self.all_accounts = set() for filename in get_setting('accounts_files', []): try: path = to_path(get_setting('settings_dir'), filename) account_file = PythonFile(path) contents = account_file.run() master_password = contents.get('master_password') # traverse through all accounts, determine which are new, bind # required information to new accounts, and update account list. for account in Account.all_accounts(): if account not in self.all_accounts: account.add_fileinfo(master_password, account_file) # save a copy of account so it is not garbage collected self.all_accounts.add(account) except Error as err: err.terminate() terminate_if_errors()
def test_lsf_narrow(): """list files with select constraint""" # setup f1 = to_path('f1') touch(f1) f2 = to_path('f2') touch(f2) # run test files = lsf(f1, f2, select='*2') # check assert set(str(f) for f in files) == set(['f2']) # cleanup rm(f1, f2)
def test_lsf_rissole(): """list files""" # setup f1 = to_path('f1') touch(f1) f2 = to_path('f2') touch(f2) # run test files = lsf(f1, f2) # check assert set(str(f) for f in files) == set(['f1', 'f2']) # cleanup rm(f1, f2)
def read_defaults(self): settings = {} try: from appdirs import user_config_dir config_file = to_path(user_config_dir('vdiff'), 'config') try: code = config_file.read_text() try: compiled = compile(code, str(config_file), 'exec') exec(compiled, settings) except Exception as e: error(e, culprit=config_file) except FileNotFoundError: pass except OSError as e: warn(os_error(e)) if self.useGUI is not None: settings['gui'] = self.useGUI except ImportError: pass if settings.get('gui', DEFAULT_GUI): if 'DISPLAY' not in os.environ: warn('$DISPLAY not set, ignoring request for gvim.') else: self.cmd = settings.get('gvimdiff', DEFAULT_GVIM) return self.cmd = settings.get('vimdiff', DEFAULT_VIM)
def test_rm_cymbal(): """remove directory""" # setup d1 = to_path('d1') mkdir(d1) d1f1 = to_path('d1/f1') touch(d1f1) f2 = to_path('f2') touch(f2) # run test rm(d1, f2) # check assert not d1.exists() assert not f2.exists()
def run(cls, command, args, settings, options): # read command line cmdline = docopt(cls.USAGE, argv=[command] + args) paths = cmdline['<path>'] archive = cmdline['--archive'] date = cmdline['--date'] # add cwd to paths paths = [to_path(cwd(), p) for p in paths] # assure that paths correspond to src_dirs src_dirs = settings.src_dirs unknown_path = False # get the desired archive if date and not archive: archive = get_name_of_nearest_archive(settings, date) if not archive: archive = get_name_of_latest_archive(settings) output('Archive:', archive) # run borg borg = settings.run_borg( cmd='extract', args=[settings.destination(archive)] + paths, emborg_opts=options, ) out = borg.stdout if out: output(out.rstrip())
def test_lsf_rissole(): """list files""" # setup f1 = to_path("f1") touch(f1) f2 = to_path("f2") touch(f2) # run test files = lsf(f1, f2) # check assert set(str(f) for f in files) == set(["f1", "f2"]) # cleanup rm(f1, f2)
def test_ls_rissole(): """list files""" # setup f1 = to_path('f1') touch(f1) f2 = to_path('f2') touch(f2) # run test paths = ls(f1, f2) # check assert set(str(f) for f in paths) == set(['f1', 'f2']) # cleanup rm(f1, f2)
def test_ls_narrow(): """list files with select constraint""" # setup f1 = to_path('f1') touch(f1) f2 = to_path('f2') touch(f2) # run test paths = ls(f1, f2, select='*2') # check assert set(str(f) for f in paths) == set(['f2']) # cleanup rm(f1, f2)
def test_cp_endorse(): """copy file to existing file""" # setup f1 = to_path('f1') touch(f1) f2 = to_path('f2') touch(f2) # run test cp(f1, f2) # check assert f2.is_file() # cleanup rm(f1, f2)
def test_lsf_narrow(): """list files with select constraint""" # setup f1 = to_path("f1") touch(f1) f2 = to_path("f2") touch(f2) # run test files = lsf(f1, f2, select="*2") # check assert set(str(f) for f in files) == set(["f2"]) # cleanup rm(f1, f2)
def check(self): # add some possibly useful placeholders into settings home_dir = os.environ.get("HOME") if home_dir and "home_dir" not in self.settings: self.settings["home_dir"] = home_dir self.settings["config_dir"] = CONFIG_DIR self.settings["log_dir"] = DATA_DIR self.do_not_expand = Collection(self.settings.get("do_not_expand", "")) # gather the string valued settings together (can be used by resolve) self.str_settings = { k: v for k, v in self.settings.items() if is_str(v) } # complain about required settings that are missing missing = [] required_settings = "repository".split() for each in required_settings: if not self.settings.get(each): missing.append(each) if missing: m = conjoin(missing) raise Error(f"{m}: no value given for {plural(m):setting}.") self.working_dir = to_path(self.settings.get("working_dir", "/")) if not self.working_dir.exists(): raise Error("{self.working_dir!s} not found.", culprit="working_dir") if not self.working_dir.is_absolute(): raise Error("must be an absolute path.", culprit="working_dir")
def __new__(cls, server, include_file, bypass, trial_run): if server in AuthKeys.known: self = AuthKeys.known[server] if include_file != self.include_file: warn( 'inconsistent remote include file:', fmt('{include_file} != {self.include_file} in {server}.') ) return self self = super(AuthKeys, cls).__new__(cls) AuthKeys.known[server] = self self.server = server self.bypass = bypass self.trial_run = trial_run self.keys = {} self.comment = {} self.restrictions = {} self.include_file = include_file self.include = None # get remote include file if it exists if include_file and not bypass: narrate(fmt(' retrieving remote include file from {server}.')) try: try: run_sftp(self.server, [ fmt('get .ssh/{inc} {inc}.{server}', inc=include_file) ]) self.include = to_path(include_file + '.' + server).read_text() except OSError as err: comment(fmt(' sftp {server}: {include_file} not found.')) except OSError as err: error(os_error(err)) return self
def test_cp_gathering(): """copy file into an existing directory""" # setup d1 = to_path('d1') mkdir(d1) f1 = to_path('f1') touch(f1) # run test cp(f1, d1) # check assert to_path('d1/f1').is_file() # cleanup rm(d1)
def read_config(): if Config.get('READ'): return # already read # First open the config file from .gpg import PythonFile path = get_setting('config_file') assert path.suffix.lower() not in ['.gpg', '.asc'] config_file = PythonFile(path) try: contents = config_file.run() for k, v in contents.items(): if k.startswith('_'): continue if k not in CONFIG_DEFAULTS: warn('%s: unknown.' % k, culprit=config_file) continue if k.endswith('_executable'): argv = v.split() if is_str(v) else list(v) path = to_path(argv[0]) if not path.is_absolute(): warn( 'should use absolute path for executables.', culprit=(config_file, k) ) Config[k] = v Config['READ'] = True except Error as err: comment('not found.', culprit=config_file) # Now open the hashes file hashes_file = PythonFile(get_setting('hashes_file')) try: contents = hashes_file.run() Config.update({k.lower(): v for k,v in contents.items()}) except Error as err: pass # Now open the account list file account_list_file = PythonFile(get_setting('account_list_file')) try: contents = account_list_file.run() Config.update({k.lower(): v for k,v in contents.items()}) except Error as err: pass # initilize GPG from .gpg import GnuPG GnuPG.initialize() # Now read the user key file user_key_file = get_setting('user_key_file') if user_key_file: user_key_file = PythonFile(get_setting('user_key_file')) try: contents = user_key_file.run() Config.update({k.lower(): v for k,v in contents.items()}) except Error as err: pass
def test_mv_gathering(): """move file into an existing directory""" # setup d1 = to_path('d1') mkdir(d1) f1 = to_path('f1') touch(f1) # run test mv(f1, d1) # check assert to_path('d1/f1').is_file() assert not f1.exists() # cleanup rm(d1, f1)