Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: root dir index errors in mass add table and api, as well as refa… #8726

Merged
merged 4 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 5 additions & 5 deletions sickchill/gui/slick/views/displayShow.mako
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<%inherit file="/layouts/main.mako" />
<%!
import datetime
from urllib.parse import quote
from urllib.parse import quote, urljoin
from sickchill import settings
from sickchill.oldbeard import subtitles, notifiers, scdatetime, network_timezones, helpers

Expand Down Expand Up @@ -548,10 +548,10 @@
% if settings.DOWNLOAD_URL and epResult['location']:
<%
filename = epResult['location']
for rootDir in settings.ROOT_DIRS.split('|'):
if rootDir.startswith('/'):
filename = filename.replace(rootDir, "")
filename = settings.DOWNLOAD_URL + quote(filename)
for rootDir in settings.ROOT_DIRS.split('|')[1:]:
if filename.startswith(rootDir):
filename = filename.replace(rootDir, "").lstrip("/\\")
filename = urljoin(settings.DOWNLOAD_URL, quote(filename))
Comment on lines +551 to +554
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for adjusting file paths for downloads using urljoin and quote from urllib.parse is correctly implemented. However, consider adding a comment explaining the purpose of this block, especially the logic for stripping the root directory from the filename and constructing the download URL. This will enhance maintainability and readability for future contributors.

Additionally, ensure that settings.ROOT_DIRS.split('|')[1:] correctly handles all expected cases, including potential edge cases where settings.ROOT_DIRS might not be formatted as expected or could be empty.

+ # Adjust file paths for downloads by stripping the root directory and constructing the download URL
  for rootDir in settings.ROOT_DIRS.split('|')[1:]:
      if filename.startswith(rootDir):
          filename = filename.replace(rootDir, "").lstrip("/\\")
  filename = urljoin(settings.DOWNLOAD_URL, quote(filename))

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
for rootDir in settings.ROOT_DIRS.split('|')[1:]:
if filename.startswith(rootDir):
filename = filename.replace(rootDir, "").lstrip("/\\")
filename = urljoin(settings.DOWNLOAD_URL, quote(filename))
# Adjust file paths for downloads by stripping the root directory and constructing the download URL
for rootDir in settings.ROOT_DIRS.split('|')[1:]:
if filename.startswith(rootDir):
filename = filename.replace(rootDir, "").lstrip("/\\")
filename = urljoin(settings.DOWNLOAD_URL, quote(filename))

%>
<a href="${filename}">${_('Download')}</a>
% endif
Expand Down
101 changes: 101 additions & 0 deletions sickchill/helper/rootdirs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
from pathlib import Path
from typing import Union

from sickchill import logger, settings


class RootDirectories:
def __init__(self, root_directories_string: str = "", root_directories_list: Union[list, None] = None) -> None:
self.default_root_index: Union[int, None] = None
self.root_directories: list = []

self.parse(root_directories_string or settings.ROOT_DIRS, root_directories_list)
logger.debug(f"parsed roots: {[str(directory) for directory in self]} from {settings.ROOT_DIRS}")
if self.default:
logger.debug(f"default root directory: {self[self.default]}")
else:
logger.debug(f"no default root directory set")

def parse(self, root_directories_string: str = "", root_directories_list: Union[list, None] = None) -> None:
split_setting = root_directories_list or root_directories_string.split("|")

if len(split_setting) < 2:
return

self.default_root_index = int(split_setting[0])
for root_directory in split_setting[1:]:
self.add(root_directory)

def add(self, root_directory: Union[str, Path]) -> bool:
root_directory = Path(root_directory).resolve()
if not root_directory.is_dir():
logger.debug(f"tried to add a non-existent root directory: {root_directory}")
return False

if root_directory in self.root_directories:
logger.debug(f"tried to add a root directory that is already added: {root_directory}")
return False

logger.debug(f"adding root directory {root_directory}")
self.root_directories.append(root_directory)

self.__check_default_index()

return True

def delete(self, root_directory: Union[str, Path]) -> bool:
root_directory = Path(root_directory)
if root_directory in self.root_directories:
self.root_directories.remove(root_directory)
self.__check_default_index()
return True
return False

@property
def default(self) -> int:
return self.default_root_index

@default.setter
def default(self, value: Union[int, str]) -> None:
value = int(value)
self.default_root_index = value
self.__check_default_index()

def info(self) -> list:
output = []
for root_dir in self:
output.append({"valid": root_dir.is_dir(), "location": str(root_dir), "default": int(root_dir is self[self.default])})

return output or {}

def __check_default_index(self):
if not self.root_directories:
self.default_root_index = None
return

if not self.default_root_index or self.default_root_index > len(self.root_directories):
self.default_root_index = 1

def __str__(self) -> str:
return "|".join(f"{item}" for item in [self.default_root_index] + self.root_directories)

def __getitem__(self, item: int) -> Path:
return self.root_directories[item - 1]

def __setitem__(self, index: int, value: Path):
self.root_directories[index - 1] = value
self.__check_default_index()

def __delitem__(self, key):
self.root_directories.pop(key - 1)
self.__check_default_index()

def __contains__(self, item):
return item in self.root_directories

def __iter__(self):
for item in self.root_directories:
yield item

def __len__(self):
return len(self.root_directories)
Comment on lines +7 to +101
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RootDirectories class implementation is generally well-structured and makes good use of pathlib.Path for path manipulation. However, there are several areas where improvements can be made for clarity, efficiency, and robustness:

  1. Error Handling in add Method: The method logs a debug message when trying to add a non-existent directory but does not raise an exception. Consider raising an exception or returning a more explicit error to the caller to handle this case more robustly.
  2. Default Root Directory Index Handling: The logic for setting and checking the default root directory index (default_root_index) could be simplified or documented more clearly. The use of 1 as a default index in __check_default_index (line 77) is not immediately intuitive since Python lists are zero-indexed.
  3. Return Value of info Method: The info method returns an empty dictionary ({}) if there are no root directories (line 69). This is inconsistent with the expected return type of a list. Consider returning an empty list ([]) for consistency.
  4. Magic Numbers: The use of magic numbers, such as the default root index 1 in __check_default_index, could be replaced with named constants for clarity.
  5. Efficiency in __str__ Method: The __str__ method constructs the string representation by iterating over self.root_directories and converting each Path object to a string. This is efficient, but ensure that this method's performance is acceptable for the expected size of self.root_directories.

Overall, the class provides a solid foundation for managing root directories, but addressing these points could enhance its clarity, robustness, and maintainability.

5 changes: 4 additions & 1 deletion sickchill/oldbeard/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os.path
import platform
import re
from pathlib import Path
from urllib import parse

import rarfile
Expand Down Expand Up @@ -300,7 +301,9 @@ def change_unpack_dir(unpack_dir):
return True

if os.path.normpath(settings.UNPACK_DIR) != os.path.normpath(unpack_dir):
if bool(settings.ROOT_DIRS) and any(helpers.is_subdirectory(unpack_dir, rd) for rd in settings.ROOT_DIRS.split("|")[1:]):
if settings.ROOT_DIRS and any(
Path(root_directory).resolve() in Path(unpack_dir).resolve().parents for root_directory in settings.ROOT_DIRS.split("|")[1:]
):
Comment on lines +304 to +306
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of pathlib.Path for checking if the unpack_dir is a sub-directory of any TV root directory is a significant improvement in path handling. However, there's a potential performance consideration when settings.ROOT_DIRS contains a large number of directories, as this will perform resolve() and parents checks for each root directory. While this is typically not a concern for most use cases, it's something to be aware of in environments with extensive directory structures.

Consider caching the resolved paths of settings.ROOT_DIRS if this operation is performed frequently, to minimize the performance impact.

# don't change if it's in any of the TV root directories
logger.info("Unable to change unpack directory to a sub-directory of a TV root dir")
return False
Expand Down
25 changes: 0 additions & 25 deletions sickchill/oldbeard/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -950,31 +950,6 @@ def has_hidden_attribute(filepath):
return False


def real_path(path):
"""
Returns:
the canonicalized absolute pathname. The resulting path will have no symbolic link, '/./' or '/../' components.
"""
return os.path.normpath(os.path.normcase(os.path.realpath(path)))


def is_subdirectory(subdir_path, topdir_path):
"""
Returns true if a subdir_path is a subdirectory of topdir_path
else otherwise.

Parameters:
subdir_path: The full path to the subdirectory
topdir_path: The full path to the top directory to check subdir_path against
"""
topdir_path = real_path(topdir_path)
subdir_path = real_path(subdir_path)

# checks if the common prefix of both is equal to directory
# e.g. /a/b/c/d.rst and directory is /a/b, the common prefix is /a/b
return os.path.commonprefix([subdir_path, topdir_path]) == topdir_path


def set_up_anidb_connection():
"""Connect to anidb"""

Comment on lines 950 to 955
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 NOTE
This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [1-1]

The file imports a significant number of modules, which is expected for a utility file like helpers.py. However, it's important to ensure that all imported modules are used within the file to avoid unnecessary imports that can lead to increased memory usage and slower startup times.

Consider reviewing the imports to ensure all are necessary and remove any that are unused.


📝 NOTE
This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [1-1]

The function make_dirs and its Windows-specific handling suggest an attempt to address platform-specific directory creation issues. However, the use of os.makedirs(path) with the exist_ok=True parameter (available in Python 3.2 and later) could simplify this logic by making it unnecessary to check if the directory exists before attempting to create it.

Consider simplifying the directory creation logic by using os.makedirs(path, exist_ok=True) to avoid platform-specific checks and manual existence verification.

- if not os.path.isdir(path):
-     try:
-         os.makedirs(path)
+ try:
+     os.makedirs(path, exist_ok=True)

📝 NOTE
This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [1-1]

The use of global variables (e.g., MESSAGE_COUNTER and settings.CLIENT_WEB_URLS) for managing state within utility functions can lead to issues with thread safety and make the code harder to test and maintain.

Consider refactoring the code to reduce reliance on global state, possibly by encapsulating related functionality within classes or passing state explicitly between functions where feasible.

Expand Down
52 changes: 32 additions & 20 deletions sickchill/oldbeard/processTV.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,30 +36,31 @@ def delete_folder(folder, check_empty=True):
return: True on success, False on failure
"""

folder = Path(folder).resolve()
# check if it's a folder
if not os.path.isdir(folder):
if not folder.is_dir():
return False

# check if it isn't TV_DOWNLOAD_DIR
if settings.TV_DOWNLOAD_DIR and helpers.real_path(folder) == helpers.real_path(settings.TV_DOWNLOAD_DIR):
if settings.TV_DOWNLOAD_DIR and str(Path(folder).resolve()) == str(Path(settings.TV_DOWNLOAD_DIR).resolve()):
Copy link
Contributor

@coderabbitai coderabbitai bot Feb 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comparing paths using Path.resolve() ensures that the comparison is done using absolute paths, which is a robust way to handle path comparisons. However, converting both sides of the comparison to strings for equality check is unnecessary. Direct comparison of Path objects is supported and more efficient.

- if settings.TV_DOWNLOAD_DIR and str(Path(folder).resolve()) == str(Path(settings.TV_DOWNLOAD_DIR).resolve()):
+ if settings.TV_DOWNLOAD_DIR and Path(folder).resolve() == Path(settings.TV_DOWNLOAD_DIR).resolve():

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
if settings.TV_DOWNLOAD_DIR and str(Path(folder).resolve()) == str(Path(settings.TV_DOWNLOAD_DIR).resolve()):
if settings.TV_DOWNLOAD_DIR and Path(folder).resolve() == Path(settings.TV_DOWNLOAD_DIR).resolve():

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In pathlib, the slashes are not normalized according to the operating system until you call str

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@miigotu: Thank you for your input. Pathlib's design abstracts away the differences between operating systems, including how slashes are handled in file paths. When comparing Path objects directly, as in the suggested change, the comparison is based on the resolved, absolute paths, not their string representations. This means that the normalization of slashes, which occurs when converting a Path object to a string, does not affect the comparison of Path objects themselves. Therefore, the suggested change should work correctly across different operating systems without needing to convert Path objects to strings for the purpose of slash normalization.

return False

# check if it's empty folder when wanted to be checked
if check_empty:
check_files = os.listdir(folder)
if check_files:
logger.info(f"Not deleting folder {folder} found the following files: {check_files}")
found_files = [file for file in folder.iterdir()]
if found_files:
logger.info(f"Not deleting folder {folder} found the following files: {found_files}")
return False

try:
logger.info(f"Deleting folder (if it's empty): {folder}")
os.rmdir(folder)
folder.rmdir()
except (OSError, IOError) as error:
logger.warning(f"Warning: unable to delete folder: {folder}: {error}")
return False
else:
try:
logger.info("Deleting folder: " + folder)
logger.info(f"Deleting folder: {folder}")
shutil.rmtree(folder)
except (OSError, IOError) as error:
logger.warning(f"Warning: unable to delete folder: {folder}: {error}")
Expand All @@ -82,27 +83,28 @@ def delete_files(process_path, unwanted_files, result, force=False):
elif not result.result:
return

process_path = Path(process_path)
# Delete all file not needed
for cur_file in unwanted_files:
cur_file_path = os.path.join(process_path, cur_file)
if not os.path.isfile(cur_file_path):
for current_file in unwanted_files:
file_path = process_path / current_file
if not file_path.is_file():
continue # Prevent error when a notwantedfiles is an associated files

result.output += log_helper(f"Deleting file: {cur_file}", logger.DEBUG)
result.output += log_helper(f"Deleting file: {current_file}", logger.DEBUG)

# check first the read-only attribute
file_attribute = os.stat(cur_file_path)[0]
file_attribute = file_path.stat()[0]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retrieving file attributes using file_path.stat() and checking for the write permission bit is a correct approach. However, the extraction of the mode ([0]) from the result of stat() is incorrect when using pathlib. The correct way to access the mode is through the st_mode attribute.

- file_attribute = file_path.stat()[0]
+ file_attribute = file_path.stat().st_mode

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
file_attribute = file_path.stat()[0]
file_attribute = file_path.stat().st_mode

if not file_attribute & stat.S_IWRITE:
# File is read-only, so make it writeable
result.output += log_helper(f"Changing ReadOnly Flag for file: {cur_file}", logger.DEBUG)
result.output += log_helper(f"Changing ReadOnly Flag for file: {current_file}", logger.DEBUG)
try:
os.chmod(cur_file_path, stat.S_IWRITE)
file_path.chmod(stat.S_IWRITE)
except OSError as error:
result.output += log_helper(f"Cannot change permissions of {cur_file_path}: {error}", logger.DEBUG)
result.output += log_helper(f"Cannot change permissions of {current_file}: {error}", logger.DEBUG)
try:
os.remove(cur_file_path)
file_path.unlink(True)
Copy link
Contributor

@coderabbitai coderabbitai bot Feb 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of file_path.unlink(True) is incorrect. The unlink method does not take any arguments in pathlib.Path. If the intention was to force deletion, note that unlink does not have a force parameter. This line will raise a TypeError.

- file_path.unlink(True)
+ file_path.unlink()

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
file_path.unlink(True)
file_path.unlink()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The signature for unlink in pathlib.Path changed in python 3.8, adding a parameter miising_ok.

It is now Path.unlink(missing_ok: bool = False)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@miigotu: Thank you for the correction. You're right, starting with Python 3.8, the Path.unlink method includes a missing_ok parameter, allowing the method to be called with an argument to avoid raising an error if the file does not exist. My previous comment was based on outdated information. I appreciate your clarification.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In python 3.8+ pathlib.Path.unlink takes a missong_ok:bool parameter

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@miigotu: Absolutely, you're correct. The missing_ok parameter in Path.unlink for Python 3.8+ allows for more flexible file handling, especially in scenarios where the absence of a file should not raise an error. Thank you for your patience and for clarifying this important detail. Your expertise is greatly appreciated!

except OSError as error:
result.output += log_helper(f"Unable to delete file {cur_file}: {error}", logger.DEBUG)
result.output += log_helper(f"Unable to delete file {current_file}: {error}", logger.DEBUG)


def log_helper(message, level=logging.INFO):
Expand Down Expand Up @@ -132,13 +134,17 @@ def process_dir(process_path, release_name=None, process_method=None, force=Fals

# if the client and SickChill are not on the same machine translate the directory into a network directory
elif all(
[settings.TV_DOWNLOAD_DIR, os.path.isdir(settings.TV_DOWNLOAD_DIR), os.path.normpath(process_path) == os.path.normpath(settings.TV_DOWNLOAD_DIR)]
[
settings.TV_DOWNLOAD_DIR,
Path(settings.TV_DOWNLOAD_DIR).is_dir(),
str(Path(process_path).resolve()) == str(Path(settings.TV_DOWNLOAD_DIR).resolve()),
]
Comment on lines +137 to +141
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic to check if the client and SickChill are on the same machine and to translate the directory into a network directory is thoughtful. However, the conversion of process_path to a Path object and then back to a string using os.path.join is inconsistent. Since the codebase is being refactored to use pathlib, consider using pathlib operations throughout for consistency.

- process_path = os.path.join(settings.TV_DOWNLOAD_DIR, os.path.abspath(process_path).split(os.path.sep)[-1])
+ process_path = Path(settings.TV_DOWNLOAD_DIR) / Path(process_path).name

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
[
settings.TV_DOWNLOAD_DIR,
Path(settings.TV_DOWNLOAD_DIR).is_dir(),
str(Path(process_path).resolve()) == str(Path(settings.TV_DOWNLOAD_DIR).resolve()),
]
[
settings.TV_DOWNLOAD_DIR,
Path(settings.TV_DOWNLOAD_DIR).is_dir(),
str(Path(process_path).resolve()) == str(Path(settings.TV_DOWNLOAD_DIR).resolve()),
]

):
process_path = os.path.join(settings.TV_DOWNLOAD_DIR, os.path.abspath(process_path).split(os.path.sep)[-1])
result.output += log_helper(f"Trying to use folder: {process_path} ", logger.DEBUG)

# if we didn't find a real dir then quit
if not os.path.isdir(process_path):
if not Path(process_path).is_dir():
result.output += log_helper(
"Unable to figure out what folder to process. "
"If your downloader and SickChill aren't on the same PC "
Expand All @@ -162,6 +168,8 @@ def process_dir(process_path, release_name=None, process_method=None, force=Fals
result.output += log_helper(_("Processing {process_path}").format(process_path=process_path))
generator_to_use = os.walk(process_path, followlinks=settings.PROCESSOR_FOLLOW_SYMLINKS)

rar_files = []

for current_directory, directory_names, filenames in generator_to_use:
result.result = True

Expand Down Expand Up @@ -273,7 +281,11 @@ def validate_dir(process_path, release_name, failed, result):
result.missed_files.append(f"{process_path} : Failed download")
return False

if settings.TV_DOWNLOAD_DIR and helpers.real_path(process_path) != helpers.real_path(settings.TV_DOWNLOAD_DIR) and helpers.is_hidden_folder(process_path):
if (
settings.TV_DOWNLOAD_DIR
and str(Path(process_path).resolve()) != str(Path(settings.TV_DOWNLOAD_DIR).resolve())
and helpers.is_hidden_folder(process_path)
):
result.output += log_helper(f"Ignoring hidden folder: {process_path}", logger.DEBUG)
if not process_path.endswith("@eaDir"):
result.missed_files.append(f"{process_path} : Hidden folder")
Expand Down
2 changes: 1 addition & 1 deletion sickchill/oldbeard/traktChecker.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ def _add_show_with_defaults(indexer, indexer_id, name, status):
root_dirs = settings.ROOT_DIRS.split("|")

try:
location = root_dirs[int(root_dirs[0]) + 1]
location = root_dirs[int(root_dirs[0])]
except Exception:
location = None

Expand Down
4 changes: 3 additions & 1 deletion sickchill/show/indexers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Union

from .handler import ShowIndexer

indexer = None
indexer: Union[ShowIndexer, None] = None
2 changes: 1 addition & 1 deletion sickchill/show_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from sickchill import logger, settings
from sickchill.helper.exceptions import CantRefreshShowException, CantUpdateShowException
from sickchill.oldbeard import db, network_timezones, ui
from sickchill.show import Show
from sickchill.show.Show import Show


class ShowUpdater(object):
Expand Down
2 changes: 1 addition & 1 deletion sickchill/start.py
Original file line number Diff line number Diff line change
Expand Up @@ -1236,7 +1236,7 @@ def save_config():
"metadata_mede8er": settings.METADATA_MEDE8ER,
"backlog_days": int(settings.BACKLOG_DAYS),
"backlog_missing_only": int(settings.BACKLOG_MISSING_ONLY),
"root_dirs": settings.ROOT_DIRS if settings.ROOT_DIRS else "",
"root_dirs": settings.ROOT_DIRS or "",
"tv_download_dir": settings.TV_DOWNLOAD_DIR,
"keep_processed_dir": int(settings.KEEP_PROCESSED_DIR),
"process_method": settings.PROCESS_METHOD,
Expand Down
10 changes: 9 additions & 1 deletion sickchill/tv.py
Original file line number Diff line number Diff line change
Expand Up @@ -880,7 +880,11 @@ def load_imdb_info(self):

if not self.imdb_id:
# TODO: Load tvmaze/tvdb info into other imdb_info fields
self.imdb_id = helpers.imdb_from_tvdbid_on_tvmaze(self.indexerid)
# noinspection PyBroadException
try:
self.imdb_id = helpers.imdb_from_tvdbid_on_tvmaze(self.indexerid)
except Exception:
self.imdb_id = None

try:
client = Cinemagoer()
Expand Down Expand Up @@ -941,6 +945,8 @@ def load_imdb_info(self):

logger.debug(f"{self.indexerid}: Loading show info from IMDb")
imdb_title: dict = client.get_movie(self.imdb_id.strip("t"))
if not imdb_title:
return

self.imdb_info = {
"indexer_id": self.indexerid,
Expand All @@ -959,6 +965,8 @@ def load_imdb_info(self):
}

logger.debug(f"{self.indexerid}: Obtained info from IMDb ->{self.imdb_info}")
except KeyError:
logger.info(f"Could not get IMDB info for {self.name}")
except (
TypeError,
ValueError,
Expand Down