Browse Source

More pep8 non-agressive fixes.

pull/346/head
Jonathon Saine 10 years ago
parent
commit
cc0b15eb46
  1. 4
      SABHelper.py
  2. 140
      sabnzbd/api.py
  3. 4
      sabnzbd/bpsmeter.py
  4. 16
      sabnzbd/cfg.py
  5. 57
      sabnzbd/config.py
  6. 17
      sabnzbd/constants.py
  7. 19
      sabnzbd/utils/diskspeed.py
  8. 4
      sabnzbd/utils/getipaddress.py
  9. 2
      sabnzbd/utils/getperformance.py
  10. 20
      sabnzbd/utils/happyeyeballs.py
  11. 7
      sabnzbd/utils/servertests.py
  12. 22
      sabnzbd/utils/systrayiconthread.py
  13. 3
      sabnzbd/utils/upload.py

4
SABHelper.py

@ -102,8 +102,6 @@ def main():
############################################################################## ##############################################################################
# Windows Service Support # Windows Service Support
############################################################################## ##############################################################################
import servicemanager import servicemanager
@ -152,8 +150,6 @@ class SABHelper(win32serviceutil.ServiceFramework):
############################################################################## ##############################################################################
# Platform specific startup code # Platform specific startup code
############################################################################## ##############################################################################
if __name__ == '__main__': if __name__ == '__main__':
win32serviceutil.HandleCommandLine(SABHelper, argv=sys.argv) win32serviceutil.HandleCommandLine(SABHelper, argv=sys.argv)

140
sabnzbd/api.py

@ -33,7 +33,8 @@ except:
# Work-around for Python-ports with bad "locale" support # Work-around for Python-ports with bad "locale" support
pass pass
try: try:
import win32api, win32file import win32api
import win32file
except ImportError: except ImportError:
pass pass
@ -65,8 +66,9 @@ import sabnzbd.rss
import sabnzbd.emailer import sabnzbd.emailer
#------------------------------------------------------------------------------ ##############################################################################
# API error messages # API error messages
##############################################################################
_MSG_NO_VALUE = 'expect one parameter' _MSG_NO_VALUE = 'expect one parameter'
_MSG_NO_VALUE2 = 'expect two parameters' _MSG_NO_VALUE2 = 'expect two parameters'
_MSG_INT_VALUE = 'expect integer value' _MSG_INT_VALUE = 'expect integer value'
@ -79,36 +81,36 @@ _MSG_NO_SUCH_CONFIG = 'Config item does not exist'
_MSG_BAD_SERVER_PARMS = 'Incorrect server settings' _MSG_BAD_SERVER_PARMS = 'Incorrect server settings'
#------------------------------------------------------------------------------
# For Windows: determine executable extensions # For Windows: determine executable extensions
if os.name == 'nt': if os.name == 'nt':
PATHEXT = os.environ.get('PATHEXT', '').lower().split(';') PATHEXT = os.environ.get('PATHEXT', '').lower().split(';')
else: else:
PATHEXT = [] PATHEXT = []
#------------------------------------------------------------------------------
def api_handler(kwargs): def api_handler(kwargs):
""" API Dispatcher """ API Dispatcher """
"""
mode = kwargs.get('mode', '') mode = kwargs.get('mode', '')
output = kwargs.get('output') output = kwargs.get('output')
name = kwargs.get('name', '') name = kwargs.get('name', '')
callback = kwargs.get('callback', '') callback = kwargs.get('callback', '')
if isinstance(mode, list): mode = mode[0] if isinstance(mode, list):
if isinstance(output, list): output = output[0] mode = mode[0]
if isinstance(output, list):
output = output[0]
response = _api_table.get(mode, (_api_undefined, 2))[0](name, output, kwargs) response = _api_table.get(mode, (_api_undefined, 2))[0](name, output, kwargs)
if output == 'json' and callback: if output == 'json' and callback:
response = '%s(%s)' % (callback, response) response = '%s(%s)' % (callback, response)
return response return response
#------------------------------------------------------------------------------
def _api_get_config(name, output, kwargs): def _api_get_config(name, output, kwargs):
""" API: accepts output, keyword, section """ """ API: accepts output, keyword, section """
res, data = config.get_dconfig(kwargs.get('section'), kwargs.get('keyword')) res, data = config.get_dconfig(kwargs.get('section'), kwargs.get('keyword'))
return report(output, keyword='config', data=data) return report(output, keyword='config', data=data)
def _api_set_config(name, output, kwargs): def _api_set_config(name, output, kwargs):
""" API: accepts output, keyword, section """ """ API: accepts output, keyword, section """
if kwargs.get('section') == 'servers': if kwargs.get('section') == 'servers':
@ -145,7 +147,6 @@ def _api_qstatus(name, output, kwargs):
return report(output, keyword=keyword, data=qstatus_data()) return report(output, keyword=keyword, data=qstatus_data())
#------------------------------------------------------------------------------
def _api_queue(name, output, kwargs): def _api_queue(name, output, kwargs):
""" API: Dispatcher for mode=queue """ """ API: Dispatcher for mode=queue """
value = kwargs.get('value', '') value = kwargs.get('value', '')
@ -271,6 +272,7 @@ def _api_queue_default(output, value, kwargs):
else: else:
return report(output, _MSG_NOT_IMPLEMENTED) return report(output, _MSG_NOT_IMPLEMENTED)
def _api_queue_rating(output, value, kwargs): def _api_queue_rating(output, value, kwargs):
""" API: accepts output, value(=nzo_id), type, setting, detail """ """ API: accepts output, value(=nzo_id), type, setting, detail """
vote_map = {'up': Rating.VOTE_UP, 'down': Rating.VOTE_DOWN} vote_map = {'up': Rating.VOTE_UP, 'down': Rating.VOTE_DOWN}
@ -291,7 +293,7 @@ def _api_queue_rating(output, value, kwargs):
else: else:
return report(output, _MSG_NO_VALUE) return report(output, _MSG_NO_VALUE)
#------------------------------------------------------------------------------
def _api_options(name, output, kwargs): def _api_options(name, output, kwargs):
""" API: accepts output """ """ API: accepts output """
return options_list(output) return options_list(output)
@ -378,10 +380,10 @@ def _api_addlocalfile(name, output, kwargs):
nzbname = kwargs.get('nzbname') nzbname = kwargs.get('nzbname')
if get_ext(name) in VALID_ARCHIVES: if get_ext(name) in VALID_ARCHIVES:
res = sabnzbd.dirscanner.ProcessArchiveFile(\ res = sabnzbd.dirscanner.ProcessArchiveFile(
fn, name, pp=pp, script=script, cat=cat, priority=priority, keep=True, nzbname=nzbname) fn, name, pp=pp, script=script, cat=cat, priority=priority, keep=True, nzbname=nzbname)
elif get_ext(name) in ('.nzb', '.gz', '.bz2'): elif get_ext(name) in ('.nzb', '.gz', '.bz2'):
res = sabnzbd.dirscanner.ProcessSingleFile(\ res = sabnzbd.dirscanner.ProcessSingleFile(
fn, name, pp=pp, script=script, cat=cat, priority=priority, keep=True, nzbname=nzbname) fn, name, pp=pp, script=script, cat=cat, priority=priority, keep=True, nzbname=nzbname)
else: else:
logging.info('API-call addlocalfile: "%s" not a proper file name', name) logging.info('API-call addlocalfile: "%s" not a proper file name', name)
@ -439,6 +441,7 @@ def _api_change_script(name, output, kwargs):
else: else:
return report(output, _MSG_NO_VALUE) return report(output, _MSG_NO_VALUE)
def _api_change_opts(name, output, kwargs): def _api_change_opts(name, output, kwargs):
""" API: accepts output, value(=nzo_id), value2(=pp) """ """ API: accepts output, value(=nzo_id), value2(=pp) """
value = kwargs.get('value') value = kwargs.get('value')
@ -681,14 +684,17 @@ def _api_rss_now(name, output, kwargs):
scheduler.force_rss() scheduler.force_rss()
return report(output) return report(output)
def _api_retry_all(name, output, kwargs): def _api_retry_all(name, output, kwargs):
""" API: Retry all failed items in History """ """ API: Retry all failed items in History """
return report(output, keyword='status', data=retry_all_jobs) return report(output, keyword='status', data=retry_all_jobs)
def _api_reset_quota(name, output, kwargs): def _api_reset_quota(name, output, kwargs):
""" Reset quota left """ """ Reset quota left """
BPSMeter.do.reset_quota(force=True) BPSMeter.do.reset_quota(force=True)
def _api_test_email(name, output, kwargs): def _api_test_email(name, output, kwargs):
""" API: send a test email, return result """ """ API: send a test email, return result """
logging.info("Sending testmail") logging.info("Sending testmail")
@ -703,48 +709,54 @@ def _api_test_email(name, output, kwargs):
res = None res = None
return report(output, error=res) return report(output, error=res)
def _api_test_notif(name, output, kwargs): def _api_test_notif(name, output, kwargs):
""" API: send a test to Notification Center, return result """ """ API: send a test to Notification Center, return result """
logging.info("Sending test notification") logging.info("Sending test notification")
res = sabnzbd.growler.send_notification_center('SABnzbd', T('Test Notification'), 'other') res = sabnzbd.growler.send_notification_center('SABnzbd', T('Test Notification'), 'other')
return report(output, error=res) return report(output, error=res)
def _api_test_growl(name, output, kwargs): def _api_test_growl(name, output, kwargs):
""" API: send a test Growl notification, return result """ """ API: send a test Growl notification, return result """
logging.info("Sending Growl notification") logging.info("Sending Growl notification")
res = sabnzbd.growler.send_growl('SABnzbd', T('Test Notification'), 'other', test=kwargs) res = sabnzbd.growler.send_growl('SABnzbd', T('Test Notification'), 'other', test=kwargs)
return report(output, error=res) return report(output, error=res)
def _api_test_osd(name, output, kwargs): def _api_test_osd(name, output, kwargs):
""" API: send a test OSD notification, return result """ """ API: send a test OSD notification, return result """
logging.info("Sending OSD notification") logging.info("Sending OSD notification")
res = sabnzbd.growler.send_notify_osd('SABnzbd', T('Test Notification')) res = sabnzbd.growler.send_notify_osd('SABnzbd', T('Test Notification'))
return report(output, error=res) return report(output, error=res)
def _api_test_prowl(name, output, kwargs): def _api_test_prowl(name, output, kwargs):
""" API: send a test Prowl notification, return result """ """ API: send a test Prowl notification, return result """
logging.info("Sending Prowl notification") logging.info("Sending Prowl notification")
res = sabnzbd.growler.send_prowl('SABnzbd', T('Test Notification'), 'other', force=True, test=kwargs) res = sabnzbd.growler.send_prowl('SABnzbd', T('Test Notification'), 'other', force=True, test=kwargs)
return report(output, error=res) return report(output, error=res)
def _api_test_pushover(name, output, kwargs): def _api_test_pushover(name, output, kwargs):
""" API: send a test Pushover notification, return result """ """ API: send a test Pushover notification, return result """
logging.info("Sending Pushover notification") logging.info("Sending Pushover notification")
res = sabnzbd.growler.send_pushover('SABnzbd', T('Test Notification'), 'other', force=True, test=kwargs) res = sabnzbd.growler.send_pushover('SABnzbd', T('Test Notification'), 'other', force=True, test=kwargs)
return report(output, error=res) return report(output, error=res)
def _api_test_pushbullet(name, output, kwargs): def _api_test_pushbullet(name, output, kwargs):
""" API: send a test Pushbullet notification, return result """ """ API: send a test Pushbullet notification, return result """
logging.info("Sending Pushbullet notification") logging.info("Sending Pushbullet notification")
res = sabnzbd.growler.send_pushbullet('SABnzbd', T('Test Notification'), 'other', force=True, test=kwargs) res = sabnzbd.growler.send_pushbullet('SABnzbd', T('Test Notification'), 'other', force=True, test=kwargs)
return report(output, error=res) return report(output, error=res)
def _api_undefined(name, output, kwargs): def _api_undefined(name, output, kwargs):
""" API: accepts output """ """ API: accepts output """
return report(output, _MSG_NOT_IMPLEMENTED) return report(output, _MSG_NOT_IMPLEMENTED)
#------------------------------------------------------------------------------
def _api_browse(name, output, kwargs): def _api_browse(name, output, kwargs):
""" Return tree of local path """ """ Return tree of local path """
compact = kwargs.get('compact') compact = kwargs.get('compact')
@ -759,7 +771,6 @@ def _api_browse(name, output, kwargs):
return report(output, keyword='paths', data=paths) return report(output, keyword='paths', data=paths)
#------------------------------------------------------------------------------
def _api_config(name, output, kwargs): def _api_config(name, output, kwargs):
""" API: Dispatcher for "config" """ """ API: Dispatcher for "config" """
return _api_config_table.get(name, (_api_config_undefined, 2))[0](output, kwargs) return _api_config_table.get(name, (_api_config_undefined, 2))[0](output, kwargs)
@ -813,6 +824,7 @@ def _api_config_set_apikey(output, kwargs):
config.save_config() config.save_config()
return report(output, keyword='apikey', data=cfg.api_key()) return report(output, keyword='apikey', data=cfg.api_key())
def _api_config_set_nzbkey(output, kwargs): def _api_config_set_nzbkey(output, kwargs):
""" API: accepts output """ """ API: accepts output """
cfg.nzb_key.set(config.create_api_key()) cfg.nzb_key.set(config.create_api_key())
@ -848,7 +860,7 @@ def _api_server_stats(name, output, kwargs):
return report(output, keyword='', data=stats) return report(output, keyword='', data=stats)
#------------------------------------------------------------------------------ ##############################################################################
_api_table = { _api_table = {
'server_stats': (_api_server_stats, 2), 'server_stats': (_api_server_stats, 2),
'get_config': (_api_get_config, 3), 'get_config': (_api_get_config, 3),
@ -926,7 +938,6 @@ _api_config_table = {
} }
#------------------------------------------------------------------------------
def api_level(cmd, name): def api_level(cmd, name):
""" Return access level required for this API call """ """ Return access level required for this API call """
if cmd in _api_table: if cmd in _api_table:
@ -937,7 +948,7 @@ def api_level(cmd, name):
return _api_config_table[cmd][1] return _api_config_table[cmd][1]
return 4 return 4
#------------------------------------------------------------------------------
def report(output, error=None, keyword='value', data=None, callback=None, compat=False): def report(output, error=None, keyword='value', data=None, callback=None, compat=False):
""" Report message in json, xml or plain text """ Report message in json, xml or plain text
If error is set, only an status/error report is made. If error is set, only an status/error report is made.
@ -960,7 +971,6 @@ def report(output, error=None, keyword='value', data=None, callback=None, compat
if callback: if callback:
response = '%s(%s)' % (callback, response) response = '%s(%s)' % (callback, response)
elif output == 'xml': elif output == 'xml':
if not keyword: if not keyword:
# xml always needs an outer keyword, even when json doesn't # xml always needs an outer keyword, even when json doesn't
@ -996,14 +1006,13 @@ def report(output, error=None, keyword='value', data=None, callback=None, compat
return response return response
#------------------------------------------------------------------------------
class xml_factory(object): class xml_factory(object):
""" """ Recursive xml string maker. Feed it a mixed tuple/dict/item object and will output into an xml string
Recursive xml string maker. Feed it a mixed tuple/dict/item object and will output into an xml string
Current limitations: Current limitations:
In Two tiered lists hardcoded name of "item": <cat_list><item> </item></cat_list> In Two tiered lists hardcoded name of "item": <cat_list><item> </item></cat_list>
In Three tiered lists hardcoded name of "slot": <tier1><slot><tier2> </tier2></slot></tier1> In Three tiered lists hardcoded name of "slot": <tier1><slot><tier2> </tier2></slot></tier1>
""" """
def __init__(self): def __init__(self):
self.__text = '' self.__text = ''
@ -1055,10 +1064,8 @@ class xml_factory(object):
return text return text
#------------------------------------------------------------------------------
def handle_server_api(output, kwargs): def handle_server_api(output, kwargs):
""" Special handler for API-call 'set_config' [servers] """ Special handler for API-call 'set_config' [servers] """
"""
name = kwargs.get('keyword') name = kwargs.get('keyword')
if not name: if not name:
name = kwargs.get('name') name = kwargs.get('name')
@ -1075,10 +1082,8 @@ def handle_server_api(output, kwargs):
return name return name
#------------------------------------------------------------------------------
def handle_rss_api(output, kwargs): def handle_rss_api(output, kwargs):
""" Special handler for API-call 'set_config' [rss] """ Special handler for API-call 'set_config' [rss] """
"""
name = kwargs.get('keyword') name = kwargs.get('keyword')
if not name: if not name:
name = kwargs.get('name') name = kwargs.get('name')
@ -1093,10 +1098,8 @@ def handle_rss_api(output, kwargs):
return name return name
#------------------------------------------------------------------------------
def handle_cat_api(output, kwargs): def handle_cat_api(output, kwargs):
""" Special handler for API-call 'set_config' [categories] """ Special handler for API-call 'set_config' [categories] """
"""
name = kwargs.get('keyword') name = kwargs.get('keyword')
if not name: if not name:
name = kwargs.get('name') name = kwargs.get('name')
@ -1111,7 +1114,6 @@ def handle_cat_api(output, kwargs):
return name return name
#------------------------------------------------------------------------------
def build_queue(web_dir=None, root=None, verbose=False, prim=True, webdir='', verbose_list=None, def build_queue(web_dir=None, root=None, verbose=False, prim=True, webdir='', verbose_list=None,
dictionary=None, history=False, start=None, limit=None, dummy2=None, trans=False, output=None, dictionary=None, history=False, start=None, limit=None, dummy2=None, trans=False, output=None,
search=None): search=None):
@ -1270,7 +1272,8 @@ def build_queue(web_dir=None, root=None, verbose=False, prim=True, webdir='', ve
finished = [] finished = []
active = [] active = []
queued = [] queued = []
if verbose or nzo_id in verbose_list:#this will list files in the xml output, wanted yes/no? # this will list files in the xml output, wanted yes/no?
if verbose or nzo_id in verbose_list:
slot['verbosity'] = "True" slot['verbosity'] = "True"
for tup in finished_files: for tup in finished_files:
bytes_left, bytes, fn, date = tup bytes_left, bytes, fn, date = tup
@ -1350,7 +1353,6 @@ def build_queue(web_dir=None, root=None, verbose=False, prim=True, webdir='', ve
return info, pnfo_list, bytespersec, verbose_list, dictn return info, pnfo_list, bytespersec, verbose_list, dictn
#------------------------------------------------------------------------------
def fast_queue(): def fast_queue():
""" Return paused, bytes_left, bpsnow, time_left """ """ Return paused, bytes_left, bpsnow, time_left """
bytes_left = NzbQueue.do.remaining() bytes_left = NzbQueue.do.remaining()
@ -1360,10 +1362,8 @@ def fast_queue():
return paused, bytes_left, bpsnow, time_left return paused, bytes_left, bpsnow, time_left
#------------------------------------------------------------------------------
def qstatus_data(): def qstatus_data():
"""Build up the queue status as a nested object and output as a JSON object """Build up the queue status as a nested object and output as a JSON object """
"""
qnfo = NzbQueue.do.queue_info() qnfo = NzbQueue.do.queue_info()
pnfo_list = qnfo[QNFO_PNFO_LIST_FIELD] pnfo_list = qnfo[QNFO_PNFO_LIST_FIELD]
@ -1409,7 +1409,6 @@ def qstatus_data():
return status return status
#------------------------------------------------------------------------------
def build_file_list(id): def build_file_list(id):
qnfo = NzbQueue.do.queue_info() qnfo = NzbQueue.do.queue_info()
pnfo_list = qnfo[QNFO_PNFO_LIST_FIELD] pnfo_list = qnfo[QNFO_PNFO_LIST_FIELD]
@ -1422,7 +1421,6 @@ def build_file_list(id):
active_files = pnfo[PNFO_ACTIVE_FILES_FIELD] active_files = pnfo[PNFO_ACTIVE_FILES_FIELD]
queued_files = pnfo[PNFO_QUEUED_FILES_FIELD] queued_files = pnfo[PNFO_QUEUED_FILES_FIELD]
n = 0 n = 0
for tup in finished_files: for tup in finished_files:
bytes_left, bytes, fn, date = tup bytes_left, bytes, fn, date = tup
@ -1471,17 +1469,15 @@ def build_file_list(id):
return jobs return jobs
#------------------------------------------------------------------------------
def rss_qstatus(): def rss_qstatus():
""" Return a RSS feed with the queue status """ Return a RSS feed with the queue status """
"""
qnfo = NzbQueue.do.queue_info() qnfo = NzbQueue.do.queue_info()
pnfo_list = qnfo[QNFO_PNFO_LIST_FIELD] pnfo_list = qnfo[QNFO_PNFO_LIST_FIELD]
rss = RSS() rss = RSS()
rss.channel.title = "SABnzbd Queue" rss.channel.title = "SABnzbd Queue"
rss.channel.description = "Overview of current downloads" rss.channel.description = "Overview of current downloads"
rss.channel.link = "http://%s:%s/sabnzbd/queue" % ( \ rss.channel.link = "http://%s:%s/sabnzbd/queue" % (
cfg.cherryhost(), cfg.cherryport()) cfg.cherryhost(), cfg.cherryport())
rss.channel.language = "en" rss.channel.language = "en"
@ -1503,7 +1499,6 @@ def rss_qstatus():
mb = (bytes / MEBI) mb = (bytes / MEBI)
nzo_id = pnfo[PNFO_NZO_ID_FIELD] nzo_id = pnfo[PNFO_NZO_ID_FIELD]
if mb == mbleft: if mb == mbleft:
percentage = "0%" percentage = "0%"
else: else:
@ -1534,10 +1529,8 @@ def rss_qstatus():
return rss.write() return rss.write()
#------------------------------------------------------------------------------
def options_list(output): def options_list(output):
return report(output, keyword='options', data= return report(output, keyword='options', data={
{
'yenc': sabnzbd.decoder.HAVE_YENC, 'yenc': sabnzbd.decoder.HAVE_YENC,
'par2': sabnzbd.newsunpack.PAR2_COMMAND, 'par2': sabnzbd.newsunpack.PAR2_COMMAND,
'par2c': sabnzbd.newsunpack.PAR2C_COMMAND, 'par2c': sabnzbd.newsunpack.PAR2C_COMMAND,
@ -1550,8 +1543,6 @@ def options_list(output):
}) })
#------------------------------------------------------------------------------
def retry_job(job, new_nzb, password): def retry_job(job, new_nzb, password):
""" Re enter failed job in the download queue """ """ Re enter failed job in the download queue """
if job: if job:
@ -1569,14 +1560,12 @@ def retry_job(job, new_nzb, password):
return None return None
#------------------------------------------------------------------------------
def retry_all_jobs(): def retry_all_jobs():
""" Re enter all failed jobs in the download queue """ """ Re enter all failed jobs in the download queue """
history_db = cherrypy.thread_data.history_db history_db = cherrypy.thread_data.history_db
return NzbQueue.do.retry_all_jobs(history_db) return NzbQueue.do.retry_all_jobs(history_db)
#------------------------------------------------------------------------------
def del_job_files(job_paths): def del_job_files(job_paths):
""" Remove files of each path in the list """ """ Remove files of each path in the list """
for path in job_paths: for path in job_paths:
@ -1584,7 +1573,6 @@ def del_job_files(job_paths):
remove_all(path, recursive=True) remove_all(path, recursive=True)
#------------------------------------------------------------------------------
def del_hist_job(job, del_files): def del_hist_job(job, del_files):
""" Remove history element """ """ Remove history element """
if job: if job:
@ -1601,7 +1589,7 @@ def del_hist_job(job, del_files):
remove_all(path, recursive=True) remove_all(path, recursive=True)
return True return True
#------------------------------------------------------------------------------
def Tspec(txt): def Tspec(txt):
""" Translate special terms """ """ Translate special terms """
if txt == 'None': if txt == 'None':
@ -1612,12 +1600,10 @@ def Tspec(txt):
return txt return txt
_SKIN_CACHE = {} # Stores pre-translated acronyms _SKIN_CACHE = {} # Stores pre-translated acronyms
# This special is to be used in interface.py for template processing # This special is to be used in interface.py for template processing
# to be passed for the $T function: so { ..., 'T' : Ttemplate, ...} # to be passed for the $T function: so { ..., 'T' : Ttemplate, ...}
def Ttemplate(txt): def Ttemplate(txt):
""" Translation function for Skin texts """ Translation function for Skin texts """
"""
global _SKIN_CACHE global _SKIN_CACHE
if txt in _SKIN_CACHE: if txt in _SKIN_CACHE:
return _SKIN_CACHE[txt] return _SKIN_CACHE[txt]
@ -1628,8 +1614,7 @@ def Ttemplate(txt):
def clear_trans_cache(): def clear_trans_cache():
""" Clean cache for skin translations """ Clean cache for skin translations """
"""
global _SKIN_CACHE global _SKIN_CACHE
dummy = _SKIN_CACHE dummy = _SKIN_CACHE
_SKIN_CACHE = {} _SKIN_CACHE = {}
@ -1677,7 +1662,6 @@ def build_header(prim, webdir='', search=None):
header['my_lcldata'] = sabnzbd.DIR_LCLDATA header['my_lcldata'] = sabnzbd.DIR_LCLDATA
header['my_home'] = sabnzbd.DIR_HOME header['my_home'] = sabnzbd.DIR_HOME
header['webdir'] = webdir header['webdir'] = webdir
header['pid'] = os.getpid() header['pid'] = os.getpid()
@ -1741,8 +1725,6 @@ def build_header(prim, webdir='', search=None):
return (header, qnfo[QNFO_PNFO_LIST_FIELD], bytespersec) return (header, qnfo[QNFO_PNFO_LIST_FIELD], bytespersec)
#------------------------------------------------------------------------------
def build_history(start=None, limit=None, verbose=False, verbose_list=None, search=None, failed_only=0, def build_history(start=None, limit=None, verbose=False, verbose_list=None, search=None, failed_only=0,
categories=None, output=None): categories=None, output=None):
@ -1755,7 +1737,8 @@ def build_history(start=None, limit=None, verbose=False, verbose_list=None, sear
verbose_list = [] verbose_list = []
limit = int_conv(limit) limit = int_conv(limit)
if not limit: limit = 1000000 if not limit:
limit = 1000000
start = int_conv(start) start = int_conv(start)
failed_only = int_conv(failed_only) failed_only = int_conv(failed_only)
@ -1864,12 +1847,12 @@ def build_history(start=None, limit=None, verbose=False, verbose_list=None, sear
if item.get('status') != 'Failed': if item.get('status') != 'Failed':
item['path'] = '' item['path'] = ''
item['retry'] = int(bool(item.get('status') == 'Failed' and \ item['retry'] = int(bool(item.get('status') == 'Failed' and
path and \ path and
path not in retry_folders and \ path not in retry_folders and
starts_with_path(path, cfg.download_dir.get_path()) and \ starts_with_path(path, cfg.download_dir.get_path()) and
os.path.exists(path)) and \ os.path.exists(path)) and
not bool(globber(os.path.join(path, JOB_ADMIN), 'SABnzbd_n*')) \ not bool(globber(os.path.join(path, JOB_ADMIN), 'SABnzbd_n*'))
) )
if item['report'] == 'future': if item['report'] == 'future':
item['retry'] = True item['retry'] = True
@ -1900,10 +1883,8 @@ def build_history(start=None, limit=None, verbose=False, verbose_list=None, sear
return (items, fetched_items, total_items) return (items, fetched_items, total_items)
#------------------------------------------------------------------------------
def format_history_for_queue(): def format_history_for_queue():
''' Retrieves the information on currently active history items, and formats them for displaying in the queue ''' """ Retrieves the information on currently active history items, and formats them for displaying in the queue """
slotinfo = [] slotinfo = []
history_items = get_active_history() history_items = get_active_history()
@ -1918,7 +1899,7 @@ def format_history_for_queue():
def get_active_history(queue=None, items=None): def get_active_history(queue=None, items=None):
# Get the currently in progress and active history queue. """ Get the currently in progress and active history queue. """
if items is None: if items is None:
items = [] items = []
if queue is None: if queue is None:
@ -1951,7 +1932,6 @@ def get_active_history(queue=None, items=None):
return items return items
#------------------------------------------------------------------------------
def format_bytes(bytes): def format_bytes(bytes):
b = to_units(bytes) b = to_units(bytes)
if b == '': if b == '':
@ -1961,9 +1941,7 @@ def format_bytes(bytes):
def calc_timeleft(bytesleft, bps): def calc_timeleft(bytesleft, bps):
""" """ Calculate the time left in the format HH:MM:SS """
Calculate the time left in the format HH:MM:SS
"""
try: try:
totalseconds = int(bytesleft / bps) totalseconds = int(bytesleft / bps)
minutes, seconds = divmod(totalseconds, 60) minutes, seconds = divmod(totalseconds, 60)
@ -1978,8 +1956,7 @@ def calc_timeleft(bytesleft, bps):
def calc_age(date, trans=False): def calc_age(date, trans=False):
""" """ Calculate the age difference between now and date.
Calculate the age difference between now and date.
Value is returned as either days, hours, or minutes. Value is returned as either days, hours, or minutes.
When 'trans' is True, time symbols will be translated. When 'trans' is True, time symbols will be translated.
""" """
@ -2026,7 +2003,7 @@ def list_scripts(default=False):
if path and os.access(path, os.R_OK): if path and os.access(path, os.R_OK):
for script in globber_full(path): for script in globber_full(path):
if os.path.isfile(script): if os.path.isfile(script):
if (sabnzbd.WIN32 and os.path.splitext(script)[1].lower() in PATHEXT and \ if (sabnzbd.WIN32 and os.path.splitext(script)[1].lower() in PATHEXT and
not (win32api.GetFileAttributes(script) & win32file.FILE_ATTRIBUTE_HIDDEN)) or \ not (win32api.GetFileAttributes(script) & win32file.FILE_ATTRIBUTE_HIDDEN)) or \
script.endswith('.py') or \ script.endswith('.py') or \
(not sabnzbd.WIN32 and os.access(script, os.X_OK) and not os.path.basename(script).startswith('.')): (not sabnzbd.WIN32 and os.access(script, os.X_OK) and not os.path.basename(script).startswith('.')):
@ -2054,7 +2031,6 @@ def remove_callable(dic):
return dic return dic
#------------------------------------------------------------------------------
_PLURAL_TO_SINGLE = { _PLURAL_TO_SINGLE = {
'categories': 'category', 'categories': 'category',
'servers': 'server', 'servers': 'server',
@ -2064,6 +2040,8 @@ _PLURAL_TO_SINGLE = {
'files': 'file', 'files': 'file',
'jobs': 'job' 'jobs': 'job'
} }
def plural_to_single(kw, def_kw=''): def plural_to_single(kw, def_kw=''):
try: try:
return _PLURAL_TO_SINGLE[kw] return _PLURAL_TO_SINGLE[kw]
@ -2071,7 +2049,6 @@ def plural_to_single(kw, def_kw=''):
return def_kw return def_kw
#------------------------------------------------------------------------------
def del_from_section(kwargs): def del_from_section(kwargs):
""" Remove keyword in section """ """ Remove keyword in section """
section = kwargs.get('section', '') section = kwargs.get('section', '')
@ -2090,7 +2067,6 @@ def del_from_section(kwargs):
return False return False
#------------------------------------------------------------------------------
def history_remove_failed(): def history_remove_failed():
""" Remove all failed jobs from history, including files """ """ Remove all failed jobs from history, including files """
logging.info('Scheduled removal of all failed jobs') logging.info('Scheduled removal of all failed jobs')

4
sabnzbd/bpsmeter.py

@ -253,8 +253,7 @@ class BPSMeter(object):
# Speedometer # Speedometer
try: try:
self.bps = (self.bps * (self.last_update - self.start_time) self.bps = (self.bps * (self.last_update - self.start_time) + amount) / (t - self.start_time)
+ amount) / (t - self.start_time)
except: except:
self.bps = 0.0 self.bps = 0.0
@ -406,7 +405,6 @@ class BPSMeter(object):
# The <day> and <hh:mm> part can both be optional # The <day> and <hh:mm> part can both be optional
__re_day = re.compile('^\s*(\d+)[^:]*') __re_day = re.compile('^\s*(\d+)[^:]*')
__re_hm = re.compile('(\d+):(\d+)\s*$') __re_hm = re.compile('(\d+):(\d+)\s*$')
def get_quota(self): def get_quota(self):
""" If quota active, return check-function, hour, minute """ """ If quota active, return check-function, hour, minute """
if self.have_quota: if self.have_quota:

16
sabnzbd/cfg.py

@ -30,9 +30,9 @@ from sabnzbd.config import OptionBool, OptionNumber, OptionPassword, \
validate_octal, validate_safedir, validate_dir_exists, \ validate_octal, validate_safedir, validate_dir_exists, \
create_api_key, validate_notempty create_api_key, validate_notempty
#------------------------------------------------------------------------------ ##############################################################################
# Email validation support # Email validation support
# ##############################################################################
RE_VAL = re.compile('[^@ ]+@[^.@ ]+\.[^.@ ]') RE_VAL = re.compile('[^@ ]+@[^.@ ]+\.[^.@ ]')
def validate_email(value): def validate_email(value):
global email_endjob, email_full, email_rss global email_endjob, email_full, email_rss
@ -55,15 +55,14 @@ def validate_server(value):
else: else:
return None, value return None, value
#------------------------------------------------------------------------------
if sabnzbd.WIN32: if sabnzbd.WIN32:
DEF_FOLDER_MAX = 128 DEF_FOLDER_MAX = 128
else: else:
DEF_FOLDER_MAX = 256 DEF_FOLDER_MAX = 256
#------------------------------------------------------------------------------ ##############################################################################
# Configuration instances # Configuration instances
# ##############################################################################
quick_check = OptionBool('misc', 'quick_check', True) quick_check = OptionBool('misc', 'quick_check', True)
sfv_check = OptionBool('misc', 'sfv_check', True) sfv_check = OptionBool('misc', 'sfv_check', True)
@ -181,7 +180,7 @@ configlock = OptionBool('misc', 'config_lock', 0)
umask = OptionStr('misc', 'permissions', '', validation=validate_octal) umask = OptionStr('misc', 'permissions', '', validation=validate_octal)
download_dir = OptionDir('misc', 'download_dir', DEF_DOWNLOAD_DIR, create=False, validation=validate_safedir) download_dir = OptionDir('misc', 'download_dir', DEF_DOWNLOAD_DIR, create=False, validation=validate_safedir)
download_free = OptionStr('misc', 'download_free') download_free = OptionStr('misc', 'download_free')
complete_dir = OptionDir('misc', 'complete_dir', DEF_COMPLETE_DIR, create=False, \ complete_dir = OptionDir('misc', 'complete_dir', DEF_COMPLETE_DIR, create=False,
apply_umask=True, validation=validate_notempty) apply_umask=True, validation=validate_notempty)
script_dir = OptionDir('misc', 'script_dir', create=True, writable=False) script_dir = OptionDir('misc', 'script_dir', create=True, writable=False)
nzb_backup_dir = OptionDir('misc', 'nzb_backup_dir', DEF_NZBBACK_DIR) nzb_backup_dir = OptionDir('misc', 'nzb_backup_dir', DEF_NZBBACK_DIR)
@ -365,9 +364,9 @@ warn_dupl_jobs = OptionBool('misc', 'warn_dupl_jobs', True)
new_nzb_on_failure = OptionBool('misc', 'new_nzb_on_failure', False) new_nzb_on_failure = OptionBool('misc', 'new_nzb_on_failure', False)
#------------------------------------------------------------------------------ ##############################################################################
# Set root folders for Folder config-items # Set root folders for Folder config-items
# ##############################################################################
def set_root_folders(home, lcldata): def set_root_folders(home, lcldata):
email_dir.set_root(home) email_dir.set_root(home)
download_dir.set_root(home) download_dir.set_root(home)
@ -379,6 +378,7 @@ def set_root_folders(home, lcldata):
log_dir.set_root(lcldata) log_dir.set_root(lcldata)
password_file.set_root(home) password_file.set_root(home)
def set_root_folders2(): def set_root_folders2():
https_cert.set_root(admin_dir.get_path()) https_cert.set_root(admin_dir.get_path())
https_key.set_root(admin_dir.get_path()) https_key.set_root(admin_dir.get_path())

57
sabnzbd/config.py

@ -46,13 +46,14 @@ modified = False # Signals a change in option dictionary
class Option(object): class Option(object):
""" Basic option class, basic fields """ """ Basic option class, basic fields """
def __init__(self, section, keyword, default_val=None, add=True, protect=False): def __init__(self, section, keyword, default_val=None, add=True, protect=False):
""" Basic option """ Basic option
section : single section or comma-separated list of sections section : single section or comma-separated list of sections
a list will be a hierarchy: "foo, bar" --> [foo][[bar]] a list will be a hierarchy: "foo, bar" --> [foo][[bar]]
keyword : keyword in the (last) section keyword : keyword in the (last) section
default_val : value returned when no value has been set default_val : value returned when no value has been set
callback : procedure to call when value is succesfully changed callback : procedure to call when value is successfully changed
protect : Do not allow setting via the API (specifically set_dict) protect : Do not allow setting via the API (specifically set_dict)
""" """
self.__sections = section.split(',') self.__sections = section.split(',')
@ -125,9 +126,9 @@ class Option(object):
return self.__sections, self.__keyword return self.__sections, self.__keyword
class OptionNumber(Option): class OptionNumber(Option):
""" Numeric option class, int/float is determined from default value """ """ Numeric option class, int/float is determined from default value """
def __init__(self, section, keyword, default_val=0, minval=None, maxval=None, validation=None, add=True, protect=False): def __init__(self, section, keyword, default_val=0, minval=None, maxval=None, validation=None, add=True, protect=False):
Option.__init__(self, section, keyword, default_val, add=add, protect=protect) Option.__init__(self, section, keyword, default_val, add=add, protect=protect)
self.__minval = minval self.__minval = minval
@ -159,6 +160,7 @@ class OptionNumber(Option):
class OptionBool(Option): class OptionBool(Option):
""" Boolean option class """ """ Boolean option class """
def __init__(self, section, keyword, default_val=False, add=True, protect=False): def __init__(self, section, keyword, default_val=False, add=True, protect=False):
Option.__init__(self, section, keyword, int(default_val), add=add, protect=protect) Option.__init__(self, section, keyword, int(default_val), add=add, protect=protect)
@ -174,6 +176,7 @@ class OptionBool(Option):
class OptionDir(Option): class OptionDir(Option):
""" Directory option class """ """ Directory option class """
def __init__(self, section, keyword, default_val='', apply_umask=False, create=True, validation=None, writable=True, add=True): def __init__(self, section, keyword, default_val='', apply_umask=False, create=True, validation=None, writable=True, add=True):
self.__validation = validation self.__validation = validation
self.__root = '' # Base directory for relative paths self.__root = '' # Base directory for relative paths
@ -193,7 +196,6 @@ class OptionDir(Option):
else: else:
return p.replace('\\', '/') if '\\' in p else p return p.replace('\\', '/') if '\\' in p else p
def get_path(self): def get_path(self):
""" Return full absolute path """ """ Return full absolute path """
value = self.get() value = self.get()
@ -240,8 +242,10 @@ class OptionDir(Option):
""" Set auto-creation value """ """ Set auto-creation value """
self.__create = value self.__create = value
class OptionList(Option): class OptionList(Option):
""" List option class """ """ List option class """
def __init__(self, section, keyword, default_val=None, validation=None, add=True, protect=False): def __init__(self, section, keyword, default_val=None, validation=None, add=True, protect=False):
self.__validation = validation self.__validation = validation
if default_val is None: if default_val is None:
@ -272,12 +276,14 @@ class OptionList(Option):
r = len(lst) r = len(lst)
for n in xrange(r): for n in xrange(r):
txt += lst[n] txt += lst[n]
if n < r-1: txt += ', ' if n < r - 1:
txt += ', '
return txt return txt
class OptionStr(Option): class OptionStr(Option):
""" String class """ """ String class """
def __init__(self, section, keyword, default_val='', validation=None, add=True, strip=True, protect=False): def __init__(self, section, keyword, default_val='', validation=None, add=True, strip=True, protect=False):
Option.__init__(self, section, keyword, default_val, add=add, protect=protect) Option.__init__(self, section, keyword, default_val, add=add, protect=protect)
self.__validation = validation self.__validation = validation
@ -306,6 +312,7 @@ class OptionStr(Option):
class OptionPassword(Option): class OptionPassword(Option):
""" Password class """ """ Password class """
def __init__(self, section, keyword, default_val='', add=True): def __init__(self, section, keyword, default_val='', add=True):
Option.__init__(self, section, keyword, default_val, add=add) Option.__init__(self, section, keyword, default_val, add=add)
self.get_string = self.get_stars self.get_string = self.get_stars
@ -361,6 +368,7 @@ def delete_from_database(section, keyword):
class ConfigServer(object): class ConfigServer(object):
""" Class defining a single server """ """ Class defining a single server """
def __init__(self, name, values): def __init__(self, name, values):
self.__name = name self.__name = name
@ -441,6 +449,7 @@ class ConfigServer(object):
class ConfigCat(object): class ConfigCat(object):
""" Class defining a single category """ """ Class defining a single category """
def __init__(self, name, values): def __init__(self, name, values):
self.__name = name self.__name = name
name = 'categories,' + name name = 'categories,' + name
@ -482,6 +491,7 @@ class ConfigCat(object):
class OptionFilters(Option): class OptionFilters(Option):
""" Filter list class """ """ Filter list class """
def __init__(self, section, keyword, add=True): def __init__(self, section, keyword, add=True):
Option.__init__(self, section, keyword, add=add) Option.__init__(self, section, keyword, add=add)
self.set([]) self.set([])
@ -545,8 +555,10 @@ class OptionFilters(Option):
self.set(filters) self.set(filters)
return True return True
class ConfigRSS(object): class ConfigRSS(object):
""" Class defining a single Feed definition """ """ Class defining a single Feed definition """
def __init__(self, name, values): def __init__(self, name, values):
self.__name = name self.__name = name
name = 'rss,' + name name = 'rss,' + name
@ -598,7 +610,6 @@ class ConfigRSS(object):
return 'rss', self.__name return 'rss', self.__name
def get_dconfig(section, keyword, nested=False): def get_dconfig(section, keyword, nested=False):
""" Return a config values dictonary, """ Return a config values dictonary,
Single item or slices based on 'section', 'keyword' Single item or slices based on 'section', 'keyword'
@ -641,8 +652,7 @@ def get_dconfig(section, keyword, nested=False):
def get_config(section, keyword): def get_config(section, keyword):
""" Return a config object, based on 'section', 'keyword' """ Return a config object, based on 'section', 'keyword' """
"""
try: try:
return database[section][keyword] return database[section][keyword]
except KeyError: except KeyError:
@ -651,8 +661,7 @@ def get_config(section, keyword):
def set_config(kwargs): def set_config(kwargs):
""" Set a config item, using values in dictionary """ Set a config item, using values in dictionary """
"""
try: try:
item = database[kwargs.get('section')][kwargs.get('keyword')] item = database[kwargs.get('section')][kwargs.get('keyword')]
except KeyError: except KeyError:
@ -662,21 +671,19 @@ def set_config(kwargs):
def delete(section, keyword): def delete(section, keyword):
""" Delete specific config item """ Delete specific config item """
"""
try: try:
database[section][keyword].delete() database[section][keyword].delete()
except KeyError: except KeyError:
return return
################################################################################ ##############################################################################
#
# INI file support # INI file support
# #
# This does input and output of configuration to an INI file. # This does input and output of configuration to an INI file.
# It translates this data structure to the config database. # It translates this data structure to the config database.
##############################################################################
@synchronized(SAVE_CONFIG_LOCK) @synchronized(SAVE_CONFIG_LOCK)
def read_config(path): def read_config(path):
""" Read the complete INI file and check its version number """ Read the complete INI file and check its version number
@ -775,7 +782,6 @@ def _read_config(path, try_backup=False):
return True, "" return True, ""
@synchronized(SAVE_CONFIG_LOCK) @synchronized(SAVE_CONFIG_LOCK)
def save_config(force=False): def save_config(force=False):
""" Update Setup file with current option values """ """ Update Setup file with current option values """
@ -854,7 +860,6 @@ def save_config(force=False):
return res return res
def define_servers(): def define_servers():
""" Define servers listed in the Setup file """ Define servers listed in the Setup file
return a list of ConfigServer instances return a list of ConfigServer instances
@ -871,6 +876,7 @@ def define_servers():
except KeyError: except KeyError:
pass pass
def get_servers(): def get_servers():
global database global database
try: try:
@ -909,7 +915,7 @@ def get_categories(cat=0):
database['categories'] = {} database['categories'] = {}
cats = database['categories'] cats = database['categories']
if '*' not in cats: if '*' not in cats:
ConfigCat('*', {'pp' : old_def('dirscan_opts', '3'), 'script' : old_def('dirscan_script', 'None'), \ ConfigCat('*', {'pp': old_def('dirscan_opts', '3'), 'script': old_def('dirscan_script', 'None'),
'priority': old_def('dirscan_priority', NORMAL_PRIORITY)}) 'priority': old_def('dirscan_priority', NORMAL_PRIORITY)})
save_config(True) save_config(True)
if not isinstance(cat, int): if not isinstance(cat, int):
@ -931,6 +937,7 @@ def define_rss():
except KeyError: except KeyError:
pass pass
def get_rss(): def get_rss():
global database global database
try: try:
@ -938,18 +945,16 @@ def get_rss():
except KeyError: except KeyError:
return {} return {}
def get_filename(): def get_filename():
global CFG global CFG
return CFG.filename return CFG.filename
################################################################################ ##############################################################################
#
# Default Validation handlers # Default Validation handlers
# ##############################################################################
__PW_PREFIX = '!!!encoded!!!' __PW_PREFIX = '!!!encoded!!!'
#------------------------------------------------------------------------------
def encode_password(pw): def encode_password(pw):
""" Encode password in hexadecimal if needed """ """ Encode password in hexadecimal if needed """
enc = False enc = False
@ -1041,8 +1046,7 @@ def validate_notempty(root, value, default):
def create_api_key(): def create_api_key():
""" Return a new randomized API_KEY """ Return a new randomized API_KEY """
"""
import time import time
try: try:
from hashlib import md5 from hashlib import md5
@ -1061,12 +1065,11 @@ def create_api_key():
return m.hexdigest() return m.hexdigest()
#------------------------------------------------------------------------------ _FIXES = (
_FIXES = \
(
('enable_par_multicore', 'par2_multicore'), ('enable_par_multicore', 'par2_multicore'),
) )
def compatibility_fix(cf): def compatibility_fix(cf):
""" Convert obsolete INI entries """ """ Convert obsolete INI entries """
for item in _FIXES: for item in _FIXES:

17
sabnzbd/constants.py

@ -125,20 +125,16 @@ IGNORED_FOLDERS = ('@eaDir', '.appleDouble')
# (MATCHER, [EXTRA, MATCHERS]) # (MATCHER, [EXTRA, MATCHERS])
series_match = [(r'( [sS]|[\d]+)x(\d+)', # 1x01 series_match = [(r'( [sS]|[\d]+)x(\d+)', # 1x01
[ r'^[-\.]+([sS]|[\d])+x(\d+)', [r'^[-\.]+([sS]|[\d])+x(\d+)', r'^[-\.](\d+)']),
r'^[-\.](\d+)'
] ),
(r'[Ss](\d+)[\.\-]?[Ee](\d+)', # S01E01 (r'[Ss](\d+)[\.\-]?[Ee](\d+)', # S01E01
[ r'^[-\.]+[Ss](\d+)[\.\-]?[Ee](\d+)', [r'^[-\.]+[Ss](\d+)[\.\-]?[Ee](\d+)', r'^[-\.](\d+)']),
r'^[-\.](\d+)'
] ),
(r'[ \-_\.](\d)(\d{2,2})[ \-_\.]', # .101. / _101_ / etc. (r'[ \-_\.](\d)(\d{2,2})[ \-_\.]', # .101. / _101_ / etc.
[ []),
] ),
(r'[ \-_\.](\d)(\d{2,2})$', # .101 at end of title (r'[ \-_\.](\d)(\d{2,2})$', # .101 at end of title
[ [])
] )
] ]
date_match = [r'(\d{4})\W(\d{1,2})\W(\d{1,2})', # 2008-10-16 date_match = [r'(\d{4})\W(\d{1,2})\W(\d{1,2})', # 2008-10-16
@ -148,6 +144,7 @@ year_match = r'[\W]([1|2]\d{3})([^\w]|$)' # Something '(YYYY)' or '.YYYY.' or '
sample_match = r'((^|[\W_])sample\d*[\W_])' # something-sample.avi sample_match = r'((^|[\W_])sample\d*[\W_])' # something-sample.avi
class Status(): class Status():
COMPLETED = 'Completed' COMPLETED = 'Completed'
CHECKING = 'Checking' CHECKING = 'Checking'

19
sabnzbd/utils/diskspeed.py

@ -1,9 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
import time, os, sys import time
import os
import sys
def writetofile(filename, mysizeMB): def writetofile(filename, mysizeMB):
# writes string to specified file repeatdely, until mysizeMB is reached. Then deletes fle # writes string to specified file repeat delay, until mysizeMB is reached. Then deletes file
mystring = "The quick brown fox jumps over the lazy dog" mystring = "The quick brown fox jumps over the lazy dog"
writeloops = int(1000000 * mysizeMB / len(mystring)) writeloops = int(1000000 * mysizeMB / len(mystring))
try: try:
@ -16,13 +19,12 @@ def writetofile(filename,mysizeMB):
f.close() f.close()
os.remove(filename) os.remove(filename)
##############
def diskspeedmeasure(dirname): def diskspeedmeasure(dirname):
# returns writing speed to dirname in MB/s # returns writing speed to dirname in MB/s
# method: keep writing a file, until 0.5 seconds is passed. Then divide bytes written by time passed # method: keep writing a file, until 0.5 seconds is passed. Then divide bytes written by time passed
filesize = 1 # in MB filesize = 1 # MB
maxtime = 0.5 # in sec maxtime = 0.5 # sec
filename = os.path.join(dirname, 'outputTESTING.txt') filename = os.path.join(dirname, 'outputTESTING.txt')
start = time.time() start = time.time()
loopcounter = 0 loopcounter = 0
@ -33,11 +35,10 @@ def diskspeedmeasure(dirname):
return None return None
loopcounter += 1 loopcounter += 1
diff = time.time() - start diff = time.time() - start
if diff > maxtime: break if diff > maxtime:
break
return (loopcounter * filesize) / diff return (loopcounter * filesize) / diff
############## Start of main
if __name__ == "__main__": if __name__ == "__main__":
@ -65,5 +66,3 @@ if __name__ == "__main__":
raise raise
print "Done" print "Done"

4
sabnzbd/utils/getipaddress.py

@ -2,6 +2,7 @@
import socket import socket
def localipv4(): def localipv4():
try: try:
s_ipv4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s_ipv4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
@ -13,6 +14,7 @@ def localipv4():
pass pass
return ipv4 return ipv4
def publicipv4(): def publicipv4():
try: try:
import urllib2 import urllib2
@ -24,6 +26,7 @@ def publicipv4():
pass pass
return public_ipv4 return public_ipv4
def ipv6(): def ipv6():
try: try:
s_ipv6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) s_ipv6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
@ -38,4 +41,3 @@ if __name__ == '__main__':
print localipv4() print localipv4()
print publicipv4() print publicipv4()
print ipv6() print ipv6()

2
sabnzbd/utils/getperformance.py

@ -24,8 +24,6 @@ def getpystone():
return value return value
if __name__ == '__main__': if __name__ == '__main__':
print getpystone() print getpystone()
print getcpu() print getcpu()

20
sabnzbd/utils/happyeyeballs.py

@ -23,16 +23,19 @@ def happyeyeballs(HOST, **kwargs):
shortesttime = 10000000 # something very big shortesttime = 10000000 # something very big
quickestserver = None quickestserver = None
if DEBUG: print "Checking", HOST, PORT, "SSL:", SSL, "DEBUG:", DEBUG if DEBUG:
print "Checking", HOST, PORT, "SSL:", SSL, "DEBUG:", DEBUG
try: try:
allinfo = socket.getaddrinfo(HOST, 80, 0, 0, socket.IPPROTO_TCP) allinfo = socket.getaddrinfo(HOST, 80, 0, 0, socket.IPPROTO_TCP)
except: except:
if DEBUG: print "Could not resolve", HOST if DEBUG:
print "Could not resolve", HOST
return None return None
for i in allinfo: for i in allinfo:
address = i[4][0] address = i[4][0]
if DEBUG: print "Address is ", address if DEBUG:
print "Address is ", address
# note: i[0] contains socket.AF_INET or socket.AF_INET6 # note: i[0] contains socket.AF_INET or socket.AF_INET6
try: try:
@ -52,18 +55,20 @@ def happyeyeballs(HOST, **kwargs):
wrappedSocket.close() wrappedSocket.close()
delay = 1000.0 * (time.clock() - start) delay = 1000.0 * (time.clock() - start)
if DEBUG: print "Connecting took:", delay, "msec" if DEBUG:
print "Connecting took:", delay, "msec"
if delay < shortesttime: if delay < shortesttime:
shortesttime = delay shortesttime = delay
quickestserver = address quickestserver = address
except: except:
if DEBUG: print "Something went wrong (possibly just no connection)" if DEBUG:
print "Something went wrong (possibly just no connection)"
pass pass
if DEBUG: print "Quickest server is", quickestserver if DEBUG:
print "Quickest server is", quickestserver
return quickestserver return quickestserver
if __name__ == '__main__': if __name__ == '__main__':
print happyeyeballs('www.google.com') print happyeyeballs('www.google.com')
print happyeyeballs('www.google.com', port=443, ssl=True) print happyeyeballs('www.google.com', port=443, ssl=True)
@ -74,4 +79,3 @@ if __name__ == '__main__':
print happyeyeballs('newszilla.xs4all.nl', port=119) print happyeyeballs('newszilla.xs4all.nl', port=119)
print happyeyeballs('does.not.resolve', port=443, ssl=True, debug=True) print happyeyeballs('does.not.resolve', port=443, ssl=True, debug=True)
print happyeyeballs('216.58.211.164') print happyeyeballs('216.58.211.164')

7
sabnzbd/utils/servertests.py

@ -28,6 +28,7 @@ from sabnzbd.config import get_servers
from sabnzbd.encoding import xml_name from sabnzbd.encoding import xml_name
from sabnzbd.misc import int_conv from sabnzbd.misc import int_conv
def test_nntp_server_dict(kwargs): def test_nntp_server_dict(kwargs):
# Grab the host/port/user/pass/connections/ssl # Grab the host/port/user/pass/connections/ssl
host = kwargs.get('host', '').strip() host = kwargs.get('host', '').strip()
@ -48,13 +49,12 @@ def test_nntp_server_dict(kwargs):
else: else:
port = 119 port = 119
return test_nntp_server(host, port, server, username=username,
return test_nntp_server(host, port, server, username=username, \
password=password, ssl=ssl, ssl_type=ssl_type) password=password, ssl=ssl, ssl_type=ssl_type)
def test_nntp_server(host, port, server=None, username=None, password=None, ssl=None, ssl_type='t1'): def test_nntp_server(host, port, server=None, username=None, password=None, ssl=None, ssl_type='t1'):
''' Will connect (blocking) to the nttp server and report back any errors ''' """ Will connect (blocking) to the nttp server and report back any errors """
timeout = 4.0 timeout = 4.0
if '*' in password and not password.strip('*'): if '*' in password and not password.strip('*'):
# If the password is masked, try retrieving it from the config # If the password is masked, try retrieving it from the config
@ -104,7 +104,6 @@ def test_nntp_server(host, port, server=None, username=None, password=None, ssl=
except: except:
return False, unicode(sys.exc_info()[1]) return False, unicode(sys.exc_info()[1])
if not username or not password: if not username or not password:
nw.nntp.sock.sendall('ARTICLE <test@home>\r\n') nw.nntp.sock.sendall('ARTICLE <test@home>\r\n')
try: try:

22
sabnzbd/utils/systrayiconthread.py

@ -19,8 +19,8 @@ except ImportError:
from threading import Thread from threading import Thread
from time import sleep from time import sleep
class SysTrayIconThread(Thread): class SysTrayIconThread(Thread):
'''TODO'''
QUIT = 'QUIT' QUIT = 'QUIT'
SPECIAL_ACTIONS = [QUIT] SPECIAL_ACTIONS = [QUIT]
@ -47,13 +47,11 @@ class SysTrayIconThread(Thread):
self.menu_actions_by_id = dict(self.menu_actions_by_id) self.menu_actions_by_id = dict(self.menu_actions_by_id)
del self._next_action_id del self._next_action_id
self.default_menu_index = (default_menu_index or 0) self.default_menu_index = (default_menu_index or 0)
self.window_class_name = window_class_name or "SysTrayIconPy" self.window_class_name = window_class_name or "SysTrayIconPy"
self.start() self.start()
def initialize(self): def initialize(self):
message_map = {win32gui.RegisterWindowMessage("TaskbarCreated"): self.restart, message_map = {win32gui.RegisterWindowMessage("TaskbarCreated"): self.restart,
win32con.WM_DESTROY: self.destroy, win32con.WM_DESTROY: self.destroy,
@ -63,7 +61,7 @@ class SysTrayIconThread(Thread):
window_class = win32gui.WNDCLASS() window_class = win32gui.WNDCLASS()
hinst = window_class.hInstance = win32gui.GetModuleHandle(None) hinst = window_class.hInstance = win32gui.GetModuleHandle(None)
window_class.lpszClassName = self.window_class_name window_class.lpszClassName = self.window_class_name
window_class.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW; window_class.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW
window_class.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW) window_class.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW)
window_class.hbrBackground = win32con.COLOR_WINDOW window_class.hbrBackground = win32con.COLOR_WINDOW
window_class.lpfnWndProc = message_map # could also specify a wndproc. window_class.lpfnWndProc = message_map # could also specify a wndproc.
@ -115,8 +113,9 @@ class SysTrayIconThread(Thread):
return result return result
def get_icon(self, path): def get_icon(self, path):
hicon = self.icons.get(path); hicon = self.icons.get(path)
if hicon != None: return hicon if hicon != None:
return hicon
# Try and find a custom icon # Try and find a custom icon
hinst = win32gui.GetModuleHandle(None) hinst = win32gui.GetModuleHandle(None)
@ -137,8 +136,10 @@ class SysTrayIconThread(Thread):
def refresh_icon(self): def refresh_icon(self):
hicon = self.get_icon(self.icon) hicon = self.get_icon(self.icon)
if self.notify_id: message = win32gui.NIM_MODIFY if self.notify_id:
else: message = win32gui.NIM_ADD message = win32gui.NIM_MODIFY
else:
message = win32gui.NIM_ADD
self.notify_id = (self.hwnd, self.notify_id = (self.hwnd,
0, 0,
win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP, win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP,
@ -155,7 +156,8 @@ class SysTrayIconThread(Thread):
self.refresh_icon() self.refresh_icon()
def destroy(self, hwnd, msg, wparam, lparam): def destroy(self, hwnd, msg, wparam, lparam):
if self.on_quit: self.on_quit(self) if self.on_quit:
self.on_quit(self)
nid = (self.hwnd, 0) nid = (self.hwnd, 0)
win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, nid) win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, nid)
win32gui.PostQuitMessage(0) # Terminate the app. win32gui.PostQuitMessage(0) # Terminate the app.
@ -242,6 +244,7 @@ class SysTrayIconThread(Thread):
else: else:
menu_action(self) menu_action(self)
def non_string_iterable(obj): def non_string_iterable(obj):
try: try:
iter(obj) iter(obj)
@ -249,4 +252,3 @@ def non_string_iterable(obj):
return False return False
else: else:
return not isinstance(obj, basestring) return not isinstance(obj, basestring)

3
sabnzbd/utils/upload.py

@ -16,7 +16,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
""" """
sabnzbd.utils.upload - File assosiation functions for adding nzb files to sabnzbd sabnzbd.utils.upload - File association functions for adding nzb files to sabnzbd
""" """
import urllib2 import urllib2
@ -30,6 +30,7 @@ from sabnzbd.constants import VALID_ARCHIVES
from sabnzbd.dirscanner import ProcessArchiveFile, ProcessSingleFile from sabnzbd.dirscanner import ProcessArchiveFile, ProcessSingleFile
def upload_file(url, fp): def upload_file(url, fp):
""" Function for uploading nzbs to a running sabnzbd instance """ """ Function for uploading nzbs to a running sabnzbd instance """
try: try:

Loading…
Cancel
Save