logging improvements
All checks were successful
ci/woodpecker/push/tests Pipeline was successful

This commit is contained in:
Ivan Schaller 2022-07-15 14:04:22 +02:00
parent 66e916a580
commit 820c891fd7
12 changed files with 117 additions and 53 deletions

View file

@ -9,6 +9,23 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- Add support for more sites - Add support for more sites
## [2.1.11] - 2022-07-
### Fixed
- The `--read` option now filters empty lines, so it will not generate an error anymore
- An error which was caused by the interactive input method when you did not specify a chapter or to list them
### Added
- `autoflake` test in `justfile`
- Some more things which get logged
### Changed
- Adjusted the new logging implementation. It shows now more info about the module the log is from, and some other
improvements
## [2.1.10] - 2022-07-14 ## [2.1.10] - 2022-07-14
### Fixed ### Fixed

View file

@ -82,6 +82,10 @@ test_mypy:
test_pytest: test_pytest:
@python3 -m tox -e basic @python3 -m tox -e basic
test_autoflake:
@python3 -m autoflake --remove-all-unused-imports -r -v mangadlp/
@python3 -m autoflake --check --remove-all-unused-imports -r -v mangadlp/
test_tox: test_tox:
@python3 -m tox @python3 -m tox
@ -111,6 +115,7 @@ lint:
just test_black just test_black
just test_isort just test_isort
just test_mypy just test_mypy
just test_autoflake
@echo -e "\n\033[0;32m=== ALL DONE ===\033[0m\n" @echo -e "\n\033[0;32m=== ALL DONE ===\033[0m\n"
tests: tests:
@ -120,6 +125,7 @@ tests:
just test_black just test_black
just test_isort just test_isort
just test_mypy just test_mypy
just test_autoflake
just test_pytest just test_pytest
@echo -e "\n\033[0;32m=== ALL DONE ===\033[0m\n" @echo -e "\n\033[0;32m=== ALL DONE ===\033[0m\n"

View file

@ -1,9 +1,4 @@
import logging from mangadlp.logger import prepare_logger
# prepare logger with default level INFO==20 # prepare logger with default level INFO==20
logging.basicConfig( prepare_logger()
format="%(asctime)s | %(levelname)s: %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
level=20,
handlers=[logging.StreamHandler()],
)

View file

@ -1,4 +1,3 @@
import logging
import re import re
import sys import sys
from time import sleep from time import sleep
@ -7,9 +6,10 @@ from typing import Any
import requests import requests
import mangadlp.utils as utils import mangadlp.utils as utils
from mangadlp.logger import Logger
# prepare logger # prepare logger
log = logging.getLogger(__name__) log = Logger(__name__)
class Mangadex: class Mangadex:
@ -39,7 +39,7 @@ class Mangadex:
# make initial request # make initial request
def get_manga_data(self) -> requests.Response: def get_manga_data(self) -> requests.Response:
log.debug(f"Getting manga data for: {self.manga_uuid}") log.verbose(f"Getting manga data for: {self.manga_uuid}")
counter = 1 counter = 1
while counter <= 3: while counter <= 3:
try: try:
@ -78,7 +78,7 @@ class Mangadex:
# get the title of the manga (and fix the filename) # get the title of the manga (and fix the filename)
def get_manga_title(self) -> str: def get_manga_title(self) -> str:
log.debug(f"Getting manga title for: {self.manga_uuid}") log.verbose(f"Getting manga title for: {self.manga_uuid}")
manga_data = self.manga_data.json() manga_data = self.manga_data.json()
try: try:
title = manga_data["data"]["attributes"]["title"][self.language] title = manga_data["data"]["attributes"]["title"][self.language]
@ -96,7 +96,9 @@ class Mangadex:
# check if chapters are available in requested language # check if chapters are available in requested language
def check_chapter_lang(self) -> int: def check_chapter_lang(self) -> int:
log.debug(f"Checking for chapters in specified language for: {self.manga_uuid}") log.verbose(
f"Checking for chapters in specified language for: {self.manga_uuid}"
)
r = requests.get( r = requests.get(
f"{self.api_base_url}/manga/{self.manga_uuid}/feed?limit=0&{self.api_additions}" f"{self.api_base_url}/manga/{self.manga_uuid}/feed?limit=0&{self.api_additions}"
) )
@ -116,7 +118,7 @@ class Mangadex:
# get chapter data like name, uuid etc # get chapter data like name, uuid etc
def get_chapter_data(self) -> dict: def get_chapter_data(self) -> dict:
log.debug(f"Getting chapter data for: {self.manga_uuid}") log.verbose(f"Getting chapter data for: {self.manga_uuid}")
api_sorting = "order[chapter]=asc&order[volume]=asc" api_sorting = "order[chapter]=asc&order[volume]=asc"
# check for chapters in specified lang # check for chapters in specified lang
total_chapters = self.check_chapter_lang() total_chapters = self.check_chapter_lang()
@ -174,7 +176,7 @@ class Mangadex:
# get images for the chapter (mangadex@home) # get images for the chapter (mangadex@home)
def get_chapter_images(self, chapter: str, wait_time: float) -> list: def get_chapter_images(self, chapter: str, wait_time: float) -> list:
log.debug(f"Getting chapter images for: {self.manga_uuid}") log.verbose(f"Getting chapter images for: {self.manga_uuid}")
athome_url = f"{self.api_base_url}/at-home/server" athome_url = f"{self.api_base_url}/at-home/server"
chapter_uuid = self.manga_chapter_data[chapter][0] chapter_uuid = self.manga_chapter_data[chapter][0]
@ -220,7 +222,7 @@ class Mangadex:
# create list of chapters # create list of chapters
def create_chapter_list(self) -> list: def create_chapter_list(self) -> list:
log.debug(f"Creating chapter list for: {self.manga_uuid}") log.verbose(f"Creating chapter list for: {self.manga_uuid}")
chapter_list = [] chapter_list = []
for chapter in self.manga_chapter_data.items(): for chapter in self.manga_chapter_data.items():
chapter_info = self.get_chapter_infos(chapter[0]) chapter_info = self.get_chapter_infos(chapter[0])

View file

@ -1,4 +1,3 @@
import logging
import re import re
import shutil import shutil
import sys import sys
@ -7,12 +6,11 @@ from typing import Any
import mangadlp.downloader as downloader import mangadlp.downloader as downloader
import mangadlp.utils as utils import mangadlp.utils as utils
# supported api's
from mangadlp.api.mangadex import Mangadex from mangadlp.api.mangadex import Mangadex
from mangadlp.logger import Logger
# prepare logger # prepare logger
log = logging.getLogger(__name__) log = Logger(__name__)
class MangaDLP: class MangaDLP:
@ -27,7 +25,6 @@ class MangaDLP:
:param forcevol: Force naming of volumes. Useful for mangas where chapters reset each volume :param forcevol: Force naming of volumes. Useful for mangas where chapters reset each volume
:param download_path: Download path. Defaults to '<script_dir>/downloads' :param download_path: Download path. Defaults to '<script_dir>/downloads'
:param download_wait: Time to wait for each picture to download in seconds :param download_wait: Time to wait for each picture to download in seconds
:param verbosity: Verbosity of the output. Uses the logging library values
:return: Nothing. Just the files :return: Nothing. Just the files
""" """
@ -42,7 +39,6 @@ class MangaDLP:
forcevol: bool = False, forcevol: bool = False,
download_path: str = "downloads", download_path: str = "downloads",
download_wait: float = 0.5, download_wait: float = 0.5,
verbosity: int = 20,
) -> None: ) -> None:
# init parameters # init parameters
self.url_uuid = url_uuid self.url_uuid = url_uuid
@ -53,7 +49,6 @@ class MangaDLP:
self.forcevol = forcevol self.forcevol = forcevol
self.download_path = download_path self.download_path = download_path
self.download_wait = download_wait self.download_wait = download_wait
self.verbosity = verbosity
# prepare everything # prepare everything
self._prepare() self._prepare()
@ -110,15 +105,14 @@ class MangaDLP:
# check url for match # check url for match
if api_mangadex.search(url_uuid) or api_mangadex2.search(url_uuid): if api_mangadex.search(url_uuid) or api_mangadex2.search(url_uuid):
return Mangadex return Mangadex
# this is only for testing multiple apis # this is only for testing multiple apis
if api_test.search(url_uuid): elif api_test.search(url_uuid):
log.critical("Not supported yet") log.critical("Not supported yet")
sys.exit(1) sys.exit(1)
# no supported api found # no supported api found
log.error(f"No supported api in link/uuid found: {url_uuid}") log.error(f"No supported api in link/uuid found: {url_uuid}")
raise ValueError sys.exit(1)
# once called per manga # once called per manga
def get_manga(self) -> None: def get_manga(self) -> None:
@ -129,7 +123,7 @@ class MangaDLP:
print_divider = "=========================================" print_divider = "========================================="
# show infos # show infos
log.info(f"{print_divider}") log.info(f"{print_divider}")
log.warning(f"Manga Name: {self.manga_title}") log.lean(f"Manga Name: {self.manga_title}")
log.info(f"Manga UUID: {self.manga_uuid}") log.info(f"Manga UUID: {self.manga_uuid}")
log.info(f"Total chapters: {len(self.manga_chapter_list)}") log.info(f"Total chapters: {len(self.manga_chapter_list)}")
@ -148,7 +142,7 @@ class MangaDLP:
) )
# show chapters to download # show chapters to download
log.warning(f"Chapters selected: {', '.join(chapters_to_download)}") log.lean(f"Chapters selected: {', '.join(chapters_to_download)}")
log.info(f"{print_divider}") log.info(f"{print_divider}")
# create manga folder # create manga folder
@ -173,15 +167,15 @@ class MangaDLP:
# done with manga # done with manga
log.info(f"{print_divider}") log.info(f"{print_divider}")
log.warning(f"Done with manga: {self.manga_title}") log.lean(f"Done with manga: {self.manga_title}")
# filter skipped list # filter skipped list
skipped_chapters = list(filter(None, skipped_chapters)) skipped_chapters = list(filter(None, skipped_chapters))
if len(skipped_chapters) >= 1: if len(skipped_chapters) >= 1:
log.warning(f"Skipped chapters: {', '.join(skipped_chapters)}") log.lean(f"Skipped chapters: {', '.join(skipped_chapters)}")
# filter error list # filter error list
error_chapters = list(filter(None, error_chapters)) error_chapters = list(filter(None, error_chapters))
if len(error_chapters) >= 1: if len(error_chapters) >= 1:
log.warning(f"Chapters with errors: {', '.join(error_chapters)}") log.lean(f"Chapters with errors: {', '.join(error_chapters)}")
log.info(f"{print_divider}\n") log.info(f"{print_divider}\n")
@ -227,7 +221,6 @@ class MangaDLP:
# check if chapter already exists # check if chapter already exists
# check for folder, if file format is an empty string # check for folder, if file format is an empty string
if chapter_archive_path.exists(): if chapter_archive_path.exists():
if self.verbosity != "lean":
log.warning(f"'{chapter_archive_path}' already exists. Skipping") log.warning(f"'{chapter_archive_path}' already exists. Skipping")
# add to skipped chapters list # add to skipped chapters list
return ( return (
@ -243,13 +236,13 @@ class MangaDLP:
chapter_path.mkdir(parents=True, exist_ok=True) chapter_path.mkdir(parents=True, exist_ok=True)
# verbose log # verbose log
log.debug(f"Chapter UUID: {chapter_infos['uuid']}") log.verbose(f"Chapter UUID: {chapter_infos['uuid']}")
log.debug(f"Filename: '{chapter_archive_path.name}'") log.verbose(f"Filename: '{chapter_archive_path.name}'")
log.debug(f"File path: '{chapter_archive_path}'") log.verbose(f"File path: '{chapter_archive_path}'")
log.debug(f"Image URLS:\n{chapter_image_urls}") log.verbose(f"Image URLS:\n{chapter_image_urls}")
# log # log
log.warning(f"Downloading: '{chapter_filename}'") log.lean(f"Downloading: '{chapter_filename}'")
# download images # download images
try: try:
@ -273,12 +266,12 @@ class MangaDLP:
else: else:
# Done with chapter # Done with chapter
log.warning(f"Successfully downloaded: '{chapter_filename}'") log.lean(f"Successfully downloaded: '{chapter_filename}'")
return {"chapter_path": chapter_path} return {"chapter_path": chapter_path}
# create an archive of the chapter if needed # create an archive of the chapter if needed
def archive_chapter(self, chapter_path: Path) -> dict: def archive_chapter(self, chapter_path: Path) -> dict:
log.warning(f"Creating archive '{chapter_path}{self.file_format}'") log.lean(f"Creating archive '{chapter_path}{self.file_format}'")
try: try:
# check if image folder is existing # check if image folder is existing
if not chapter_path.exists(): if not chapter_path.exists():

View file

@ -8,9 +8,10 @@ from typing import Union
import requests import requests
import mangadlp.utils as utils import mangadlp.utils as utils
from mangadlp.logger import Logger
# prepare logger # prepare logger
log = logging.getLogger(__name__) log = Logger(__name__)
# download images # download images
def download_chapter( def download_chapter(
@ -27,7 +28,7 @@ def download_chapter(
# show progress bar for default log level # show progress bar for default log level
if logging.root.level == logging.INFO: if logging.root.level == logging.INFO:
utils.progress_bar(image_num, total_img) utils.progress_bar(image_num, total_img)
log.debug(f"Downloading image {image_num}/{total_img}") log.verbose(f"Downloading image {image_num}/{total_img}")
counter = 1 counter = 1
while counter <= 3: while counter <= 3:

View file

@ -1,13 +1,13 @@
import argparse import argparse
import logging
import sys import sys
from pathlib import Path from pathlib import Path
import mangadlp.app as app import mangadlp.app as app
import mangadlp.logger as logger import mangadlp.logger as logger
from mangadlp.logger import Logger
# prepare logger # prepare logger
log = logging.getLogger(__name__) log = Logger(__name__)
MDLP_VERSION = "2.1.10" MDLP_VERSION = "2.1.10"
@ -34,7 +34,7 @@ def check_args(args):
# read in the list of links from a file # read in the list of links from a file
def readin_list(readlist: str) -> list: def readin_list(readlist: str) -> list:
list_file = Path(readlist) list_file = Path(readlist)
log.debug(f"Reading in list '{str(list_file)}'") log.verbose(f"Reading in list '{str(list_file)}'")
try: try:
url_str = list_file.read_text() url_str = list_file.read_text()
url_list = url_str.splitlines() url_list = url_str.splitlines()
@ -43,7 +43,7 @@ def readin_list(readlist: str) -> list:
# filter empty lines and remove them # filter empty lines and remove them
filtered_list = list(filter(len, url_list)) filtered_list = list(filter(len, url_list))
log.debug(f"Mangas from list: {filtered_list}") log.verbose(f"Mangas from list: {filtered_list}")
return filtered_list return filtered_list
@ -59,7 +59,6 @@ def call_app(args):
args.forcevol, args.forcevol,
args.path, args.path,
args.wait, args.wait,
args.verbosity,
) )
mdlp.get_manga() mdlp.get_manga()
@ -196,7 +195,16 @@ def get_args():
required=False, required=False,
help="Lean logging. Minimal log output. Defaults to false", help="Lean logging. Minimal log output. Defaults to false",
action="store_const", action="store_const",
const=30, const=25,
default=20,
)
verbosity.add_argument(
"--verbose",
dest="verbosity",
required=False,
help="Verbose logging. More log output. Defaults to false",
action="store_const",
const=15,
default=20, default=20,
) )
verbosity.add_argument( verbosity.add_argument(

View file

@ -1,6 +1,18 @@
import logging import logging
# prepare custom levels and default config of logger
def prepare_logger():
logging.basicConfig(
format="%(asctime)s | %(levelname)s: %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
level=20,
handlers=[logging.StreamHandler()],
)
logging.addLevelName(level=15, levelName="VERBOSE")
logging.addLevelName(level=25, levelName="LEAN")
# set log message format # set log message format
def format_logger(verbosity: int): def format_logger(verbosity: int):
logging.getLogger().setLevel(verbosity) logging.getLogger().setLevel(verbosity)
@ -18,3 +30,33 @@ def format_logger(verbosity: int):
datefmt="%Y-%m-%d %H:%M:%S", datefmt="%Y-%m-%d %H:%M:%S",
force=True, force=True,
) )
class Logger:
def __init__(self, name: str):
self.name = name
# create logger
self.log = logging.getLogger(self.name)
# custom log levels
def verbose(self, message: str):
self.log.log(level=15, msg=message)
def lean(self, message: str):
self.log.log(level=25, msg=message)
# default log levels
def critical(self, message: str):
self.log.critical(msg=message)
def error(self, message: str):
self.log.error(msg=message)
def warning(self, message: str):
self.log.warning(msg=message)
def info(self, message: str):
self.log.info(msg=message)
def debug(self, message: str):
self.log.debug(msg=message)

View file

@ -1,12 +1,13 @@
import logging
import re import re
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
from zipfile import ZipFile from zipfile import ZipFile
from mangadlp.logger import Logger
# prepare logger # prepare logger
log = logging.getLogger(__name__) log = Logger(__name__)
# create an archive of the chapter images # create an archive of the chapter images
def make_archive(chapter_path: Path, file_format: str) -> None: def make_archive(chapter_path: Path, file_format: str) -> None:

View file

@ -13,6 +13,7 @@ def test_check_api_mangadex():
def test_check_api_none(): def test_check_api_none():
url = "https://abc.defghjk/title/abc/def" url = "https://abc.defghjk/title/abc/def"
with pytest.raises(ValueError) as e: with pytest.raises(SystemExit) as e:
app.MangaDLP(url_uuid=url, list_chapters=True, download_wait=2) app.MangaDLP(url_uuid=url, list_chapters=True, download_wait=2)
assert e.type == ValueError assert e.type == SystemExit
assert e.value.code == 1

View file

@ -57,7 +57,6 @@ def test_chapter_list_full():
forcevol=True, forcevol=True,
download_path="tests", download_path="tests",
download_wait=2, download_wait=2,
verbosity=10,
) )
chap_list = utils.get_chapter_list("1:1,1:2,1:4-1:7,2:", mdlp.manga_chapter_list) chap_list = utils.get_chapter_list("1:1,1:2,1:4-1:7,2:", mdlp.manga_chapter_list)
assert chap_list == [ assert chap_list == [

View file

@ -33,7 +33,6 @@ def test_full_api_mangadex(wait_20s):
forcevol=False, forcevol=False,
download_path="tests", download_path="tests",
download_wait=2, download_wait=2,
verbosity=10,
) )
mdlp.get_manga() mdlp.get_manga()