def __call__(self): selected_files = self.pane.get_selected_files() if len(selected_files) >= 1 or (len(selected_files) == 0 and self.get_chosen_files()): if len(selected_files) == 0 and self.get_chosen_files(): selected_files.append(self.get_chosen_files()[0]) # # Loop through each file/directory selected. # for filedir in selected_files: p = as_human_readable(filedir) filepath = os.path.abspath(p) if os.path.isdir(filepath): # # It is a directory. Process as a directory. # newDir = filepath + "-copy" copy(as_url(filepath), as_url(newDir)) else: if os.path.isfile(filepath): # # It is a file. Process as a file. # dirPath, ofilenmc = os.path.split(filepath) ofilenm, ext = os.path.splitext(ofilenmc) nfilenm = os.path.join(dirPath, ofilenm + "-copy" + ext) copy(as_url(filepath), as_url(nfilenm)) else: show_alert('Bad file path : {0}'.format(filepath))
def test_no_src_dir(self): path = __file__ dir_url = as_url(os.path.dirname(path)) self.assertEqual( as_url(path), _from_human_readable(path, dir_url, None) )
def test_copy_directory(self): with TemporaryDirectory() as tmp_dir: src = Path(tmp_dir, 'src') src.mkdir() self._create_test_directory_structure(src) dst = Path(tmp_dir, 'dst') self._fs.copy(as_url(src), as_url(dst)) self.assertEqual(self._jsonify_directory(src), self._jsonify_directory(dst))
def __call__(self): self.current_dir = self.pane.get_path() result = show_quicksearch(self._suggest_my_subfolders_and_files) if result: query, file_path = result new_path = dirname(file_path) thePane = self.pane self.pane.set_path( as_url(new_path), lambda: thePane.place_cursor_at(as_url(file_path)))
def mkdir(self, path): if self.exists(path): raise FileExistsError(path) zip_path, path_in_zip = self._split(path) if not path_in_zip: self._create_empty_archive(zip_path) elif not self.exists(str(PurePosixPath(path).parent)): raise filenotfounderror(path) else: with TemporaryDirectory() as tmp_dir: self.copy(as_url(tmp_dir), as_url(path, self.scheme))
def test_add_directory(self): with TemporaryDirectory() as zip_contents: with ZipFile(self._zip) as zip_file: zip_file.extractall(zip_contents) with TemporaryDirectory() as zip_container: zip_path = os.path.join(zip_container, 'test.zip') self._create_empty_zip(zip_path) self._fs.copy( as_url(os.path.join(zip_contents, 'ZipFileTest')), join(as_url(zip_path, 'zip://'), 'ZipFileTest')) self._expect_zip_contents(self._get_zip_contents(), zip_path)
def _test_transfer_file(self, transfer_fn, deletes_src): with TemporaryDirectory() as tmp_dir: src = Path(tmp_dir, 'src') f_contents = '1234' src.write_text(f_contents) dst = Path(tmp_dir, 'dst') transfer_fn(as_url(src), as_url(dst)) self.assertTrue(dst.exists()) self.assertEqual(f_contents, dst.read_text()) if deletes_src: self.assertFalse(src.exists())
def __call__(self): # # Get the directory path. # selected_files = self.pane.get_selected_files() if len(selected_files) >= 1 or (len(selected_files) == 0 and self.get_chosen_files()): if len(selected_files) == 0 and self.get_chosen_files(): selected_files.append(self.get_chosen_files()[0]) dirName = as_human_readable(selected_files[0]) if os.path.isfile(dirName): # # It's a file, not a directory. Get the directory # name for this file's parent directory. # dirName = os.path.dirname(dirName) # # Set the directory obtained as a project directory. # with open(PROJECTDIR, "w") as f: f.write(dirName) # # Add to the list of projects. Get a name # from the user. # projName, checked = show_prompt("Name this Project:") projEntry = projName + "|" + dirName writeappend = 'w' if os.path.isfile(PROJECTSLIST): writeappend = 'a' with open(PROJECTSLIST, writeappend) as f: f.write(projEntry + "\n") # # Create the launch script file and open in the # editor. # scriptFile = dirName + "/.startproject" with open(scriptFile, 'w') as f: f.write("#!/bin/sh\n\n") os.chmod(scriptFile, stat.S_IEXEC | stat.S_IRUSR | stat.S_IWUSR) if (_THIRDPARTY_PLUGINS_DIR + "/OpenWithEditor") in _get_thirdparty_plugins(): self.pane.run_command("my_open_with_editor", args={'url': as_url(scriptFile)}) else: self.pane.run_command("open_with_editor", args={'url': as_url(scriptFile)}) else: # # Technically, this will never be reached. Just here # for completeness. # show_alert("No directory selected")
def test_move_directory(self, use_rename=True): with TemporaryDirectory() as tmp_dir: src = Path(tmp_dir, 'src') src.mkdir() self._create_test_directory_structure(src) src_contents = self._jsonify_directory(src) dst = Path(tmp_dir, 'dst') for task in self._fs._prepare_move(as_url(src), as_url(dst), use_rename=use_rename): task() self.assertFalse(src.exists()) self.assertEqual(src_contents, self._jsonify_directory(dst))
def test_add_file(self): with TemporaryDirectory() as tmp_dir: file_to_add = os.path.join(tmp_dir, 'tmp.txt') file_contents = 'added!' with open(file_to_add, 'w') as f: f.write(file_contents) dest_url_in_zip = self._url('ZipFileTest/Directory/added.txt') self._fs.copy(as_url(file_to_add), dest_url_in_zip) dest_url = join(as_url(tmp_dir), 'extracted.txt') self._fs.copy(dest_url_in_zip, dest_url) with open(as_human_readable(dest_url)) as f: actual_contents = f.read() self.assertEqual(file_contents, actual_contents)
def test_prepare_move_fails_cleanly(self): """ Consider moving a file from src to dst. When src and dst are on the same drive (as indicated by stat().st_dev having the same value), then a simple os.rename(src, dst) suffices to "move" the file. On the other hand, if src and dst are not on the same device, then LocalFileSystem (LFS) needs to 1) copy src to dst and 2) delete src. This test checks that 2) is only performed if 1) was successful, and thus that no data loss occurs. It does this by forcing LFS to use the copy-move (and not the rename) implementation. Then, it makes 1) fail by making dst read-only. """ with TemporaryDirectory() as tmp_dir: src = Path(tmp_dir, 'src') # Need to give src some contents. Otherwise, the write to dst goes # through without raising a PermissionError. src.write_text('some_contents') src_url = as_url(src) dst_dir = Path(tmp_dir, 'dst_dir') dst_dir.mkdir() dst = dst_dir / 'dst' dst.touch() # Make dst read-only. dst.chmod(dst.stat().st_mode ^ S_IWRITE) try: permission_error_raised = False for task in self._fs._prepare_move( src_url, as_url(dst), use_rename=False ): try: task() except PermissionError: permission_error_raised = True self.assertTrue( permission_error_raised, 'PermissionError was not raised upon writing to read-only ' 'dst. This test may have to be updated to trigger this ' 'error in a different way.' ) self.assertTrue( src.exists(), 'LocalFileSystem deleted the source file even though ' 'copying it to the destination failed. This can lead to ' 'data loss!' ) finally: # Make file writable again. Otherwise cleaning up the temporary # directory fails on Windows. dst.chmod(dst.stat().st_mode | S_IWRITE)
def __call__(self): show_status_message('Creating a Script...') scriptVars = _GetScriptVars() script, flags = show_prompt("New Script Name?") newScript = scriptVars['directory'] + os.sep + script if os.path.isdir(newScript): show_alert("This is a directory.") else: if os.path.isfile(newScript): show_alert("Script already exists.") else: # # Create the script file. # fp = open(newScript,"w+") fp.write("#!/bin/sh\n\n") fp.write("#\n# The following variable are usable:\n#\n") fp.write("# $FILES_SELECTED - The currently selected file\n") fp.write("# $LEFT_PANE - The directory of the left pane\n") fp.write("# $RIGHT_PANE - The directory of the right pane\n") fp.write("# $CURRENT_DIRECTORY - The currently selected directory\n") fp.write("# $LEFT_PANE_SELECTED_FILE - The currently selected file in the left pane\n") fp.write("# $RIGHT_PANE_SELECTED_FILE - The currently selected file in the right pane\n") fp.close() os.chmod(newScript,0o755) # # Edit the script file. # if self.pane.is_command_visible('open_with_editor'): self.pane.run_command('open_with_editor',{'url': as_url(newScript)}) clear_status_message()
def openCommand(option, files, path): sublime_path = get_current_sublime_install_path() if not exists(as_url(sublime_path)): show_alert('Invalid Sublime Text path: ' + sublime_path) choice = show_alert('Update Path to Sublime Text?', buttons=YES | NO) if choice == YES: if not set_sublime_install_path(): # user failed to set sublime install path. bail. show_alert( 'command failed because no valid path to Sublime Text given' ) return else: # no path to use, user doesnt want to set one now. bail. show_alert( 'command failed because no valid path to Sublime Text given') return _SUBLIMETEXTPATH = sublime_path args = [to_path(x) for x in files] cmd = [_SUBLIMETEXTPATH] + option + args env = create_clean_environment() Popen(cmd, shell=False, cwd=path, stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL, env=env)
def setUp(self): super().setUp() self._ui = StubUI(self) self._root = as_url('C:\\' if PLATFORM == 'Windows' else '/') self._src = join(self._root, 'src') self._dest = join(self._root, 'dest') self._a = join(self._root, 'src/a') self._a_txt = join(self._root, 'src/a.txt') self._b_txt = join(self._root, 'src/b.txt') self._fs = self.FileSystem({ self._src: { 'is_dir': True }, self._dest: { 'is_dir': True }, self._a: { 'is_dir': True }, self._a_txt: { 'is_dir': False }, self._b_txt: { 'is_dir': False }, })
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 test_move_file_between_archives(self, operation=None, get_contents=None): if operation is None: operation = self._fs.move if get_contents is None: get_contents = self._pop_from_dir_dict src_path = 'ZipFileTest/Directory/Subdirectory/file 3.txt' expected_contents = self._get_zip_contents() src_contents = get_contents(expected_contents, src_path) with TemporaryDirectory() as dst_dir: dst_zip = os.path.join(dst_dir, 'dest.zip') # Give the Zip file some contents: dummy_txt = os.path.join(dst_dir, 'dummy.txt') dummy_contents = 'some contents' with open(dummy_txt, 'w') as f: f.write(dummy_contents) with ZipFile(dst_zip, 'w') as zip_file: zip_file.write(dummy_txt, 'dummy.txt') dst_url = join(as_url(dst_zip, 'zip://'), 'dest.txt') operation(self._url(src_path), dst_url) self.assertEqual(expected_contents, self._get_zip_contents()) self.assertEqual( { 'dummy.txt': dummy_contents, 'dest.txt': src_contents }, self._get_zip_contents(dst_zip))
def resolve(self, path): path = self._url_to_os_path(path) if not self._isabs(path): raise filenotfounderror(path) if PLATFORM == 'Windows': is_unc_server = path.startswith(r'\\') and not '\\' in path[2:] if is_unc_server: # Python can handle \\server\folder but not \\server. Defer to # the network:// file system. return 'network://' + path[2:] p = Path(path) try: try: path = p.resolve(strict=True) except TypeError: # fman's "production Python version" is 3.6 but we want to be # able to develop using 3.5 as well. So add this workaround for # Python < 3.6: path = p.resolve() except FileNotFoundError: if not p.exists(): raise except OSError as e: # We for instance get errno.EINVAL ("[WinError 1]") when trying to # resolve folders on Cryptomator drives on Windows. Ignore it: if e.errno != errno.EINVAL: raise return as_url(path)
def __call__(self, dirNum=0): global LASTPOP, POPDIR, POPPING LASTPOP = LASTPOP - 1 - dirNum if LASTPOP < 0: LASTPOP = 0 POPPING = True self.pane.set_path(as_url(POPDIR[LASTPOP]))
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): show_status_message('Regular Expressions Selection') result = show_quicksearch(self._suggest_projects) if result: query, regexp = result try: pattern = re.compile(regexp) except Exception as e: show_alert('Your Regular Expression statement is not valid.' + str(e)) self.__call__() return used = False lines = [""] if os.path.isfile(REGULAREXPRESSIONHIST): with open(REGULAREXPRESSIONHIST, "r") as f: lines = f.readlines() for line in lines: if line.strip() == regexp: used = True if not used: with open(REGULAREXPRESSIONHIST, "a") as f: f.write(regexp + "\n") scheme, currentDir = splitscheme(self.pane.get_path()) for filep in iterdir(self.pane.get_path()): if pattern.search(filep): self.pane.toggle_selection( as_url(currentDir + os.sep + filep, scheme)) clear_status_message()
def test_delete_readonly_file(self): with TemporaryDirectory() as tmp_dir: path = Path(tmp_dir, 'file') path.touch() path.chmod(path.stat().st_mode ^ S_IWRITE) urlpath = splitscheme(as_url(path))[1] self._fs.delete(urlpath)
def resolve(self, path): for suffix in self._suffixes: if suffix in path.lower(): if not self.exists(path): raise FileNotFoundError(self.scheme + path) return super().resolve(path) return self._fs.resolve(as_url(path))
def get_current_sublime_install_path(): settings = load_json(_SUBLIMETEXTCONFIGFILE, default={'path': _SUBLIMETEXTPATHDEFAULT}) if settings['path'] and exists(as_url(settings['path'])): return settings['path'] else: return _SUBLIMETEXTPATHDEFAULT
def _test_move_dir_out_of_archive(self, path_in_zip): expected_zip_contents = self._get_zip_contents() removed = self._pop_from_dir_dict(expected_zip_contents, path_in_zip) with TemporaryDirectory() as tmp_dir: dst_dir = os.path.join(tmp_dir, 'dest') self._fs.move(self._url(path_in_zip), as_url(dst_dir)) self.assertEqual(expected_zip_contents, self._get_zip_contents()) self.assertEqual(removed, self._read_directory(dst_dir))
def _test_extract_dir(self, path_in_zip): expected_files = self._get_zip_contents(path_in_zip=path_in_zip) with TemporaryDirectory() as tmp_dir: # Create a subdirectory because the destination directory of a copy # operation must not yet exist: dst_dir = os.path.join(tmp_dir, 'dest') self._fs.copy(self._url(path_in_zip), as_url(dst_dir)) self.assertEqual(expected_files, self._read_directory(dst_dir))
def test_delete_symlink_to_directory(self): with TemporaryDirectory() as tmp_dir: a = Path(tmp_dir, 'a') a.mkdir() b = Path(tmp_dir, 'b') b.symlink_to(a) self._fs.delete(splitscheme(as_url(b))[1]) self.assertFalse(b.exists(), 'Failed to delete symlink to folder')
def test_file(self): file_path = os.path.join(self._root, 'file.txt') selection_start = file_path.rindex(os.sep) + 1 selection_end = selection_start + len('file') self.assertEqual( (file_path, selection_start, selection_end), get_dest_suggestion(as_url(file_path)) )
def test_dir(self): dir_path = os.path.join(self._root, 'dir') selection_start = dir_path.rindex(os.sep) + 1 selection_end = None self.assertEqual( (dir_path, selection_start, selection_end), get_dest_suggestion(as_url(dir_path)) )
def get_current_tortoisesvnproc_install_path(): settings = load_json(_TORTOISEPROCCONFIGFILE, default={'path': _TORTOISEPROCPATHDEFAULT}) if settings['path'] and exists(as_url(settings['path'])): return settings['path'] else: return _TORTOISEPROCPATHDEFAULT
def __call__(self): with TemporaryDirectory() as tmp_dir: dest = Path(tmp_dir, *self._path_in_zip.split('/')) dest.parent.mkdir(parents=True, exist_ok=True) src = Path(self._src_ospath) try: dest.symlink_to(src, src.is_dir()) except OSError: # This for instance happens on non-NTFS drives on Windows. # We need to incur the cost of physically copying the file: self._fman_fs.copy(as_url(src), as_url(dest)) args = ['a', self._zip_path, self._path_in_zip] if PLATFORM != 'Windows': args.insert(1, '-l') self.run_7zip_with_progress(args, cwd=tmp_dir) dest_path = self._zip_path + '/' + self._path_in_zip self._zip_fs.notify_file_added(dest_path)