we were previously doing this only for the `wutta.config.include` and `wutta.config.require` settings, and pyramid (or paste?) has been handling certain other ones, e.g. for beaker session cache paths. but we really need to be able to rely on this being available "everywhere" or else it's just confusing.
870 lines
32 KiB
Python
870 lines
32 KiB
Python
# -*- coding: utf-8; -*-
|
|
|
|
import configparser
|
|
import os
|
|
from unittest import TestCase
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
import pytest
|
|
|
|
from wuttjamaican import conf as mod
|
|
# TODO: get rid of this eventually
|
|
from wuttjamaican import conf
|
|
from wuttjamaican.exc import ConfigurationError
|
|
from wuttjamaican.app import AppHandler
|
|
from wuttjamaican.testing import FileTestCase
|
|
|
|
|
|
class TestWuttaConfig(FileTestCase):
|
|
|
|
def make_config(self, **kwargs):
|
|
return mod.WuttaConfig(**kwargs)
|
|
|
|
def test_contstructor_basic(self):
|
|
config = conf.WuttaConfig()
|
|
self.assertEqual(config.appname, 'wutta')
|
|
self.assertEqual(config.files_read, [])
|
|
|
|
def test_constructor_valid_files(self):
|
|
myfile = self.write_file('my.conf', '')
|
|
config = conf.WuttaConfig(files=[myfile])
|
|
self.assertEqual(len(config.files_read), 1)
|
|
self.assertEqual(config.files_read[0], myfile)
|
|
|
|
def test_constructor_missing_files(self):
|
|
invalid = os.path.join(self.tempdir, 'invalid.conf')
|
|
self.assertRaises(FileNotFoundError, conf.WuttaConfig, files=[invalid])
|
|
|
|
def test_constructor_required_files_are_present(self):
|
|
first = self.write_file('first.conf', """\
|
|
[foo]
|
|
bar = 1
|
|
baz = A
|
|
""")
|
|
|
|
second = self.write_file('second.conf', """\
|
|
[wutta.config]
|
|
require = %(here)s/first.conf
|
|
|
|
[foo]
|
|
baz = B
|
|
""")
|
|
|
|
config = conf.WuttaConfig(files=[second])
|
|
self.assertEqual(len(config.files_read), 2)
|
|
# nb. files_read listing is in order of "priority" which is
|
|
# same the as order in which files were initially read
|
|
self.assertEqual(config.files_read[0], second)
|
|
self.assertEqual(config.files_read[1], first)
|
|
self.assertEqual(config.get('foo.bar'), '1')
|
|
self.assertEqual(config.get('foo.baz'), 'B')
|
|
|
|
def test_constructor_required_files_are_missing(self):
|
|
second = self.write_file('second.conf', """\
|
|
[wutta.config]
|
|
require = %(here)s/first.conf
|
|
|
|
[foo]
|
|
baz = B
|
|
""")
|
|
|
|
self.assertRaises(FileNotFoundError, conf.WuttaConfig, files=[second])
|
|
|
|
def test_constructor_included_files_are_present(self):
|
|
first = self.write_file('first.conf', """\
|
|
[foo]
|
|
bar = 1
|
|
baz = A
|
|
""")
|
|
|
|
second = self.write_file('second.conf', """\
|
|
[wutta.config]
|
|
include = %(here)s/first.conf
|
|
|
|
[foo]
|
|
baz = B
|
|
""")
|
|
|
|
config = conf.WuttaConfig(files=[second])
|
|
self.assertEqual(len(config.files_read), 2)
|
|
# nb. files_read listing is in order of "priority" which is
|
|
# same the as order in which files were initially read
|
|
self.assertEqual(config.files_read[0], second)
|
|
self.assertEqual(config.files_read[1], first)
|
|
self.assertEqual(config.get('foo.bar'), '1')
|
|
self.assertEqual(config.get('foo.baz'), 'B')
|
|
|
|
def test_constructor_included_files_are_missing(self):
|
|
second = self.write_file('second.conf', """\
|
|
[wutta.config]
|
|
include = %(here)s/first.conf
|
|
|
|
[foo]
|
|
baz = B
|
|
""")
|
|
|
|
config = conf.WuttaConfig(files=[second])
|
|
self.assertEqual(len(config.files_read), 1)
|
|
self.assertEqual(config.files_read[0], second)
|
|
self.assertIsNone(config.get('foo.bar'))
|
|
self.assertEqual(config.get('foo.baz'), 'B')
|
|
|
|
def test_files_only_read_once(self):
|
|
base = self.write_file('base.conf', """
|
|
[foo]
|
|
bar = 1
|
|
baz = A
|
|
""")
|
|
|
|
middle = self.write_file('middle.conf', """
|
|
[wutta.config]
|
|
require = %(here)s/base.conf
|
|
|
|
[foo]
|
|
baz = B
|
|
""")
|
|
|
|
top = self.write_file('top.conf', """
|
|
[wutta.config]
|
|
require = %(here)s/middle.conf
|
|
|
|
[foo]
|
|
baz = C
|
|
""")
|
|
|
|
config = conf.WuttaConfig(files=[top, middle, base])
|
|
self.assertEqual(len(config.files_read), 3)
|
|
# nb. files_read listing is in order of "priority" which is
|
|
# same the as order in which files were initially read
|
|
self.assertEqual(config.files_read[0], top)
|
|
self.assertEqual(config.files_read[1], middle)
|
|
self.assertEqual(config.files_read[2], base)
|
|
self.assertEqual(config.get('foo.bar'), '1')
|
|
self.assertEqual(config.get('foo.baz'), 'C')
|
|
|
|
def test_prioritized_files(self):
|
|
first = self.write_file('first.conf', """\
|
|
[foo]
|
|
bar = 1
|
|
""")
|
|
|
|
second = self.write_file('second.conf', """\
|
|
[wutta.config]
|
|
require = %(here)s/first.conf
|
|
""")
|
|
|
|
config = conf.WuttaConfig(files=[second])
|
|
files = config.get_prioritized_files()
|
|
self.assertEqual(len(files), 2)
|
|
self.assertEqual(files[0], second)
|
|
self.assertEqual(files[1], first)
|
|
|
|
def test_default_vars_interpolated(self):
|
|
myconf = self.write_file('my.conf', """
|
|
[foo]
|
|
bar = %(here)s/bar.txt
|
|
baz = %(__file__)s
|
|
""")
|
|
|
|
config = conf.WuttaConfig(files=[myconf])
|
|
self.assertEqual(config.get('foo.bar'), f'{self.tempdir}/bar.txt')
|
|
self.assertEqual(config.get('foo.baz'), myconf)
|
|
|
|
def test_constructor_defaults(self):
|
|
config = conf.WuttaConfig()
|
|
self.assertEqual(config.defaults, {})
|
|
self.assertIsNone(config.get('foo'))
|
|
|
|
config = conf.WuttaConfig(defaults={'foo': 'bar'})
|
|
self.assertEqual(config.defaults, {'foo': 'bar'})
|
|
self.assertEqual(config.get('foo'), 'bar')
|
|
|
|
def test_constructor_db_flags(self):
|
|
try:
|
|
# nb. we don't need this import but the test will not
|
|
# behave correctly unless the lib is installed
|
|
import sqlalchemy
|
|
except ImportError:
|
|
pytest.skip("test is not relevant without sqlalchemy")
|
|
|
|
myfile = self.write_file('my.conf', """\
|
|
[wutta.config]
|
|
usedb = true
|
|
preferdb = true
|
|
""")
|
|
|
|
# flags are off by default
|
|
config = conf.WuttaConfig()
|
|
self.assertFalse(config.usedb)
|
|
self.assertFalse(config.preferdb)
|
|
|
|
# but may override via constructor
|
|
config = conf.WuttaConfig(usedb=True, preferdb=True)
|
|
self.assertTrue(config.usedb)
|
|
self.assertTrue(config.preferdb)
|
|
|
|
# and also may override via config file
|
|
config = conf.WuttaConfig(files=[myfile])
|
|
self.assertTrue(config.usedb)
|
|
self.assertTrue(config.preferdb)
|
|
|
|
def test_constructor_db_not_supported(self):
|
|
try:
|
|
# nb. we don't need this import but the test will not
|
|
# behave correctly unless the lib is installed
|
|
import sqlalchemy
|
|
except ImportError:
|
|
pytest.skip("test is not relevant without sqlalchemy")
|
|
|
|
# flags are off by default
|
|
config = conf.WuttaConfig()
|
|
self.assertFalse(config.usedb)
|
|
self.assertFalse(config.preferdb)
|
|
|
|
# but caller may enable the flags (if sqlalchemy available)
|
|
config = conf.WuttaConfig(usedb=True, preferdb=True)
|
|
self.assertTrue(config.usedb)
|
|
self.assertTrue(config.preferdb)
|
|
|
|
# but db flags are force-disabled if sqlalchemy not available,
|
|
# regardless of flag values caller provides...
|
|
|
|
orig_import = __import__
|
|
|
|
def mock_import(name, *args, **kwargs):
|
|
if name == 'wuttjamaican.db':
|
|
raise ImportError
|
|
return orig_import(name, *args, **kwargs)
|
|
|
|
with patch('builtins.__import__', side_effect=mock_import):
|
|
config = conf.WuttaConfig(usedb=True, preferdb=True)
|
|
self.assertFalse(config.usedb)
|
|
self.assertFalse(config.preferdb)
|
|
|
|
def test_constructor_may_configure_logging(self):
|
|
myfile = self.write_file('my.conf', """\
|
|
[wutta.config]
|
|
configure_logging = true
|
|
""")
|
|
|
|
with patch.object(conf.WuttaConfig, '_configure_logging') as method:
|
|
|
|
# no logging config by default
|
|
config = conf.WuttaConfig()
|
|
method.assert_not_called()
|
|
|
|
# but may override via constructor
|
|
method.reset_mock()
|
|
config = conf.WuttaConfig(configure_logging=True)
|
|
method.assert_called_once()
|
|
|
|
# and also may override via config file
|
|
method.reset_mock()
|
|
config = conf.WuttaConfig(files=[myfile])
|
|
method.assert_called_once()
|
|
|
|
def test_constructor_configures_logging(self):
|
|
myfile = self.write_file('my.conf', """\
|
|
[wutta]
|
|
timezone.default = America/Chicago
|
|
|
|
[wutta.config]
|
|
configure_logging = true
|
|
""")
|
|
|
|
with patch('wuttjamaican.conf.logging') as logging:
|
|
|
|
# basic constructor attempts logging config
|
|
config = conf.WuttaConfig(configure_logging=True)
|
|
logging.config.fileConfig.assert_called_once()
|
|
|
|
# if logging config fails, error is *not* raised
|
|
logging.config.fileConfig.reset_mock()
|
|
logging.config.fileConfig.side_effect = configparser.NoSectionError('logging')
|
|
config = conf.WuttaConfig(configure_logging=True)
|
|
logging.config.fileConfig.assert_called_once()
|
|
|
|
# and it works if we specify config file
|
|
logging.config.fileConfig.reset_mock()
|
|
config = conf.WuttaConfig(files=[myfile])
|
|
logging.config.fileConfig.assert_called_once()
|
|
|
|
def test_config_has_no_app_after_init(self):
|
|
|
|
# initial config should *not* have an app yet, otherwise
|
|
# extensions cannot specify a default app handler
|
|
config = conf.WuttaConfig()
|
|
self.assertFalse(hasattr(config, '_app'))
|
|
|
|
# but after that we can get an app okay
|
|
app = config.get_app()
|
|
self.assertIs(app, config._app)
|
|
|
|
def test_setdefault(self):
|
|
config = conf.WuttaConfig()
|
|
|
|
# value is empty by default
|
|
self.assertIsNone(config.get('foo'))
|
|
|
|
# but we can change that by setting default
|
|
config.setdefault('foo', 'bar')
|
|
self.assertEqual(config.get('foo'), 'bar')
|
|
|
|
# also, value is returned when we set default
|
|
self.assertIsNone(config.get('baz'))
|
|
self.assertEqual(config.setdefault('baz', 'blarg'), 'blarg')
|
|
|
|
def test_get_require_with_default(self):
|
|
config = conf.WuttaConfig()
|
|
self.assertRaises(ValueError, config.get, 'foo', require=True, default='bar')
|
|
|
|
def test_get_require_missing(self):
|
|
config = conf.WuttaConfig()
|
|
self.assertRaises(ConfigurationError, config.get, 'foo', require=True)
|
|
|
|
def test_get_with_default(self):
|
|
config = conf.WuttaConfig()
|
|
# nb. returns None if no default specified
|
|
self.assertIsNone(config.get('foo'))
|
|
self.assertEqual(config.get('foo', default='bar'), 'bar')
|
|
|
|
def test_get_from_db(self):
|
|
try:
|
|
import sqlalchemy as sa
|
|
from wuttjamaican.db import Session
|
|
except ImportError:
|
|
pytest.skip("test is not relevant without sqlalchemy")
|
|
|
|
# minimal config, but at least it needs db cxn info
|
|
config = conf.WuttaConfig(defaults={'wutta.db.default.url': 'sqlite://'})
|
|
|
|
session = Session()
|
|
|
|
# setup table for testing
|
|
session.execute(sa.text("""
|
|
create table setting (
|
|
name varchar(255) primary key,
|
|
value text
|
|
);
|
|
"""))
|
|
session.commit()
|
|
|
|
# setting not yet defined
|
|
self.assertIsNone(config.get_from_db('foo'))
|
|
|
|
# insert setting value to db
|
|
session.execute(sa.text("insert into setting values ('foo', 'bar')"))
|
|
session.commit()
|
|
|
|
# now setting returns a value
|
|
self.assertEqual(config.get_from_db('foo'), 'bar')
|
|
|
|
# also works if we provide the session
|
|
self.assertEqual(config.get_from_db('foo', session=session), 'bar')
|
|
|
|
session.close()
|
|
|
|
def test_get_default(self):
|
|
config = conf.WuttaConfig()
|
|
self.assertIsNone(config.get('foo'))
|
|
self.assertEqual(config.get('foo', default='bar'), 'bar')
|
|
|
|
def test_get_require(self):
|
|
config = conf.WuttaConfig()
|
|
self.assertIsNone(config.get('foo'))
|
|
self.assertRaises(ConfigurationError, config.get, 'foo', require=True)
|
|
|
|
def test_get_require_message(self):
|
|
config = conf.WuttaConfig()
|
|
self.assertIsNone(config.get('foo'))
|
|
try:
|
|
config.get('foo', require=True, message="makin stuff up")
|
|
except ConfigurationError as error:
|
|
self.assertIn("makin stuff up", str(error))
|
|
|
|
def test_get_preferdb(self):
|
|
try:
|
|
import sqlalchemy as sa
|
|
from wuttjamaican.db import Session
|
|
except ImportError:
|
|
pytest.skip("test is not relevant without sqlalchemy")
|
|
|
|
# start out with a default value
|
|
config = conf.WuttaConfig(defaults={'wutta.db.default.url': 'sqlite://',
|
|
'foo': 'bar'})
|
|
self.assertEqual(config.get('foo'), 'bar')
|
|
|
|
session = Session()
|
|
|
|
# setup table for testing
|
|
session.execute(sa.text("""
|
|
create table setting (
|
|
name varchar(255) primary key,
|
|
value text
|
|
);
|
|
"""))
|
|
session.execute(sa.text("insert into setting values ('foo', 'baz')"))
|
|
session.commit()
|
|
|
|
# we did not specify usedb=True, so original default is still returned
|
|
self.assertFalse(config.usedb)
|
|
self.assertEqual(config.get('foo'), 'bar')
|
|
|
|
# usedb but no preferdb means original default is still returned
|
|
self.assertEqual(config.get('foo', usedb=True), 'bar')
|
|
|
|
# but preferdb should mean newer db value is returned
|
|
self.assertEqual(config.get('foo', usedb=True, preferdb=True), 'baz')
|
|
|
|
# try a different key to ensure db fallback works if no default present
|
|
session.execute(sa.text("insert into setting values ('blarg', 'blitz')"))
|
|
session.commit()
|
|
self.assertIsNone(config.get('blarg'))
|
|
self.assertEqual(config.get('blarg', usedb=True), 'blitz')
|
|
|
|
session.close()
|
|
|
|
def test_get_ambiguous(self):
|
|
config = conf.WuttaConfig()
|
|
|
|
# value is returned if key is not ambiguous
|
|
config.setdefault('foo', 'bar')
|
|
self.assertEqual(config.get('foo'), 'bar')
|
|
|
|
# but None is returned if key is ambiguous
|
|
config.setdefault('foo.bar', 'baz')
|
|
self.assertIsNone(config.get('foo'))
|
|
|
|
def test_require(self):
|
|
config = conf.WuttaConfig()
|
|
self.assertRaises(ConfigurationError, config.require, 'foo')
|
|
|
|
def test_get_bool(self):
|
|
config = conf.WuttaConfig()
|
|
self.assertFalse(config.get_bool('foo.bar'))
|
|
config.setdefault('foo.bar', 'true')
|
|
self.assertTrue(config.get_bool('foo.bar'))
|
|
|
|
def test_get_int(self):
|
|
config = conf.WuttaConfig()
|
|
self.assertIsNone(config.get_int('foo.bar'))
|
|
config.setdefault('foo.bar', '42')
|
|
self.assertEqual(config.get_int('foo.bar'), 42)
|
|
|
|
def test_get_list(self):
|
|
config = conf.WuttaConfig()
|
|
self.assertIsNone(config.get_list('foo.bar'))
|
|
config.setdefault('foo.bar', 'hello world')
|
|
self.assertEqual(config.get_list('foo.bar'), ['hello', 'world'])
|
|
|
|
def test_parse_bool_null(self):
|
|
config = self.make_config()
|
|
self.assertIsNone(config.parse_bool(None))
|
|
|
|
def test_parse_bool_bool(self):
|
|
config = self.make_config()
|
|
self.assertTrue(config.parse_bool(True))
|
|
self.assertFalse(config.parse_bool(False))
|
|
|
|
def test_parse_bool_string_true(self):
|
|
config = self.make_config()
|
|
self.assertTrue(config.parse_bool('true'))
|
|
self.assertTrue(config.parse_bool('yes'))
|
|
self.assertTrue(config.parse_bool('y'))
|
|
self.assertTrue(config.parse_bool('on'))
|
|
self.assertTrue(config.parse_bool('1'))
|
|
|
|
def test_parse_bool_string_false(self):
|
|
config = self.make_config()
|
|
self.assertFalse(config.parse_bool('false'))
|
|
self.assertFalse(config.parse_bool('no'))
|
|
self.assertFalse(config.parse_bool('n'))
|
|
self.assertFalse(config.parse_bool('off'))
|
|
self.assertFalse(config.parse_bool('0'))
|
|
# nb. assume false for unrecognized input
|
|
self.assertFalse(config.parse_bool('whatever-else'))
|
|
|
|
def test_parse_list_null(self):
|
|
config = self.make_config()
|
|
value = config.parse_list(None)
|
|
self.assertIsInstance(value, list)
|
|
self.assertEqual(len(value), 0)
|
|
|
|
def test_parse_list_list_instance(self):
|
|
config = self.make_config()
|
|
mylist = []
|
|
value = config.parse_list(mylist)
|
|
self.assertIs(value, mylist)
|
|
|
|
def test_parse_list_single_value(self):
|
|
config = self.make_config()
|
|
value = config.parse_list('foo')
|
|
self.assertEqual(len(value), 1)
|
|
self.assertEqual(value[0], 'foo')
|
|
|
|
def test_parse_list_single_value_padded_by_spaces(self):
|
|
config = self.make_config()
|
|
value = config.parse_list(' foo ')
|
|
self.assertEqual(len(value), 1)
|
|
self.assertEqual(value[0], 'foo')
|
|
|
|
def test_parse_list_slash_is_not_a_separator(self):
|
|
config = self.make_config()
|
|
value = config.parse_list('/dev/null')
|
|
self.assertEqual(len(value), 1)
|
|
self.assertEqual(value[0], '/dev/null')
|
|
|
|
def test_parse_list_multiple_values_separated_by_whitespace(self):
|
|
config = self.make_config()
|
|
value = config.parse_list('foo bar baz')
|
|
self.assertEqual(len(value), 3)
|
|
self.assertEqual(value[0], 'foo')
|
|
self.assertEqual(value[1], 'bar')
|
|
self.assertEqual(value[2], 'baz')
|
|
|
|
def test_parse_list_multiple_values_separated_by_commas(self):
|
|
config = self.make_config()
|
|
value = config.parse_list('foo,bar,baz')
|
|
self.assertEqual(len(value), 3)
|
|
self.assertEqual(value[0], 'foo')
|
|
self.assertEqual(value[1], 'bar')
|
|
self.assertEqual(value[2], 'baz')
|
|
|
|
def test_parse_list_multiple_values_separated_by_whitespace_and_commas(self):
|
|
config = self.make_config()
|
|
value = config.parse_list(' foo, bar baz')
|
|
self.assertEqual(len(value), 3)
|
|
self.assertEqual(value[0], 'foo')
|
|
self.assertEqual(value[1], 'bar')
|
|
self.assertEqual(value[2], 'baz')
|
|
|
|
def test_parse_list_multiple_values_separated_by_whitespace_and_commas_with_some_quoting(self):
|
|
config = self.make_config()
|
|
value = config.parse_list("""
|
|
foo
|
|
"C:\\some path\\with spaces\\and, a comma",
|
|
baz
|
|
""")
|
|
self.assertEqual(len(value), 3)
|
|
self.assertEqual(value[0], 'foo')
|
|
self.assertEqual(value[1], 'C:\\some path\\with spaces\\and, a comma')
|
|
self.assertEqual(value[2], 'baz')
|
|
|
|
def test_parse_list_multiple_values_separated_by_whitespace_and_commas_with_single_quotes(self):
|
|
config = self.make_config()
|
|
value = config.parse_list("""
|
|
foo
|
|
'C:\\some path\\with spaces\\and, a comma',
|
|
baz
|
|
""")
|
|
self.assertEqual(len(value), 3)
|
|
self.assertEqual(value[0], 'foo')
|
|
self.assertEqual(value[1], 'C:\\some path\\with spaces\\and, a comma')
|
|
self.assertEqual(value[2], 'baz')
|
|
|
|
def test_get_app(self):
|
|
|
|
# default handler
|
|
config = conf.WuttaConfig()
|
|
self.assertEqual(config.default_app_handler_spec, 'wuttjamaican.app:AppHandler')
|
|
app = config.get_app()
|
|
self.assertIsInstance(app, AppHandler)
|
|
# nb. make extra sure we didn't get a subclass
|
|
self.assertIs(type(app), AppHandler)
|
|
|
|
# custom default handler
|
|
config = conf.WuttaConfig()
|
|
config.default_app_handler_spec = 'tests.test_conf:CustomAppHandler'
|
|
app = config.get_app()
|
|
self.assertIsInstance(app, CustomAppHandler)
|
|
|
|
def test_get_engine_maker(self):
|
|
try:
|
|
from wuttjamaican.db.conf import make_engine_from_config
|
|
except ImportError:
|
|
pytest.skip("test is not relevant without sqlalchemy")
|
|
|
|
# default func
|
|
config = conf.WuttaConfig()
|
|
self.assertEqual(config.default_engine_maker_spec, 'wuttjamaican.db.conf:make_engine_from_config')
|
|
make_engine = config.get_engine_maker()
|
|
self.assertIs(make_engine, make_engine_from_config)
|
|
|
|
# custom default func
|
|
config = conf.WuttaConfig()
|
|
config.default_engine_maker_spec = 'tests.test_conf:custom_make_engine_from_config'
|
|
make_engine = config.get_engine_maker()
|
|
self.assertIs(make_engine, custom_make_engine_from_config)
|
|
|
|
def test_production(self):
|
|
config = conf.WuttaConfig()
|
|
|
|
# false if not defined
|
|
self.assertFalse(config.production())
|
|
|
|
# but config may specify
|
|
config.setdefault('wutta.production', 'true')
|
|
self.assertTrue(config.production())
|
|
|
|
|
|
class CustomAppHandler(AppHandler):
|
|
pass
|
|
|
|
|
|
def custom_make_engine_from_config():
|
|
pass
|
|
|
|
|
|
class TestWuttaConfigExtension(TestCase):
|
|
|
|
def test_basic(self):
|
|
config = conf.WuttaConfig()
|
|
ext = conf.WuttaConfigExtension()
|
|
self.assertIsNone(ext.key)
|
|
self.assertEqual(repr(ext), 'WuttaConfigExtension(key=None)')
|
|
|
|
|
|
class TestGenericDefaultFiles(TestCase):
|
|
|
|
def test_linux(self):
|
|
files = conf.generic_default_files('wuttatest')
|
|
self.assertIsInstance(files, list)
|
|
self.assertTrue(len(files) > 1)
|
|
self.assertIn('/etc/wuttatest.conf', files)
|
|
|
|
def test_win32(self):
|
|
win32com = MagicMock()
|
|
win32com.shell.SHGetSpecialFolderPath.return_value = r'C:' + os.sep
|
|
with patch.dict('sys.modules', **{'win32com.shell': win32com}):
|
|
with patch('wuttjamaican.conf.sys', platform='win32'):
|
|
|
|
files = conf.generic_default_files('wuttatest')
|
|
self.assertIsInstance(files, list)
|
|
self.assertTrue(len(files) > 1)
|
|
self.assertIn(os.path.join('C:', 'wuttatest.conf'), files)
|
|
|
|
def test_win32_broken(self):
|
|
orig_import = __import__
|
|
|
|
def mock_import(name, *args, **kwargs):
|
|
if name == 'win32com.shell':
|
|
raise ImportError
|
|
return orig_import(name, *args, **kwargs)
|
|
|
|
with patch('builtins.__import__', side_effect=mock_import):
|
|
with patch('wuttjamaican.conf.sys', platform='win32'):
|
|
|
|
files = conf.generic_default_files('wuttatest')
|
|
self.assertIsInstance(files, list)
|
|
self.assertEqual(len(files), 0)
|
|
|
|
|
|
class TestGetConfigPaths(FileTestCase):
|
|
|
|
def test_winsvc(self):
|
|
myconf = self.write_file('my.conf', """
|
|
[wutta.config]
|
|
winsvc.RattailFileMonitor = /path/to/other/file
|
|
""")
|
|
|
|
files = conf.get_config_paths(files=[myconf], winsvc='RattailFileMonitor')
|
|
self.assertEqual(files, ['/path/to/other/file'])
|
|
|
|
def test_nonexistent_default_files(self):
|
|
files = conf.get_config_paths(files=None,
|
|
env_files_name='IGNORE_THIS',
|
|
default_files=['/this/does/not/exist'])
|
|
self.assertEqual(files, [])
|
|
|
|
|
|
class TestMakeConfig(FileTestCase):
|
|
|
|
# nb. we use appname='wuttatest' in this suite to avoid any
|
|
# "valid" default config files, env vars etc. which may be present
|
|
# on the dev machine
|
|
|
|
def test_generic_default_files(self):
|
|
generic = self.write_file('generic.conf', '')
|
|
|
|
with patch('wuttjamaican.conf.generic_default_files') as generic_default_files:
|
|
with patch('wuttjamaican.conf.WuttaConfig') as WuttaConfig:
|
|
|
|
# generic files are used if nothing is specified
|
|
generic_default_files.return_value = [generic]
|
|
config = conf.make_config(appname='wuttatest')
|
|
generic_default_files.assert_called_once_with('wuttatest')
|
|
WuttaConfig.assert_called_once_with([generic], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
|
|
# make sure empty defaults works too
|
|
generic_default_files.reset_mock()
|
|
generic_default_files.return_value = []
|
|
WuttaConfig.reset_mock()
|
|
config = conf.make_config(appname='wuttatest')
|
|
generic_default_files.assert_called_once_with('wuttatest')
|
|
WuttaConfig.assert_called_once_with([], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
|
|
def test_specify_default_files(self):
|
|
generic = self.write_file('generic.conf', '')
|
|
myfile = self.write_file('my.conf', '')
|
|
|
|
with patch('wuttjamaican.conf.generic_default_files') as generic_default_files:
|
|
with patch('wuttjamaican.conf.WuttaConfig') as WuttaConfig:
|
|
|
|
# generic defaults are used if nothing specified
|
|
generic_default_files.return_value = [generic]
|
|
config = conf.make_config(appname='wuttatest')
|
|
generic_default_files.assert_called_once_with('wuttatest')
|
|
WuttaConfig.assert_called_once_with([generic], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
|
|
# can specify single default file
|
|
generic_default_files.reset_mock()
|
|
WuttaConfig.reset_mock()
|
|
config = conf.make_config(appname='wuttatest', default_files=myfile)
|
|
generic_default_files.assert_not_called()
|
|
WuttaConfig.assert_called_once_with([myfile], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
|
|
# can specify default files as list
|
|
generic_default_files.reset_mock()
|
|
WuttaConfig.reset_mock()
|
|
config = conf.make_config(appname='wuttatest', default_files=[myfile])
|
|
generic_default_files.assert_not_called()
|
|
WuttaConfig.assert_called_once_with([myfile], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
|
|
# can specify default files as callable
|
|
generic_default_files.reset_mock()
|
|
WuttaConfig.reset_mock()
|
|
config = conf.make_config(appname='wuttatest', default_files=lambda appname: [myfile])
|
|
generic_default_files.assert_not_called()
|
|
WuttaConfig.assert_called_once_with([myfile], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
|
|
def test_specify_plus_files(self):
|
|
generic = self.write_file('generic.conf', '')
|
|
myfile = self.write_file('my.conf', '')
|
|
|
|
with patch('wuttjamaican.conf.generic_default_files') as generic_default_files:
|
|
with patch('wuttjamaican.conf.WuttaConfig') as WuttaConfig:
|
|
|
|
generic_default_files.return_value = [generic]
|
|
|
|
# no plus files by default
|
|
config = conf.make_config(appname='wuttatest')
|
|
generic_default_files.assert_called_once_with('wuttatest')
|
|
WuttaConfig.assert_called_once_with([generic], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
|
|
# can specify single plus file
|
|
generic_default_files.reset_mock()
|
|
WuttaConfig.reset_mock()
|
|
config = conf.make_config(appname='wuttatest', plus_files=myfile)
|
|
generic_default_files.assert_called_once_with('wuttatest')
|
|
WuttaConfig.assert_called_once_with([generic, myfile], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
|
|
# can specify plus files as list
|
|
generic_default_files.reset_mock()
|
|
WuttaConfig.reset_mock()
|
|
config = conf.make_config(appname='wuttatest', plus_files=[myfile])
|
|
generic_default_files.assert_called_once_with('wuttatest')
|
|
WuttaConfig.assert_called_once_with([generic, myfile], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
|
|
# can specify plus files via env
|
|
generic_default_files.reset_mock()
|
|
WuttaConfig.reset_mock()
|
|
config = conf.make_config(appname='wuttatest',
|
|
env={'WUTTATEST_CONFIG_PLUS_FILES': myfile})
|
|
generic_default_files.assert_called_once_with('wuttatest')
|
|
WuttaConfig.assert_called_once_with([generic, myfile], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
|
|
def test_specify_primary_files(self):
|
|
generic = self.write_file('generic.conf', '')
|
|
myfile = self.write_file('my.conf', '')
|
|
|
|
with patch('wuttjamaican.conf.generic_default_files') as generic_default_files:
|
|
with patch('wuttjamaican.conf.WuttaConfig') as WuttaConfig:
|
|
|
|
generic_default_files.return_value = [generic]
|
|
|
|
# generic files by default
|
|
config = conf.make_config(appname='wuttatest')
|
|
generic_default_files.assert_called_once_with('wuttatest')
|
|
WuttaConfig.assert_called_once_with([generic], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
|
|
# can specify single primary file (nb. no default files)
|
|
generic_default_files.reset_mock()
|
|
WuttaConfig.reset_mock()
|
|
config = conf.make_config(myfile, appname='wuttatest')
|
|
generic_default_files.assert_not_called()
|
|
WuttaConfig.assert_called_once_with([myfile], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
|
|
# can specify primary files as list
|
|
generic_default_files.reset_mock()
|
|
WuttaConfig.reset_mock()
|
|
config = conf.make_config([myfile], appname='wuttatest')
|
|
generic_default_files.assert_not_called()
|
|
WuttaConfig.assert_called_once_with([myfile], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
|
|
# can specify primary files via env
|
|
generic_default_files.reset_mock()
|
|
WuttaConfig.reset_mock()
|
|
config = conf.make_config(appname='wuttatest',
|
|
env={'WUTTATEST_CONFIG_FILES': myfile})
|
|
generic_default_files.assert_not_called()
|
|
WuttaConfig.assert_called_once_with([myfile], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
|
|
def test_extensions(self):
|
|
generic = self.write_file('generic.conf', '')
|
|
myfile = self.write_file('my.conf', '')
|
|
|
|
with patch.object(mod, 'WuttaConfig') as WuttaConfig:
|
|
with patch.object(mod, 'load_entry_points') as load_entry_points:
|
|
|
|
# no entry points loaded if extend=False
|
|
config = mod.make_config(appname='wuttatest', extend=False)
|
|
WuttaConfig.assert_called_once_with([], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
load_entry_points.assert_not_called()
|
|
|
|
# confirm entry points for default appname
|
|
load_entry_points.reset_mock()
|
|
WuttaConfig.reset_mock()
|
|
config = mod.make_config([], appname='wutta')
|
|
WuttaConfig.assert_called_once_with([], appname='wutta',
|
|
usedb=None, preferdb=None)
|
|
load_entry_points.assert_called_once_with('wutta.config.extensions')
|
|
|
|
# confirm entry points for custom appname
|
|
load_entry_points.reset_mock()
|
|
WuttaConfig.reset_mock()
|
|
config = mod.make_config(appname='wuttatest')
|
|
WuttaConfig.assert_called_once_with([], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
load_entry_points.assert_called_once_with('wuttatest.config.extensions')
|
|
|
|
# confirm extensions are invoked
|
|
load_entry_points.reset_mock()
|
|
foo_obj = MagicMock()
|
|
foo_cls = MagicMock(return_value=foo_obj)
|
|
load_entry_points.return_value = {'foo': foo_cls}
|
|
WuttaConfig.reset_mock()
|
|
testconfig = MagicMock()
|
|
WuttaConfig.return_value = testconfig
|
|
config = mod.make_config(appname='wuttatest')
|
|
WuttaConfig.assert_called_once_with([], appname='wuttatest',
|
|
usedb=None, preferdb=None)
|
|
load_entry_points.assert_called_once_with('wuttatest.config.extensions')
|
|
foo_cls.assert_called_once_with()
|
|
foo_obj.configure.assert_called_once_with(testconfig)
|
|
foo_obj.startup.assert_called_once_with(testconfig)
|