mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2025-10-09 02:12:04 +00:00
Merge pull request #1045 from oddstr13/pr-cleanup-3
Misc cleanup and refractoring
This commit is contained in:
commit
31df896497
12 changed files with 173 additions and 51 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -70,6 +70,7 @@ Thumbs.db
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
!.vscode/settings.json
|
!.vscode/settings.json
|
||||||
pyinstrument/
|
pyinstrument/
|
||||||
|
.venv/
|
||||||
|
|
||||||
# Now managed by templates
|
# Now managed by templates
|
||||||
addon.xml
|
addon.xml
|
||||||
|
|
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
"ms-vscode-remote.remote-containers",
|
"ms-vscode-remote.remote-containers",
|
||||||
"ms-python.black-formatter"
|
"ms-python.black-formatter",
|
||||||
|
"ms-python.mypy-type-checker"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ from importlib import reload
|
||||||
|
|
||||||
# Workaround for threads using datetime: _striptime is locked
|
# Workaround for threads using datetime: _striptime is locked
|
||||||
import _strptime # noqa:F401
|
import _strptime # noqa:F401
|
||||||
|
|
||||||
import xbmc
|
import xbmc
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,12 @@ from .objects import Movies, TVShows, MusicVideos, Music
|
||||||
from .database import Database, get_sync, save_sync, jellyfin_db
|
from .database import Database, get_sync, save_sync, jellyfin_db
|
||||||
from .helper import translate, settings, window, progress, dialog, LazyLogger, xmls
|
from .helper import translate, settings, window, progress, dialog, LazyLogger, xmls
|
||||||
from .helper.utils import get_screensaver, set_screensaver
|
from .helper.utils import get_screensaver, set_screensaver
|
||||||
from .helper.exceptions import LibraryException, PathValidationException
|
from .helper.exceptions import (
|
||||||
|
LibraryException,
|
||||||
|
LibraryExitException,
|
||||||
|
LibrarySyncLaterException,
|
||||||
|
PathValidationException,
|
||||||
|
)
|
||||||
|
|
||||||
##################################################################################################
|
##################################################################################################
|
||||||
|
|
||||||
|
@ -169,11 +174,13 @@ class FullSync(object):
|
||||||
selection = dialog("multi", translate(33120), choices)
|
selection = dialog("multi", translate(33120), choices)
|
||||||
|
|
||||||
if selection is None:
|
if selection is None:
|
||||||
raise LibraryException("LibrarySelection")
|
# TODO: Why are we handling these two differently?
|
||||||
|
# presumably one means the dialog got aborted, the other means that we just pressed ok without selecting any libraries
|
||||||
|
raise LibraryException("Library selection dialog returned None.")
|
||||||
elif not selection:
|
elif not selection:
|
||||||
LOG.info("Nothing was selected.")
|
LOG.info("Nothing was selected.")
|
||||||
|
|
||||||
raise LibraryException("SyncLibraryLater")
|
raise LibrarySyncLaterException("No libraries were selected, sync later.")
|
||||||
|
|
||||||
if 0 in selection:
|
if 0 in selection:
|
||||||
selection = list(range(1, len(libraries) + 1))
|
selection = list(range(1, len(libraries) + 1))
|
||||||
|
@ -275,11 +282,13 @@ class FullSync(object):
|
||||||
|
|
||||||
media[library["CollectionType"]](library)
|
media[library["CollectionType"]](library)
|
||||||
except LibraryException as error:
|
except LibraryException as error:
|
||||||
|
# TODO: Fixme; We're catching all LibraryException here,
|
||||||
if error.status == "StopCalled":
|
# but silently ignoring any that isn't the exit condition.
|
||||||
|
# Investigate what would be appropriate behavior here.
|
||||||
|
if isinstance(error, LibraryExitException):
|
||||||
save_sync(self.sync)
|
save_sync(self.sync)
|
||||||
|
|
||||||
raise
|
raise
|
||||||
|
LOG.warning("Ignoring exception %s", error)
|
||||||
|
|
||||||
except PathValidationException:
|
except PathValidationException:
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
##################################################################################################
|
##################################################################################################
|
||||||
|
|
||||||
from . import settings, LazyLogger
|
from . import settings, LazyLogger
|
||||||
from .utils import translate_path
|
from .utils import translate_path
|
||||||
import json
|
|
||||||
|
|
||||||
##################################################################################################
|
##################################################################################################
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,15 @@ class HTTPException(Exception):
|
||||||
|
|
||||||
|
|
||||||
class LibraryException(Exception):
|
class LibraryException(Exception):
|
||||||
# Jellyfin library sync exception
|
pass
|
||||||
def __init__(self, status):
|
|
||||||
self.status = status
|
|
||||||
|
class LibraryExitException(LibraryException):
|
||||||
|
"Exception raised to propagate application exit."
|
||||||
|
|
||||||
|
|
||||||
|
class LibrarySyncLaterException(LibraryException):
|
||||||
|
"Raised when no libraries are selected for sync."
|
||||||
|
|
||||||
|
|
||||||
class PathValidationException(Exception):
|
class PathValidationException(Exception):
|
||||||
|
@ -30,5 +36,3 @@ class PathValidationException(Exception):
|
||||||
|
|
||||||
TODO: Investigate the usage of this to see if it can be done better.
|
TODO: Investigate the usage of this to see if it can be done better.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
|
||||||
class LazyLogger(object):
|
class LazyLogger(object):
|
||||||
"""`helper.loghandler.getLogger()` is used everywhere.
|
"""
|
||||||
|
`helper.loghandler.getLogger()` is used everywhere.
|
||||||
This class helps to avoid import errors.
|
This class helps to avoid import errors.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -19,3 +22,88 @@ class LazyLogger(object):
|
||||||
|
|
||||||
self.__logger = getLogger(self.__logger_name)
|
self.__logger = getLogger(self.__logger_name)
|
||||||
return getattr(self.__logger, name)
|
return getattr(self.__logger, name)
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# Following are stubs of methods provided by `logging.Logger`. #
|
||||||
|
# Please ensure any actually functional code is above this comment. #
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
|
||||||
|
def setLevel(self, level):
|
||||||
|
"""
|
||||||
|
Set the logging level of this logger. level must be an int or a str.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def debug(self, msg, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Log 'msg % args' with severity 'DEBUG'.
|
||||||
|
|
||||||
|
To pass exception information, use the keyword argument exc_info with
|
||||||
|
a true value, e.g.
|
||||||
|
|
||||||
|
logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def info(self, msg, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Log 'msg % args' with severity 'INFO'.
|
||||||
|
|
||||||
|
To pass exception information, use the keyword argument exc_info with
|
||||||
|
a true value, e.g.
|
||||||
|
|
||||||
|
logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def warning(self, msg, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Log 'msg % args' with severity 'WARNING'.
|
||||||
|
|
||||||
|
To pass exception information, use the keyword argument exc_info with
|
||||||
|
a true value, e.g.
|
||||||
|
|
||||||
|
logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def error(self, msg, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Log 'msg % args' with severity 'ERROR'.
|
||||||
|
|
||||||
|
To pass exception information, use the keyword argument exc_info with
|
||||||
|
a true value, e.g.
|
||||||
|
|
||||||
|
logger.error("Houston, we have a %s", "major problem", exc_info=1)
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def exception(self, msg, *args, exc_info=True, **kwargs):
|
||||||
|
"""
|
||||||
|
Convenience method for logging an ERROR with exception information.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def critical(self, msg, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Log 'msg % args' with severity 'CRITICAL'.
|
||||||
|
|
||||||
|
To pass exception information, use the keyword argument exc_info with
|
||||||
|
a true value, e.g.
|
||||||
|
|
||||||
|
logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def log(self, level, msg, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Log 'msg % args' with the integer severity 'level'.
|
||||||
|
|
||||||
|
To pass exception information, use the keyword argument exc_info with
|
||||||
|
a true value, e.g.
|
||||||
|
|
||||||
|
logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
|
@ -162,18 +162,6 @@ def dialog(dialog_type, *args, **kwargs):
|
||||||
return types[dialog_type](*args, **kwargs)
|
return types[dialog_type](*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def should_stop():
|
|
||||||
"""Checkpoint during the sync process."""
|
|
||||||
if xbmc.Monitor().waitForAbort(0.00001):
|
|
||||||
return True
|
|
||||||
|
|
||||||
if window("jellyfin_should_stop.bool"):
|
|
||||||
LOG.info("exiiiiitttinggg")
|
|
||||||
return True
|
|
||||||
|
|
||||||
return not window("jellyfin_online.bool")
|
|
||||||
|
|
||||||
|
|
||||||
def get_screensaver():
|
def get_screensaver():
|
||||||
"""Get the current screensaver value."""
|
"""Get the current screensaver value."""
|
||||||
result = JSONRPC("Settings.getSettingValue").execute(
|
result = JSONRPC("Settings.getSettingValue").execute(
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||||
|
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
|
import xbmc
|
||||||
|
|
||||||
from . import LazyLogger
|
from . import LazyLogger
|
||||||
|
|
||||||
from .utils import should_stop
|
from .utils import window
|
||||||
from .exceptions import LibraryException
|
from .exceptions import LibraryExitException
|
||||||
from .translate import translate
|
from .translate import translate
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
@ -22,6 +25,7 @@ def progress(message=None):
|
||||||
"""Will start and close the progress dialog."""
|
"""Will start and close the progress dialog."""
|
||||||
|
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
|
@wraps(func)
|
||||||
def wrapper(self, item=None, *args, **kwargs):
|
def wrapper(self, item=None, *args, **kwargs):
|
||||||
|
|
||||||
dialog = xbmcgui.DialogProgressBG()
|
dialog = xbmcgui.DialogProgressBG()
|
||||||
|
@ -53,16 +57,18 @@ def progress(message=None):
|
||||||
def stop(func):
|
def stop(func):
|
||||||
"""Wrapper to catch exceptions and return using catch"""
|
"""Wrapper to catch exceptions and return using catch"""
|
||||||
|
|
||||||
|
@wraps(func)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
|
|
||||||
try:
|
if xbmc.Monitor().waitForAbort(0.00001):
|
||||||
if should_stop(): # ??? TODO: Fixme
|
raise LibraryExitException("Kodi aborted, exiting...")
|
||||||
raise Exception
|
|
||||||
|
|
||||||
except Exception as error:
|
if window("jellyfin_should_stop.bool"):
|
||||||
LOG.exception(error)
|
LOG.info("exiiiiitttinggg")
|
||||||
|
raise LibraryExitException("Should stop flag raised, exiting...")
|
||||||
|
|
||||||
raise LibraryException("StopCalled")
|
if not window("jellyfin_online.bool"):
|
||||||
|
raise LibraryExitException("Jellyfin not online, exiting...")
|
||||||
|
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
|
@ -72,6 +78,7 @@ def stop(func):
|
||||||
def jellyfin_item(func):
|
def jellyfin_item(func):
|
||||||
"""Wrapper to retrieve the jellyfin_db item."""
|
"""Wrapper to retrieve the jellyfin_db item."""
|
||||||
|
|
||||||
|
@wraps(func)
|
||||||
def wrapper(self, item, *args, **kwargs):
|
def wrapper(self, item, *args, **kwargs):
|
||||||
e_item = self.jellyfin_db.get_item_by_id(
|
e_item = self.jellyfin_db.get_item_by_id(
|
||||||
item["Id"] if isinstance(item, dict) else item
|
item["Id"] if isinstance(item, dict) else item
|
||||||
|
|
|
@ -19,7 +19,11 @@ from .views import Views
|
||||||
from .downloader import GetItemWorker
|
from .downloader import GetItemWorker
|
||||||
from .helper import translate, api, stop, settings, window, dialog, event, LazyLogger
|
from .helper import translate, api, stop, settings, window, dialog, event, LazyLogger
|
||||||
from .helper.utils import split_list, set_screensaver, get_screensaver
|
from .helper.utils import split_list, set_screensaver, get_screensaver
|
||||||
from .helper.exceptions import LibraryException
|
from .helper.exceptions import (
|
||||||
|
LibraryException,
|
||||||
|
LibraryExitException,
|
||||||
|
LibrarySyncLaterException,
|
||||||
|
)
|
||||||
from .jellyfin import Jellyfin
|
from .jellyfin import Jellyfin
|
||||||
|
|
||||||
##################################################################################################
|
##################################################################################################
|
||||||
|
@ -93,7 +97,8 @@ class Library(threading.Thread):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.service()
|
self.service()
|
||||||
except LibraryException:
|
except LibraryException as error:
|
||||||
|
LOG.warning(error)
|
||||||
break
|
break
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
LOG.exception(error)
|
LOG.exception(error)
|
||||||
|
@ -438,11 +443,9 @@ class Library(threading.Thread):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except LibraryException as error:
|
|
||||||
LOG.error(error.status)
|
|
||||||
|
|
||||||
if error.status in "SyncLibraryLater":
|
|
||||||
|
|
||||||
|
except LibrarySyncLaterException as error:
|
||||||
|
LOG.error(error)
|
||||||
dialog("ok", "{jellyfin}", translate(33129))
|
dialog("ok", "{jellyfin}", translate(33129))
|
||||||
settings("SyncInstallRunDone.bool", True)
|
settings("SyncInstallRunDone.bool", True)
|
||||||
sync = get_sync()
|
sync = get_sync()
|
||||||
|
@ -451,6 +454,9 @@ class Library(threading.Thread):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
except LibraryException as error:
|
||||||
|
LOG.error(error)
|
||||||
|
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
LOG.exception(error)
|
LOG.exception(error)
|
||||||
|
|
||||||
|
@ -758,8 +764,12 @@ class UpdateWorker(threading.Thread):
|
||||||
(item["Type"], api.API(item).get_naming())
|
(item["Type"], api.API(item).get_naming())
|
||||||
)
|
)
|
||||||
except LibraryException as error:
|
except LibraryException as error:
|
||||||
if error.status == "StopCalled":
|
# TODO: Fixme; We're catching all LibraryException here,
|
||||||
|
# but silently ignoring any that isn't the exit condition.
|
||||||
|
# Investigate what would be appropriate behavior here.
|
||||||
|
if isinstance(error, LibraryExitException):
|
||||||
break
|
break
|
||||||
|
LOG.warning("Ignoring exception %s", error)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
LOG.exception(error)
|
LOG.exception(error)
|
||||||
|
|
||||||
|
@ -823,8 +833,12 @@ class UserDataWorker(threading.Thread):
|
||||||
elif item["Type"] == "Audio":
|
elif item["Type"] == "Audio":
|
||||||
music.userdata(item)
|
music.userdata(item)
|
||||||
except LibraryException as error:
|
except LibraryException as error:
|
||||||
if error.status == "StopCalled":
|
# TODO: Fixme; We're catching all LibraryException here,
|
||||||
|
# but silently ignoring any that isn't the exit condition.
|
||||||
|
# Investigate what would be appropriate behavior here.
|
||||||
|
if isinstance(error, LibraryExitException):
|
||||||
break
|
break
|
||||||
|
LOG.warning("Ignoring exception %s", error)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
LOG.exception(error)
|
LOG.exception(error)
|
||||||
|
|
||||||
|
@ -943,8 +957,12 @@ class RemovedWorker(threading.Thread):
|
||||||
try:
|
try:
|
||||||
obj(item["Id"])
|
obj(item["Id"])
|
||||||
except LibraryException as error:
|
except LibraryException as error:
|
||||||
if error.status == "StopCalled":
|
# TODO: Fixme; We're catching all LibraryException here,
|
||||||
|
# but silently ignoring any that isn't the exit condition.
|
||||||
|
# Investigate what would be appropriate behavior here.
|
||||||
|
if isinstance(error, LibraryExitException):
|
||||||
break
|
break
|
||||||
|
LOG.warning("Ignoring exception %s", error)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
LOG.exception(error)
|
LOG.exception(error)
|
||||||
finally:
|
finally:
|
||||||
|
|
4
mypy.ini
Normal file
4
mypy.ini
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[mypy]
|
||||||
|
check_untyped_defs = True
|
||||||
|
warn_unused_configs = True
|
||||||
|
files = .
|
2
tox.ini
2
tox.ini
|
@ -1,7 +1,7 @@
|
||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 9999
|
max-line-length = 9999
|
||||||
import-order-style = pep8
|
import-order-style = pep8
|
||||||
exclude = .git,.vscode
|
exclude = .git,.vscode,.venv
|
||||||
extend-ignore =
|
extend-ignore =
|
||||||
I202
|
I202
|
||||||
E203
|
E203
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue