windows running

This commit is contained in:
Jesse Bannon 2023-02-24 16:11:57 -08:00
parent ddcdcd5647
commit d1705e3942
6 changed files with 84 additions and 55 deletions

4
.gitignore vendored
View file

@ -142,4 +142,6 @@ docker/*.whl
docker/root/*.whl docker/root/*.whl
docker/root/defaults/examples docker/root/defaults/examples
.local/ .local/
ffmpeg.exe

View file

@ -1,11 +1,6 @@
import argparse import argparse
import errno
import fcntl
import gc import gc
import os
import sys import sys
from contextlib import contextmanager
from pathlib import Path
from typing import List from typing import List
from typing import Tuple from typing import Tuple
@ -13,8 +8,8 @@ from ytdl_sub.cli.download_args_parser import DownloadArgsParser
from ytdl_sub.cli.main_args_parser import parser from ytdl_sub.cli.main_args_parser import parser
from ytdl_sub.config.config_file import ConfigFile from ytdl_sub.config.config_file import ConfigFile
from ytdl_sub.subscriptions.subscription import Subscription from ytdl_sub.subscriptions.subscription import Subscription
from ytdl_sub.utils.exceptions import ValidationException
from ytdl_sub.utils.file_handler import FileHandlerTransactionLog from ytdl_sub.utils.file_handler import FileHandlerTransactionLog
from ytdl_sub.utils.file_lock import working_directory_lock
from ytdl_sub.utils.logger import Logger from ytdl_sub.utils.logger import Logger
logger = Logger.get() logger = Logger.get()
@ -119,45 +114,6 @@ def _view_url_from_cli(
return subscription, subscription.download(dry_run=True) return subscription, subscription.download(dry_run=True)
@contextmanager
def _working_directory_lock(config: ConfigFile):
"""
Create and try to lock the file /tmp/working_directory_name
Raises
------
ValidationException
Lock is acquired from another process running ytdl-sub in the same working directory
OSError
Other lock error occurred
"""
working_directory_path = Path(os.getcwd()) / config.config_options.working_directory
lock_file_path = (
Path(os.getcwd())
/ config.config_options.lock_directory
/ str(working_directory_path).replace("/", "_")
)
lock_file = open(lock_file_path, "w", encoding="utf-8")
try:
fcntl.lockf(lock_file, fcntl.LOCK_EX | fcntl.LOCK_NB)
except OSError as exc:
if exc.errno in (errno.EACCES, errno.EAGAIN):
raise ValidationException(
"Cannot run two instances of ytdl-sub "
"with the same working directory at the same time"
) from exc
lock_file.close()
raise exc
try:
yield
finally:
fcntl.flock(lock_file, fcntl.LOCK_UN)
lock_file.close()
def main() -> List[Tuple[Subscription, FileHandlerTransactionLog]]: def main() -> List[Tuple[Subscription, FileHandlerTransactionLog]]:
""" """
Entrypoint for ytdl-sub, without the error handling Entrypoint for ytdl-sub, without the error handling
@ -172,7 +128,7 @@ def main() -> List[Tuple[Subscription, FileHandlerTransactionLog]]:
config: ConfigFile = ConfigFile.from_file_path(args.config).initialize() config: ConfigFile = ConfigFile.from_file_path(args.config).initialize()
transaction_logs: List[Tuple[Subscription, FileHandlerTransactionLog]] = [] transaction_logs: List[Tuple[Subscription, FileHandlerTransactionLog]] = []
with _working_directory_lock(config=config): with working_directory_lock(config=config):
if args.subparser == "sub": if args.subparser == "sub":
transaction_logs = _download_subscriptions_from_yaml_files(config=config, args=args) transaction_logs = _download_subscriptions_from_yaml_files(config=config, args=args)

View file

@ -1,4 +1,5 @@
import subprocess import subprocess
import sys
import tempfile import tempfile
from typing import Dict from typing import Dict
from typing import List from typing import List
@ -26,7 +27,10 @@ class FFMPEG:
@classmethod @classmethod
def _ensure_installed(cls): def _ensure_installed(cls):
try: try:
subprocess.check_output(["which", "ffmpeg"]) if sys.platform.startswith("win32"):
subprocess.check_output([".\\ffmpeg", "-version"])
else:
subprocess.check_output(["which", "ffmpeg"])
except subprocess.CalledProcessError as subprocess_error: except subprocess.CalledProcessError as subprocess_error:
raise ValidationException( raise ValidationException(
"Trying to use a feature which requires ffmpeg, but it cannot be found" "Trying to use a feature which requires ffmpeg, but it cannot be found"

View file

@ -0,0 +1,67 @@
import errno
import os
import sys
from contextlib import contextmanager
from pathlib import Path
from ytdl_sub.config.config_file import ConfigFile
from ytdl_sub.utils.exceptions import ValidationException
from ytdl_sub.utils.logger import Logger
logger = Logger.get()
@contextmanager
def _working_directory_lock_unix(config: ConfigFile):
"""
Create and try to lock the file /tmp/working_directory_name
Raises
------
ValidationException
Lock is acquired from another process running ytdl-sub in the same working directory
OSError
Other lock error occurred
"""
# pylint: disable=import-outside-toplevel
import fcntl
working_directory_path = Path(os.getcwd()) / config.config_options.working_directory
lock_file_path = (
Path(os.getcwd())
/ config.config_options.lock_directory
/ str(working_directory_path).replace("/", "_")
)
lock_file = open(lock_file_path, "w", encoding="utf-8")
try:
fcntl.lockf(lock_file, fcntl.LOCK_EX | fcntl.LOCK_NB)
except OSError as exc:
if exc.errno in (errno.EACCES, errno.EAGAIN):
raise ValidationException(
"Cannot run two instances of ytdl-sub "
"with the same working directory at the same time"
) from exc
lock_file.close()
raise exc
try:
yield
finally:
fcntl.flock(lock_file, fcntl.LOCK_UN)
lock_file.close()
@contextmanager
def working_directory_lock(config: ConfigFile):
if sys.platform.startswith("win32"):
logger.info(
"Working directory lock not supported in Windows. "
"Ensure only one instance of ytdl-sub runs at once using working directory %s",
config.config_options.working_directory,
)
yield
else:
with _working_directory_lock_unix(config):
yield

View file

@ -3,9 +3,9 @@ from pathlib import Path
REGENERATE_FIXTURES: bool = False REGENERATE_FIXTURES: bool = False
RESOURCE_PATH = Path("tests/resources") RESOURCE_PATH: Path = Path("tests") / "resources"
_FILE_FIXTURE_PATH = RESOURCE_PATH / "file_fixtures" _FILE_FIXTURE_PATH: Path = RESOURCE_PATH / "file_fixtures"
def copy_file_fixture(fixture_name: str, output_file_path: str | Path) -> None: def copy_file_fixture(fixture_name: str, output_file_path: Path) -> None:
shutil.copy(_FILE_FIXTURE_PATH / fixture_name, output_file_path) shutil.copy(_FILE_FIXTURE_PATH / fixture_name, output_file_path)

View file

@ -3,9 +3,9 @@ import time
import pytest import pytest
from ytdl_sub.cli.main import _working_directory_lock
from ytdl_sub.config.config_file import ConfigFile from ytdl_sub.config.config_file import ConfigFile
from ytdl_sub.utils.exceptions import ValidationException from ytdl_sub.utils.exceptions import ValidationException
from ytdl_sub.utils.file_lock import working_directory_lock
@pytest.fixture @pytest.fixture
@ -18,15 +18,15 @@ def config() -> ConfigFile:
def test_working_directory_lock(config: ConfigFile): def test_working_directory_lock(config: ConfigFile):
new_pid = os.fork() new_pid = os.fork()
if new_pid == 0: # is child if new_pid == 0: # is child
with _working_directory_lock(config=config): with working_directory_lock(config=config):
time.sleep(3) time.sleep(3)
return return
time.sleep(1) time.sleep(1)
with pytest.raises(ValidationException, match="Cannot run two instances of ytdl-sub"): with pytest.raises(ValidationException, match="Cannot run two instances of ytdl-sub"):
with _working_directory_lock(config=config): with working_directory_lock(config=config):
time.sleep(1) time.sleep(1)
time.sleep(3) time.sleep(3)
with _working_directory_lock(config=config): with working_directory_lock(config=config):
pass pass