def open(paths: Iterable[str]) -> None: # pylint: disable=redefined-builtin """Deprecated open function for backwards compatibility.""" # TODO remove in v0.7.0 log.warning( "Calling 'api.open' directly is deprecated, use 'api.open_paths' instead" ) open_paths(paths)
def _on_quit(self): if self.state() == QProcess.Running: log.warning( "Decoupling external command '%s' with pid %d", self.program(), self.pid(), )
def _run_command(count: str, cmdname: str, args: List[str], mode: api.modes.Mode) -> None: """Run a given command. Args: count: Count to use for the command. cmdname: Name of the command passed. args: Arguments passed. mode: Mode to run the command in. """ try: cmd = api.commands.get(cmdname, mode) if cmd.store: _last_command[mode] = LastCommand(count, cmdname, args) cmd(args, count=count) api.status.update("ran command") except api.commands.CommandNotFound as e: log.error(str(e)) raise CommandPartFailed from e except ( api.commands.ArgumentError, api.commands.CommandError, api.modes.InvalidMode, ) as e: log.error("%s: %s", cmdname, e) raise CommandPartFailed from e except api.commands.CommandWarning as w: log.warning("%s: %s", cmdname, str(w)) raise CommandPartFailed from w except api.commands.CommandInfo as i: log.info("%s: %s", cmdname, i) raise CommandPartFailed from i
def delete(paths: List[str]) -> None: """Move one or more images to the trash directory. **syntax:** ``:delete path [path ...]`` positional arguments: * ``paths``: The path(s) to the images to delete. .. note:: This only deletes images, not any other path(s). """ _last_deleted.clear() images = [path for path in paths if files.is_image(path)] if not images: raise api.commands.CommandError("No images to delete") failed_images = [] for filename in images: try: trash_filename = trash_manager.delete(filename) _last_deleted.append(os.path.basename(trash_filename)) except OSError: failed_images.append(filename) n_fail = len(failed_images) n_success = len(images) - n_fail fail_msg = f"Failed to delete {', '.join(failed_images)}" if n_fail > 0 else "" succ_msg = f"Deleted {n_success} images" if n_success > 0 else "" if fail_msg: log.warning(f"{succ_msg + ' but ' if succ_msg else ''}{fail_msg}") elif succ_msg: log.info(succ_msg)
def _open_path(self, path: str, close: bool): """Open a given path possibly closing the library.""" if not path: log.warning("Library: selecting empty path") elif os.path.isdir(path): self._open_directory(path) else: self._open_image(path, close)
def _log_unknown_module(module_name: str) -> None: """Display log warning for unknown module. The lru_cache is used so each module is only logged once, not on every evaluation of the status text. Args: module_name: Module string that is unknown. """ log.warning("Disabling unknown statusbar module '%s'", module_name)
def _process_pipe(self) -> None: """Open paths from stdout.""" _logger.debug("Opening paths from '%s'...", self.program()) stdout = qbytearray_to_str(self.readAllStandardOutput()) try: api.open_paths(path for path in stdout.split("\n") if os.path.exists(path)) _logger.debug("... opened paths from pipe") api.status.update("opened paths from pipe") except api.commands.CommandError: log.warning("%s: No paths from pipe", self.program())
def __call__(self, command: str, *args: str, pipe=False) -> None: """Run external command with arguments.""" if self.state() == QProcess.Running: log.warning("Closing running process '%s'", self.program()) self.close() self._pipe = pipe arglist: List[str] = flatten( glob.glob(arg) if contains_any(arg, "*?[]") else (arg,) for arg in args ) _logger.debug("Running external command '%s' with '%r'", command, arglist) self.start(command, arglist)
def rename( paths: List[str], base: str, start: int = 1, separator: str = "_", overwrite: bool = False, skip_image_check: bool = False, ) -> None: """Rename images with a common base. **syntax:** ``:rename path [path ...] base [--start=INDEX] [--separator=SEPARATOR] [--overwrite] [--skip-image-check]`` Example:: ``:rename * identifier`` would rename all images in the filelist to ``identifier_001``, ``identifier_002``, ..., ``identifier_NNN``. positional arguments: * ``paths``: The path(s) to rename. * ``base``: Base name to use for numbering. optional arguments: * ``--start``: Index to start numbering with. Default: 1. * ``--separator``: Separator between base and numbers. Default: '_'. * ``--overwrite``: Overwrite existing paths when renaming. * ``--skip-image-check``: Do not check if all renamed paths are images. """ paths = [ path for path in paths if files.is_image(path) or skip_image_check ] if not paths: raise api.commands.CommandError("No paths to rename") marked = [] for i, path in enumerate(paths, start=start): _, extension = os.path.splitext(path) dirname = os.path.dirname(path) basename = f"{base}{separator}{i:03d}{extension}" outfile = os.path.join(dirname, basename) if os.path.exists(outfile) and not overwrite: log.warning( "Outfile '%s' exists, skipping. To overwrite add '--overwrite'.", outfile, ) else: _logger.debug("%s -> %s", path, outfile) os.rename(path, outfile) if path in api.mark.paths: # Keep mark status of the renamed path marked.append(outfile) api.mark.mark(marked)
def run_startup_commands(*commands: str) -> None: """Run commands given via --command at startup. Args: commands: All command strings given via individual --command arguments. """ total = len(commands) for i, command in enumerate(commands, start=1): _logger.debug("Startup commands: running %d/%d '%s'", i, total, command) if "quit" in command: # This does not work without a running app log.warning("Quitting forcefully as the app does not exist") app.Application.preexit(customtypes.Exit.success) sys.exit(customtypes.Exit.success) else: runners.run(command, mode=api.modes.current())
def __init__(self, filename=""): super().__init__(filename) try: self._metadata = piexif.load(filename) except FileNotFoundError: _logger.debug("File %s not found", filename) self._metadata = None except piexif.InvalidImageDataError: log.warning( "Piexif only supports the file types JPEG and TIFF.<br>\n" "Please install pyexiv2 for better file type support.<br>\n" "For more information see<br>\n" "https://karlch.github.io/vimiv-qt/documentation/exif.html", once=True, ) self._metadata = None
def delete(paths: List[str], ask: bool = False) -> None: """Move one or more images to the trash directory. **syntax:** ``:delete path [path ...]`` positional arguments: * ``paths``: The path(s) to the images to delete. optional arguments: * ``--ask``: Prompt for confirmation before deleting the images. .. note:: This only deletes images, not any other path(s). """ if ask and not api.prompt.ask_question( title="delete", body=f"delete {quotedjoin(paths)}?" ): return _last_deleted.clear() images = [path for path in paths if files.is_image(path)] if not images: raise api.commands.CommandError("No images to delete") failed_images = [] for filename in images: try: trash_filename = trash_manager.delete(filename) _last_deleted.append(os.path.basename(trash_filename)) except OSError: failed_images.append(filename) n_fail = len(failed_images) n_success = len(images) - n_fail fail_msg = f"Failed to delete {', '.join(failed_images)}" if n_fail > 0 else "" succ_msg = f"Deleted {n_success} images" if n_success > 0 else "" if fail_msg: log.warning(f"{succ_msg + ' but ' if succ_msg else ''}{fail_msg}") elif succ_msg: log.info(succ_msg)
def log_warning(message, qtbot): log.warning(message)