Browse Source

Py3: Get SABnzbd to start

pull/1161/head
Safihre 8 years ago
parent
commit
c451f15afe
  1. 40
      SABnzbd.py
  2. 22
      sabnzbd/__init__.py
  3. 8
      sabnzbd/assembler.py
  4. 4
      sabnzbd/cfg.py
  5. 15
      sabnzbd/config.py
  6. 47
      sabnzbd/encoding.py
  7. 8
      sabnzbd/getipaddress.py
  8. 2
      sabnzbd/lang.py
  9. 2
      sabnzbd/scheduler.py
  10. 2
      sabnzbd/utils/kronos.py

40
SABnzbd.py

@ -17,18 +17,8 @@
import sys import sys
import imp import imp
if sys.version_info[:2] < (2, 7) or sys.version_info[:2] >= (3, 0): if sys.version_info[:2] <= (3, 0):
print("Sorry, requires Python 2.7.") print("Sorry, requires Python 3")
sys.exit(1)
# Make sure UTF-8 is default 8bit encoding
if not hasattr(sys, "setdefaultencoding"):
imp.reload(sys)
try:
sys.setdefaultencoding('utf-8')
except:
print('Sorry, you MUST add the SABnzbd folder to the PYTHONPATH environment variable')
print('or find another way to force Python to use UTF-8 for text encoding.')
sys.exit(1) sys.exit(1)
import logging import logging
@ -45,10 +35,10 @@ import re
try: try:
import Cheetah import Cheetah
if Cheetah.Version[0] != '2': if Cheetah.Version[0] != '3':
raise ValueError raise ValueError
except ValueError: except ValueError:
print("Sorry, requires Python module Cheetah 2.0rc7 or higher.") print("Sorry, requires Python module Cheetah 3 or higher.")
sys.exit(1) sys.exit(1)
except: except:
print("The Python module Cheetah is required") print("The Python module Cheetah is required")
@ -72,13 +62,7 @@ except:
SQLITE_DLL = False SQLITE_DLL = False
import locale import locale
import builtins
try:
locale.setlocale(locale.LC_ALL, "")
builtins.__dict__['codepage'] = locale.getlocale()[1] or 'cp1252'
except:
# Work-around for Python-ports with bad "locale" support
builtins.__dict__['codepage'] = 'cp1252'
import sabnzbd import sabnzbd
import sabnzbd.lang import sabnzbd.lang
@ -1078,8 +1062,7 @@ def main():
logdir = sabnzbd.cfg.log_dir.get_path() logdir = sabnzbd.cfg.log_dir.get_path()
if fork and not logdir: if fork and not logdir:
print("Error:") print("Error: I refuse to fork without a log directory!")
print("I refuse to fork without a log directory!")
sys.exit(1) sys.exit(1)
if clean_up: if clean_up:
@ -1161,16 +1144,11 @@ def main():
logging.info('Arguments = %s', sabnzbd.CMDLINE) logging.info('Arguments = %s', sabnzbd.CMDLINE)
# Find encoding; relevant for unrar activities # Find encoding; relevant for unrar activities
try: logging.info('Preferred encoding = %s', sys.stdin.encoding)
preferredencoding = locale.getpreferredencoding()
logging.info('Preferred encoding = %s', preferredencoding)
except:
logging.info('Preferred encoding = ERROR')
preferredencoding = ''
# On Linux/FreeBSD/Unix "UTF-8" is strongly, strongly adviced: # On Linux/FreeBSD/Unix "UTF-8" is strongly, strongly adviced:
if not sabnzbd.WIN32 and not sabnzbd.DARWIN and not ('utf' in preferredencoding.lower() and '8' in preferredencoding.lower()): if not sabnzbd.WIN32 and not sabnzbd.DARWIN and not ('utf' in sys.stdin.encoding.lower() and '8' in sys.stdin.encoding.lower()):
logging.warning(T("SABnzbd was started with encoding %s, this should be UTF-8. Expect problems with Unicoded file and directory names in downloads.") % preferredencoding) logging.warning(T("SABnzbd was started with encoding %s, this should be UTF-8. Expect problems with Unicoded file and directory names in downloads.") % sys.stdin.encoding)
# SSL Information # SSL Information
logging.info("SSL version = %s", ssl.OPENSSL_VERSION) logging.info("SSL version = %s", ssl.OPENSSL_VERSION)

22
sabnzbd/__init__.py

@ -269,13 +269,13 @@ def initialize(pause_downloader=False, clean_up=False, evalSched=False, repair=0
cfg.quota_size.callback(guard_quota_size) cfg.quota_size.callback(guard_quota_size)
cfg.quota_day.callback(guard_quota_dp) cfg.quota_day.callback(guard_quota_dp)
cfg.quota_period.callback(guard_quota_dp) cfg.quota_period.callback(guard_quota_dp)
cfg.fsys_type.callback(guard_fsys_type) ###### cfg.fsys_type.callback(guard_fsys_type)
cfg.language.callback(sabnzbd.notifier.reset_growl) cfg.language.callback(sabnzbd.notifier.reset_growl)
cfg.enable_https_verification.callback(guard_https_ver) cfg.enable_https_verification.callback(guard_https_ver)
guard_https_ver() guard_https_ver()
# Set Posix filesystem encoding # Set Posix filesystem encoding
sabnzbd.encoding.change_fsys(cfg.fsys_type()) ###### sabnzbd.encoding.change_fsys(cfg.fsys_type())
# Set cache limit # Set cache limit
if not cfg.cache_limit() or (cfg.cache_limit() == '200M' and (sabnzbd.WIN32 or sabnzbd.DARWIN)): if not cfg.cache_limit() or (cfg.cache_limit() == '200M' and (sabnzbd.WIN32 or sabnzbd.DARWIN)):
@ -512,9 +512,9 @@ def guard_quota_dp():
scheduler.restart(force=True) scheduler.restart(force=True)
def guard_fsys_type(): # def guard_fsys_type():
""" Callback for change of file system naming type """ # """ Callback for change of file system naming type """
sabnzbd.encoding.change_fsys(cfg.fsys_type()) # sabnzbd.encoding.change_fsys(cfg.fsys_type())
def set_https_verification(value): def set_https_verification(value):
@ -882,9 +882,6 @@ def save_data(data, _id, path, do_pickle=True, silent=False):
try: try:
with open(path, 'wb') as data_file: with open(path, 'wb') as data_file:
if do_pickle: if do_pickle:
if cfg.use_pickle():
pickle.dump(data, data_file)
else:
pickle.dump(data, data_file) pickle.dump(data, data_file)
else: else:
data_file.write(data) data_file.write(data)
@ -915,9 +912,6 @@ def load_data(_id, path, remove=True, do_pickle=True, silent=False):
try: try:
with open(path, 'rb') as data_file: with open(path, 'rb') as data_file:
if do_pickle: if do_pickle:
if cfg.use_pickle():
data = pickle.load(data_file)
else:
data = pickle.load(data_file) data = pickle.load(data_file)
else: else:
data = data_file.read() data = data_file.read()
@ -951,9 +945,6 @@ def save_admin(data, _id):
for t in range(3): for t in range(3):
try: try:
with open(path, 'wb') as data_file: with open(path, 'wb') as data_file:
if cfg.use_pickle():
data = pickle.dump(data, data_file)
else:
data = pickle.dump(data, data_file) data = pickle.dump(data, data_file)
break break
except: except:
@ -976,9 +967,6 @@ def load_admin(_id, remove=False, silent=False):
try: try:
with open(path, 'rb') as data_file: with open(path, 'rb') as data_file:
if cfg.use_pickle():
data = pickle.load(data_file)
else:
data = pickle.load(data_file) data = pickle.load(data_file)
if remove: if remove:
misc.remove_file(path) misc.remove_file(path)

8
sabnzbd/assembler.py

@ -45,13 +45,9 @@ from sabnzbd.rating import Rating
class Assembler(Thread): class Assembler(Thread):
do = None # Link to the instance of this method do = None # Link to the instance of this method
def __init__(self, queue=None): def __init__(self):
Thread.__init__(self) Thread.__init__(self)
self.queue = queue.Queue()
if queue:
self.queue = queue
else:
self.queue = queue.Queue()
Assembler.do = self Assembler.do = self
def stop(self): def stop(self):

4
sabnzbd/cfg.py

@ -79,7 +79,6 @@ configlock = OptionBool('misc', 'config_lock', 0)
############################################################################## ##############################################################################
# One time trackers # One time trackers
############################################################################## ##############################################################################
converted_nzo_pickles = OptionBool('misc', 'converted_nzo_pickles', False)
warned_old_queue = OptionNumber('misc', 'warned_old_queue', QUEUE_VERSION) warned_old_queue = OptionNumber('misc', 'warned_old_queue', QUEUE_VERSION)
sched_converted = OptionBool('misc', 'sched_converted', False) sched_converted = OptionBool('misc', 'sched_converted', False)
notified_new_skin = OptionNumber('misc', 'notified_new_skin', 0) notified_new_skin = OptionNumber('misc', 'notified_new_skin', 0)
@ -255,7 +254,6 @@ allow_incomplete_nzb = OptionBool('misc', 'allow_incomplete_nzb', False)
enable_bonjour = OptionBool('misc', 'enable_bonjour', True) enable_bonjour = OptionBool('misc', 'enable_bonjour', True)
reject_duplicate_files = OptionBool('misc', 'reject_duplicate_files', False) reject_duplicate_files = OptionBool('misc', 'reject_duplicate_files', False)
max_art_opt = OptionBool('misc', 'max_art_opt', False) max_art_opt = OptionBool('misc', 'max_art_opt', False)
use_pickle = OptionBool('misc', 'use_pickle', False)
ipv6_hosting = OptionBool('misc', 'ipv6_hosting', False) ipv6_hosting = OptionBool('misc', 'ipv6_hosting', False)
fixed_ports = OptionBool('misc', 'fixed_ports', False) fixed_ports = OptionBool('misc', 'fixed_ports', False)
api_warnings = OptionBool('misc', 'api_warnings', True, protect=True) api_warnings = OptionBool('misc', 'api_warnings', True, protect=True)
@ -270,7 +268,7 @@ req_completion_rate = OptionNumber('misc', 'req_completion_rate', 100.2, 100, 20
selftest_host = OptionStr('misc', 'selftest_host', 'self-test.sabnzbd.org') selftest_host = OptionStr('misc', 'selftest_host', 'self-test.sabnzbd.org')
movie_rename_limit = OptionStr('misc', 'movie_rename_limit', '100M') movie_rename_limit = OptionStr('misc', 'movie_rename_limit', '100M')
size_limit = OptionStr('misc', 'size_limit', '0') size_limit = OptionStr('misc', 'size_limit', '0')
fsys_type = OptionNumber('misc', 'fsys_type', 0, 0, 2) ###### fsys_type = OptionNumber('misc', 'fsys_type', 0, 0, 2)
show_sysload = OptionNumber('misc', 'show_sysload', 2, 0, 2) show_sysload = OptionNumber('misc', 'show_sysload', 2, 0, 2)
history_limit = OptionNumber('misc', 'history_limit', 10, 0) history_limit = OptionNumber('misc', 'history_limit', 10, 0)
wait_ext_drive = OptionNumber('misc', 'wait_ext_drive', 5, 1, 60) wait_ext_drive = OptionNumber('misc', 'wait_ext_drive', 5, 1, 60)

15
sabnzbd/config.py

@ -26,7 +26,7 @@ import threading
import shutil import shutil
import time import time
import random import random
from hashlib import md5 import uuid
from urllib.parse import urlparse from urllib.parse import urlparse
import sabnzbd.misc import sabnzbd.misc
from sabnzbd.constants import CONFIG_VERSION, NORMAL_PRIORITY, DEFAULT_PRIORITY, MAX_WIN_DFOLDER from sabnzbd.constants import CONFIG_VERSION, NORMAL_PRIORITY, DEFAULT_PRIORITY, MAX_WIN_DFOLDER
@ -727,7 +727,7 @@ def _read_config(path, try_backup=False):
return False, 'Cannot create INI file %s' % path return False, 'Cannot create INI file %s' % path
try: try:
fp = open(path, 'rb') fp = open(path, 'r')
lines = fp.read().split('\n') lines = fp.read().split('\n')
if len(lines) == 1: if len(lines) == 1:
fp.seek(0) fp.seek(0)
@ -1093,13 +1093,4 @@ 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 """
# Create some values to seed md5 return uuid.uuid4().hex
t = str(time.time())
r = str(random.random())
# Create the md5 instance and give it the current time
m = md5(t)
# Update the md5 instance with the random variable
m.update(r)
# Return a hex digest of the md5, eg 49f68a5c8493ec2c0bf489821c21fc3b
return m.hexdigest()

47
sabnzbd/encoding.py

@ -52,6 +52,7 @@ def change_fsys(value):
def platform_encode(p): def platform_encode(p):
return p
""" Return Unicode name, if not already Unicode, decode with UTF-8 or latin1 """ """ Return Unicode name, if not already Unicode, decode with UTF-8 or latin1 """
if isinstance(p, str): if isinstance(p, str):
try: try:
@ -92,6 +93,7 @@ def special_fixer(p):
def unicoder(p, force=False): def unicoder(p, force=False):
return p
""" Make sure a Unicode string is returned """ Make sure a Unicode string is returned
When `force` is True, ignore filesystem encoding When `force` is True, ignore filesystem encoding
""" """
@ -109,6 +111,7 @@ def unicoder(p, force=False):
def xml_name(p, keep_escape=False, encoding=None): def xml_name(p, keep_escape=False, encoding=None):
return p
""" Prepare name for use in HTML/XML contect """ """ Prepare name for use in HTML/XML contect """
if isinstance(p, str): if isinstance(p, str):
@ -135,18 +138,8 @@ class LatinFilter(Filter):
def filter(self, val, str=str, **kw): def filter(self, val, str=str, **kw):
if isinstance(val, str): if isinstance(val, str):
return val return val
elif isinstance(val, str):
try:
if sabnzbd.WIN32:
return val.decode(codepage)
else:
return val.decode('utf-8')
except:
return val.decode(codepage, 'replace')
elif val is None:
return ''
else: else:
return str(str(val)) return str(val)
class EmailFilter(Filter): class EmailFilter(Filter):
@ -155,6 +148,9 @@ class EmailFilter(Filter):
""" """
def filter(self, val, str=str, **kw): def filter(self, val, str=str, **kw):
return val
if isinstance(val, str): if isinstance(val, str):
return val return val
elif isinstance(val, str): elif isinstance(val, str):
@ -174,32 +170,11 @@ class EmailFilter(Filter):
# #
# Use to transform 8-bit console output to plain Python strings # Use to transform 8-bit console output to plain Python strings
# #
import string
TAB_850 = \
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F" \
"\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F" \
"\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF" \
"\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF" \
"\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF" \
"\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF" \
"\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF" \
"\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"
TAB_LATIN = \
"\xC7\xFC\xE9\xE2\xE4\xE0\xE5\xE7\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5" \
"\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xFF\xD6\xDC\xF8\xA3\xD8\xD7\x66" \
"\xE1\xED\xF3\xFA\xF1\xD1\xAA\xBA\xBF\xAE\xAC\xDB\xBC\xA1\xAB\xBB" \
"\x7E\x7E\x7E\x7E\x7E\xC1\xC2\xC0\xA9\x7E\x7E\x7E\x7E\xA2\xA5\x7E" \
"\x7E\x7E\x7E\x7E\x7E\x7E\xE3\xc3\x7E\x7E\x7E\x7E\x7E\x7E\x7E\xA4" \
"\xF0\xD0\xCA\xCB\xC8\x7E\xCD\xCE\xCF\x7E\x7E\x7E\x7E\xA6\xCC\x7E" \
"\xD3\xDF\xD4\xD2\xF5\xD5\xB5\xFE\xDE\xDA\xDB\xD9\xFD\xDD\xAF\xB4" \
"\xAD\xB1\x5F\xBE\xB6\xA7\xF7\xB8\xB0\xA8\xB7\xB9\xB3\xB2\x7E\xA0"
gTABLE_850_LATIN = string.maketrans(TAB_850, TAB_LATIN)
gTABLE_LATIN_850 = string.maketrans(TAB_LATIN, TAB_850)
def TRANS(p): def TRANS(p):
return p
""" For Windows: Translate CP850 to Python's Latin-1 and return in Unicode """ For Windows: Translate CP850 to Python's Latin-1 and return in Unicode
Others: return original string Others: return original string
""" """
@ -215,6 +190,7 @@ def TRANS(p):
def UNTRANS(p): def UNTRANS(p):
return p
""" For Windows: Translate Python's Latin-1 to CP850 """ For Windows: Translate Python's Latin-1 to CP850
Others: return original string Others: return original string
""" """
@ -230,6 +206,7 @@ def UNTRANS(p):
def fixup_ff4(p): def fixup_ff4(p):
return p
""" Fix incompatibility between CherryPy and Firefox-4 on OSX, """ Fix incompatibility between CherryPy and Firefox-4 on OSX,
where a filename contains &#xx; encodings where a filename contains &#xx; encodings
""" """
@ -279,6 +256,7 @@ def html_escape(txt):
def deunicode(p): def deunicode(p):
return p
""" Return the correct 8bit ASCII encoding for the platform: """ Return the correct 8bit ASCII encoding for the platform:
Latin-1 for Windows/Posix-non-UTF and UTF-8 for OSX/Posix-UTF Latin-1 for Windows/Posix-non-UTF and UTF-8 for OSX/Posix-UTF
""" """
@ -303,4 +281,3 @@ def deunicode(p):
return p return p
auto_fsys()

8
sabnzbd/getipaddress.py

@ -77,9 +77,10 @@ def publicipv4():
# we only want IPv4 resolving, so socket.AF_INET: # we only want IPv4 resolving, so socket.AF_INET:
result = addresslookup4(sabnzbd.cfg.selftest_host()) result = addresslookup4(sabnzbd.cfg.selftest_host())
except: except:
# something very bad: no urllib2, no resolving of selftest_host, no network at all # something very bad: no urllib2, no resolving of selftest_host, no network at all
public_ipv4 = None public_ipv4 = None
return public_ipv4 return public_ipv4
# we got one or more IPv4 address(es), so let's connect to them # we got one or more IPv4 address(es), so let's connect to them
for item in result: for item in result:
selftest_ipv4 = item[4][0] # get next IPv4 address of sabnzbd.cfg.selftest_host() selftest_ipv4 = item[4][0] # get next IPv4 address of sabnzbd.cfg.selftest_host()
@ -90,8 +91,8 @@ def publicipv4():
req.add_header('User-Agent', 'SABnzbd+/%s' % sabnzbd.version.__version__ ) req.add_header('User-Agent', 'SABnzbd+/%s' % sabnzbd.version.__version__ )
# specify the Host, because we only provide the IPv4 address in the URL: # specify the Host, because we only provide the IPv4 address in the URL:
req.add_header('Host', sabnzbd.cfg.selftest_host()) req.add_header('Host', sabnzbd.cfg.selftest_host())
# get the response # get the response, timeout 2 seconds, in case the website is not accessible
public_ipv4 = urllib.request.urlopen(req, timeout=2).read() # timeout 2 seconds, in case the website is not accessible public_ipv4 = urllib.request.urlopen(req, timeout=2).read().decode('utf-8')
# ... check the response is indeed an IPv4 address: # ... check the response is indeed an IPv4 address:
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
# if we get here without exception, we're done: # if we get here without exception, we're done:
@ -101,6 +102,7 @@ def publicipv4():
# the connect OR the inet_aton raised an exception, so: # the connect OR the inet_aton raised an exception, so:
# continue the for loop to try next server IPv4 address # continue the for loop to try next server IPv4 address
pass pass
if not ipv4_found: if not ipv4_found:
public_ipv4 = None public_ipv4 = None
return public_ipv4 return public_ipv4

2
sabnzbd/lang.py

@ -67,7 +67,7 @@ def set_language(language=None):
lng = gettext.translation(_DOMAIN, _LOCALEDIR, [language], fallback=True, codeset='latin-1') lng = gettext.translation(_DOMAIN, _LOCALEDIR, [language], fallback=True, codeset='latin-1')
# The unicode flag will make _() return Unicode # The unicode flag will make _() return Unicode
lng.install(str=True, names=['lgettext']) lng.install(names=['lgettext'])
builtins.__dict__['T'] = builtins.__dict__['_'] # Unicode builtins.__dict__['T'] = builtins.__dict__['_'] # Unicode
builtins.__dict__['Ta'] = builtins.__dict__['_'] # Unicode (Used to Latin-1, compatibility support) builtins.__dict__['Ta'] = builtins.__dict__['_'] # Unicode (Used to Latin-1, compatibility support)
builtins.__dict__['Tx'] = builtins.__dict__['_'] # Dynamic translation (unicode) builtins.__dict__['Tx'] = builtins.__dict__['_'] # Dynamic translation (unicode)

2
sabnzbd/scheduler.py

@ -299,7 +299,7 @@ def sort_schedules(all_events, now=None):
if not all_events: if not all_events:
break break
events.sort(lambda x, y: x[0] - y[0]) events.sort(key=lambda x, y: x[0] - y[0])
return events return events

2
sabnzbd/utils/kronos.py

@ -361,7 +361,7 @@ class DayTaskRescheduler:
now[3], now[4] = self.timeonday now[3], now[4] = self.timeonday
# seconds # seconds
now[5] = 0 now[5] = 0
return time.mktime(now) return time.mktime(tuple(now))
def reschedule(self, scheduler): def reschedule(self, scheduler):
"""Reschedule this task according to the daytime for the task. """Reschedule this task according to the daytime for the task.

Loading…
Cancel
Save