Browse Source

More pep8 non-agressive fixes.

pull/346/head
Jonathon Saine 10 years ago
parent
commit
cc0b15eb46
  1. 4
      SABHelper.py
  2. 592
      sabnzbd/api.py
  3. 24
      sabnzbd/bpsmeter.py
  4. 56
      sabnzbd/cfg.py
  5. 83
      sabnzbd/config.py
  6. 107
      sabnzbd/constants.py
  7. 2
      sabnzbd/interface.py
  8. 111
      sabnzbd/utils/diskspeed.py
  9. 6
      sabnzbd/utils/getipaddress.py
  10. 6
      sabnzbd/utils/getperformance.py
  11. 40
      sabnzbd/utils/happyeyeballs.py
  12. 7
      sabnzbd/utils/servertests.py
  13. 38
      sabnzbd/utils/systrayiconthread.py
  14. 7
      sabnzbd/utils/upload.py

4
SABHelper.py

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

592
sabnzbd/api.py

File diff suppressed because it is too large

24
sabnzbd/bpsmeter.py

@ -131,17 +131,17 @@ class BPSMeter(object):
self.month_total = {}
self.grand_total = {}
self.end_of_day = tomorrow(t) # Time that current day will end
self.end_of_week = next_week(t) # Time that current day will end
self.end_of_day = tomorrow(t) # Time that current day will end
self.end_of_week = next_week(t) # Time that current day will end
self.end_of_month = next_month(t) # Time that current month will end
self.q_day = 1 # Day of quota reset
self.q_period = 'm' # Daily/Weekly/Monthly quota = d/w/m
self.quota = self.left = 0.0 # Quota and remaining quota
self.have_quota = False # Flag for quota active
self.q_time = 0L # Next reset time for quota
self.q_hour = 0 # Quota reset hour
self.q_minute = 0 # Quota reset minute
self.quota_enabled = True # Scheduled quota enable/disable
self.q_day = 1 # Day of quota reset
self.q_period = 'm' # Daily/Weekly/Monthly quota = d/w/m
self.quota = self.left = 0.0 # Quota and remaining quota
self.have_quota = False # Flag for quota active
self.q_time = 0L # Next reset time for quota
self.q_hour = 0 # Quota reset hour
self.q_minute = 0 # Quota reset minute
self.quota_enabled = True # Scheduled quota enable/disable
BPSMeter.do = self
def save(self):
@ -253,8 +253,7 @@ class BPSMeter(object):
# Speedometer
try:
self.bps = (self.bps * (self.last_update - self.start_time)
+ amount) / (t - self.start_time)
self.bps = (self.bps * (self.last_update - self.start_time) + amount) / (t - self.start_time)
except:
self.bps = 0.0
@ -406,7 +405,6 @@ class BPSMeter(object):
# The <day> and <hh:mm> part can both be optional
__re_day = re.compile('^\s*(\d+)[^:]*')
__re_hm = re.compile('(\d+):(\d+)\s*$')
def get_quota(self):
""" If quota active, return check-function, hour, minute """
if self.have_quota:

56
sabnzbd/cfg.py

@ -22,17 +22,17 @@ import re
import sabnzbd
from sabnzbd.constants import DEF_HOST, DEF_PORT_WIN_SSL, DEF_PORT_WIN, DEF_STDINTF, \
DEF_DOWNLOAD_DIR, DEF_NZBBACK_DIR, DEF_PORT_UNIX_SSL, \
NORMAL_PRIORITY, DEF_SCANRATE, DEF_PORT_UNIX, DEF_COMPLETE_DIR, \
DEF_ADMIN_DIR
DEF_DOWNLOAD_DIR, DEF_NZBBACK_DIR, DEF_PORT_UNIX_SSL, \
NORMAL_PRIORITY, DEF_SCANRATE, DEF_PORT_UNIX, DEF_COMPLETE_DIR, \
DEF_ADMIN_DIR
from sabnzbd.config import OptionBool, OptionNumber, OptionPassword, \
OptionDir, OptionStr, OptionList, no_nonsense, \
validate_octal, validate_safedir, validate_dir_exists, \
create_api_key, validate_notempty
OptionDir, OptionStr, OptionList, no_nonsense, \
validate_octal, validate_safedir, validate_dir_exists, \
create_api_key, validate_notempty
#------------------------------------------------------------------------------
##############################################################################
# Email validation support
#
##############################################################################
RE_VAL = re.compile('[^@ ]+@[^.@ ]+\.[^.@ ]')
def validate_email(value):
global email_endjob, email_full, email_rss
@ -55,27 +55,26 @@ def validate_server(value):
else:
return None, value
#------------------------------------------------------------------------------
if sabnzbd.WIN32:
DEF_FOLDER_MAX = 128
else:
DEF_FOLDER_MAX = 256
#------------------------------------------------------------------------------
##############################################################################
# Configuration instances
#
##############################################################################
quick_check = OptionBool('misc', 'quick_check', True)
sfv_check = OptionBool('misc', 'sfv_check', True)
email_server = OptionStr('misc', 'email_server', validation=validate_server)
email_to = OptionList('misc', 'email_to', validation=validate_email)
email_from = OptionStr('misc', 'email_from', validation=validate_email)
email_server = OptionStr('misc', 'email_server', validation=validate_server)
email_to = OptionList('misc', 'email_to', validation=validate_email)
email_from = OptionStr('misc', 'email_from', validation=validate_email)
email_account = OptionStr('misc', 'email_account')
email_pwd = OptionPassword('misc', 'email_pwd')
email_endjob = OptionNumber('misc', 'email_endjob', 0, 0, 2)
email_full = OptionBool('misc', 'email_full', False)
email_dir = OptionDir('misc', 'email_dir', create=True)
email_rss = OptionBool('misc', 'email_rss', False)
email_pwd = OptionPassword('misc', 'email_pwd')
email_endjob = OptionNumber('misc', 'email_endjob', 0, 0, 2)
email_full = OptionBool('misc', 'email_full', False)
email_dir = OptionDir('misc', 'email_dir', create=True)
email_rss = OptionBool('misc', 'email_rss', False)
version_check = OptionNumber('misc', 'check_new_rel', 1)
autobrowser = OptionBool('misc', 'auto_browser', True)
@ -100,8 +99,8 @@ overwrite_files = OptionBool('misc', 'overwrite_files', False)
flat_unpack = OptionBool('misc', 'flat_unpack', False)
par_option = OptionStr('misc', 'par_option', '', validation=no_nonsense)
nice = OptionStr('misc', 'nice', '', validation=no_nonsense)
ionice = OptionStr('misc', 'ionice', '', validation=no_nonsense)
nice = OptionStr('misc', 'nice', '', validation=no_nonsense)
ionice = OptionStr('misc', 'ionice', '', validation=no_nonsense)
ignore_wrong_unrar = OptionBool('misc', 'ignore_wrong_unrar', False)
par2_multicore = OptionBool('misc', 'par2_multicore', True)
allow_64bit_tools = OptionBool('misc', 'allow_64bit_tools', True)
@ -181,12 +180,12 @@ configlock = OptionBool('misc', 'config_lock', 0)
umask = OptionStr('misc', 'permissions', '', validation=validate_octal)
download_dir = OptionDir('misc', 'download_dir', DEF_DOWNLOAD_DIR, create=False, validation=validate_safedir)
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)
script_dir = OptionDir('misc', 'script_dir', create=True, writable=False)
nzb_backup_dir = OptionDir('misc', 'nzb_backup_dir', DEF_NZBBACK_DIR)
admin_dir = OptionDir('misc', 'admin_dir', DEF_ADMIN_DIR, validation=validate_safedir)
#log_dir = OptionDir('misc', 'log_dir', 'logs')
# log_dir = OptionDir('misc', 'log_dir', 'logs')
dirscan_dir = OptionDir('misc', 'dirscan_dir', create=False)
dirscan_speed = OptionNumber('misc', 'dirscan_speed', DEF_SCANRATE, 0, 3600)
size_limit = OptionStr('misc', 'size_limit', '0')
@ -212,7 +211,7 @@ login_realm = OptionStr('misc', 'login_realm', 'SABnzbd')
bandwidth_perc = OptionNumber('misc', 'bandwidth_perc', 0, 0, 100)
bandwidth_max = OptionStr('misc', 'bandwidth_max')
refresh_rate = OptionNumber('misc', 'refresh_rate', 0)
rss_rate = OptionNumber('misc', 'rss_rate', 60, 15, 24*60)
rss_rate = OptionNumber('misc', 'rss_rate', 60, 15, 24 * 60)
cache_limit = OptionStr('misc', 'cache_limit')
web_dir = OptionStr('misc', 'web_dir', DEF_STDINTF)
web_dir2 = OptionStr('misc', 'web_dir2')
@ -234,7 +233,7 @@ log_new = OptionBool('logging', 'log_new', False)
https_cert = OptionDir('misc', 'https_cert', 'server.cert', create=False)
https_key = OptionDir('misc', 'https_key', 'server.key', create=False)
https_chain = OptionDir('misc','https_chain', create=False)
https_chain = OptionDir('misc', 'https_chain', create=False)
enable_https = OptionBool('misc', 'enable_https', False)
language = OptionStr('misc', 'language', 'en')
@ -251,7 +250,7 @@ nzb_key = OptionStr('misc', 'nzb_key', create_api_key())
disable_key = OptionBool('misc', 'disable_api_key', False, protect=True)
api_warnings = OptionBool('misc', 'api_warnings', True, protect=True)
local_ranges = OptionList('misc', 'local_ranges', protect=True)
inet_exposure = OptionNumber('misc', 'inet_exposure', 0, protect=True) # 0=local-only, 1=nzb, 2=api, 3=full_api, 4=webui
inet_exposure = OptionNumber('misc', 'inet_exposure', 0, protect=True) # 0=local-only, 1=nzb, 2=api, 3=full_api, 4=webui
max_art_tries = OptionNumber('misc', 'max_art_tries', 3, 2)
max_art_opt = OptionBool('misc', 'max_art_opt', False)
use_pickle = OptionBool('misc', 'use_pickle', False)
@ -365,9 +364,9 @@ warn_dupl_jobs = OptionBool('misc', 'warn_dupl_jobs', True)
new_nzb_on_failure = OptionBool('misc', 'new_nzb_on_failure', False)
#------------------------------------------------------------------------------
##############################################################################
# Set root folders for Folder config-items
#
##############################################################################
def set_root_folders(home, lcldata):
email_dir.set_root(home)
download_dir.set_root(home)
@ -379,6 +378,7 @@ def set_root_folders(home, lcldata):
log_dir.set_root(lcldata)
password_file.set_root(home)
def set_root_folders2():
https_cert.set_root(admin_dir.get_path())
https_key.set_root(admin_dir.get_path())

83
sabnzbd/config.py

@ -46,13 +46,14 @@ modified = False # Signals a change in option dictionary
class Option(object):
""" Basic option class, basic fields """
def __init__(self, section, keyword, default_val=None, add=True, protect=False):
""" Basic option
section : single section or comma-separated list of sections
a list will be a hierarchy: "foo, bar" --> [foo][[bar]]
keyword : keyword in the (last) section
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)
"""
self.__sections = section.split(',')
@ -88,7 +89,7 @@ class Option(object):
def get_dict(self, safe=False):
""" Return value a dictionary """
return { self.__keyword : self.get() }
return {self.__keyword: self.get()}
def set_dict(self, dict):
""" Set value based on dictionary """
@ -125,9 +126,9 @@ class Option(object):
return self.__sections, self.__keyword
class OptionNumber(Option):
""" 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):
Option.__init__(self, section, keyword, default_val, add=add, protect=protect)
self.__minval = minval
@ -159,6 +160,7 @@ class OptionNumber(Option):
class OptionBool(Option):
""" Boolean option class """
def __init__(self, section, keyword, default_val=False, add=True, protect=False):
Option.__init__(self, section, keyword, int(default_val), add=add, protect=protect)
@ -174,6 +176,7 @@ class OptionBool(Option):
class OptionDir(Option):
""" Directory option class """
def __init__(self, section, keyword, default_val='', apply_umask=False, create=True, validation=None, writable=True, add=True):
self.__validation = validation
self.__root = '' # Base directory for relative paths
@ -192,7 +195,6 @@ class OptionDir(Option):
return p.replace('/', '\\') if '/' in p else p
else:
return p.replace('\\', '/') if '\\' in p else p
def get_path(self):
""" Return full absolute path """
@ -240,8 +242,10 @@ class OptionDir(Option):
""" Set auto-creation value """
self.__create = value
class OptionList(Option):
""" List option class """
def __init__(self, section, keyword, default_val=None, validation=None, add=True, protect=False):
self.__validation = validation
if default_val is None:
@ -249,7 +253,7 @@ class OptionList(Option):
Option.__init__(self, section, keyword, default_val, add=add, protect=protect)
def set(self, value):
""" Set the list given a comma-separated string or a list"""
""" Set the list given a comma-separated string or a list """
error = None
if value is not None:
if not isinstance(value, list):
@ -272,12 +276,14 @@ class OptionList(Option):
r = len(lst)
for n in xrange(r):
txt += lst[n]
if n < r-1: txt += ', '
if n < r - 1:
txt += ', '
return txt
class OptionStr(Option):
""" String class """
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)
self.__validation = validation
@ -306,6 +312,7 @@ class OptionStr(Option):
class OptionPassword(Option):
""" Password class """
def __init__(self, section, keyword, default_val='', add=True):
Option.__init__(self, section, keyword, default_val, add=add)
self.get_string = self.get_stars
@ -325,9 +332,9 @@ class OptionPassword(Option):
def get_dict(self, safe=False):
""" Return value a dictionary """
if safe:
return { self._Option__keyword : self.get_stars() }
return {self._Option__keyword: self.get_stars()}
else:
return { self._Option__keyword : self.get() }
return {self._Option__keyword: self.get()}
def set(self, pw):
""" Set password, encode it """
@ -361,6 +368,7 @@ def delete_from_database(section, keyword):
class ConfigServer(object):
""" Class defining a single server """
def __init__(self, name, values):
self.__name = name
@ -368,7 +376,7 @@ class ConfigServer(object):
self.displayname = OptionStr(name, 'displayname', '', add=False)
self.host = OptionStr(name, 'host', '', add=False)
self.port = OptionNumber(name, 'port', 119, 0, 2**16-1, add=False)
self.port = OptionNumber(name, 'port', 119, 0, 2 ** 16 - 1, add=False)
self.timeout = OptionNumber(name, 'timeout', 120, 30, 240, add=False)
self.username = OptionStr(name, 'username', '', add=False)
self.password = OptionPassword(name, 'password', '', add=False)
@ -441,6 +449,7 @@ class ConfigServer(object):
class ConfigCat(object):
""" Class defining a single category """
def __init__(self, name, values):
self.__name = name
name = 'categories,' + name
@ -482,6 +491,7 @@ class ConfigCat(object):
class OptionFilters(Option):
""" Filter list class """
def __init__(self, section, keyword, add=True):
Option.__init__(self, section, keyword, add=add)
self.set([])
@ -521,7 +531,7 @@ class OptionFilters(Option):
dict = {}
n = 0
for filter in self.get():
dict['filter'+str(n)] = filter
dict['filter' + str(n)] = filter
n = n + 1
return dict
@ -545,8 +555,10 @@ class OptionFilters(Option):
self.set(filters)
return True
class ConfigRSS(object):
""" Class defining a single Feed definition """
def __init__(self, name, values):
self.__name = name
name = 'rss,' + name
@ -598,7 +610,6 @@ class ConfigRSS(object):
return 'rss', self.__name
def get_dconfig(section, keyword, nested=False):
""" Return a config values dictonary,
Single item or slices based on 'section', 'keyword'
@ -633,16 +644,15 @@ def get_dconfig(section, keyword, nested=False):
data = item.get_dict(safe=True)
if not nested:
if section in ('servers', 'categories', 'rss'):
data = {section : [ data ]}
data = {section: [data]}
else:
data = {section : data}
data = {section: data}
return True, data
def get_config(section, keyword):
""" Return a config object, based on 'section', 'keyword'
"""
""" Return a config object, based on 'section', 'keyword' """
try:
return database[section][keyword]
except KeyError:
@ -651,8 +661,7 @@ def get_config(section, keyword):
def set_config(kwargs):
""" Set a config item, using values in dictionary
"""
""" Set a config item, using values in dictionary """
try:
item = database[kwargs.get('section')][kwargs.get('keyword')]
except KeyError:
@ -662,21 +671,19 @@ def set_config(kwargs):
def delete(section, keyword):
""" Delete specific config item
"""
""" Delete specific config item """
try:
database[section][keyword].delete()
except KeyError:
return
################################################################################
#
##############################################################################
# INI file support
#
# This does input and output of configuration to an INI file.
# It translates this data structure to the config database.
##############################################################################
@synchronized(SAVE_CONFIG_LOCK)
def read_config(path):
""" Read the complete INI file and check its version number
@ -775,7 +782,6 @@ def _read_config(path, try_backup=False):
return True, ""
@synchronized(SAVE_CONFIG_LOCK)
def save_config(force=False):
""" Update Setup file with current option values """
@ -793,7 +799,7 @@ def save_config(force=False):
CFG[section] = {}
for subsec in database[section]:
if section == 'servers':
subsec_mod = subsec.replace('[', '{').replace(']','}')
subsec_mod = subsec.replace('[', '{').replace(']', '}')
else:
subsec_mod = subsec
try:
@ -833,7 +839,7 @@ def save_config(force=False):
except:
# Something wrong with the backup,
logging.error(T('Cannot create backup file for %s'), bakname)
logging.info("Traceback: ", exc_info = True)
logging.info("Traceback: ", exc_info=True)
return res
# Write new config file
@ -843,7 +849,7 @@ def save_config(force=False):
res = True
except:
logging.error(T('Cannot write to INI file %s'), filename)
logging.info("Traceback: ", exc_info = True)
logging.info("Traceback: ", exc_info=True)
try:
os.remove(filename)
except:
@ -854,7 +860,6 @@ def save_config(force=False):
return res
def define_servers():
""" Define servers listed in the Setup file
return a list of ConfigServer instances
@ -871,6 +876,7 @@ def define_servers():
except KeyError:
pass
def get_servers():
global database
try:
@ -909,8 +915,8 @@ def get_categories(cat=0):
database['categories'] = {}
cats = database['categories']
if '*' not in cats:
ConfigCat('*', {'pp' : old_def('dirscan_opts', '3'), 'script' : old_def('dirscan_script', 'None'), \
'priority' : old_def('dirscan_priority', NORMAL_PRIORITY)})
ConfigCat('*', {'pp': old_def('dirscan_opts', '3'), 'script': old_def('dirscan_script', 'None'),
'priority': old_def('dirscan_priority', NORMAL_PRIORITY)})
save_config(True)
if not isinstance(cat, int):
try:
@ -931,6 +937,7 @@ def define_rss():
except KeyError:
pass
def get_rss():
global database
try:
@ -938,18 +945,16 @@ def get_rss():
except KeyError:
return {}
def get_filename():
global CFG
return CFG.filename
################################################################################
#
##############################################################################
# Default Validation handlers
#
##############################################################################
__PW_PREFIX = '!!!encoded!!!'
#------------------------------------------------------------------------------
def encode_password(pw):
""" Encode password in hexadecimal if needed """
enc = False
@ -973,7 +978,7 @@ def decode_password(pw, name):
if pw and pw.startswith(__PW_PREFIX):
for n in range(len(__PW_PREFIX), len(pw), 2):
try:
ch = chr( int(pw[n] + pw[n+1], 16) )
ch = chr(int(pw[n] + pw[n + 1], 16))
except ValueError:
logging.error(T('Incorrectly encoded password %s'), name)
return ''
@ -1041,8 +1046,7 @@ def validate_notempty(root, value, default):
def create_api_key():
""" Return a new randomized API_KEY
"""
""" Return a new randomized API_KEY """
import time
try:
from hashlib import md5
@ -1061,12 +1065,11 @@ def create_api_key():
return m.hexdigest()
#------------------------------------------------------------------------------
_FIXES = \
(
_FIXES = (
('enable_par_multicore', 'par2_multicore'),
)
def compatibility_fix(cf):
""" Convert obsolete INI entries """
for item in _FIXES:

107
sabnzbd/constants.py

@ -54,15 +54,15 @@ GIGI = float(2 ** 30)
MEBI = float(2 ** 20)
KIBI = float(2 ** 10)
BYTES_FILE_NAME_OLD = 'totals9.sab'
BYTES_FILE_NAME = 'totals10.sab'
QUEUE_FILE_TMPL = 'queue%s.sab'
QUEUE_FILE_NAME = QUEUE_FILE_TMPL % QUEUE_VERSION
POSTPROC_QUEUE_FILE_NAME = 'postproc%s.sab' % POSTPROC_QUEUE_VERSION
RSS_FILE_NAME = 'rss_data.sab'
SCAN_FILE_NAME = 'watched_data2.sab'
TERM_FLAG_FILE = 'running.sab'
FUTURE_Q_FOLDER = 'future'
BYTES_FILE_NAME_OLD = 'totals9.sab'
BYTES_FILE_NAME = 'totals10.sab'
QUEUE_FILE_TMPL = 'queue%s.sab'
QUEUE_FILE_NAME = QUEUE_FILE_TMPL % QUEUE_VERSION
POSTPROC_QUEUE_FILE_NAME = 'postproc%s.sab' % POSTPROC_QUEUE_VERSION
RSS_FILE_NAME = 'rss_data.sab'
SCAN_FILE_NAME = 'watched_data2.sab'
TERM_FLAG_FILE = 'running.sab'
FUTURE_Q_FOLDER = 'future'
JOB_ADMIN = '__ADMIN__'
VERIFIED_FILE = '__verified__'
QCHECK_FILE = '__skip_qcheck__'
@ -78,36 +78,36 @@ DB_QUEUE_NAME = 'queue%s.db' % DB_QUEUE_VERSION
DEF_DOWNLOAD_DIR = 'Downloads/incomplete'
DEF_COMPLETE_DIR = 'Downloads/complete'
DEF_ADMIN_DIR = 'admin'
DEF_LOG_DIR = 'logs'
DEF_NZBBACK_DIR = ''
DEF_LANGUAGE = 'locale'
DEF_INTERFACES = 'interfaces'
DEF_ADMIN_DIR = 'admin'
DEF_LOG_DIR = 'logs'
DEF_NZBBACK_DIR = ''
DEF_LANGUAGE = 'locale'
DEF_INTERFACES = 'interfaces'
DEF_INT_LANGUAGE = 'locale'
DEF_EMAIL_TMPL = 'email'
DEF_STDCONFIG = 'Config'
DEF_STDINTF = 'Glitter'
DEF_SKIN_COLORS = {'smpl' : 'white', 'Glitter' : 'Default', 'plush' : 'gold'}
DEF_MAIN_TMPL = 'templates/main.tmpl'
DEF_INI_FILE = 'sabnzbd.ini'
DEF_HOST = '127.0.0.1'
DEF_PORT_WIN = 8080
DEF_PORT_UNIX = 8080
DEF_EMAIL_TMPL = 'email'
DEF_STDCONFIG = 'Config'
DEF_STDINTF = 'Glitter'
DEF_SKIN_COLORS = {'smpl': 'white', 'Glitter': 'Default', 'plush': 'gold'}
DEF_MAIN_TMPL = 'templates/main.tmpl'
DEF_INI_FILE = 'sabnzbd.ini'
DEF_HOST = '127.0.0.1'
DEF_PORT_WIN = 8080
DEF_PORT_UNIX = 8080
DEF_PORT_WIN_SSL = 9090
DEF_PORT_UNIX_SSL= 9090
DEF_WORKDIR = 'sabnzbd'
DEF_LOG_FILE = 'sabnzbd.log'
DEF_LOG_ERRFILE = 'sabnzbd.error.log'
DEF_LOG_CHERRY = 'cherrypy.log'
DEF_TIMEOUT = 60
MIN_TIMEOUT = 10
MAX_TIMEOUT = 200
DEF_LOGLEVEL = 1
DEF_SCANRATE = 5
DEF_QRATE = 0
DEF_PORT_UNIX_SSL = 9090
DEF_WORKDIR = 'sabnzbd'
DEF_LOG_FILE = 'sabnzbd.log'
DEF_LOG_ERRFILE = 'sabnzbd.error.log'
DEF_LOG_CHERRY = 'cherrypy.log'
DEF_TIMEOUT = 60
MIN_TIMEOUT = 10
MAX_TIMEOUT = 200
DEF_LOGLEVEL = 1
DEF_SCANRATE = 5
DEF_QRATE = 0
MIN_DECODE_QUEUE = 5
MAX_DECODE_QUEUE = 10
MAX_WARNINGS = 20
MAX_WARNINGS = 20
REPAIR_PRIORITY = 3
TOP_PRIORITY = 2
@ -123,30 +123,27 @@ VALID_ARCHIVES = ('.zip', '.rar', '.7z')
IGNORED_FOLDERS = ('@eaDir', '.appleDouble')
#(MATCHER, [EXTRA,MATCHERS])
series_match = [ (r'( [sS]|[\d]+)x(\d+)', # 1x01
[ r'^[-\.]+([sS]|[\d])+x(\d+)',
r'^[-\.](\d+)'
] ),
(r'[Ss](\d+)[\.\-]?[Ee](\d+)', # S01E01
[ r'^[-\.]+[Ss](\d+)[\.\-]?[Ee](\d+)',
r'^[-\.](\d+)'
] ),
(r'[ \-_\.](\d)(\d{2,2})[ \-_\.]', # .101. / _101_ / etc.
[
] ),
(r'[ \-_\.](\d)(\d{2,2})$', # .101 at end of title
[
] )
# (MATCHER, [EXTRA, MATCHERS])
series_match = [(r'( [sS]|[\d]+)x(\d+)', # 1x01
[r'^[-\.]+([sS]|[\d])+x(\d+)', r'^[-\.](\d+)']),
(r'[Ss](\d+)[\.\-]?[Ee](\d+)', # S01E01
[r'^[-\.]+[Ss](\d+)[\.\-]?[Ee](\d+)', r'^[-\.](\d+)']),
(r'[ \-_\.](\d)(\d{2,2})[ \-_\.]', # .101. / _101_ / etc.
[]),
(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
r'(\d{1,2})\W(\d{1,2})\W(\d{4})'] #10.16.2008
date_match = [r'(\d{4})\W(\d{1,2})\W(\d{1,2})', # 2008-10-16
r'(\d{1,2})\W(\d{1,2})\W(\d{4})'] # 10.16.2008
year_match = r'[\W]([1|2]\d{3})([^\w]|$)' # Something '(YYYY)' or '.YYYY.' or ' YYYY '
year_match = r'[\W]([1|2]\d{3})([^\w]|$)' # Something '(YYYY)' or '.YYYY.' or ' YYYY '
sample_match = r'((^|[\W_])sample\d*[\W_])' # something-sample.avi
sample_match = r'((^|[\W_])sample\d*[\W_])' # something-sample.avi
class Status():
COMPLETED = 'Completed'

2
sabnzbd/interface.py

@ -282,7 +282,7 @@ class MainPage(object):
cfg.warned_old_queue.set(True)
config.save_config()
return panic_old_queue()
if not cfg.notified_new_skin() and cfg.web_dir() != 'Glitter':
logging.warning(T('Try our new skin Glitter! Fresh new design that is optimized for desktop and mobile devices. Go to Config -> General to change your skin.'))
if not cfg.notified_new_skin():

111
sabnzbd/utils/diskspeed.py

@ -1,69 +1,68 @@
#!/usr/bin/env python
import time, os, sys
import time
import os
import sys
def writetofile(filename,mysizeMB):
# writes string to specified file repeatdely, until mysizeMB is reached. Then deletes fle
mystring = "The quick brown fox jumps over the lazy dog"
writeloops = int(1000000*mysizeMB/len(mystring))
try:
f = open(filename, 'w')
except:
# no better idea than:
raise
for x in range(0, writeloops):
f.write(mystring)
f.close()
os.remove(filename)
##############
def writetofile(filename, mysizeMB):
# writes string to specified file repeat delay, until mysizeMB is reached. Then deletes file
mystring = "The quick brown fox jumps over the lazy dog"
writeloops = int(1000000 * mysizeMB / len(mystring))
try:
f = open(filename, 'w')
except:
# no better idea than:
raise
for x in range(0, writeloops):
f.write(mystring)
f.close()
os.remove(filename)
def diskspeedmeasure(dirname):
# 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
filesize = 1 # in MB
maxtime = 0.5 # in sec
filename = os.path.join(dirname,'outputTESTING.txt')
start = time.time()
loopcounter = 0
while True:
try:
writetofile(filename, filesize)
except:
return None
loopcounter += 1
diff = time.time() - start
if diff > maxtime: break
return (loopcounter*filesize)/diff
############## Start of main
def diskspeedmeasure(dirname):
# 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
filesize = 1 # MB
maxtime = 0.5 # sec
filename = os.path.join(dirname, 'outputTESTING.txt')
start = time.time()
loopcounter = 0
while True:
try:
writetofile(filename, filesize)
except:
return None
loopcounter += 1
diff = time.time() - start
if diff > maxtime:
break
return (loopcounter * filesize) / diff
if __name__ == "__main__":
print "Let's go"
if len(sys.argv) >= 2:
dirname = sys.argv[1]
if not os.path.isdir(dirname):
print "Specified argument is not a directory. Bailing out"
sys.exit(1)
else:
# no argument, so use current working directory
dirname = os.getcwd()
print "Using current working directory"
try:
speed = diskspeedmeasure(dirname)
print("Disk writing speed: %.2f Mbytes per second" % speed)
except IOError, e:
#print "IOError:", e
if e.errno == 13:
print "Could not create test file. Check that you have write rights to directory", dirname
except:
print "Something else went wrong"
raise
print "Let's go"
print "Done"
if len(sys.argv) >= 2:
dirname = sys.argv[1]
if not os.path.isdir(dirname):
print "Specified argument is not a directory. Bailing out"
sys.exit(1)
else:
# no argument, so use current working directory
dirname = os.getcwd()
print "Using current working directory"
try:
speed = diskspeedmeasure(dirname)
print("Disk writing speed: %.2f Mbytes per second" % speed)
except IOError, e:
# print "IOError:", e
if e.errno == 13:
print "Could not create test file. Check that you have write rights to directory", dirname
except:
print "Something else went wrong"
raise
print "Done"

6
sabnzbd/utils/getipaddress.py

@ -2,6 +2,7 @@
import socket
def localipv4():
try:
s_ipv4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
@ -13,17 +14,19 @@ def localipv4():
pass
return ipv4
def publicipv4():
try:
import urllib2
f = urllib2.urlopen("http://api.ipify.org", timeout=2) # timeout 2 seconds, in case website is not accessible
public_ipv4 = f.read()
socket.inet_aton(public_ipv4) # if we got anything else than a plain IPv4 address, this will raise an exception
socket.inet_aton(public_ipv4) # if we got anything else than a plain IPv4 address, this will raise an exception
except:
public_ipv4 = None
pass
return public_ipv4
def ipv6():
try:
s_ipv6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
@ -38,4 +41,3 @@ if __name__ == '__main__':
print localipv4()
print publicipv4()
print ipv6()

6
sabnzbd/utils/getperformance.py

@ -18,14 +18,12 @@ def getpystone():
try:
exec "from " + pystonemodule + " import pystones"
value = int(pystones(1000)[1])
break # import and calculation worked, so we're done. Get out of the for loop
break # import and calculation worked, so we're done. Get out of the for loop
except:
pass # ... the import went wrong, so continue in the for loop
pass # ... the import went wrong, so continue in the for loop
return value
if __name__ == '__main__':
print getpystone()
print getcpu()

40
sabnzbd/utils/happyeyeballs.py

@ -8,31 +8,34 @@ import ssl
def happyeyeballs(HOST, **kwargs):
try:
PORT=kwargs['port']
PORT = kwargs['port']
except:
PORT=80
PORT = 80
try:
SSL=kwargs['ssl']
SSL = kwargs['ssl']
except:
SSL=False
SSL = False
try:
DEBUG=kwargs['debug']
DEBUG = kwargs['debug']
except:
DEBUG=False
DEBUG = False
shortesttime = 10000000 # something very big
shortesttime = 10000000 # something very big
quickestserver = None
if DEBUG: print "Checking", HOST, PORT, "SSL:", SSL, "DEBUG:", DEBUG
if DEBUG:
print "Checking", HOST, PORT, "SSL:", SSL, "DEBUG:", DEBUG
try:
allinfo = socket.getaddrinfo(HOST, 80, 0, 0, socket.IPPROTO_TCP)
except:
if DEBUG: print "Could not resolve", HOST
if DEBUG:
print "Could not resolve", HOST
return None
for i in allinfo:
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
try:
@ -45,25 +48,27 @@ def happyeyeballs(HOST, **kwargs):
s.close()
else:
# WRAP SOCKET
wrappedSocket = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
wrappedSocket = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
# CONNECT
wrappedSocket.connect((address, PORT))
# CLOSE SOCKET CONNECTION
wrappedSocket.close()
delay = 1000.0*(time.clock() - start)
if DEBUG: print "Connecting took:", delay, "msec"
delay = 1000.0 * (time.clock() - start)
if DEBUG:
print "Connecting took:", delay, "msec"
if delay < shortesttime:
shortesttime = delay
quickestserver = address
except:
if DEBUG: print "Something went wrong (possibly just no connection)"
if DEBUG:
print "Something went wrong (possibly just no connection)"
pass
if DEBUG: print "Quickest server is", quickestserver
if DEBUG:
print "Quickest server is", quickestserver
return quickestserver
if __name__ == '__main__':
print happyeyeballs('www.google.com')
print happyeyeballs('www.google.com', port=443, ssl=True)
@ -72,6 +77,5 @@ if __name__ == '__main__':
print happyeyeballs('block.cheapnews.eu', port=443, ssl=True)
print happyeyeballs('block.cheapnews.eu', port=443, ssl=True, debug=True)
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')

7
sabnzbd/utils/servertests.py

@ -28,6 +28,7 @@ from sabnzbd.config import get_servers
from sabnzbd.encoding import xml_name
from sabnzbd.misc import int_conv
def test_nntp_server_dict(kwargs):
# Grab the host/port/user/pass/connections/ssl
host = kwargs.get('host', '').strip()
@ -48,13 +49,12 @@ def test_nntp_server_dict(kwargs):
else:
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)
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
if '*' in password and not password.strip('*'):
# 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:
return False, unicode(sys.exc_info()[1])
if not username or not password:
nw.nntp.sock.sendall('ARTICLE <test@home>\r\n')
try:

38
sabnzbd/utils/systrayiconthread.py

@ -19,8 +19,8 @@ except ImportError:
from threading import Thread
from time import sleep
class SysTrayIconThread(Thread):
'''TODO'''
QUIT = 'QUIT'
SPECIAL_ACTIONS = [QUIT]
@ -40,33 +40,31 @@ class SysTrayIconThread(Thread):
self.hover_text = hover_text
self.on_quit = on_quit
# menu_options = menu_options + (('Quit', None, self.QUIT),)
# menu_options = menu_options + (('Quit', None, self.QUIT),)
self._next_action_id = self.FIRST_ID
self.menu_actions_by_id = set()
self.menu_options = self._add_ids_to_menu_options(list(menu_options))
self.menu_actions_by_id = dict(self.menu_actions_by_id)
del self._next_action_id
self.default_menu_index = (default_menu_index or 0)
self.window_class_name = window_class_name or "SysTrayIconPy"
self.start()
def initialize(self):
message_map = {win32gui.RegisterWindowMessage("TaskbarCreated"): self.restart,
win32con.WM_DESTROY: self.destroy,
win32con.WM_COMMAND: self.command,
win32con.WM_USER+20 : self.notify,}
win32con.WM_USER + 20: self.notify, }
# Register the Window class.
window_class = win32gui.WNDCLASS()
hinst = window_class.hInstance = win32gui.GetModuleHandle(None)
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.hbrBackground = win32con.COLOR_WINDOW
window_class.lpfnWndProc = message_map # could also specify a wndproc.
window_class.lpfnWndProc = message_map # could also specify a wndproc.
classAtom = win32gui.RegisterClass(window_class)
# Create the Window.
style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU
@ -115,8 +113,9 @@ class SysTrayIconThread(Thread):
return result
def get_icon(self, path):
hicon = self.icons.get(path);
if hicon != None: return hicon
hicon = self.icons.get(path)
if hicon != None:
return hicon
# Try and find a custom icon
hinst = win32gui.GetModuleHandle(None)
@ -137,12 +136,14 @@ class SysTrayIconThread(Thread):
def refresh_icon(self):
hicon = self.get_icon(self.icon)
if self.notify_id: message = win32gui.NIM_MODIFY
else: message = win32gui.NIM_ADD
if self.notify_id:
message = win32gui.NIM_MODIFY
else:
message = win32gui.NIM_ADD
self.notify_id = (self.hwnd,
0,
win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP,
win32con.WM_USER+20,
win32con.WM_USER + 20,
hicon,
self.hover_text)
try:
@ -155,17 +156,18 @@ class SysTrayIconThread(Thread):
self.refresh_icon()
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)
win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, nid)
win32gui.PostQuitMessage(0) # Terminate the app.
win32gui.PostQuitMessage(0) # Terminate the app.
def notify(self, hwnd, msg, wparam, lparam):
if lparam==win32con.WM_LBUTTONDBLCLK:
if lparam == win32con.WM_LBUTTONDBLCLK:
self.execute_menu_option(self.default_menu_index + self.FIRST_ID)
elif lparam==win32con.WM_RBUTTONUP:
elif lparam == win32con.WM_RBUTTONUP:
self.show_menu()
elif lparam==win32con.WM_LBUTTONUP:
elif lparam == win32con.WM_LBUTTONUP:
pass
return True
@ -242,6 +244,7 @@ class SysTrayIconThread(Thread):
else:
menu_action(self)
def non_string_iterable(obj):
try:
iter(obj)
@ -249,4 +252,3 @@ def non_string_iterable(obj):
return False
else:
return not isinstance(obj, basestring)

7
sabnzbd/utils/upload.py

@ -16,7 +16,7 @@
# 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
@ -30,6 +30,7 @@ from sabnzbd.constants import VALID_ARCHIVES
from sabnzbd.dirscanner import ProcessArchiveFile, ProcessSingleFile
def upload_file(url, fp):
""" Function for uploading nzbs to a running sabnzbd instance """
try:
@ -48,7 +49,7 @@ def upload_file(url, fp):
sabnzbd.newsunpack.get_from_url(url)
except:
logging.error("Failed to upload file: %s", fp)
logging.info("Traceback: ", exc_info = True)
logging.info("Traceback: ", exc_info=True)
def add_local(f):
@ -63,4 +64,4 @@ def add_local(f):
else:
logging.error("Filename not found: %s", f)
else:
logging.error("File not found: %s", f)
logging.error("File not found: %s", f)

Loading…
Cancel
Save