Skip to content

Commit

Permalink
CLI: Allow multiple files for directly passed video files
Browse files Browse the repository at this point in the history
  • Loading branch information
Vodes committed Jan 6, 2025
1 parent 7b89184 commit 2d24e7c
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 44 deletions.
113 changes: 79 additions & 34 deletions vspreview/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,34 @@
from PyQt6.QtWidgets import QApplication

from .core.logger import set_log_level, setup_logger

# import vsenv as early as possible:
# This is so other modules cannot accidentally use and lock us into a different policy.
from .core.vsenv import set_vsengine_loop
from .main import MainWindow
from .plugins import get_installed_plugins
from .plugins.abstract import FileResolverPlugin, ResolvedScript
from .plugins.install import install_plugins, plugins_commands, print_available_plugins, uninstall_plugins
from .plugins.install import (
install_plugins,
plugins_commands,
print_available_plugins,
uninstall_plugins,
)

from vstools import FileSignatures, FileType

__all__ = [
'main'
]
__all__ = ["main"]


def get_resolved_script(filepath: Path) -> tuple[ResolvedScript, FileResolverPlugin | None] | int:
def get_resolved_script(
filepath: Path,
) -> tuple[ResolvedScript, FileResolverPlugin | None] | int:
for plugin in get_installed_plugins(FileResolverPlugin, False).values():
if plugin.can_run_file(filepath):
return plugin.resolve_path(filepath), plugin

if not filepath.exists():
logging.error('Script or file path is invalid.')
logging.error("Script or file path is invalid.")
return 1

return ResolvedScript(filepath, str(filepath)), None
Expand All @@ -41,37 +49,53 @@ def get_resolved_script(filepath: Path) -> tuple[ResolvedScript, FileResolverPlu
def main(_args: Sequence[str] | None = None, no_exit: bool = False) -> int:
from .utils import exit_func

parser = ArgumentParser(prog='VSPreview')
parser = ArgumentParser(prog="VSPreview")
parser.add_argument(
'script_path_or_command', type=str, nargs='?',
help=f'Path to Vapoursynth script or plugins command {",".join(plugins_commands)}'
"script_path_or_command",
type=str,
nargs="?",
help=f'Path to Vapoursynth script, video file(s) or plugins command {", ".join(plugins_commands)}',
)
parser.add_argument(
'plugins', type=str, nargs='*',
help=f'Plugins to {"/".join(plugins_commands[:-1])} or arguments to pass to the script environment.'
"plugins",
type=str,
nargs="*",
help=f'Plugins to {"/".join(plugins_commands[:-1])} or arguments to pass to the script environment.',
)
parser.add_argument("--version", "-v", action="version", version="%(prog)s 0.2b")
parser.add_argument(
'--version', '-v', action='version', version='%(prog)s 0.2b'
"--preserve-cwd",
"-c",
action="store_true",
help="do not chdir to script parent directory",
)
parser.add_argument(
'--preserve-cwd', '-c', action='store_true', help='do not chdir to script parent directory'
"-f", "--frame", type=int, help="Frame to load initially (defaults to 0)"
)
parser.add_argument('-f', '--frame', type=int, help='Frame to load initially (defaults to 0)')
parser.add_argument(
'--vscode-setup', type=str, choices=['override', 'append', 'ignore'], nargs='?', const='append',
help='Installs launch settings in cwd\'s .vscode'
"--vscode-setup",
type=str,
choices=["override", "append", "ignore"],
nargs="?",
const="append",
help="Installs launch settings in cwd's .vscode",
)
parser.add_argument(
"--verbose", help="Set the logging to verbose.", action="store_true"
)
parser.add_argument(
"--force", help="Force the install of a plugin even if it exists already.", action="store_true"
"--force",
help="Force the install of a plugin even if it exists already.",
action="store_true",
)
parser.add_argument(
"--no-deps", help="Ignore downloading dependencies.", action="store_true"
)
parser.add_argument(
"--force-storage", help="Force override or local/global storage.", action="store_true", default=False
"--force-storage",
help="Force override or local/global storage.",
action="store_true",
default=False,
)

args = parser.parse_args(_args)
Expand All @@ -80,6 +104,7 @@ def main(_args: Sequence[str] | None = None, no_exit: bool = False) -> int:

if args.verbose:
from vstools import VSDebug

set_log_level(logging.DEBUG, logging.DEBUG)
VSDebug(use_logging=True)
else:
Expand All @@ -94,32 +119,34 @@ def main(_args: Sequence[str] | None = None, no_exit: bool = False) -> int:

script_path_or_command = args.script_path_or_command

if not script_path_or_command and not (args.plugins and (script_path_or_command := next(iter(args.plugins)))):
logging.error('Script path required.')
if not script_path_or_command and not (
args.plugins and (script_path_or_command := next(iter(args.plugins)))
):
logging.error("Script/Video path required.")
return exit_func(1, no_exit)

if script_path_or_command.startswith('--') and args.plugins:
if script_path_or_command.startswith("--") and args.plugins:
script_path_or_command = args.plugins.pop()
args.plugins = [args.script_path_or_command, *args.plugins]

if (command := script_path_or_command) in plugins_commands:
if command == 'available':
if command == "available":
print_available_plugins()
return exit_func(0, no_exit)

if not args.plugins:
logging.error('You must provide at least one plugin!')
logging.error("You must provide at least one plugin!")
return exit_func(1, no_exit)

set_log_level(logging.INFO)

plugins = list(args.plugins)

if command == 'install':
if command == "install":
install_plugins(plugins, args.force, args.no_deps)
elif command == 'uninstall':
elif command == "uninstall":
uninstall_plugins(plugins)
elif command == 'update':
elif command == "update":
uninstall_plugins(plugins, True)
install_plugins(plugins, True, args.no_deps)

Expand All @@ -132,16 +159,20 @@ def main(_args: Sequence[str] | None = None, no_exit: bool = False) -> int:

script, file_resolve_plugin = script_or_err

if not args.preserve_cwd:
if (
not args.preserve_cwd
and not file_resolve_plugin._config.namespace == "dev.setsugen.vssource_load"
):
os.chdir(script.path.parent)

first_run = not hasattr(main, 'app')
first_run = not hasattr(main, "app")

if first_run:
main.app = QApplication(sys.argv)
set_vsengine_loop()
else:
from .core.vsenv import get_current_environment, make_environment

make_environment()
get_current_environment().use()

Expand All @@ -151,7 +182,7 @@ def main(_args: Sequence[str] | None = None, no_exit: bool = False) -> int:

def _parse_arg(kv: str) -> tuple[str, str | int | float]:
v: str | int | float
k, v = kv.split('=', maxsplit=1)
k, v = kv.split("=", maxsplit=1)

try:
v = int(v)
Expand All @@ -161,16 +192,30 @@ def _parse_arg(kv: str) -> tuple[str, str | int | float]:
except ValueError:
...

return k.strip('--'), v
return k.strip("--"), v

if args.plugins:
arguments |= {k: v for k, v in map(_parse_arg, args.plugins)}
if file_resolve_plugin._config.namespace == "dev.setsugen.vssource_load":
additional_files = list[Path](
Path(filepath).resolve() for filepath in args.plugins
)
arguments.update(additional_files=additional_files)
else:
arguments |= {k: v for k, v in map(_parse_arg, args.plugins)}

main.main_window = MainWindow(
Path(os.getcwd()) if args.preserve_cwd else script.path.parent, no_exit, script.reload_enabled, args.force_storage
Path(os.getcwd()) if args.preserve_cwd else script.path.parent,
no_exit,
script.reload_enabled,
args.force_storage,
)
main.main_window.load_script(
script.path, list(arguments.items()), False, args.frame or None, script.display_name, file_resolve_plugin
script.path,
list(arguments.items()),
False,
args.frame or None,
script.display_name,
file_resolve_plugin,
)

ret_code = main.app.exec()
Expand All @@ -185,5 +230,5 @@ def _parse_arg(kv: str) -> tuple[str, str | int | float]:
return exit_func(ret_code, no_exit)


if __name__ == '__main__':
if __name__ == "__main__":
main()
31 changes: 21 additions & 10 deletions vspreview/plugins/builtins/vssource_load.ppy
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@ from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING

if __name__ != '__vspreview__':
from vspreview.plugins import FileResolvePluginConfig, FileResolverPlugin, ResolvedScript
if __name__ != "__vspreview__":
from vspreview.plugins import (
FileResolvePluginConfig,
FileResolverPlugin,
ResolvedScript,
)

__all__ = [
'FileResolveWithVSSource'
]
__all__ = ["FileResolveWithVSSource"]

class FileResolveWithVSSource(FileResolverPlugin):
_config = FileResolvePluginConfig('dev.setsugen.vssource_load', 'VSSource Loader')
_config = FileResolvePluginConfig(
"dev.setsugen.vssource_load", "VSSource Loader"
)

def can_run_file(self, filepath: Path) -> bool:
if filepath.is_dir():
Expand All @@ -30,17 +34,20 @@ if __name__ != '__vspreview__':
return False

def resolve_path(self, filepath: Path) -> ResolvedScript:
return ResolvedScript(Path(__file__), str(filepath), dict(filepath=filepath), False)
return ResolvedScript(
Path(__file__), str(filepath), dict(filepath=filepath), False
)
else:
from vssource import parse_video_filepath, source
from vstools import set_output

if TYPE_CHECKING:
filepath: Path = Path()
pattern: str = ''
pattern: str = ""
additional_files: list[Path] | None = None
else:
if 'pattern' not in locals():
pattern = '*'
if "pattern" not in locals():
pattern = "*"

if filepath.is_dir():
for file in filepath.glob(pattern):
Expand All @@ -51,3 +58,7 @@ else:
...
else:
set_output(source(filepath), filepath.name)

if "additional_files" in locals():
for file in additional_files:
set_output(source(file), file.name)

0 comments on commit 2d24e7c

Please sign in to comment.