def _prepare_move(self, src_url, dst_url, measure_size=False, use_rename=True, expected_st_dev=None): if expected_st_dev is None: expected_st_dev = {} src_path, dst_path = self._check_transfer_precnds(src_url, dst_url) if use_rename: src_stat = self.stat(src_path) dst_par_path = splitscheme(dirname(dst_url))[1] try: dst_par_dev = expected_st_dev[dst_par_path] except KeyError: dst_par_dev = self.stat(dst_par_path).st_dev if src_stat.st_dev == dst_par_dev: yield Task('Moving ' + basename(src_url), size=1, fn=self._rename, args=(src_url, dst_url)) return src_is_dir = self.is_dir(src_path) if src_is_dir: yield Task('Creating ' + basename(dst_url), fn=self.mkdir, args=(dst_path, )) dst_par_path = splitscheme(dirname(dst_url))[1] # Expect `dst_path` to inherit .st_dev from its parent: try: expected_st_dev[dst_path] = expected_st_dev[dst_par_path] except KeyError: expected_st_dev[dst_path] = self.stat(dst_par_path).st_dev for name in self.iterdir(src_path): try: yield from self._prepare_move(join(src_url, name), join(dst_url, name), measure_size, use_rename, expected_st_dev) except FileNotFoundError: pass yield DeleteIfEmpty(self, src_url) else: size = self.size_bytes(src_path) if measure_size else 0 # It's tempting to "yield copy" then "yield delete" here. But this # can lead to data loss: fman / the user may choose to ignore errors # in a particular subtask. (Eg. moving file1.txt failed but the user # wants to go on to move file2.txt.) If we ignored a failure in # "yield copy" but then execute the "yield delete", we would delete # a file that has not been copied! # To avoid this, we "copy and delete" as a single, atomic task: yield MoveByCopying(self, src_url, dst_url, size)
def test_relative_path_parent_dir(self): src_file = join(self.src, 'test.txt') self._touch(src_file, '1234') self._perform_on(src_file, dest_dir='..') dest_dir_abs = dirname(self.src) self._expect_files({'src', 'test.txt'}, dest_dir_abs) self._assert_file_contents_equal(join(dest_dir_abs, 'test.txt'), '1234')
def _iter_parents(url): while True: yield url new_url = dirname(url) if new_url == url: break url = new_url
def __call__(self): # check file under cursor current_file = self.pane.get_file_under_cursor() # simply checking the file extension if re.compile(r'\.lnk$').search(current_file): # ok, let's receive the real folder containing the target of that shortcut shellscript = os.path.dirname(__file__) + "\link_target.ps1 " command = "powershell -ExecutionPolicy Bypass -NoLogo -Noninteractive -noprofile" command += ' -file "' + shellscript + '"' command += ' -link "' + as_human_readable(current_file) + '"' #show_status_message("Command: " + command) # temporary target = as_url(os.popen(command).read().strip()) show_status_message("Target: " + target, 2) # what did we get? if False == exists(target): # target is not reachable... show_alert(target + " doesn't exist.") elif is_dir(target): # target is a folder, we go to it self.pane.set_path(target) else: # target is a file, we go to its directory self.pane.set_path(dirname(target)) else: # nope, wrong thing show_alert(current_file + " is not a shortcut.")
def __call__(self, use_regex=False): result = show_quicksearch(self._get_items) if result: query, value = result if value: value = as_url(value) self.pane.set_path(dirname(value))
def __call__(self, url=None): if url is None: url = self.pane.get_file_under_cursor() or self.pane.get_path() if not is_dir(url): url = dirname(url) new_url = Flat.scheme + splitscheme(url)[1] self.pane.set_path(new_url)
def _get_action(self): file_under_cursor = self.pane.get_file_under_cursor() selected_files = self.pane.get_selected_files() chosen_files = selected_files or \ ([file_under_cursor] if file_under_cursor else []) location = self.pane.get_path() scheme, path = splitscheme(location) if scheme == 'file://': if file_under_cursor is None: # Either we're in an empty folder, or the user # right-clicked inside a directory. if self._is_drive(path): return lambda: _show_drive_properties(path) else: dir_ = as_human_readable(dirname(location)) filenames = [basename(location)] else: dir_ = as_human_readable(location) filenames = [basename(f) for f in chosen_files] return lambda: _show_file_properties(dir_, filenames) elif scheme == 'drives://': if file_under_cursor is None: # This usually happens when the user right-clicked in the drive # overview (but not _on_ a drive). return None drive = splitscheme(file_under_cursor)[1] if self._is_drive(drive): return lambda: _show_drive_properties(drive) elif scheme == 'network://': # We check `path` because when it's empty, we're at the # overview of network locations. Servers don't have a Properties # dialog. So we can't do anything there. if path: for f in chosen_files: try: f_fileurl = resolve(f) except OSError: continue if splitscheme(f_fileurl)[0] != 'file://': # Sanity check. We don't actually expect this. continue dir_ = as_human_readable(dirname(f_fileurl)) break else: return filenames = [basename(f) for f in chosen_files] return lambda: _show_file_properties(dir_, filenames)
def test_different_scheme(self): dest_path = as_human_readable(join(self._dest, 'a.txt')) sel_start = dest_path.rindex(os.sep) + 1 self._expect_prompt( ('Move "a.txt" to', dest_path, sel_start, sel_start + 1), (dest_path, True)) src_url = 'zip:///dest.zip/a.txt' src_dir = dirname(src_url) self._check([src_url], (self._dest, 'a.txt'), src_dir=src_dir)
def __call__(self, url=None): text, ok = show_prompt('Enter Filter e.g. *.txt', default="*.txt", selection_start=2) if url is None: url = self.pane.get_file_under_cursor() or self.pane.get_path() if not is_dir(url): url = dirname(url) Flat.filtertext = text new_url = Flat.scheme + splitscheme(url)[1] # Not working yet if ok and text: self.pane.set_path(new_url + '?' + text)
def test_overwrite_files(self, answers=(YES, YES), expect_overrides=(True, True), files=('a.txt', 'b.txt'), perform_on_files=None): if perform_on_files is None: perform_on_files = files src_files = [join(self.src, *relpath.split('/')) for relpath in files] dest_files = [ join(self.dest, *relpath.split('/')) for relpath in files ] file_contents = lambda src_file_path: os.path.basename(src_file_path) for i, src_file_path in enumerate(src_files): self._makedirs(dirname(src_file_path), exist_ok=True) self._touch(src_file_path, file_contents(src_file_path)) dest_file_path = dest_files[i] self._makedirs(dirname(dest_file_path), exist_ok=True) self._touch(dest_file_path) for i, answer in enumerate(answers): file_name = os.path.basename(files[i]) self._expect_alert( ('%s exists. Do you want to overwrite it?' % file_name, YES | NO | YES_TO_ALL | NO_TO_ALL | ABORT, YES), answer=answer) self._perform_on( *[join(self.src, fname) for fname in perform_on_files]) for i, expect_override in enumerate(expect_overrides): dest_file = dest_files[i] with self._open(dest_file, 'r') as f: contents = f.read() if expect_override: self.assertEqual(file_contents(src_files[i]), contents) else: self.assertEqual( '', contents, 'File %s was overwritten, contrary to expectations.' % os.path.basename(dest_file)) return src_files
def _prepare_move(self, src_url, dst_url, measure_size=False): src_path, dst_path = self._check_transfer_precnds(src_url, dst_url) src_stat = self.stat(src_path) dst_dir_dev = self.stat(splitscheme(dirname(dst_url))[1]).st_dev if src_stat.st_dev == dst_dir_dev: yield Task('Moving ' + basename(src_url), size=1, fn=self._rename, args=(src_url, dst_url)) return yield from self._prepare_copy(src_url, dst_url, measure_size) yield Task('Postprocessing ' + basename(src_url), fn=self.delete, args=(src_path, ))
def _get_dest_url(self, src_file): dest_name = self._dest_name or basename(src_file) if self._src_dir: try: rel_path = \ relpath(join(dirname(src_file), dest_name), self._src_dir) except ValueError as e: raise ValueError('Could not construct path. ' 'src_file: %r, dest_name: %r, src_dir: %r' % (src_file, dest_name, self._src_dir)) from e is_in_src_dir = not rel_path.startswith(pardir) if is_in_src_dir: try: splitscheme(self._dest_dir) except ValueError as no_scheme: return join(self._src_dir, self._dest_dir, rel_path) else: return join(self._dest_dir, rel_path) return join(self._dest_dir, dest_name)
def __init__(self, descr_verb, files, dest_dir, dest_name=None, fs=fman.fs): if dest_name and len(files) > 1: raise ValueError( 'Destination name can only be given when there is one file.') super().__init__(self._get_title(descr_verb, files)) self._files = files self._dest_dir = dest_dir self._descr_verb = descr_verb self._dest_name = dest_name self._fs = fs self._src_dir = dirname(files[0]) self._tasks = [] self._num_files = 0 self._cannot_move_to_self_shown = False self._override_all = None self._ignore_exceptions = False
def _touch(self, file_url, contents=None): self._makedirs(dirname(file_url), exist_ok=True) self._fs.touch(file_url) if contents is not None: with self._open(file_url, 'w') as f: f.write(contents)