diff --git a/SickBeard.py b/SickBeard.py
index 00d0a84d..947ed781 100755
--- a/SickBeard.py
+++ b/SickBeard.py
@@ -21,6 +21,7 @@
from __future__ import with_statement
import time
+import signal
import sys
import shutil
import subprocess
@@ -52,15 +53,15 @@ if sys.hexversion >= 0x020600F0:
import locale
import datetime
import threading
-import signal
import traceback
import getopt
import sickbeard
+from sickbeard.event_queue import Events
from sickbeard import db
from sickbeard.tv import TVShow
-from sickbeard import logger
+from sickbeard import logger, network_timezones, failed_history, name_cache
from sickbeard.webserveInit import SRWebServer
from sickbeard.version import SICKBEARD_VERSION
from sickbeard.databases.mainDB import MIN_DB_VERSION
@@ -68,14 +69,16 @@ from sickbeard.databases.mainDB import MAX_DB_VERSION
from lib.configobj import ConfigObj
+throwaway = datetime.datetime.strptime('20110101', '%Y%m%d')
+
signal.signal(signal.SIGINT, sickbeard.sig_handler)
signal.signal(signal.SIGTERM, sickbeard.sig_handler)
-throwaway = datetime.datetime.strptime('20110101', '%Y%m%d')
-
class SickRage(object):
def __init__(self):
+ sickbeard.events = Events(self.shutdown)
+
self.webserver = None
self.runAsDaemon = False
self.CREATEPID = False
@@ -313,6 +316,16 @@ class SickRage(object):
# Fire up all our threads
sickbeard.start()
+ # Build internal name cache
+ name_cache.buildNameCache()
+
+ # refresh network timezones
+ network_timezones.update_network_dict()
+
+ # sure, why not?
+ if sickbeard.USE_FAILED_DOWNLOADS:
+ failed_history.trimHistory()
+
# Start an update if we're supposed to
if self.forceUpdate or sickbeard.UPDATE_SHOWS_ON_START:
sickbeard.showUpdateScheduler.action.run(force=True) # @UndefinedVariable
@@ -320,7 +333,8 @@ class SickRage(object):
if sickbeard.LAUNCH_BROWSER and not (self.noLaunch or self.runAsDaemon):
sickbeard.launchBrowser(self.startPort)
- while(sickbeard.started):
+ # main loop
+ while(True):
time.sleep(1)
def daemonize(self):
@@ -421,56 +435,54 @@ class SickRage(object):
except:
return False
+ def shutdown(self, type):
+ if sickbeard.started:
+ # stop all tasks
+ sickbeard.halt()
+
+ # shutdown web server
+ if self.webserver:
+ self.webserver.shutDown()
+ self.webserver = None
+
+ # save all shows to DB
+ sickbeard.saveAll()
+
+ # if run as daemon delete the pidfile
+ if self.runAsDaemon and self.CREATEPID:
+ self.remove_pid_file(self.PIDFILE)
+
+ if type == sickbeard.events.SystemEvent.RESTART:
+ install_type = sickbeard.versionCheckScheduler.action.install_type
+
+ popen_list = []
+
+ if install_type in ('git', 'source'):
+ popen_list = [sys.executable, sickbeard.MY_FULLNAME]
+ elif install_type == 'win':
+ if hasattr(sys, 'frozen'):
+ # c:\dir\to\updater.exe 12345 c:\dir\to\sickbeard.exe
+ popen_list = [os.path.join(sickbeard.PROG_DIR, 'updater.exe'), str(sickbeard.PID), sys.executable]
+ else:
+ logger.log(u"Unknown SB launch method, please file a bug report about this", logger.ERROR)
+ popen_list = [sys.executable, os.path.join(sickbeard.PROG_DIR, 'updater.py'), str(sickbeard.PID),
+ sys.executable,
+ sickbeard.MY_FULLNAME]
+
+ if popen_list:
+ popen_list += sickbeard.MY_ARGS
+ if '--nolaunch' not in popen_list:
+ popen_list += ['--nolaunch']
+ logger.log(u"Restarting SickRage with " + str(popen_list))
+ logger.close()
+ subprocess.Popen(popen_list, cwd=os.getcwd())
+
+ # system exit
+ os._exit(0)
+
if __name__ == "__main__":
if sys.hexversion >= 0x020600F0:
freeze_support()
- sr = None
- try:
- # init sickrage
- sr = SickRage()
-
- # start sickrage
- sr.start()
-
- # shutdown web server
- sr.webserver.shutDown()
- sr.webserver.join()
- sr.webserver = None
-
- # if run as daemon delete the pidfile
- if sr.runAsDaemon and sr.CREATEPID:
- sr.remove_pid_file(sr.PIDFILE)
-
- if not sickbeard.shutdown:
- install_type = sickbeard.versionCheckScheduler.action.install_type
-
- popen_list = []
-
- if install_type in ('git', 'source'):
- popen_list = [sys.executable, sickbeard.MY_FULLNAME]
- elif install_type == 'win':
- if hasattr(sys, 'frozen'):
- # c:\dir\to\updater.exe 12345 c:\dir\to\sickbeard.exe
- popen_list = [os.path.join(sickbeard.PROG_DIR, 'updater.exe'), str(sickbeard.PID), sys.executable]
- else:
- logger.log(u"Unknown SB launch method, please file a bug report about this", logger.ERROR)
- popen_list = [sys.executable, os.path.join(sickbeard.PROG_DIR, 'updater.py'), str(sickbeard.PID), sys.executable,
- sickbeard.MY_FULLNAME]
-
- if popen_list:
- popen_list += sickbeard.MY_ARGS
- if '--nolaunch' not in popen_list:
- popen_list += ['--nolaunch']
- logger.log(u"Restarting SickRage with " + str(popen_list))
- logger.close()
- subprocess.Popen(popen_list, cwd=os.getcwd())
-
- # exit process
- os._exit(0)
- except:
- if sr:
- logger.log(traceback.format_exc(), logger.ERROR)
- else:
- print(traceback.format_exc())
- sys.exit(1)
\ No newline at end of file
+ # start sickrage
+ SickRage().start()
\ No newline at end of file
diff --git a/gui/slick/images/network/bs11.png b/gui/slick/images/network/bs11.png
new file mode 100644
index 00000000..24b92199
Binary files /dev/null and b/gui/slick/images/network/bs11.png differ
diff --git a/gui/slick/images/network/niconico.png b/gui/slick/images/network/niconico.png
new file mode 100644
index 00000000..41169023
Binary files /dev/null and b/gui/slick/images/network/niconico.png differ
diff --git a/gui/slick/interfaces/default/home.tmpl b/gui/slick/interfaces/default/home.tmpl
index 58c3fa9d..03a9c624 100644
--- a/gui/slick/interfaces/default/home.tmpl
+++ b/gui/slick/interfaces/default/home.tmpl
@@ -229,7 +229,7 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
#set $den = $curShowAll[0]
#end if
#else
- #set $dlStat = "0"
+ #set $dlStat = "0 / 0"
#set $nom = 0
#set $den = 1
#end if
diff --git a/gui/slick/interfaces/default/home_newShow.tmpl b/gui/slick/interfaces/default/home_newShow.tmpl
index 60ce3e43..964978e5 100644
--- a/gui/slick/interfaces/default/home_newShow.tmpl
+++ b/gui/slick/interfaces/default/home_newShow.tmpl
@@ -39,7 +39,7 @@
#else:
-
+
*
@@ -50,7 +50,7 @@
#end for
-
+
* This will only affect the language of the retrieved metadata file contents and episode filenames.
This DOES NOT allow SickRage to download non-english TV episodes!
diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py
index 218466b8..ce787008 100644
--- a/sickbeard/__init__.py
+++ b/sickbeard/__init__.py
@@ -41,7 +41,6 @@ from sickbeard import helpers, db, exceptions, show_queue, search_queue, schedul
from sickbeard import logger
from sickbeard import naming
from sickbeard import dailysearcher
-from sickbeard import maintenance
from sickbeard import scene_numbering, scene_exceptions, name_cache
from indexers.indexer_api import indexerApi
from indexers.indexer_exceptions import indexer_shownotfound, indexer_exception, indexer_error, indexer_episodenotfound, \
@@ -50,7 +49,6 @@ from sickbeard.common import SD, SKIPPED, NAMING_REPEAT
from sickbeard.databases import mainDB, cache_db, failed_db
from lib.configobj import ConfigObj
-from tornado.ioloop import IOLoop
import xml.etree.ElementTree as ElementTree
PID = None
@@ -76,7 +74,9 @@ PIDFILE = ''
DAEMON = None
NO_RESIZE = False
-maintenanceScheduler = None
+# system events
+events = None
+
dailySearchScheduler = None
backlogSearchScheduler = None
showUpdateScheduler = None
@@ -105,7 +105,6 @@ CUR_COMMIT_HASH = None
INIT_LOCK = Lock()
started = False
-shutdown = False
ACTUAL_LOG_DIR = None
LOG_DIR = None
@@ -479,7 +478,7 @@ def initialize(consoleLogging=True):
USE_FAILED_DOWNLOADS, DELETE_FAILED, ANON_REDIRECT, LOCALHOST_IP, TMDB_API_KEY, DEBUG, PROXY_SETTING, \
AUTOPOSTPROCESSER_FREQUENCY, DEFAULT_AUTOPOSTPROCESSER_FREQUENCY, MIN_AUTOPOSTPROCESSER_FREQUENCY, \
ANIME_DEFAULT, NAMING_ANIME, ANIMESUPPORT, USE_ANIDB, ANIDB_USERNAME, ANIDB_PASSWORD, ANIDB_USE_MYLIST, \
- ANIME_SPLIT_HOME, maintenanceScheduler, SCENE_DEFAULT
+ ANIME_SPLIT_HOME, SCENE_DEFAULT
if __INITIALIZED__:
return False
@@ -872,7 +871,7 @@ def initialize(consoleLogging=True):
USE_ANIDB = check_setting_str(CFG, 'ANIDB', 'use_anidb', '')
ANIDB_USERNAME = check_setting_str(CFG, 'ANIDB', 'anidb_username', '')
ANIDB_PASSWORD = check_setting_str(CFG, 'ANIDB', 'anidb_password', '')
- ANIDB_USE_MYLIST = check_setting_str(CFG, 'ANIDB', 'anidb_use_mylist', '')
+ ANIDB_USE_MYLIST = bool(check_setting_int(CFG, 'ANIDB', 'anidb_use_mylist', 0))
ANIME_SPLIT_HOME = bool(check_setting_int(CFG, 'ANIME', 'anime_split_home', 0))
METADATA_XBMC = check_setting_str(CFG, 'General', 'metadata_xbmc', '0|0|0|0|0|0|0|0|0|0')
@@ -957,10 +956,6 @@ def initialize(consoleLogging=True):
threadName="CHECKVERSION",
silent=False)
- maintenanceScheduler = scheduler.Scheduler(maintenance.Maintenance(),
- cycleTime=datetime.timedelta(hours=1),
- threadName="MAINTENANCE")
-
showQueueScheduler = scheduler.Scheduler(show_queue.ShowQueue(),
cycleTime=datetime.timedelta(seconds=3),
threadName="SHOWQUEUE")
@@ -1123,7 +1118,7 @@ def initialize(consoleLogging=True):
def start():
- global __INITIALIZED__, maintenanceScheduler, backlogSearchScheduler, \
+ global __INITIALIZED__, backlogSearchScheduler, \
showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \
properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \
subtitlesFinderScheduler, USE_SUBTITLES,traktCheckerScheduler, \
@@ -1133,9 +1128,6 @@ def start():
if __INITIALIZED__:
- # start the maintenance scheduler
- maintenanceScheduler.thread.start()
-
# start the daily search scheduler
dailySearchScheduler.thread.start()
@@ -1171,11 +1163,11 @@ def start():
def halt():
- global __INITIALIZED__, maintenanceScheduler, backlogSearchScheduler, \
+ global __INITIALIZED__, backlogSearchScheduler, \
showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \
properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \
subtitlesFinderScheduler, traktCheckerScheduler, \
- dailySearchScheduler, started
+ dailySearchScheduler, events, started
with INIT_LOCK:
@@ -1183,12 +1175,10 @@ def halt():
logger.log(u"Aborting all threads")
- # abort all the threads
-
- maintenanceScheduler.abort = True
- logger.log(u"Waiting for the MAINTENANCE scheduler thread to exit")
+ events.alive = False
+ logger.log(u"Waiting for the EVENTS thread to exit")
try:
- maintenanceScheduler.thread.join(10)
+ events.join(10)
except:
pass
@@ -1277,7 +1267,7 @@ def halt():
def sig_handler(signum=None, frame=None):
if type(signum) != type(None):
logger.log(u"Signal %i caught, saving and exiting..." % int(signum))
- saveAndShutdown()
+ events.put(events.SystemEvent.SHUTDOWN)
def saveAll():
global showList
@@ -1291,32 +1281,6 @@ def saveAll():
logger.log(u"Saving config file to disk")
save_config()
-def saveAndShutdown(restart=False):
- global shutdown, started
-
- # flag restart/shutdown
- if not restart:
- shutdown = True
-
- # proceed with shutdown
- started = False
-
-def invoke_command(to_call, *args, **kwargs):
-
- def delegate():
- to_call(*args, **kwargs)
-
- logger.log(u"Placed invoked command: " + repr(delegate) + " for " + repr(to_call) + " with " + repr(
- args) + " and " + repr(kwargs), logger.DEBUG)
-
- IOLoop.current().add_callback(delegate)
-
-def invoke_restart(soft=True):
- invoke_command(restart, soft=soft)
-
-def invoke_shutdown():
- invoke_command(saveAndShutdown, False)
-
def restart(soft=True):
if soft:
halt()
@@ -1324,7 +1288,7 @@ def restart(soft=True):
logger.log(u"Re-initializing all data")
initialize()
else:
- saveAndShutdown(True)
+ events.put(events.SystemEvent.RESTART)
def save_config():
diff --git a/sickbeard/common.py b/sickbeard/common.py
index dcc466f5..2e532750 100644
--- a/sickbeard/common.py
+++ b/sickbeard/common.py
@@ -222,13 +222,9 @@ class Quality:
return Quality.RAWHDTV
elif checkName(["1080p", "hdtv", "x264"], all):
return Quality.FULLHDTV
- elif checkName(["720p", "web.dl", "h.?264"], all) or checkName(["720p", "itunes", "h.?264"], all):
+ elif checkName(["720p", "web.dl|webrip"], all) or checkName(["720p", "itunes", "h.?264"], all):
return Quality.HDWEBDL
- elif checkName(["1080p", "web.dl", "h.?264"], all) or checkName(["1080p", "itunes", "h.?264"], all):
- return Quality.FULLHDWEBDL
- elif checkName(["720p", "webrip", "x264"], all):
- return Quality.HDWEBDL
- elif checkName(["1080p", "webrip", "x264"], all):
+ elif checkName(["1080p", "web.dl|webrip"], all) or checkName(["1080p", "itunes", "h.?264"], all):
return Quality.FULLHDWEBDL
elif checkName(["720p", "bluray|hddvd|b[r|d]rip", "x264"], all):
return Quality.HDBLURAY
diff --git a/sickbeard/dailysearcher.py b/sickbeard/dailysearcher.py
index ac528d1e..60ce9cff 100644
--- a/sickbeard/dailysearcher.py
+++ b/sickbeard/dailysearcher.py
@@ -44,7 +44,7 @@ class DailySearcher():
for curProviderCount, curProvider in enumerate(providers):
try:
- logger.log(u"Updating [" + curProvider.name + "} RSS cache ...")
+ logger.log(u"Updating [" + curProvider.name + "] RSS cache ...")
curProvider.cache.updateCache()
except exceptions.AuthException, e:
logger.log(u"Authentication error: " + ex(e), logger.ERROR)
diff --git a/sickbeard/event_queue.py b/sickbeard/event_queue.py
new file mode 100644
index 00000000..1b32558a
--- /dev/null
+++ b/sickbeard/event_queue.py
@@ -0,0 +1,45 @@
+from threading import Thread
+from Queue import Queue, Empty
+from tornado.ioloop import IOLoop
+
+class Event:
+ def __init__(self, type):
+ self._type = type
+
+ @property
+ def type(self):
+ return self._type
+
+class Events(Thread):
+ def __init__(self, callback):
+ super(Events, self).__init__()
+ self.queue = Queue()
+ self.daemon = True
+ self.alive = True
+ self.callback = callback
+ self.name = "EVENT-QUEUE"
+
+ # auto-start
+ self.start()
+
+ def put(self, type):
+ self.queue.put_nowait(type)
+
+ def run(self):
+ while(self.alive):
+ try:
+ # get event type
+ type = self.queue.get(True, 1)
+
+ # perform callback if we got a event type
+ self.callback(type)
+
+ # event completed
+ self.queue.task_done()
+ except Empty:
+ type = None
+
+ # System Events
+ class SystemEvent(Event):
+ RESTART = "RESTART"
+ SHUTDOWN = "SHUTDOWN"
\ No newline at end of file
diff --git a/sickbeard/maintenance.py b/sickbeard/maintenance.py
deleted file mode 100644
index ccc3f871..00000000
--- a/sickbeard/maintenance.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Author: Nic Wolfe
-# URL: http://code.google.com/p/sickbeard/
-#
-# This file is part of SickRage.
-#
-# SickRage is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# SickRage is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with SickRage. If not, see .
-
-from __future__ import with_statement
-import threading
-import sickbeard
-
-from sickbeard import scene_exceptions
-from sickbeard import failed_history
-from sickbeard import network_timezones
-from sickbeard import name_cache
-
-class Maintenance():
- def __init__(self):
- self.lock = threading.Lock()
-
- self.amActive = False
-
- def run(self, force=False):
- self.amActive = True
-
- # clear internal name cache
- name_cache.clearCache()
-
- # get and update scene exceptions lists
- scene_exceptions.retrieve_exceptions()
-
- # build internal name cache for searches and parsing
- name_cache.buildNameCache()
-
- # refresh network timezones
- network_timezones.update_network_dict()
-
- # sure, why not?
- if sickbeard.USE_FAILED_DOWNLOADS:
- failed_history.trimHistory()
-
- self.amActive = False
\ No newline at end of file
diff --git a/sickbeard/name_cache.py b/sickbeard/name_cache.py
index 6661b89d..401db5dc 100644
--- a/sickbeard/name_cache.py
+++ b/sickbeard/name_cache.py
@@ -96,7 +96,10 @@ def buildNameCache():
# clear internal name cache
clearCache()
- logger.log(u"Updating internal name cache", logger.MESSAGE)
+ # update scene exception names
+ sickbeard.scene_exceptions.retrieve_exceptions()
+
+ logger.log(u"Building internal name cache", logger.MESSAGE)
cacheDB = db.DBConnection('cache.db')
cache_results = cacheDB.select("SELECT * FROM scene_names")
@@ -111,5 +114,4 @@ def buildNameCache():
for name in sickbeard.scene_exceptions.get_scene_exceptions(show.indexerid, season=curSeason):
nameCache[sickbeard.helpers.full_sanitizeSceneName(name)] = show.indexerid
- logger.log(u"Updated internal name cache", logger.MESSAGE)
logger.log(u"Internal name cache set to: " + str(nameCache), logger.DEBUG)
\ No newline at end of file
diff --git a/sickbeard/name_parser/parser.py b/sickbeard/name_parser/parser.py
index 74f163a8..a77eaae7 100644
--- a/sickbeard/name_parser/parser.py
+++ b/sickbeard/name_parser/parser.py
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with SickRage. If not, see .
+import time
import re
import datetime
import os.path
@@ -123,8 +124,8 @@ class NameParser(object):
if not self.showObj and not self.naming_pattern:
# Regex pattern to return the Show / Series Name regardless of the file pattern tossed at it, matched 53 show name examples from regexes.py
show_patterns = [
- '''^(?P.*?)\W+(?:(?:S\d[\dE._ -])|(?:\d\d?x)|(?:\d{4}\W\d\d\W\d\d)|(?:(?:part|pt)[\._ -]?(\d|[ivx]))|Season\W+\d+\W+|E\d+\W+|(?:\d{1,3}.+\d{1,}[a-zA-Z]{2}\W+[a-zA-Z]{3,}\W+\d{4}.+))''',
- '''^((\[.*?\])|(\d+[\.-]))*[ _\.]*(?P.*?)(([ ._-]+\d+)|([ ._-]+s\d{2})).*'''
+ '''^(?P.*)\W+(?:(?:S\d[\dE._ -])|(?:\d\d?x)|(?:\d{4}\W\d\d\W\d\d)|(?:(?:part|pt)[\._ -]?(\d|[ivx]))|Season\W+\d+\W+|E\d+\W+|(?:\d{1,3}.+\d{1,}[a-zA-Z]{2}\W+[a-zA-Z]{3,}\W+\d{4}.+))''',
+ '''^((\[.*?\])|(\d+[\.-]))*[ _\.]*(?P.*)(([ ._-]+\d+)|([ ._-]+s\d{2})).*'''
]
# find show object
@@ -133,6 +134,8 @@ class NameParser(object):
if self.showObj:
break
else:
+ time.sleep(0.05)
+
raise InvalidShowException(
"Unable to parse " + name.encode(sickbeard.SYS_ENCODING, 'xmlcharrefreplace'))
@@ -251,6 +254,8 @@ class NameParser(object):
result.score += 1
matches.append(result)
+ time.sleep(0.05)
+
if len(matches):
result = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score)
diff --git a/sickbeard/providers/rsstorrent.py b/sickbeard/providers/rsstorrent.py
index 64d6e64d..52166a8f 100644
--- a/sickbeard/providers/rsstorrent.py
+++ b/sickbeard/providers/rsstorrent.py
@@ -41,6 +41,7 @@ class TorrentRssProvider(generic.TorrentProvider):
self.url = re.sub('\/$', '', url)
self.url = url
self.enabled = True
+ self.ratio = None
self.supportsBacklog = False
self.search_mode = search_mode
@@ -164,6 +165,8 @@ class TorrentRssProvider(generic.TorrentProvider):
logger.log(u"Saved custom_torrent html dump " + dumpName + " ", logger.MESSAGE)
return True
+ def seedRatio(self):
+ return self.ratio
class TorrentRssCache(tvcache.TVCache):
def __init__(self, provider):
@@ -186,4 +189,4 @@ class TorrentRssCache(tvcache.TVCache):
return None
logger.log(u"Attempting to add item to cache: " + title, logger.DEBUG)
- return self._addCacheEntry(title, url)
\ No newline at end of file
+ return self._addCacheEntry(title, url)
diff --git a/sickbeard/search_queue.py b/sickbeard/search_queue.py
index c1968440..dfd4f863 100644
--- a/sickbeard/search_queue.py
+++ b/sickbeard/search_queue.py
@@ -43,9 +43,6 @@ class SearchQueue(generic_queue.GenericQueue):
generic_queue.GenericQueue.__init__(self)
self.queue_name = "SEARCHQUEUE"
- def __del__(self):
- pass
-
def is_in_queue(self, show, segment):
for cur_item in self.queue:
if isinstance(cur_item, BacklogQueueItem) and cur_item.show == show and cur_item.segment == segment:
@@ -77,17 +74,20 @@ class SearchQueue(generic_queue.GenericQueue):
def add_item(self, item):
if isinstance(item, DailySearchQueueItem) and not self.is_in_queue(item.show, item.segment):
+ sickbeard.name_cache.buildNameCache()
generic_queue.GenericQueue.add_item(self, item)
elif isinstance(item, BacklogQueueItem) and not self.is_in_queue(item.show, item.segment):
+ sickbeard.name_cache.buildNameCache()
generic_queue.GenericQueue.add_item(self, item)
elif isinstance(item, ManualSearchQueueItem) and not self.is_in_queue(item.show, item.segment):
+ sickbeard.name_cache.buildNameCache()
generic_queue.GenericQueue.add_item(self, item)
elif isinstance(item, FailedQueueItem) and not self.is_in_queue(item.show, item.segment):
+ sickbeard.name_cache.buildNameCache()
generic_queue.GenericQueue.add_item(self, item)
else:
logger.log(u"Not adding item, it's already in the queue", logger.DEBUG)
-
class DailySearchQueueItem(generic_queue.QueueItem):
def __init__(self, show, segment):
generic_queue.QueueItem.__init__(self, 'Daily Search', DAILY_SEARCH)
diff --git a/sickbeard/showUpdater.py b/sickbeard/showUpdater.py
index 8d371af3..46c0734c 100644
--- a/sickbeard/showUpdater.py
+++ b/sickbeard/showUpdater.py
@@ -37,6 +37,13 @@ class ShowUpdater():
update_datetime = datetime.datetime.now()
update_date = update_datetime.date()
+ # refresh network timezones
+ network_timezones.update_network_dict()
+
+ # sure, why not?
+ if sickbeard.USE_FAILED_DOWNLOADS:
+ failed_history.trimHistory()
+
logger.log(u"Doing full update on all shows")
# clean out cache directory, remove everything > 12 hours old
diff --git a/sickbeard/tv.py b/sickbeard/tv.py
index 3b9beb32..57ac05bb 100644
--- a/sickbeard/tv.py
+++ b/sickbeard/tv.py
@@ -66,7 +66,6 @@ class TVShow(object):
self._indexerid = int(indexerid)
self._indexer = int(indexer)
self._name = ""
- self._location = ""
self._imdbid = ""
self._network = ""
self._genre = ""
@@ -93,6 +92,7 @@ class TVShow(object):
self.dirty = True
+ self._location = ""
self.lock = threading.Lock()
self.isDirGood = False
self.episodes = {}
@@ -103,9 +103,6 @@ class TVShow(object):
self.loadFromDB()
- def __del__(self):
- pass
-
name = property(lambda self: self._name, dirty_setter("_name"))
indexerid = property(lambda self: self._indexerid, dirty_setter("_indexerid"))
indexer = property(lambda self: self._indexer, dirty_setter("_indexer"))
@@ -172,7 +169,7 @@ class TVShow(object):
logger.log(u"Setter sets location to " + newLocation, logger.DEBUG)
# Don't validate dir if user wants to add shows without creating a dir
if sickbeard.ADD_SHOWS_WO_DIR or ek.ek(os.path.isdir, newLocation):
- self._location = newLocation
+ dirty_setter("_location")(self, newLocation)
self._isDirGood = True
else:
raise exceptions.NoNFOException("Invalid folder for the show!")
@@ -834,7 +831,7 @@ class TVShow(object):
self.flatten_folders = int(sqlResults[0]["flatten_folders"])
self.paused = int(sqlResults[0]["paused"])
- self._location = sqlResults[0]["location"]
+ self.location = sqlResults[0]["location"]
if not self.lang:
self.lang = sqlResults[0]["lang"]
diff --git a/sickbeard/versionChecker.py b/sickbeard/versionChecker.py
index 4e9e60dc..4b45a355 100644
--- a/sickbeard/versionChecker.py
+++ b/sickbeard/versionChecker.py
@@ -64,7 +64,7 @@ class CheckVersion():
if sickbeard.versionCheckScheduler.action.update():
logger.log(u"Update was successful!")
ui.notifications.message('Update was successful')
- threading.Timer(2, sickbeard.invoke_restart, [False]).start()
+ sickbeard.events.put(sickbeard.events.SystemEvent.RESTART)
def find_install_type(self):
"""
diff --git a/sickbeard/webapi.py b/sickbeard/webapi.py
index 4ec6d45b..7ded782f 100644
--- a/sickbeard/webapi.py
+++ b/sickbeard/webapi.py
@@ -1524,7 +1524,7 @@ class CMD_SickBeardRestart(ApiCall):
def run(self):
""" restart sickbeard """
- threading.Timer(2, sickbeard.invoke_restart, [False]).start()
+ sickbeard.events.put(sickbeard.events.SystemEvent.RESTART)
return _responds(RESULT_SUCCESS, msg="SickRage is restarting...")
@@ -1701,7 +1701,7 @@ class CMD_SickBeardShutdown(ApiCall):
def run(self):
""" shutdown sickbeard """
- threading.Timer(2, sickbeard.invoke_shutdown).start()
+ sickbeard.events.put(sickbeard.events.SystemEvent.SHUTDOWN)
return _responds(RESULT_SUCCESS, msg="SickRage is shutting down...")
diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py
index 2ef84235..b83e9615 100644
--- a/sickbeard/webserve.py
+++ b/sickbeard/webserve.py
@@ -487,7 +487,8 @@ class MainHandler(RequestHandler):
class PageTemplate(Template):
def __init__(self, headers, *args, **KWs):
- KWs['file'] = os.path.join(sickbeard.PROG_DIR, "gui/" + sickbeard.GUI_NAME + "/interfaces/default/",KWs['file'])
+ KWs['file'] = os.path.join(sickbeard.PROG_DIR, "gui/" + sickbeard.GUI_NAME + "/interfaces/default/",
+ KWs['file'])
super(PageTemplate, self).__init__(*args, **KWs)
self.sbRoot = sickbeard.WEB_ROOT
@@ -531,6 +532,7 @@ class PageTemplate(Template):
kwargs['cacheDirForModuleFiles'] = os.path.join(sickbeard.CACHE_DIR, 'cheetah')
return super(PageTemplate, self).compile(*args, **kwargs)
+
class IndexerWebUI(MainHandler):
def __init__(self, config, log=None):
self.config = config
@@ -3432,7 +3434,7 @@ class Home(MainHandler):
if str(pid) != str(sickbeard.PID):
redirect("/home/")
- threading.Timer(2, sickbeard.invoke_shutdown).start()
+ sickbeard.events.put(sickbeard.events.SystemEvent.SHUTDOWN)
title = "Shutting down"
message = "SickRage is shutting down..."
@@ -3448,7 +3450,7 @@ class Home(MainHandler):
t.submenu = HomeMenu()
# restart
- threading.Timer(5, sickbeard.invoke_restart, [False]).start()
+ sickbeard.events.put(sickbeard.events.SystemEvent.RESTART)
return _munge(t)
@@ -3460,7 +3462,7 @@ class Home(MainHandler):
updated = sickbeard.versionCheckScheduler.action.update() # @UndefinedVariable
if updated:
# do a hard restart
- threading.Timer(2, sickbeard.invoke_restart, [False]).start()
+ sickbeard.events.put(sickbeard.events.SystemEvent.RESTART)
t = PageTemplate(headers=self.request.headers, file="restart_bare.tmpl")
return _munge(t)
@@ -3643,8 +3645,6 @@ class Home(MainHandler):
else:
return self._genericMessage("Error", errString)
- showObj.exceptions = scene_exceptions.get_scene_exceptions(showObj.indexerid)
-
if not location and not anyQualities and not bestQualities and not flatten_folders:
t = PageTemplate(headers=self.request.headers, file="editShow.tmpl")
t.submenu = HomeMenu()
@@ -3727,54 +3727,56 @@ class Home(MainHandler):
else:
do_update_exceptions = True
- bwl = BlackAndWhiteList(showObj.indexerid)
- if whitelist:
- whitelist = whitelist.split(",")
- shortWhiteList = []
- if helpers.set_up_anidb_connection():
- for groupName in whitelist:
- group = sickbeard.ADBA_CONNECTION.group(gname=groupName)
- for line in group.datalines:
- if line["shortname"]:
- shortWhiteList.append(line["shortname"])
- else:
- if not groupName in shortWhiteList:
- shortWhiteList.append(groupName)
+ # If directCall from mass_edit_update no scene exceptions handling
+ if not directCall:
+ bwl = BlackAndWhiteList(showObj.indexerid)
+ if whitelist:
+ whitelist = whitelist.split(",")
+ shortWhiteList = []
+ if helpers.set_up_anidb_connection():
+ for groupName in whitelist:
+ group = sickbeard.ADBA_CONNECTION.group(gname=groupName)
+ for line in group.datalines:
+ if line["shortname"]:
+ shortWhiteList.append(line["shortname"])
+ else:
+ if not groupName in shortWhiteList:
+ shortWhiteList.append(groupName)
+ else:
+ shortWhiteList = whitelist
+ bwl.set_white_keywords_for("release_group", shortWhiteList)
else:
- shortWhiteList = whitelist
- bwl.set_white_keywords_for("release_group", shortWhiteList)
- else:
- bwl.set_white_keywords_for("release_group", [])
+ bwl.set_white_keywords_for("release_group", [])
- if blacklist:
- blacklist = blacklist.split(",")
- shortBlacklist = []
- if helpers.set_up_anidb_connection():
- for groupName in blacklist:
- group = sickbeard.ADBA_CONNECTION.group(gname=groupName)
- for line in group.datalines:
- if line["shortname"]:
- shortBlacklist.append(line["shortname"])
- else:
- if not groupName in shortBlacklist:
- shortBlacklist.append(groupName)
+ if blacklist:
+ blacklist = blacklist.split(",")
+ shortBlacklist = []
+ if helpers.set_up_anidb_connection():
+ for groupName in blacklist:
+ group = sickbeard.ADBA_CONNECTION.group(gname=groupName)
+ for line in group.datalines:
+ if line["shortname"]:
+ shortBlacklist.append(line["shortname"])
+ else:
+ if not groupName in shortBlacklist:
+ shortBlacklist.append(groupName)
+ else:
+ shortBlacklist = blacklist
+ bwl.set_black_keywords_for("release_group", shortBlacklist)
else:
- shortBlacklist = blacklist
- bwl.set_black_keywords_for("release_group", shortBlacklist)
- else:
- bwl.set_black_keywords_for("release_group", [])
+ bwl.set_black_keywords_for("release_group", [])
- if whiteWords:
- whiteWords = [x.strip() for x in whiteWords.split(",")]
- bwl.set_white_keywords_for("global", whiteWords)
- else:
- bwl.set_white_keywords_for("global", [])
+ if whiteWords:
+ whiteWords = [x.strip() for x in whiteWords.split(",")]
+ bwl.set_white_keywords_for("global", whiteWords)
+ else:
+ bwl.set_white_keywords_for("global", [])
- if blackWords:
- blackWords = [x.strip() for x in blackWords.split(",")]
- bwl.set_black_keywords_for("global", blackWords)
- else:
- bwl.set_black_keywords_for("global", [])
+ if blackWords:
+ blackWords = [x.strip() for x in blackWords.split(",")]
+ bwl.set_black_keywords_for("global", blackWords)
+ else:
+ bwl.set_black_keywords_for("global", [])
errors = []
with showObj.lock:
@@ -3825,14 +3827,14 @@ class Home(MainHandler):
# if we change location clear the db of episodes, change it, write to db, and rescan
if os.path.normpath(showObj._location) != os.path.normpath(location):
logger.log(os.path.normpath(showObj._location) + " != " + os.path.normpath(location), logger.DEBUG)
- if not ek.ek(os.path.isdir, location):
+ if not ek.ek(os.path.isdir, location) and not sickbeard.CREATE_MISSING_SHOW_DIRS:
errors.append("New location %s does not exist" % location)
# don't bother if we're going to update anyway
elif not do_update:
# change it
try:
- showObj.location = location
+ showObj._location = location
try:
sickbeard.showQueueScheduler.action.refreshShow(showObj) # @UndefinedVariable
except exceptions.CantRefreshException, e:
@@ -3858,6 +3860,7 @@ class Home(MainHandler):
if do_update_exceptions:
try:
scene_exceptions.update_scene_exceptions(showObj.indexerid, exceptions_list) # @UndefinedVariable
+ showObj.exceptions = scene_exceptions.get_scene_exceptions(showObj.indexerid)
time.sleep(cpu_presets[sickbeard.CPU_PRESET])
except exceptions.CantUpdateException, e:
errors.append("Unable to force an update on scene exceptions of the show.")
diff --git a/sickbeard/webserveInit.py b/sickbeard/webserveInit.py
index 2dd33df1..ee95b01a 100644
--- a/sickbeard/webserveInit.py
+++ b/sickbeard/webserveInit.py
@@ -122,13 +122,6 @@ class SRWebServer(threading.Thread):
try:
self.io_loop.start()
self.io_loop.close(True)
-
- # stop all tasks
- sickbeard.halt()
-
- # save all shows to DB
- sickbeard.saveAll()
-
except ValueError:
# Ignore errors like "ValueError: I/O operation on closed kqueue fd". These might be thrown during a reload.
pass