Move --log from the dl cmd to the root cmd

This commit is contained in:
rlaphoenix 2023-02-24 19:54:05 +00:00
parent 4f1cff681c
commit c6976a7112
3 changed files with 47 additions and 44 deletions

View File

@ -10,11 +10,9 @@ import shutil
import sys import sys
import time import time
import traceback import traceback
from collections import defaultdict
from concurrent import futures from concurrent import futures
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from copy import deepcopy from copy import deepcopy
from datetime import datetime
from functools import partial from functools import partial
from http.cookiejar import MozillaCookieJar from http.cookiejar import MozillaCookieJar
from pathlib import Path from pathlib import Path
@ -32,7 +30,7 @@ from pywidevine.remotecdm import RemoteCdm
from tqdm import tqdm from tqdm import tqdm
from devine.core.config import config from devine.core.config import config
from devine.core.constants import LOG_FORMATTER, AnyTrack, context_settings from devine.core.constants import AnyTrack, context_settings
from devine.core.credential import Credential from devine.core.credential import Credential
from devine.core.downloaders import aria2c from devine.core.downloaders import aria2c
from devine.core.drm import DRM_T, Widevine from devine.core.drm import DRM_T, Widevine
@ -120,8 +118,6 @@ class dl:
help="Disable the source tag from the output file name and path.") help="Disable the source tag from the output file name and path.")
@click.option("--workers", type=int, default=1, @click.option("--workers", type=int, default=1,
help="Max concurrent workers to use throughout the code, particularly downloads.") help="Max concurrent workers to use throughout the code, particularly downloads.")
@click.option("--log", "log_path", type=Path, default=config.directories.logs / config.filenames.log,
help="Log path (or filename). Path can contain the following f-string args: {name} {time}.")
@click.pass_context @click.pass_context
def cli(ctx: click.Context, **kwargs: Any) -> dl: def cli(ctx: click.Context, **kwargs: Any) -> dl:
return dl(ctx, **kwargs) return dl(ctx, **kwargs)
@ -131,7 +127,6 @@ class dl:
def __init__( def __init__(
self, self,
ctx: click.Context, ctx: click.Context,
log_path: Path,
profile: Optional[str] = None, profile: Optional[str] = None,
proxy: Optional[str] = None, proxy: Optional[str] = None,
group: Optional[str] = None, group: Optional[str] = None,
@ -142,11 +137,6 @@ class dl:
raise ValueError("A subcommand to invoke was not specified, the main code cannot continue.") raise ValueError("A subcommand to invoke was not specified, the main code cannot continue.")
self.log = logging.getLogger("download") self.log = logging.getLogger("download")
if log_path:
new_log_path = self.rotate_log_file(log_path)
fh = logging.FileHandler(new_log_path, encoding="utf8")
fh.setFormatter(LOG_FORMATTER)
self.log.addHandler(fh)
self.service = Services.get_tag(ctx.invoked_subcommand) self.service = Services.get_tag(ctx.invoked_subcommand)
@ -759,37 +749,6 @@ class dl:
shutil.move(muxed_path, final_path) shutil.move(muxed_path, final_path)
self.log.info(f" + Moved to {final_path}") self.log.info(f" + Moved to {final_path}")
@staticmethod
def rotate_log_file(log_path: Path, keep: int = 20) -> Path:
"""
Update Log Filename and delete old log files.
It keeps only the 20 newest logs by default.
"""
if not log_path:
raise ValueError("A log path must be provided")
try:
log_path.relative_to(Path("")) # file name only
except ValueError:
pass
else:
log_path = config.directories.logs / log_path
log_path = log_path.parent / log_path.name.format_map(defaultdict(
str,
name="root",
time=datetime.now().strftime("%Y%m%d-%H%M%S")
))
if log_path.parent.exists():
log_files = [x for x in log_path.parent.iterdir() if x.suffix == log_path.suffix]
for log_file in log_files[::-1][keep-1:]:
# keep n newest files and delete the rest
log_file.unlink()
log_path.parent.mkdir(parents=True, exist_ok=True)
return log_path
@staticmethod @staticmethod
def get_profile(service: str) -> Optional[str]: def get_profile(service: str) -> Optional[str]:
"""Get profile for Service from config.""" """Get profile for Service from config."""

View File

@ -1,23 +1,34 @@
import logging import logging
from datetime import datetime from datetime import datetime
from pathlib import Path
import click import click
import coloredlogs import coloredlogs
from devine.core import __version__ from devine.core import __version__
from devine.core.commands import Commands from devine.core.commands import Commands
from devine.core.constants import LOG_FORMAT, context_settings from devine.core.config import config
from devine.core.constants import LOG_FORMAT, LOG_FORMATTER, context_settings
from devine.core.utilities import rotate_log_file
@click.command(cls=Commands, invoke_without_command=True, context_settings=context_settings) @click.command(cls=Commands, invoke_without_command=True, context_settings=context_settings)
@click.option("-v", "--version", is_flag=True, default=False, help="Print version information.") @click.option("-v", "--version", is_flag=True, default=False, help="Print version information.")
@click.option("-d", "--debug", is_flag=True, default=False, help="Enable DEBUG level logs.") @click.option("-d", "--debug", is_flag=True, default=False, help="Enable DEBUG level logs.")
def main(version: bool, debug: bool) -> None: @click.option("--log", "log_path", type=Path, default=config.directories.logs / config.filenames.log,
help="Log path (or filename). Path can contain the following f-string args: {name} {time}.")
def main(version: bool, debug: bool, log_path: Path) -> None:
"""Devine—Open-Source Movie, TV, and Music Downloading Solution.""" """Devine—Open-Source Movie, TV, and Music Downloading Solution."""
logging.basicConfig(level=logging.DEBUG if debug else logging.INFO) logging.basicConfig(level=logging.DEBUG if debug else logging.INFO)
log = logging.getLogger() log = logging.getLogger()
coloredlogs.install(level=log.level, fmt=LOG_FORMAT, style="{") coloredlogs.install(level=log.level, fmt=LOG_FORMAT, style="{")
if log_path:
new_log_path = rotate_log_file(log_path)
fh = logging.FileHandler(new_log_path, encoding="utf8")
fh.setFormatter(LOG_FORMATTER)
log.addHandler(fh)
log.info(f"Devine version {__version__} Copyright (c) 2019-{datetime.now().year} rlaphoenix") log.info(f"Devine version {__version__} Copyright (c) 2019-{datetime.now().year} rlaphoenix")
log.info("Convenient Widevine-DRM Downloader and Decrypter.") log.info("Convenient Widevine-DRM Downloader and Decrypter.")
log.info("https://github.com/devine-dl/devine") log.info("https://github.com/devine-dl/devine")

View File

@ -5,6 +5,8 @@ import re
import shutil import shutil
import sys import sys
import unicodedata import unicodedata
from collections import defaultdict
from datetime import datetime
from pathlib import Path from pathlib import Path
from types import ModuleType from types import ModuleType
from typing import AsyncIterator, Optional, Sequence, Union from typing import AsyncIterator, Optional, Sequence, Union
@ -20,6 +22,37 @@ from devine.core.config import config
from devine.core.constants import LANGUAGE_MAX_DISTANCE from devine.core.constants import LANGUAGE_MAX_DISTANCE
def rotate_log_file(log_path: Path, keep: int = 20) -> Path:
"""
Update Log Filename and delete old log files.
It keeps only the 20 newest logs by default.
"""
if not log_path:
raise ValueError("A log path must be provided")
try:
log_path.relative_to(Path("")) # file name only
except ValueError:
pass
else:
log_path = config.directories.logs / log_path
log_path = log_path.parent / log_path.name.format_map(defaultdict(
str,
name="root",
time=datetime.now().strftime("%Y%m%d-%H%M%S")
))
if log_path.parent.exists():
log_files = [x for x in log_path.parent.iterdir() if x.suffix == log_path.suffix]
for log_file in log_files[::-1][keep-1:]:
# keep n newest files and delete the rest
log_file.unlink()
log_path.parent.mkdir(parents=True, exist_ok=True)
return log_path
def import_module_by_path(path: Path) -> ModuleType: def import_module_by_path(path: Path) -> ModuleType:
"""Import a Python file by Path as a Module.""" """Import a Python file by Path as a Module."""
if not path: if not path: