mirror of
https://github.com/rembo10/headphones.git
synced 2026-03-22 12:49:26 +00:00
* improved unitesting (compat level for python 2.6 and unittest)
* preparation for SoftChroot (stubs and mocks)
This commit is contained in:
@@ -152,7 +152,10 @@ def main():
|
||||
headphones.DB_FILE = os.path.join(headphones.DATA_DIR, 'headphones.db')
|
||||
|
||||
# Read config and start logging
|
||||
headphones.initialize(config_file)
|
||||
try:
|
||||
headphones.initialize(config_file)
|
||||
except headphones.exceptions.SoftChrootError as e:
|
||||
raise SystemExit('FATAL ERROR')
|
||||
|
||||
if headphones.DAEMON:
|
||||
headphones.daemonize()
|
||||
|
||||
@@ -29,7 +29,8 @@ from apscheduler.schedulers.background import BackgroundScheduler
|
||||
from apscheduler.triggers.interval import IntervalTrigger
|
||||
from headphones import versioncheck, logger
|
||||
import headphones.config
|
||||
|
||||
from headphones.softchroot import SoftChroot
|
||||
import headphones.exceptions
|
||||
|
||||
# (append new extras to the end)
|
||||
POSSIBLE_EXTRAS = [
|
||||
@@ -74,6 +75,7 @@ started = False
|
||||
DATA_DIR = None
|
||||
|
||||
CONFIG = None
|
||||
SOFT_CHROOT = None
|
||||
|
||||
DB_FILE = None
|
||||
|
||||
@@ -92,11 +94,11 @@ MIRRORLIST = ["musicbrainz.org", "headphones", "custom"]
|
||||
|
||||
UMASK = None
|
||||
|
||||
|
||||
def initialize(config_file):
|
||||
with INIT_LOCK:
|
||||
|
||||
global CONFIG
|
||||
global SOFT_CHROOT
|
||||
global _INITIALIZED
|
||||
global CURRENT_VERSION
|
||||
global LATEST_VERSION
|
||||
@@ -136,6 +138,14 @@ def initialize(config_file):
|
||||
logger.initLogger(console=not QUIET, log_dir=CONFIG.LOG_DIR,
|
||||
verbose=VERBOSE)
|
||||
|
||||
if CONFIG.SOFT_CHROOT:
|
||||
# soft chroot defined, lets try to initialize:
|
||||
try:
|
||||
SOFT_CHROOT = SoftChroot(str(CONFIG.SOFT_CHROOT))
|
||||
except exceptions.SoftChrootError as e:
|
||||
logger.error("SoftChroot error: %s", e)
|
||||
raise e
|
||||
|
||||
if not CONFIG.CACHE_DIR:
|
||||
# Put the cache dir in the data dir for now
|
||||
CONFIG.CACHE_DIR = os.path.join(DATA_DIR, 'cache')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#import unittest
|
||||
#import mock
|
||||
from unittest import TestCase
|
||||
from headphones.unittestcompat import TestCase
|
||||
|
||||
import headphones.albumart
|
||||
|
||||
|
||||
@@ -236,6 +236,7 @@ _CONFIG_DEFINITIONS = {
|
||||
'SAB_USERNAME': (str, 'SABnzbd', ''),
|
||||
'SAMPLINGFREQUENCY': (int, 'General', 44100),
|
||||
'SEARCH_INTERVAL': (int, 'General', 1440),
|
||||
'SOFT_CHROOT': (path, 'General', ''),
|
||||
'SONGKICK_APIKEY': (str, 'Songkick', 'nd1We7dFW2RqxPw8'),
|
||||
'SONGKICK_ENABLED': (int, 'Songkick', 1),
|
||||
'SONGKICK_FILTER_ENABLED': (int, 'Songkick', 0),
|
||||
@@ -308,7 +309,7 @@ class Config(object):
|
||||
definition = _CONFIG_DEFINITIONS[key]
|
||||
if len(definition) == 3:
|
||||
definition_type, section, default = definition
|
||||
else:
|
||||
elif len(definition) == 4:
|
||||
definition_type, section, _, default = definition
|
||||
return key, definition_type, section, ini_key, default
|
||||
|
||||
|
||||
@@ -1,26 +1,17 @@
|
||||
#import unittest
|
||||
import sys
|
||||
import mock
|
||||
from unittest import TestCase
|
||||
from headphones.unittestcompat import TestCase
|
||||
from mock import MagicMock
|
||||
|
||||
import headphones.config
|
||||
from headphones.config import path
|
||||
|
||||
def is26():
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] == 6:
|
||||
return True
|
||||
return False
|
||||
|
||||
class ConfigPathTest(TestCase):
|
||||
def test_path(self):
|
||||
p = path('/tmp')
|
||||
|
||||
#fuckin python 2.6:
|
||||
if not is26():
|
||||
self.assertIsInstance(p, path)
|
||||
self.assertIsNotNone(p)
|
||||
self.assertTrue(True)
|
||||
self.assertIsInstance(p, path)
|
||||
self.assertIsNotNone(p)
|
||||
|
||||
def test_path_call(self):
|
||||
s = '/tmp'
|
||||
@@ -41,10 +32,7 @@ class ConfigPathTest(TestCase):
|
||||
def test_path_repr(self):
|
||||
s = '/tmp'
|
||||
p1 = path(s)
|
||||
#fuckin python 2.6:
|
||||
if not is26():
|
||||
self.assertIn('headphones.config.path', p1.__repr__())
|
||||
self.assertTrue(True)
|
||||
self.assertIn('headphones.config.path', p1.__repr__())
|
||||
|
||||
|
||||
# patch required, since Config works ower a
|
||||
@@ -62,9 +50,7 @@ class ConfigTest(TestCase):
|
||||
"""Test creating headphones.Config"""
|
||||
|
||||
cf = headphones.config.Config('/tmp/notexist')
|
||||
#fuckin python 2.6:
|
||||
if not is26():
|
||||
self.assertIsInstance(cf, headphones.config.Config)
|
||||
self.assertIsInstance(cf, headphones.config.Config)
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_write(self, config_obj_fabric_mock):
|
||||
@@ -84,6 +70,4 @@ class ConfigTest(TestCase):
|
||||
|
||||
general_opts_set = conf_mock['General'].__setitem__.call_args_list
|
||||
general_opts_set = map(lambda x: x[0][0], general_opts_set)
|
||||
#fuckin python 2.6:
|
||||
if not is26():
|
||||
self.assertIn('download_dir', general_opts_set, 'There is no download_dir in ConfigObj (submodule of Config)')
|
||||
self.assertIn('download_dir', general_opts_set, 'There is no download_dir in ConfigObj (submodule of Config)')
|
||||
|
||||
@@ -24,3 +24,9 @@ class NewzbinAPIThrottled(HeadphonesException):
|
||||
"""
|
||||
Newzbin has throttled us, deal with it
|
||||
"""
|
||||
|
||||
class SoftChrootError(HeadphonesException):
|
||||
"""
|
||||
Fatal errors in SoftChroot module
|
||||
"""
|
||||
pass
|
||||
|
||||
14
headphones/softchroot.py
Normal file
14
headphones/softchroot.py
Normal file
@@ -0,0 +1,14 @@
|
||||
import os
|
||||
from headphones.exceptions import SoftChrootError
|
||||
|
||||
class SoftChroot(object):
|
||||
def __init__(self, path):
|
||||
path = path.strip()
|
||||
|
||||
if (not os.path.exists(path) or
|
||||
not os.path.isdir(path)):
|
||||
raise SoftChrootError('No such directory: %s' % path)
|
||||
|
||||
path = path.strip(os.path.sep) + os.path.sep
|
||||
|
||||
self.chroot = path
|
||||
38
headphones/softchroot_test.py
Normal file
38
headphones/softchroot_test.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import os
|
||||
import mock
|
||||
from headphones.unittestcompat import TestCase
|
||||
from mock import MagicMock
|
||||
|
||||
from headphones.softchroot import SoftChroot
|
||||
from headphones.exceptions import SoftChrootError
|
||||
|
||||
class SoftChrootTest(TestCase):
|
||||
def test_create(self):
|
||||
""" create headphones.SoftChroot """
|
||||
|
||||
cf = SoftChroot('/tmp/')
|
||||
self.assertIsInstance(cf, SoftChroot)
|
||||
|
||||
@mock.patch('headphones.config.ConfigObj', name='ConfigObjMock')
|
||||
def test_create_on_file(self, config_obj_fabric_mock):
|
||||
""" create SoftChroot on file, not a directory """
|
||||
|
||||
path = os.path.join('tmp', 'notexist', 'asdf', '11', '12', 'np', 'itsssss')
|
||||
|
||||
with self.assertRaises(SoftChrootError) as exc:
|
||||
cf = SoftChroot(path)
|
||||
|
||||
self.assertRegexpMatches(str(exc.exception), r'No such directory')
|
||||
self.assertRegexpMatches(str(exc.exception), path)
|
||||
|
||||
@mock.patch('headphones.softchroot', name='SoftChrootMock')
|
||||
def test_create_on_file(self, config_obj_fabric_mock):
|
||||
""" create SoftChroot on file, not a directory """
|
||||
|
||||
path = os.path.join('tmp', 'notexist', 'asdf', '11', '12', 'np', 'itsssss')
|
||||
|
||||
with self.assertRaises(SoftChrootError) as exc:
|
||||
cf = SoftChroot(path)
|
||||
|
||||
self.assertRegexpMatches(str(exc.exception), r'No such directory')
|
||||
self.assertRegexpMatches(str(exc.exception), path)
|
||||
28
headphones/unittestcompat.py
Normal file
28
headphones/unittestcompat.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import sys
|
||||
from unittest import TestCase as TC
|
||||
|
||||
def _is26():
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] == 6:
|
||||
return True
|
||||
return False
|
||||
|
||||
_dummy = _is26()
|
||||
|
||||
def _d(f):
|
||||
def decorate(self, *args, **kw):
|
||||
if _dummy:
|
||||
return self.assertTrue(True)
|
||||
return f(self, *args, **kw)
|
||||
return decorate
|
||||
|
||||
class TestCase(TC):
|
||||
"""
|
||||
Wrapper for python 2.6 stubs
|
||||
"""
|
||||
@_d
|
||||
def assertIsInstance(self, *args, **kw):
|
||||
return super(TestCase, self).assertIsInstance(*args, **kw)
|
||||
|
||||
@_d
|
||||
def assertIsIn(self, *args, **kw):
|
||||
return super(TestCase, self).assertIsIn(*args, **kw)
|
||||
@@ -1369,6 +1369,7 @@ class WebInterface(object):
|
||||
|
||||
# Need to convert EXTRAS to a dictionary we can pass to the config:
|
||||
# it'll come in as a string like 2,5,6,8
|
||||
|
||||
extra_munges = {
|
||||
"dj-mix": "dj_mix",
|
||||
"mixtape/street": "mixtape_street"
|
||||
|
||||
Reference in New Issue
Block a user