Refactor Candidate class in fetchart.py to improve

validation and resizing logic
This commit is contained in:
Dr-Blank 2024-03-18 08:57:32 -04:00
parent b09806e0df
commit 66b459b8d0
No known key found for this signature in database
GPG key ID: 7452CC63F210A266

View file

@ -67,10 +67,15 @@ class Candidate:
self.match = match self.match = match
self.size = size self.size = size
def _validate(self, plugin): def _validate(self, plugin, skip_check_for=None):
"""Determine whether the candidate artwork is valid based on """Determine whether the candidate artwork is valid based on
its dimensions (width and ratio). its dimensions (width and ratio).
`skip_check_for` is a check or list of checks to skip. This is used to
avoid redundant checks when the candidate has already been
validated for a particular operation without changing
plugin configuration.
Return `CANDIDATE_BAD` if the file is unusable. Return `CANDIDATE_BAD` if the file is unusable.
Return `CANDIDATE_EXACT` if the file is usable as-is. Return `CANDIDATE_EXACT` if the file is usable as-is.
Return `CANDIDATE_DOWNSCALE` if the file must be rescaled. Return `CANDIDATE_DOWNSCALE` if the file must be rescaled.
@ -82,6 +87,11 @@ class Candidate:
if not self.path: if not self.path:
return self.CANDIDATE_BAD return self.CANDIDATE_BAD
if skip_check_for is None:
skip_check_for = []
if isinstance(skip_check_for, int):
skip_check_for = [skip_check_for]
if not ( if not (
plugin.enforce_ratio plugin.enforce_ratio
or plugin.minwidth or plugin.minwidth
@ -180,30 +190,51 @@ class Candidate:
plugin.cover_format, plugin.cover_format,
) )
if downscale: if downscale and (not self.CANDIDATE_DOWNSCALE in skip_check_for):
return self.CANDIDATE_DOWNSCALE return self.CANDIDATE_DOWNSCALE
elif downsize: if reformat and (not self.CANDIDATE_REFORMAT in skip_check_for):
return self.CANDIDATE_DOWNSIZE
elif plugin.deinterlace:
return self.CANDIDATE_DEINTERLACE
elif reformat:
return self.CANDIDATE_REFORMAT return self.CANDIDATE_REFORMAT
else: if plugin.deinterlace and (
return self.CANDIDATE_EXACT not self.CANDIDATE_DEINTERLACE in skip_check_for
):
return self.CANDIDATE_DEINTERLACE
if downsize and (not self.CANDIDATE_DOWNSIZE in skip_check_for):
return self.CANDIDATE_DOWNSIZE
return self.CANDIDATE_EXACT
def validate(self, plugin): def validate(self, plugin, skip_check_for=None):
self.check = self._validate(plugin) self.check = self._validate(plugin, skip_check_for)
return self.check return self.check
def resize(self, plugin): def resize(self, plugin):
if self.check == self.CANDIDATE_DOWNSCALE: """Resize the candidate artwork according to the plugin's
configuration until it is valid or no further resizing is
possible.
"""
# validate the candidate in case it hasn't been done yet
current_check = self.validate(plugin)
checks_performed = []
# we don't want to resize the image if it's valid or bad
while current_check not in [self.CANDIDATE_BAD, self.CANDIDATE_EXACT]:
self._resize(plugin, current_check)
checks_performed.append(current_check)
current_check = self.validate(
plugin, skip_check_for=checks_performed
)
def _resize(self, plugin, check=None):
"""Resize the candidate artwork according to the plugin's
configuration and the specified check.
"""
if check == self.CANDIDATE_DOWNSCALE:
self.path = ArtResizer.shared.resize( self.path = ArtResizer.shared.resize(
plugin.maxwidth, plugin.maxwidth,
self.path, self.path,
quality=plugin.quality, quality=plugin.quality,
max_filesize=plugin.max_filesize, max_filesize=plugin.max_filesize,
) )
elif self.check == self.CANDIDATE_DOWNSIZE: elif check == self.CANDIDATE_DOWNSIZE:
# dimensions are correct, so maxwidth is set to maximum dimension # dimensions are correct, so maxwidth is set to maximum dimension
self.path = ArtResizer.shared.resize( self.path = ArtResizer.shared.resize(
max(self.size), max(self.size),
@ -211,9 +242,9 @@ class Candidate:
quality=plugin.quality, quality=plugin.quality,
max_filesize=plugin.max_filesize, max_filesize=plugin.max_filesize,
) )
elif self.check == self.CANDIDATE_DEINTERLACE: elif check == self.CANDIDATE_DEINTERLACE:
self.path = ArtResizer.shared.deinterlace(self.path) self.path = ArtResizer.shared.deinterlace(self.path)
elif self.check == self.CANDIDATE_REFORMAT: elif check == self.CANDIDATE_REFORMAT:
self.path = ArtResizer.shared.reformat( self.path = ArtResizer.shared.reformat(
self.path, self.path,
plugin.cover_format, plugin.cover_format,