3
0
Fork 0
wuttjamaican/tests/test_conf.py

985 lines
34 KiB
Python
Raw Normal View History

# -*- 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, ConfigTestCase
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)
class TestWuttaConfigProfile(ConfigTestCase):
def make_profile(self, key):
return mod.WuttaConfigProfile(self.config, key)
def test_section(self):
profile = self.make_profile("default")
self.assertRaises(NotImplementedError, getattr, profile, "section")
def test_get_str(self):
self.config.setdefault("wutta.telemetry.default.submit_url", "/nodes/telemetry")
with patch.object(mod.WuttaConfigProfile, "section", new="wutta.telemetry"):
profile = self.make_profile("default")
self.assertEqual(profile.section, "wutta.telemetry")
url = profile.get_str("submit_url")
self.assertEqual(url, "/nodes/telemetry")