mirror of
https://github.com/SickGear/SickGear.git
synced 2024-11-24 05:45:05 +00:00
Change allow Python 3.12.5
Fix person ids fetching Fix wrong added death dates (by allowing overwriting deathday with None if birthday is on source) Fix parsing changes to IMDb bio Update test data - Change improve efficiency when saving config.ini Change prevent saving unchanged config.ini Change add flushing to config.ini file saving (configobj hack) Change add ConfigEvents queue for saving the config ini more efficiently Change catch other errors for saving config - Change improve efficiency when saving viewshow glide Change don't call '/home/set-display-show-glide' in the first place if there is no reason (params) to do so Change add sanity check for set_display_show_glide, only save changed values
This commit is contained in:
parent
80cffd7cef
commit
0c0e25e73c
34 changed files with 126 additions and 16 deletions
|
@ -1,6 +1,11 @@
|
||||||
### 3.32.4 (2024-06-2x xx:xx:00 UTC)
|
### 3.32.4 (2024-08-10 11:40:00 UTC)
|
||||||
|
|
||||||
* Change person cards to not display "eps" when number of eps is unknown
|
* Change person cards to not display "eps" when number of eps is unknown
|
||||||
|
* Fix wrong added death dates
|
||||||
|
* Fix parsing changes to IMDb bio
|
||||||
|
* Change improve efficiency when saving config.ini
|
||||||
|
* Change improve efficiency when saving viewshow glide
|
||||||
|
* Change allow Python 3.12.5
|
||||||
|
|
||||||
|
|
||||||
### 3.32.3 (2024-06-26 18:10:00 UTC)
|
### 3.32.3 (2024-06-26 18:10:00 UTC)
|
||||||
|
|
|
@ -4,6 +4,7 @@ Libs with customisations...
|
||||||
/lib/backports/configparser
|
/lib/backports/configparser
|
||||||
/lib/browser_ua
|
/lib/browser_ua
|
||||||
/lib/bs4
|
/lib/bs4
|
||||||
|
/lib/configobj/__init__.py
|
||||||
/lib/dateutil/zoneinfo/__init__.py
|
/lib/dateutil/zoneinfo/__init__.py
|
||||||
/lib/dateutil/tz/tz.py
|
/lib/dateutil/tz/tz.py
|
||||||
/lib/enzyme
|
/lib/enzyme
|
||||||
|
|
|
@ -245,9 +245,11 @@ $(document).ready(function() {
|
||||||
if (saveTime){
|
if (saveTime){
|
||||||
params.slidetime = $.SickGear.config.glideSlideTime;
|
params.slidetime = $.SickGear.config.glideSlideTime;
|
||||||
}
|
}
|
||||||
|
if (!$.isEmptyObject(params)){
|
||||||
$.get($.SickGear.Root + '/home/set-display-show-glide', params);
|
$.get($.SickGear.Root + '/home/set-display-show-glide', params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var ivTimes = [10000, 6000, 3000];
|
var ivTimes = [10000, 6000, 3000];
|
||||||
function pinState(el$){
|
function pinState(el$){
|
||||||
|
|
|
@ -219,7 +219,7 @@ class IMDbIndexer(TVInfoBase):
|
||||||
if not bio:
|
if not bio:
|
||||||
return
|
return
|
||||||
with BS4Parser(bio) as bio_item:
|
with BS4Parser(bio) as bio_item:
|
||||||
bv = bio_item.find(string='Mini Bio', recursive=True).find_next('p')
|
bv = bio_item.find('div', attrs={'data-testid': re.compile('mini_bio$')}, recursive=True)
|
||||||
for a in bv.findAll('a'):
|
for a in bv.findAll('a'):
|
||||||
a.replaceWithChildren()
|
a.replaceWithChildren()
|
||||||
for b in bv.findAll('br'):
|
for b in bv.findAll('br'):
|
||||||
|
|
|
@ -2097,6 +2097,7 @@ class ConfigObj(Section):
|
||||||
else:
|
else:
|
||||||
with open(self.filename, 'wb') as h:
|
with open(self.filename, 'wb') as h:
|
||||||
h.write(output_bytes)
|
h.write(output_bytes)
|
||||||
|
h.flush()
|
||||||
|
|
||||||
def validate(self, validator, preserve_errors=False, copy=False,
|
def validate(self, validator, preserve_errors=False, copy=False,
|
||||||
section=None):
|
section=None):
|
||||||
|
|
|
@ -38,7 +38,7 @@ warnings.filterwarnings('ignore', message='.*deprecated in cryptography.*')
|
||||||
|
|
||||||
versions = [((3, 8, 2), (3, 8, 19)),
|
versions = [((3, 8, 2), (3, 8, 19)),
|
||||||
((3, 9, 0), (3, 9, 2)), ((3, 9, 4), (3, 9, 19)),
|
((3, 9, 0), (3, 9, 2)), ((3, 9, 4), (3, 9, 19)),
|
||||||
((3, 10, 0), (3, 12, 4))] # inclusive version ranges
|
((3, 10, 0), (3, 12, 5))] # inclusive version ranges
|
||||||
if not any(list(map(lambda v: v[0] <= sys.version_info[:3] <= v[1], versions))) and not int(os.environ.get('PYT', 0)):
|
if not any(list(map(lambda v: v[0] <= sys.version_info[:3] <= v[1], versions))) and not int(os.environ.get('PYT', 0)):
|
||||||
major, minor, micro = sys.version_info[:3]
|
major, minor, micro = sys.version_info[:3]
|
||||||
print('Python %s.%s.%s detected.' % (major, minor, micro))
|
print('Python %s.%s.%s detected.' % (major, minor, micro))
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
|
|
||||||
|
import copy
|
||||||
import datetime
|
import datetime
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
|
@ -39,6 +40,7 @@ from . import auto_media_process, properFinder # must come after the above impo
|
||||||
from .common import SD, SKIPPED, USER_AGENT
|
from .common import SD, SKIPPED, USER_AGENT
|
||||||
from .config import check_section, check_setting_int, check_setting_str, ConfigMigrator, minimax
|
from .config import check_section, check_setting_int, check_setting_str, ConfigMigrator, minimax
|
||||||
from .databases import cache_db, failed_db, mainDB
|
from .databases import cache_db, failed_db, mainDB
|
||||||
|
from .event_queue import ConfigEvents
|
||||||
from .indexers.indexer_api import TVInfoAPI
|
from .indexers.indexer_api import TVInfoAPI
|
||||||
from .indexers.indexer_config import TVINFO_IMDB, TVINFO_TVDB, TmdbIndexer
|
from .indexers.indexer_config import TVINFO_IMDB, TVINFO_TVDB, TmdbIndexer
|
||||||
from .providers.generic import GenericProvider
|
from .providers.generic import GenericProvider
|
||||||
|
@ -73,6 +75,7 @@ ENV = {}
|
||||||
CFG = None # type: ConfigObj
|
CFG = None # type: ConfigObj
|
||||||
CONFIG_FILE = ''
|
CONFIG_FILE = ''
|
||||||
CONFIG_VERSION = None
|
CONFIG_VERSION = None
|
||||||
|
CONFIG_OLD = None
|
||||||
|
|
||||||
# Default encryption version (0 for None)
|
# Default encryption version (0 for None)
|
||||||
ENCRYPTION_VERSION = 0
|
ENCRYPTION_VERSION = 0
|
||||||
|
@ -86,6 +89,7 @@ DATA_DIR = ''
|
||||||
# system events
|
# system events
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
events = None # type: Events
|
events = None # type: Events
|
||||||
|
config_events = None # type: ConfigEvents
|
||||||
|
|
||||||
show_queue_scheduler = None # type: Optional[scheduler.Scheduler]
|
show_queue_scheduler = None # type: Optional[scheduler.Scheduler]
|
||||||
search_queue_scheduler = None # type: Optional[scheduler.Scheduler]
|
search_queue_scheduler = None # type: Optional[scheduler.Scheduler]
|
||||||
|
@ -667,7 +671,7 @@ def init_stage_1(console_logging):
|
||||||
WEB_HOST, WEB_ROOT, ACTUAL_CACHE_DIR, CACHE_DIR, ZONEINFO_DIR, ADD_SHOWS_WO_DIR, ADD_SHOWS_METALANG, \
|
WEB_HOST, WEB_ROOT, ACTUAL_CACHE_DIR, CACHE_DIR, ZONEINFO_DIR, ADD_SHOWS_WO_DIR, ADD_SHOWS_METALANG, \
|
||||||
CREATE_MISSING_SHOW_DIRS, SHOW_DIRS_WITH_DOTS, \
|
CREATE_MISSING_SHOW_DIRS, SHOW_DIRS_WITH_DOTS, \
|
||||||
RECENTSEARCH_STARTUP, NAMING_FORCE_FOLDERS, SOCKET_TIMEOUT, DEBUG, TVINFO_DEFAULT, \
|
RECENTSEARCH_STARTUP, NAMING_FORCE_FOLDERS, SOCKET_TIMEOUT, DEBUG, TVINFO_DEFAULT, \
|
||||||
CONFIG_FILE, CONFIG_VERSION, \
|
CONFIG_FILE, CONFIG_VERSION, CONFIG_OLD, \
|
||||||
REMOVE_FILENAME_CHARS, IMPORT_DEFAULT_CHECKED_SHOWS, WANTEDLIST_CACHE, MODULE_UPDATE_STRING, EXT_UPDATES
|
REMOVE_FILENAME_CHARS, IMPORT_DEFAULT_CHECKED_SHOWS, WANTEDLIST_CACHE, MODULE_UPDATE_STRING, EXT_UPDATES
|
||||||
# Add Show Search
|
# Add Show Search
|
||||||
global RESULTS_SORTBY
|
global RESULTS_SORTBY
|
||||||
|
@ -1537,7 +1541,7 @@ def init_stage_2():
|
||||||
search_recent_scheduler, search_subtitles_scheduler, \
|
search_recent_scheduler, search_subtitles_scheduler, \
|
||||||
search_queue_scheduler, show_queue_scheduler, people_queue_scheduler, \
|
search_queue_scheduler, show_queue_scheduler, people_queue_scheduler, \
|
||||||
watched_state_queue_scheduler, emby_watched_state_scheduler, plex_watched_state_scheduler, \
|
watched_state_queue_scheduler, emby_watched_state_scheduler, plex_watched_state_scheduler, \
|
||||||
process_media_scheduler, background_mapping_task
|
process_media_scheduler, background_mapping_task, config_events
|
||||||
|
|
||||||
# Gen Config/Misc
|
# Gen Config/Misc
|
||||||
global SHOW_UPDATE_HOUR, UPDATE_INTERVAL, UPDATE_PACKAGES_INTERVAL
|
global SHOW_UPDATE_HOUR, UPDATE_INTERVAL, UPDATE_PACKAGES_INTERVAL
|
||||||
|
@ -1728,6 +1732,9 @@ def init_stage_2():
|
||||||
except (BaseException, Exception):
|
except (BaseException, Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
config_events = ConfigEvents(_save_config)
|
||||||
|
config_events.start()
|
||||||
|
|
||||||
__INITIALIZED__ = True
|
__INITIALIZED__ = True
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -1801,7 +1808,7 @@ def sig_handler(signum=None, _=None):
|
||||||
|
|
||||||
|
|
||||||
def halt():
|
def halt():
|
||||||
global __INITIALIZED__, started
|
global __INITIALIZED__, started, config_events
|
||||||
|
|
||||||
logger.debug('Check INIT_LOCK on halt')
|
logger.debug('Check INIT_LOCK on halt')
|
||||||
with INIT_LOCK:
|
with INIT_LOCK:
|
||||||
|
@ -1811,6 +1818,11 @@ def halt():
|
||||||
|
|
||||||
logger.log('Exiting threads')
|
logger.log('Exiting threads')
|
||||||
|
|
||||||
|
try:
|
||||||
|
config_events.stopit()
|
||||||
|
except (BaseException, Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
for p in provider_ping_thread_pool:
|
for p in provider_ping_thread_pool:
|
||||||
provider_ping_thread_pool[p].stop = True
|
provider_ping_thread_pool[p].stop = True
|
||||||
|
|
||||||
|
@ -1854,6 +1866,11 @@ def halt():
|
||||||
except (BaseException, Exception) as e:
|
except (BaseException, Exception) as e:
|
||||||
logger.log('Thread %s exception %s' % (thread.name, e))
|
logger.log('Thread %s exception %s' % (thread.name, e))
|
||||||
|
|
||||||
|
try:
|
||||||
|
config_events.join(10)
|
||||||
|
except RuntimeError:
|
||||||
|
pass
|
||||||
|
|
||||||
__INITIALIZED__ = False
|
__INITIALIZED__ = False
|
||||||
started = False
|
started = False
|
||||||
|
|
||||||
|
@ -1869,10 +1886,23 @@ def save_all():
|
||||||
|
|
||||||
# save config
|
# save config
|
||||||
logger.log('Saving config file to disk')
|
logger.log('Saving config file to disk')
|
||||||
save_config()
|
_save_config(force=True)
|
||||||
|
|
||||||
|
|
||||||
def save_config():
|
def save_config(force=False):
|
||||||
|
# type: (bool) -> None
|
||||||
|
"""
|
||||||
|
add queue request for saving the config.ini
|
||||||
|
|
||||||
|
:param force: force save config even if unchanged
|
||||||
|
"""
|
||||||
|
global config_events
|
||||||
|
config_events.put(force)
|
||||||
|
|
||||||
|
|
||||||
|
def _save_config(force=False, **kwargs):
|
||||||
|
# type: (bool, ...) -> None
|
||||||
|
global CONFIG_OLD
|
||||||
new_config = ConfigObj()
|
new_config = ConfigObj()
|
||||||
new_config.filename = CONFIG_FILE
|
new_config.filename = CONFIG_FILE
|
||||||
|
|
||||||
|
@ -2425,6 +2455,9 @@ def save_config():
|
||||||
new_config['ANIME'] = {}
|
new_config['ANIME'] = {}
|
||||||
new_config['ANIME']['anime_treat_as_hdtv'] = int(ANIME_TREAT_AS_HDTV)
|
new_config['ANIME']['anime_treat_as_hdtv'] = int(ANIME_TREAT_AS_HDTV)
|
||||||
|
|
||||||
|
if not force and CONFIG_OLD == new_config and os.path.isfile(new_config.filename):
|
||||||
|
logger.debug('config.ini not dirty, not saving.')
|
||||||
|
return
|
||||||
from sg_helpers import copy_file
|
from sg_helpers import copy_file
|
||||||
backup_config = re.sub(r'\.ini$', '.bak', CONFIG_FILE)
|
backup_config = re.sub(r'\.ini$', '.bak', CONFIG_FILE)
|
||||||
from .config import check_valid_config
|
from .config import check_valid_config
|
||||||
|
@ -2440,6 +2473,7 @@ def save_config():
|
||||||
for _ in range(0, 3):
|
for _ in range(0, 3):
|
||||||
new_config.write()
|
new_config.write()
|
||||||
if check_valid_config(CONFIG_FILE):
|
if check_valid_config(CONFIG_FILE):
|
||||||
|
CONFIG_OLD = copy.deepcopy(new_config)
|
||||||
return
|
return
|
||||||
logger.warning('saving config file failed, retrying...')
|
logger.warning('saving config file failed, retrying...')
|
||||||
remove_file_perm(CONFIG_FILE)
|
remove_file_perm(CONFIG_FILE)
|
||||||
|
|
|
@ -2,6 +2,67 @@ import queue
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
|
||||||
|
class SetQueue(queue.Queue):
|
||||||
|
def _init(self, maxsize):
|
||||||
|
self.queue = set()
|
||||||
|
|
||||||
|
def _put(self, item):
|
||||||
|
self.queue.add(item)
|
||||||
|
|
||||||
|
def _get(self):
|
||||||
|
return self.queue.pop()
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigEvents(threading.Thread):
|
||||||
|
def __init__(self, callback):
|
||||||
|
super(ConfigEvents, self).__init__()
|
||||||
|
self.queue = SetQueue()
|
||||||
|
self.callback = callback
|
||||||
|
self.name = 'CONFIG-EVENTS'
|
||||||
|
self._stopper = threading.Event()
|
||||||
|
|
||||||
|
def put(self, etype):
|
||||||
|
# type: (bool) -> None
|
||||||
|
"""
|
||||||
|
put config save event into queue
|
||||||
|
|
||||||
|
:param etype: force save config.ini if unchanged
|
||||||
|
"""
|
||||||
|
self.queue.put(etype)
|
||||||
|
|
||||||
|
def stopit(self):
|
||||||
|
self._stopper.set()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
while not self._stopper.is_set():
|
||||||
|
try:
|
||||||
|
# get event type
|
||||||
|
ev_type = self.queue.get(True, 5)
|
||||||
|
except queue.Empty:
|
||||||
|
continue
|
||||||
|
except(BaseException, Exception):
|
||||||
|
continue
|
||||||
|
if ev_type in (True, False, None):
|
||||||
|
if ev_type is None:
|
||||||
|
continue
|
||||||
|
from sickgear import logger
|
||||||
|
logger.debug(f'Callback {self.callback.__name__}(event type:{ev_type})')
|
||||||
|
|
||||||
|
try:
|
||||||
|
# perform callback if we got an event type
|
||||||
|
self.callback(ev_type)
|
||||||
|
|
||||||
|
# event completed
|
||||||
|
self.queue.task_done()
|
||||||
|
except queue.Empty:
|
||||||
|
pass
|
||||||
|
except (BaseException, Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# exiting thread
|
||||||
|
self._stopper.clear()
|
||||||
|
|
||||||
|
|
||||||
class Event(object):
|
class Event(object):
|
||||||
def __init__(self, etype):
|
def __init__(self, etype):
|
||||||
self._type = etype
|
self._type = etype
|
||||||
|
|
|
@ -583,7 +583,7 @@ class Person(Referential):
|
||||||
continue
|
continue
|
||||||
if cur_key not in self.__dict__:
|
if cur_key not in self.__dict__:
|
||||||
raise Exception('Person has no property [%s]' % cur_key)
|
raise Exception('Person has no property [%s]' % cur_key)
|
||||||
if None is not cur_value:
|
if None is not cur_value or ('deathday' == cur_key and kwargs.get('birthday')):
|
||||||
if 'akas' == cur_key:
|
if 'akas' == cur_key:
|
||||||
cur_value.update(self.akas)
|
cur_value.update(self.akas)
|
||||||
elif 'nicknames' == cur_key:
|
elif 'nicknames' == cur_key:
|
||||||
|
@ -768,7 +768,7 @@ class Person(Referential):
|
||||||
self._data_failure = True
|
self._data_failure = True
|
||||||
logger.warning('Error searching extra info for person: %s - %s' % (self.name, ex(e)))
|
logger.warning('Error searching extra info for person: %s - %s' % (self.name, ex(e)))
|
||||||
continue
|
continue
|
||||||
if None is not pd and imdb_confirmed and TVINFO_IMDB == cur_tv_src:
|
if None is not pd and imdb_confirmed and TVINFO_IMDB == cur_tv_info_src:
|
||||||
rp = pd
|
rp = pd
|
||||||
break
|
break
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
|
|
|
@ -1053,11 +1053,17 @@ class MainHandler(WebHandler):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def set_display_show_glide(slidetime=None, tvid_prodid=None, start_at=None):
|
def set_display_show_glide(slidetime=None, tvid_prodid=None, start_at=None):
|
||||||
|
|
||||||
if tvid_prodid and start_at:
|
dirty_config = False
|
||||||
|
if tvid_prodid and start_at and start_at != sickgear.DISPLAY_SHOW_GLIDE.get(tvid_prodid, {}).get('start_at'):
|
||||||
sickgear.DISPLAY_SHOW_GLIDE.setdefault(tvid_prodid, {}).update({'start_at': start_at})
|
sickgear.DISPLAY_SHOW_GLIDE.setdefault(tvid_prodid, {}).update({'start_at': start_at})
|
||||||
|
dirty_config = True
|
||||||
|
|
||||||
if slidetime:
|
if slidetime and (
|
||||||
sickgear.DISPLAY_SHOW_GLIDE_SLIDETIME = sg_helpers.try_int(slidetime, 3000)
|
int_slidetime := sg_helpers.try_int(slidetime, 3000)) != sickgear.DISPLAY_SHOW_GLIDE_SLIDETIME:
|
||||||
|
sickgear.DISPLAY_SHOW_GLIDE_SLIDETIME = int_slidetime
|
||||||
|
dirty_config = True
|
||||||
|
|
||||||
|
if dirty_config:
|
||||||
sickgear.save_config()
|
sickgear.save_config()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1 +1 @@
|
||||||
2024-06-25
|
2024-06-28
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue