3
0
Fork 0

fix: format all code with black

and from now on should not deviate from that...
This commit is contained in:
Lance Edgar 2025-08-30 21:25:44 -05:00
parent 49f9a0228b
commit a6bb538ce9
59 changed files with 2762 additions and 2131 deletions

View file

@ -11,13 +11,13 @@ from wuttjamaican.cli import base as mod
here = os.path.dirname(__file__)
example_conf = os.path.join(here, 'example.conf')
example_conf = os.path.join(here, "example.conf")
class TestMakeCliConfig(TestCase):
def test_basic(self):
ctx = MagicMock(params={'config_paths': [example_conf]})
ctx = MagicMock(params={"config_paths": [example_conf]})
config = mod.make_cli_config(ctx)
self.assertIsInstance(config, WuttaConfig)
self.assertEqual(config.files_read, [example_conf])
@ -26,7 +26,7 @@ class TestMakeCliConfig(TestCase):
class TestTyperCallback(TestCase):
def test_basic(self):
ctx = MagicMock(params={'config_paths': [example_conf]})
ctx = MagicMock(params={"config_paths": [example_conf]})
mod.typer_callback(ctx)
self.assertIsInstance(ctx.wutta_config, WuttaConfig)
self.assertEqual(ctx.wutta_config.files_read, [example_conf])
@ -35,10 +35,10 @@ class TestTyperCallback(TestCase):
class TestTyperEagerImports(TestCase):
def test_basic(self):
typr = mod.make_typer(name='foobreezy')
with patch.object(mod, 'load_entry_points') as load_entry_points:
typr = mod.make_typer(name="foobreezy")
with patch.object(mod, "load_entry_points") as load_entry_points:
mod.typer_eager_imports(typr)
load_entry_points.assert_called_once_with('foobreezy.typer_imports')
load_entry_points.assert_called_once_with("foobreezy.typer_imports")
class TestMakeTyper(TestCase):

View file

@ -9,17 +9,16 @@ from wuttjamaican.app import AppHandler
here = os.path.dirname(__file__)
example_conf = os.path.join(here, 'example.conf')
example_conf = os.path.join(here, "example.conf")
class TestMakeAppdir(ConfigTestCase):
def test_basic(self):
appdir = os.path.join(self.tempdir, 'app')
ctx = MagicMock(params={'config_paths': [example_conf],
'appdir_path': appdir})
appdir = os.path.join(self.tempdir, "app")
ctx = MagicMock(params={"config_paths": [example_conf], "appdir_path": appdir})
ctx.parent.wutta_config = self.config
with patch.object(AppHandler, 'make_appdir') as make_appdir:
with patch.object(AppHandler, "make_appdir") as make_appdir:
mod.make_appdir(ctx)
make_appdir.assert_called_once_with(appdir)

View file

@ -8,13 +8,13 @@ from wuttjamaican.cli import make_uuid as mod
here = os.path.dirname(__file__)
example_conf = os.path.join(here, 'example.conf')
example_conf = os.path.join(here, "example.conf")
class TestMakeUuid(TestCase):
def test_basic(self):
ctx = MagicMock(params={'config_paths': [example_conf]})
with patch.object(mod, 'sys') as sys:
ctx = MagicMock(params={"config_paths": [example_conf]})
with patch.object(mod, "sys") as sys:
mod.make_uuid(ctx)
sys.stdout.write.assert_called_once()

View file

@ -8,8 +8,8 @@ from wuttjamaican.problems import ProblemHandler, ProblemCheck
class FakeCheck(ProblemCheck):
system_key = 'wuttatest'
problem_key = 'fake_check'
system_key = "wuttatest"
problem_key = "fake_check"
title = "Fake problem check"
@ -20,18 +20,28 @@ class TestProblems(ConfigTestCase):
ctx.parent.wutta_config = self.config
# nb. avoid printing to console
with patch.object(mod.rich, 'print') as rich_print:
with patch.object(mod.rich, "print") as rich_print:
# nb. use fake check
with patch.object(ProblemHandler, 'get_all_problem_checks', return_value=[FakeCheck]):
with patch.object(
ProblemHandler, "get_all_problem_checks", return_value=[FakeCheck]
):
with patch.object(ProblemHandler, 'run_problem_checks') as run_problem_checks:
with patch.object(
ProblemHandler, "run_problem_checks"
) as run_problem_checks:
# list problem checks
orig_organize = ProblemHandler.organize_problem_checks
def mock_organize(checks):
return orig_organize(None, checks)
with patch.object(ProblemHandler, 'organize_problem_checks', side_effect=mock_organize) as organize_problem_checks:
with patch.object(
ProblemHandler,
"organize_problem_checks",
side_effect=mock_organize,
) as organize_problem_checks:
mod.problems(ctx, list_checks=True)
organize_problem_checks.assert_called_once_with([FakeCheck])
run_problem_checks.assert_not_called()
@ -41,10 +51,13 @@ class TestProblems(ConfigTestCase):
# nb. just --list for convenience
# note that since we also specify invalid --system, no checks will
# match and hence nothing significant will be printed to stdout
mod.problems(ctx, list_checks=True, systems=['craziness'])
mod.problems(ctx, list_checks=True, systems=["craziness"])
rich_print.assert_called_once()
self.assertEqual(len(rich_print.call_args.args), 1)
self.assertIn("No problem reports exist for system", rich_print.call_args.args[0])
self.assertIn(
"No problem reports exist for system",
rich_print.call_args.args[0],
)
self.assertEqual(len(rich_print.call_args.kwargs), 0)
run_problem_checks.assert_not_called()

View file

@ -18,22 +18,20 @@ else:
role.name = "Managers"
self.assertEqual(str(role), "Managers")
class TestPermission(TestCase):
def test_basic(self):
perm = model.Permission()
self.assertEqual(str(perm), "")
perm.permission = 'users.create'
perm.permission = "users.create"
self.assertEqual(str(perm), "users.create")
class TestUser(TestCase):
def test_str(self):
user = model.User()
self.assertEqual(str(user), "")
user.username = 'barney'
user.username = "barney"
self.assertEqual(str(user), "barney")
def test_str_with_person(self):
@ -44,7 +42,6 @@ else:
user.person = person
self.assertEqual(str(user), "Barney Rubble")
class TestUserAPIToken(TestCase):
def test_str(self):

View file

@ -11,35 +11,32 @@ except ImportError:
pass
else:
class MockUser(mod.Base):
__tablename__ = 'mock_user'
uuid = mod.uuid_column(sa.ForeignKey('user.uuid'), default=False)
__tablename__ = "mock_user"
uuid = mod.uuid_column(sa.ForeignKey("user.uuid"), default=False)
user = orm.relationship(
User,
backref=orm.backref('_mock', uselist=False, cascade='all, delete-orphan'))
backref=orm.backref("_mock", uselist=False, cascade="all, delete-orphan"),
)
favorite_color = sa.Column(sa.String(length=100), nullable=False)
class TestWuttaModelBase(TestCase):
def test_make_proxy(self):
self.assertFalse(hasattr(User, 'favorite_color'))
MockUser.make_proxy(User, '_mock', 'favorite_color')
self.assertTrue(hasattr(User, 'favorite_color'))
user = User(favorite_color='green')
self.assertEqual(user.favorite_color, 'green')
self.assertFalse(hasattr(User, "favorite_color"))
MockUser.make_proxy(User, "_mock", "favorite_color")
self.assertTrue(hasattr(User, "favorite_color"))
user = User(favorite_color="green")
self.assertEqual(user.favorite_color, "green")
class TestSetting(TestCase):
def test_basic(self):
setting = mod.Setting()
self.assertEqual(str(setting), "")
setting.name = 'foo'
setting.name = "foo"
self.assertEqual(str(setting), "foo")
class TestPerson(TestCase):
def test_basic(self):

View file

@ -17,40 +17,46 @@ else:
def test_basic(self):
class MyBatch(mod.BatchMixin, model.Base):
__tablename__ = 'testing_mybatch'
__tablename__ = "testing_mybatch"
model.Base.metadata.create_all(bind=self.session.bind)
metadata = sa.MetaData()
metadata.reflect(self.session.bind)
self.assertIn('testing_mybatch', metadata.tables)
self.assertIn("testing_mybatch", metadata.tables)
batch = MyBatch(id=42, uuid=_uuid.UUID('0675cdac-ffc9-7690-8000-6023de1c8cfd'))
self.assertEqual(repr(batch), "MyBatch(uuid=UUID('0675cdac-ffc9-7690-8000-6023de1c8cfd'))")
batch = MyBatch(
id=42, uuid=_uuid.UUID("0675cdac-ffc9-7690-8000-6023de1c8cfd")
)
self.assertEqual(
repr(batch),
"MyBatch(uuid=UUID('0675cdac-ffc9-7690-8000-6023de1c8cfd'))",
)
self.assertEqual(str(batch), "00000042")
self.assertEqual(batch.id_str, "00000042")
batch2 = MyBatch()
self.assertIsNone(batch2.id_str)
class TestBatchRowMixin(DataTestCase):
def test_basic(self):
class MyBatch2(mod.BatchMixin, model.Base):
__tablename__ = 'testing_mybatch2'
__tablename__ = "testing_mybatch2"
class MyBatchRow2(mod.BatchRowMixin, model.Base):
__tablename__ = 'testing_mybatch_row2'
__tablename__ = "testing_mybatch_row2"
__batch_class__ = MyBatch2
model.Base.metadata.create_all(bind=self.session.bind)
metadata = sa.MetaData()
metadata.reflect(self.session.bind)
self.assertIn('testing_mybatch2', metadata.tables)
self.assertIn('testing_mybatch_row2', metadata.tables)
self.assertIn("testing_mybatch2", metadata.tables)
self.assertIn("testing_mybatch_row2", metadata.tables)
# nb. this gives coverage but doesn't really test much
batch = MyBatch2(id=42, uuid=_uuid.UUID('0675cdac-ffc9-7690-8000-6023de1c8cfd'))
batch = MyBatch2(
id=42, uuid=_uuid.UUID("0675cdac-ffc9-7690-8000-6023de1c8cfd")
)
row = MyBatchRow2()
batch.rows.append(row)

View file

@ -27,109 +27,130 @@ else:
def write_file(self, filename, content):
path = os.path.join(self.tempdir, filename)
with open(path, 'wt') as f:
with open(path, "wt") as f:
f.write(content)
return path
def test_no_default(self):
myfile = self.write_file('my.conf', '')
myfile = self.write_file("my.conf", "")
config = WuttaConfig([myfile])
self.assertEqual(conf.get_engines(config, 'wuttadb'), {})
self.assertEqual(conf.get_engines(config, "wuttadb"), {})
def test_default(self):
myfile = self.write_file('my.conf', """\
myfile = self.write_file(
"my.conf",
"""\
[wuttadb]
default.url = sqlite://
""")
""",
)
config = WuttaConfig([myfile])
result = conf.get_engines(config, 'wuttadb')
result = conf.get_engines(config, "wuttadb")
self.assertEqual(len(result), 1)
self.assertIn('default', result)
engine = result['default']
self.assertEqual(engine.dialect.name, 'sqlite')
self.assertIn("default", result)
engine = result["default"]
self.assertEqual(engine.dialect.name, "sqlite")
def test_default_fallback(self):
myfile = self.write_file('my.conf', """\
myfile = self.write_file(
"my.conf",
"""\
[wuttadb]
sqlalchemy.url = sqlite://
""")
""",
)
config = WuttaConfig([myfile])
result = conf.get_engines(config, 'wuttadb')
result = conf.get_engines(config, "wuttadb")
self.assertEqual(len(result), 1)
self.assertIn('default', result)
engine = result['default']
self.assertEqual(engine.dialect.name, 'sqlite')
self.assertIn("default", result)
engine = result["default"]
self.assertEqual(engine.dialect.name, "sqlite")
def test_other(self):
myfile = self.write_file('my.conf', """\
myfile = self.write_file(
"my.conf",
"""\
[otherdb]
keys = first, second
first.url = sqlite://
second.url = sqlite://
""")
""",
)
config = WuttaConfig([myfile])
result = conf.get_engines(config, 'otherdb')
result = conf.get_engines(config, "otherdb")
self.assertEqual(len(result), 2)
self.assertIn('first', result)
self.assertIn('second', result)
self.assertIn("first", result)
self.assertIn("second", result)
class TestGetSetting(TestCase):
def setUp(self):
Session = orm.sessionmaker()
engine = sa.create_engine('sqlite://')
engine = sa.create_engine("sqlite://")
self.session = Session(bind=engine)
self.session.execute(sa.text("""
self.session.execute(
sa.text(
"""
create table setting (
name varchar(255) primary key,
value text
);
"""))
"""
)
)
def tearDown(self):
self.session.close()
def test_basic_value(self):
self.session.execute(sa.text("insert into setting values ('foo', 'bar');"))
value = conf.get_setting(self.session, 'foo')
self.assertEqual(value, 'bar')
value = conf.get_setting(self.session, "foo")
self.assertEqual(value, "bar")
def test_missing_value(self):
value = conf.get_setting(self.session, 'foo')
value = conf.get_setting(self.session, "foo")
self.assertIsNone(value)
class TestMakeEngineFromConfig(TestCase):
def test_basic(self):
engine = conf.make_engine_from_config({
'sqlalchemy.url': 'sqlite://',
})
engine = conf.make_engine_from_config(
{
"sqlalchemy.url": "sqlite://",
}
)
self.assertIsInstance(engine, Engine)
def test_poolclass(self):
engine = conf.make_engine_from_config({
'sqlalchemy.url': 'sqlite://',
})
engine = conf.make_engine_from_config(
{
"sqlalchemy.url": "sqlite://",
}
)
self.assertNotIsInstance(engine.pool, NullPool)
engine = conf.make_engine_from_config({
'sqlalchemy.url': 'sqlite://',
'sqlalchemy.poolclass': 'sqlalchemy.pool:NullPool',
})
engine = conf.make_engine_from_config(
{
"sqlalchemy.url": "sqlite://",
"sqlalchemy.poolclass": "sqlalchemy.pool:NullPool",
}
)
self.assertIsInstance(engine.pool, NullPool)
def test_pool_pre_ping(self):
engine = conf.make_engine_from_config({
'sqlalchemy.url': 'sqlite://',
})
engine = conf.make_engine_from_config(
{
"sqlalchemy.url": "sqlite://",
}
)
self.assertFalse(engine.pool._pre_ping)
engine = conf.make_engine_from_config({
'sqlalchemy.url': 'sqlite://',
'sqlalchemy.pool_pre_ping': 'true',
})
engine = conf.make_engine_from_config(
{
"sqlalchemy.url": "sqlite://",
"sqlalchemy.pool_pre_ping": "true",
}
)
self.assertTrue(engine.pool._pre_ping)

View file

@ -22,20 +22,20 @@ else:
# counter table should not exist yet
metadata = sa.MetaData()
metadata.reflect(self.session.bind)
self.assertNotIn('_counter_testing', metadata.tables)
self.assertNotIn("_counter_testing", metadata.tables)
# using sqlite as backend, should make table for counter
value = handler.next_counter_value(self.session, 'testing')
value = handler.next_counter_value(self.session, "testing")
self.assertEqual(value, 1)
# counter table should exist now
metadata.reflect(self.session.bind)
self.assertIn('_counter_testing', metadata.tables)
self.assertIn("_counter_testing", metadata.tables)
# counter increments okay
value = handler.next_counter_value(self.session, 'testing')
value = handler.next_counter_value(self.session, "testing")
self.assertEqual(value, 2)
value = handler.next_counter_value(self.session, 'testing')
value = handler.next_counter_value(self.session, "testing")
self.assertEqual(value, 3)
def test_next_counter_value_postgres(self):
@ -44,20 +44,20 @@ else:
# counter table should not exist
metadata = sa.MetaData()
metadata.reflect(self.session.bind)
self.assertNotIn('_counter_testing', metadata.tables)
self.assertNotIn("_counter_testing", metadata.tables)
# nb. we have to pretty much mock this out, can't really
# test true sequence behavior for postgres since tests are
# using sqlite backend.
# using postgres as backend, should use "sequence"
with patch.object(handler, 'get_dialect', return_value='postgresql'):
with patch.object(self.session, 'execute') as execute:
with patch.object(handler, "get_dialect", return_value="postgresql"):
with patch.object(self.session, "execute") as execute:
execute.return_value.scalar.return_value = 1
value = handler.next_counter_value(self.session, 'testing')
value = handler.next_counter_value(self.session, "testing")
self.assertEqual(value, 1)
execute.return_value.scalar.assert_called_once_with()
# counter table should still not exist
metadata.reflect(self.session.bind)
self.assertNotIn('_counter_testing', metadata.tables)
self.assertNotIn("_counter_testing", metadata.tables)

View file

@ -16,18 +16,16 @@ except ImportError:
pass
else:
class TestModelBase(TestCase):
def test_dict_behavior(self):
setting = Setting()
self.assertEqual(list(iter(setting)), [('name', None), ('value', None)])
self.assertEqual(list(iter(setting)), [("name", None), ("value", None)])
self.assertIsNone(setting.name)
self.assertIsNone(setting['name'])
setting.name = 'foo'
self.assertEqual(setting['name'], 'foo')
self.assertRaises(KeyError, lambda: setting['notfound'])
self.assertIsNone(setting["name"])
setting.name = "foo"
self.assertEqual(setting["name"], "foo")
self.assertRaises(KeyError, lambda: setting["notfound"])
class TestUUID(TestCase):
@ -39,14 +37,14 @@ else:
# coverage at least..
# postgres
dialect.name = 'postgresql'
dialect.name = "postgresql"
dialect.type_descriptor.return_value = 42
result = typ.load_dialect_impl(dialect)
self.assertTrue(dialect.type_descriptor.called)
self.assertEqual(result, 42)
# other
dialect.name = 'mysql'
dialect.name = "mysql"
dialect.type_descriptor.return_value = 43
dialect.type_descriptor.reset_mock()
result = typ.load_dialect_impl(dialect)
@ -56,7 +54,7 @@ else:
def test_process_bind_param_postgres(self):
typ = mod.UUID()
dialect = MagicMock()
dialect.name = 'postgresql'
dialect.name = "postgresql"
# null
result = typ.process_bind_param(None, dialect)
@ -75,7 +73,7 @@ else:
def test_process_bind_param_other(self):
typ = mod.UUID()
dialect = MagicMock()
dialect.name = 'mysql'
dialect.name = "mysql"
# null
result = typ.process_bind_param(None, dialect)
@ -110,7 +108,6 @@ else:
result = typ.process_result_value(uuid_true, dialect)
self.assertIs(result, uuid_true)
class TestUUIDColumn(TestCase):
def test_basic(self):
@ -118,24 +115,22 @@ else:
self.assertIsInstance(column, sa.Column)
self.assertIsInstance(column.type, mod.UUID)
class TestUUIDFKColumn(TestCase):
def test_basic(self):
column = mod.uuid_fk_column('foo.bar')
column = mod.uuid_fk_column("foo.bar")
self.assertIsInstance(column, sa.Column)
self.assertIsInstance(column.type, mod.UUID)
class TestMakeTopoSortkey(DataTestCase):
def test_basic(self):
model = self.app.model
sortkey = mod.make_topo_sortkey(model)
original = ['User', 'Person', 'UserRole', 'Role']
original = ["User", "Person", "UserRole", "Role"]
# models are sorted so dependants come later
result = sorted(original, key=sortkey)
self.assertTrue(result.index('Role') < result.index('UserRole'))
self.assertTrue(result.index('User') < result.index('UserRole'))
self.assertTrue(result.index('Person') < result.index('User'))
self.assertTrue(result.index("Role") < result.index("UserRole"))
self.assertTrue(result.index("User") < result.index("UserRole"))
self.assertTrue(result.index("Person") < result.index("User"))

View file

@ -26,6 +26,7 @@ from wuttjamaican.batch import BatchHandler
class MockBatchHandler(BatchHandler):
pass
class AnotherBatchHandler(BatchHandler):
pass
@ -34,14 +35,14 @@ class TestAppHandler(FileTestCase):
def setUp(self):
self.setup_files()
self.config = WuttaConfig(appname='wuttatest')
self.config = WuttaConfig(appname="wuttatest")
self.app = mod.AppHandler(self.config)
self.config.app = self.app
def test_init(self):
self.assertIs(self.app.config, self.config)
self.assertEqual(self.app.handlers, {})
self.assertEqual(self.app.appname, 'wuttatest')
self.assertEqual(self.app.appname, "wuttatest")
def test_get_enum(self):
self.assertIs(self.app.get_enum(), wuttjamaican.enum)
@ -50,48 +51,50 @@ class TestAppHandler(FileTestCase):
# just confirm the method works on a basic level; the
# underlying function is tested elsewhere
obj = self.app.load_object('wuttjamaican.util:UNSPECIFIED')
obj = self.app.load_object("wuttjamaican.util:UNSPECIFIED")
self.assertIs(obj, UNSPECIFIED)
def test_get_appdir(self):
mockdir = self.mkdir('mockdir')
mockdir = self.mkdir("mockdir")
# default appdir
with patch.object(sys, 'prefix', new=mockdir):
with patch.object(sys, "prefix", new=mockdir):
# default is returned by default
appdir = self.app.get_appdir()
self.assertEqual(appdir, os.path.join(mockdir, 'app'))
self.assertEqual(appdir, os.path.join(mockdir, "app"))
# but not if caller wants config only
appdir = self.app.get_appdir(configured_only=True)
self.assertIsNone(appdir)
# also, cannot create if appdir path not known
self.assertRaises(ValueError, self.app.get_appdir, configured_only=True, create=True)
self.assertRaises(
ValueError, self.app.get_appdir, configured_only=True, create=True
)
# configured appdir
self.config.setdefault('wuttatest.appdir', mockdir)
self.config.setdefault("wuttatest.appdir", mockdir)
appdir = self.app.get_appdir()
self.assertEqual(appdir, mockdir)
# appdir w/ subpath
appdir = self.app.get_appdir('foo', 'bar')
self.assertEqual(appdir, os.path.join(mockdir, 'foo', 'bar'))
appdir = self.app.get_appdir("foo", "bar")
self.assertEqual(appdir, os.path.join(mockdir, "foo", "bar"))
# subpath is created
self.assertEqual(len(os.listdir(mockdir)), 0)
appdir = self.app.get_appdir('foo', 'bar', create=True)
self.assertEqual(appdir, os.path.join(mockdir, 'foo', 'bar'))
self.assertEqual(os.listdir(mockdir), ['foo'])
self.assertEqual(os.listdir(os.path.join(mockdir, 'foo')), ['bar'])
appdir = self.app.get_appdir("foo", "bar", create=True)
self.assertEqual(appdir, os.path.join(mockdir, "foo", "bar"))
self.assertEqual(os.listdir(mockdir), ["foo"])
self.assertEqual(os.listdir(os.path.join(mockdir, "foo")), ["bar"])
def test_make_appdir(self):
# appdir is created, and 3 subfolders added by default
tempdir = tempfile.mkdtemp()
appdir = os.path.join(tempdir, 'app')
appdir = os.path.join(tempdir, "app")
self.assertFalse(os.path.exists(appdir))
self.app.make_appdir(appdir)
self.assertTrue(os.path.exists(appdir))
@ -107,23 +110,30 @@ class TestAppHandler(FileTestCase):
shutil.rmtree(tempdir)
def test_render_mako_template(self):
output_conf = self.write_file('output.conf', '')
template = Template("""\
output_conf = self.write_file("output.conf", "")
template = Template(
"""\
[wutta]
app_title = WuttaTest
""")
"""
)
output = self.app.render_mako_template(template, {}, output_path=output_conf)
self.assertEqual(output, """\
self.assertEqual(
output,
"""\
[wutta]
app_title = WuttaTest
""")
""",
)
with open(output_conf, 'rt') as f:
with open(output_conf, "rt") as f:
self.assertEqual(f.read(), output)
def test_resource_path(self):
result = self.app.resource_path('wuttjamaican:templates')
self.assertEqual(result, os.path.join(os.path.dirname(mod.__file__), 'templates'))
result = self.app.resource_path("wuttjamaican:templates")
self.assertEqual(
result, os.path.join(os.path.dirname(mod.__file__), "templates")
)
def test_make_session(self):
try:
@ -138,11 +148,12 @@ app_title = WuttaTest
short_session = MagicMock()
mockdb = MagicMock(short_session=short_session)
with patch.dict('sys.modules', **{'wuttjamaican.db': mockdb}):
with patch.dict("sys.modules", **{"wuttjamaican.db": mockdb}):
with self.app.short_session(foo='bar') as s:
with self.app.short_session(foo="bar") as s:
short_session.assert_called_once_with(
foo='bar', factory=self.app.make_session)
foo="bar", factory=self.app.make_session
)
def test_get_setting(self):
try:
@ -152,22 +163,26 @@ app_title = WuttaTest
pytest.skip("test is not relevant without sqlalchemy")
Session = orm.sessionmaker()
engine = sa.create_engine('sqlite://')
engine = sa.create_engine("sqlite://")
session = Session(bind=engine)
session.execute(sa.text("""
session.execute(
sa.text(
"""
create table setting (
name varchar(255) primary key,
value text
);
"""))
"""
)
)
session.commit()
value = self.app.get_setting(session, 'foo')
value = self.app.get_setting(session, "foo")
self.assertIsNone(value)
session.execute(sa.text("insert into setting values ('foo', 'bar');"))
value = self.app.get_setting(session, 'foo')
self.assertEqual(value, 'bar')
value = self.app.get_setting(session, "foo")
self.assertEqual(value, "bar")
def test_save_setting(self):
try:
@ -177,25 +192,29 @@ app_title = WuttaTest
pytest.skip("test is not relevant without sqlalchemy")
Session = orm.sessionmaker()
engine = sa.create_engine('sqlite://')
engine = sa.create_engine("sqlite://")
session = Session(bind=engine)
session.execute(sa.text("""
session.execute(
sa.text(
"""
create table setting (
name varchar(255) primary key,
value text
);
"""))
"""
)
)
session.commit()
# value null by default
value = self.app.get_setting(session, 'foo')
value = self.app.get_setting(session, "foo")
self.assertIsNone(value)
# unless we save a value
self.app.save_setting(session, 'foo', '1')
self.app.save_setting(session, "foo", "1")
session.commit()
value = self.app.get_setting(session, 'foo')
self.assertEqual(value, '1')
value = self.app.get_setting(session, "foo")
self.assertEqual(value, "1")
def test_delete_setting(self):
try:
@ -205,43 +224,48 @@ app_title = WuttaTest
pytest.skip("test is not relevant without sqlalchemy")
Session = orm.sessionmaker()
engine = sa.create_engine('sqlite://')
engine = sa.create_engine("sqlite://")
session = Session(bind=engine)
session.execute(sa.text("""
session.execute(
sa.text(
"""
create table setting (
name varchar(255) primary key,
value text
);
"""))
"""
)
)
session.commit()
# value null by default
value = self.app.get_setting(session, 'foo')
value = self.app.get_setting(session, "foo")
self.assertIsNone(value)
# unless we save a value
self.app.save_setting(session, 'foo', '1')
self.app.save_setting(session, "foo", "1")
session.commit()
value = self.app.get_setting(session, 'foo')
self.assertEqual(value, '1')
value = self.app.get_setting(session, "foo")
self.assertEqual(value, "1")
# but then if we delete it, should be null again
self.app.delete_setting(session, 'foo')
self.app.delete_setting(session, "foo")
session.commit()
value = self.app.get_setting(session, 'foo')
value = self.app.get_setting(session, "foo")
self.assertIsNone(value)
def test_continuum_is_enabled(self):
# false by default
with patch.object(self.app, 'providers', new={}):
with patch.object(self.app, "providers", new={}):
self.assertFalse(self.app.continuum_is_enabled())
# but "any" provider technically could enable it...
class MockProvider:
def continuum_is_enabled(self):
return True
with patch.object(self.app, 'providers', new={'mock': MockProvider()}):
with patch.object(self.app, "providers", new={"mock": MockProvider()}):
self.assertTrue(self.app.continuum_is_enabled())
def test_model(self):
@ -250,7 +274,7 @@ app_title = WuttaTest
except ImportError:
pytest.skip("test not relevant without sqlalchemy")
self.assertNotIn('model', self.app.__dict__)
self.assertNotIn("model", self.app.__dict__)
self.assertIs(self.app.model, model)
def test_get_model(self):
@ -262,20 +286,20 @@ app_title = WuttaTest
self.assertIs(self.app.get_model(), model)
def test_get_title(self):
self.assertEqual(self.app.get_title(), 'WuttJamaican')
self.assertEqual(self.app.get_title(), "WuttJamaican")
def test_get_node_title(self):
# default
self.assertEqual(self.app.get_node_title(), 'WuttJamaican')
self.assertEqual(self.app.get_node_title(), "WuttJamaican")
# will fallback to app title
self.config.setdefault('wuttatest.app_title', "WuttaTest")
self.assertEqual(self.app.get_node_title(), 'WuttaTest')
self.config.setdefault("wuttatest.app_title", "WuttaTest")
self.assertEqual(self.app.get_node_title(), "WuttaTest")
# will read from config
self.config.setdefault('wuttatest.node_title', "WuttaNode")
self.assertEqual(self.app.get_node_title(), 'WuttaNode')
self.config.setdefault("wuttatest.node_title", "WuttaNode")
self.assertEqual(self.app.get_node_title(), "WuttaNode")
def test_get_node_type(self):
@ -283,8 +307,8 @@ app_title = WuttaTest
self.assertIsNone(self.app.get_node_type())
# will read from config
self.config.setdefault('wuttatest.node_type', 'warehouse')
self.assertEqual(self.app.get_node_type(), 'warehouse')
self.config.setdefault("wuttatest.node_type", "warehouse")
self.assertEqual(self.app.get_node_type(), "warehouse")
def test_get_distribution(self):
@ -296,16 +320,16 @@ app_title = WuttaTest
# works with "non-native" objects
query = Query({})
dist = self.app.get_distribution(query)
self.assertEqual(dist, 'SQLAlchemy')
self.assertEqual(dist, "SQLAlchemy")
# can override dist via config
self.config.setdefault('wuttatest.app_dist', 'importlib_metadata')
self.config.setdefault("wuttatest.app_dist", "importlib_metadata")
dist = self.app.get_distribution()
self.assertEqual(dist, 'importlib_metadata')
self.assertEqual(dist, "importlib_metadata")
# but the provided object takes precedence
dist = self.app.get_distribution(query)
self.assertEqual(dist, 'SQLAlchemy')
self.assertEqual(dist, "SQLAlchemy")
def test_get_distribution_pre_python_3_10(self):
@ -318,30 +342,32 @@ app_title = WuttaTest
importlib_metadata = MagicMock()
importlib_metadata.packages_distributions = MagicMock(
return_value={
'wuttjamaican': ['WuttJamaican'],
'config': ['python-configuration'],
})
"wuttjamaican": ["WuttJamaican"],
"config": ["python-configuration"],
}
)
orig_import = __import__
def mock_import(name, *args, **kwargs):
if name == 'importlib.metadata':
if name == "importlib.metadata":
raise ImportError
if name == 'importlib_metadata':
if name == "importlib_metadata":
return importlib_metadata
return orig_import(name, *args, **kwargs)
with patch('builtins.__import__', side_effect=mock_import):
with patch("builtins.__import__", side_effect=mock_import):
# default should always be WuttJamaican (right..?)
dist = self.app.get_distribution()
self.assertEqual(dist, 'WuttJamaican')
self.assertEqual(dist, "WuttJamaican")
# also works with "non-native" objects
from config import Configuration
config = Configuration({})
dist = self.app.get_distribution(config)
self.assertEqual(dist, 'python-configuration')
self.assertEqual(dist, "python-configuration")
# hacky sort of test, just in case we can't deduce the
# package dist based on the obj - easy enough since we
@ -350,17 +376,17 @@ app_title = WuttaTest
self.assertIsNone(dist)
# can override dist via config
self.config.setdefault('wuttatest.app_dist', 'importlib_metadata')
self.config.setdefault("wuttatest.app_dist", "importlib_metadata")
dist = self.app.get_distribution()
self.assertEqual(dist, 'importlib_metadata')
self.assertEqual(dist, "importlib_metadata")
# but the provided object takes precedence
dist = self.app.get_distribution(config)
self.assertEqual(dist, 'python-configuration')
self.assertEqual(dist, "python-configuration")
# hacky test again, this time config override should win
dist = self.app.get_distribution(42)
self.assertEqual(dist, 'importlib_metadata')
self.assertEqual(dist, "importlib_metadata")
def test_get_version(self):
from importlib.metadata import version
@ -373,31 +399,31 @@ app_title = WuttaTest
# works with "non-native" objects
query = Query({})
ver = self.app.get_version(obj=query)
self.assertEqual(ver, version('SQLAlchemy'))
self.assertEqual(ver, version("SQLAlchemy"))
# random object will not yield a dist nor version
ver = self.app.get_version(obj=42)
self.assertIsNone(ver)
# can override dist via config
self.config.setdefault('wuttatest.app_dist', 'python-configuration')
self.config.setdefault("wuttatest.app_dist", "python-configuration")
ver = self.app.get_version()
self.assertEqual(ver, version('python-configuration'))
self.assertEqual(ver, version("python-configuration"))
# but the provided object takes precedence
ver = self.app.get_version(obj=query)
self.assertEqual(ver, version('SQLAlchemy'))
self.assertEqual(ver, version("SQLAlchemy"))
# can also specify the dist
ver = self.app.get_version(dist='passlib')
self.assertEqual(ver, version('passlib'))
ver = self.app.get_version(dist="passlib")
self.assertEqual(ver, version("passlib"))
def test_make_title(self):
text = self.app.make_title('foo_bar')
text = self.app.make_title("foo_bar")
self.assertEqual(text, "Foo Bar")
def test_make_full_name(self):
name = self.app.make_full_name('Fred', '', 'Flintstone', '')
name = self.app.make_full_name("Fred", "", "Flintstone", "")
self.assertEqual(name, "Fred Flintstone")
def test_make_uuid(self):
@ -414,12 +440,10 @@ app_title = WuttaTest
pass
# with progress
self.app.progress_loop(act, [1, 2, 3], ProgressBase,
message="whatever")
self.app.progress_loop(act, [1, 2, 3], ProgressBase, message="whatever")
# without progress
self.app.progress_loop(act, [1, 2, 3], None,
message="whatever")
self.app.progress_loop(act, [1, 2, 3], None, message="whatever")
def test_get_session(self):
try:
@ -433,7 +457,7 @@ app_title = WuttaTest
self.assertIsNone(self.app.get_session(user))
Session = orm.sessionmaker()
engine = sa.create_engine('sqlite://')
engine = sa.create_engine("sqlite://")
mysession = Session(bind=engine)
mysession.add(user)
session = self.app.get_session(user)
@ -453,39 +477,39 @@ app_title = WuttaTest
def test_render_currency(self):
# null
self.assertEqual(self.app.render_currency(None), '')
self.assertEqual(self.app.render_currency(None), "")
# basic decimal example
value = decimal.Decimal('42.00')
self.assertEqual(self.app.render_currency(value), '$42.00')
value = decimal.Decimal("42.00")
self.assertEqual(self.app.render_currency(value), "$42.00")
# basic float example
value = 42.00
self.assertEqual(self.app.render_currency(value), '$42.00')
self.assertEqual(self.app.render_currency(value), "$42.00")
# decimal places will be rounded
value = decimal.Decimal('42.12345')
self.assertEqual(self.app.render_currency(value), '$42.12')
value = decimal.Decimal("42.12345")
self.assertEqual(self.app.render_currency(value), "$42.12")
# but we can declare the scale
value = decimal.Decimal('42.12345')
self.assertEqual(self.app.render_currency(value, scale=4), '$42.1234')
value = decimal.Decimal("42.12345")
self.assertEqual(self.app.render_currency(value, scale=4), "$42.1234")
# negative numbers get parens
value = decimal.Decimal('-42.42')
self.assertEqual(self.app.render_currency(value), '($42.42)')
value = decimal.Decimal("-42.42")
self.assertEqual(self.app.render_currency(value), "($42.42)")
def test_render_date(self):
self.assertEqual(self.app.render_date(None), '')
self.assertEqual(self.app.render_date(None), "")
dt = datetime.date(2024, 12, 11)
self.assertEqual(self.app.render_date(dt), '2024-12-11')
self.assertEqual(self.app.render_date(dt), "2024-12-11")
def test_render_datetime(self):
self.assertEqual(self.app.render_datetime(None), '')
self.assertEqual(self.app.render_datetime(None), "")
dt = datetime.datetime(2024, 12, 11, 8, 30, tzinfo=datetime.timezone.utc)
self.assertEqual(self.app.render_datetime(dt), '2024-12-11 08:30+0000')
self.assertEqual(self.app.render_datetime(dt), "2024-12-11 08:30+0000")
def test_render_error(self):
@ -509,15 +533,15 @@ app_title = WuttaTest
self.assertEqual(self.app.render_percent(None), "")
# typical
self.assertEqual(self.app.render_percent(12.3419), '12.34 %')
self.assertEqual(self.app.render_percent(12.3419), "12.34 %")
# more decimal places
self.assertEqual(self.app.render_percent(12.3419, decimals=3), '12.342 %')
self.assertEqual(self.app.render_percent(12.3419, decimals=4), '12.3419 %')
self.assertEqual(self.app.render_percent(12.3419, decimals=3), "12.342 %")
self.assertEqual(self.app.render_percent(12.3419, decimals=4), "12.3419 %")
# negative
self.assertEqual(self.app.render_percent(-12.3419), '(12.34 %)')
self.assertEqual(self.app.render_percent(-12.3419, decimals=3), '(12.342 %)')
self.assertEqual(self.app.render_percent(-12.3419), "(12.34 %)")
self.assertEqual(self.app.render_percent(-12.3419, decimals=3), "(12.342 %)")
def test_render_quantity(self):
@ -525,11 +549,11 @@ app_title = WuttaTest
self.assertEqual(self.app.render_quantity(None), "")
# integer decimals become integers
value = decimal.Decimal('1.000')
value = decimal.Decimal("1.000")
self.assertEqual(self.app.render_quantity(value), "1")
# but decimal places are preserved
value = decimal.Decimal('1.234')
value = decimal.Decimal("1.234")
self.assertEqual(self.app.render_quantity(value), "1.234")
# zero can be empty string
@ -537,20 +561,20 @@ app_title = WuttaTest
self.assertEqual(self.app.render_quantity(0, empty_zero=True), "")
def test_render_time_ago(self):
with patch.object(mod, 'humanize') as humanize:
humanize.naturaltime.return_value = 'now'
with patch.object(mod, "humanize") as humanize:
humanize.naturaltime.return_value = "now"
now = datetime.datetime.now()
result = self.app.render_time_ago(now)
self.assertEqual(result, 'now')
self.assertEqual(result, "now")
humanize.naturaltime.assert_called_once_with(now)
def test_get_person(self):
people = self.app.get_people_handler()
with patch.object(people, 'get_person') as get_person:
get_person.return_value = 'foo'
person = self.app.get_person('bar')
get_person.assert_called_once_with('bar')
self.assertEqual(person, 'foo')
with patch.object(people, "get_person") as get_person:
get_person.return_value = "foo"
person = self.app.get_person("bar")
get_person.assert_called_once_with("bar")
self.assertEqual(person, "foo")
def test_get_auth_handler(self):
from wuttjamaican.auth import AuthHandler
@ -561,55 +585,80 @@ app_title = WuttaTest
def test_get_batch_handler(self):
# error if handler not found
self.assertRaises(KeyError, self.app.get_batch_handler, 'CannotFindMe!')
self.assertRaises(KeyError, self.app.get_batch_handler, "CannotFindMe!")
# caller can specify default
handler = self.app.get_batch_handler('foo', default='wuttjamaican.batch:BatchHandler')
handler = self.app.get_batch_handler(
"foo", default="wuttjamaican.batch:BatchHandler"
)
self.assertIsInstance(handler, BatchHandler)
# default can be configured
self.config.setdefault('wuttatest.batch.foo.handler.default_spec',
'wuttjamaican.batch:BatchHandler')
handler = self.app.get_batch_handler('foo')
self.config.setdefault(
"wuttatest.batch.foo.handler.default_spec",
"wuttjamaican.batch:BatchHandler",
)
handler = self.app.get_batch_handler("foo")
self.assertIsInstance(handler, BatchHandler)
# preference can be configured
self.config.setdefault('wuttatest.batch.foo.handler.spec',
'tests.test_app:MockBatchHandler')
handler = self.app.get_batch_handler('foo')
self.config.setdefault(
"wuttatest.batch.foo.handler.spec", "tests.test_app:MockBatchHandler"
)
handler = self.app.get_batch_handler("foo")
self.assertIsInstance(handler, MockBatchHandler)
def test_get_batch_handler_specs(self):
# empty by default
specs = self.app.get_batch_handler_specs('foo')
specs = self.app.get_batch_handler_specs("foo")
self.assertEqual(specs, [])
# caller can specify default as string
specs = self.app.get_batch_handler_specs('foo', default='wuttjamaican.batch:BatchHandler')
self.assertEqual(specs, ['wuttjamaican.batch:BatchHandler'])
specs = self.app.get_batch_handler_specs(
"foo", default="wuttjamaican.batch:BatchHandler"
)
self.assertEqual(specs, ["wuttjamaican.batch:BatchHandler"])
# caller can specify default as list
specs = self.app.get_batch_handler_specs('foo', default=['wuttjamaican.batch:BatchHandler',
'tests.test_app:MockBatchHandler'])
self.assertEqual(specs, ['wuttjamaican.batch:BatchHandler',
'tests.test_app:MockBatchHandler'])
specs = self.app.get_batch_handler_specs(
"foo",
default=[
"wuttjamaican.batch:BatchHandler",
"tests.test_app:MockBatchHandler",
],
)
self.assertEqual(
specs,
["wuttjamaican.batch:BatchHandler", "tests.test_app:MockBatchHandler"],
)
# default can be configured
self.config.setdefault('wuttatest.batch.foo.handler.default_spec',
'wuttjamaican.batch:BatchHandler')
specs = self.app.get_batch_handler_specs('foo')
self.assertEqual(specs, ['wuttjamaican.batch:BatchHandler'])
self.config.setdefault(
"wuttatest.batch.foo.handler.default_spec",
"wuttjamaican.batch:BatchHandler",
)
specs = self.app.get_batch_handler_specs("foo")
self.assertEqual(specs, ["wuttjamaican.batch:BatchHandler"])
# the rest come from entry points
with patch.object(mod, 'load_entry_points', return_value={
'mock': MockBatchHandler,
'another': AnotherBatchHandler,
}):
specs = self.app.get_batch_handler_specs('foo')
self.assertEqual(specs, ['wuttjamaican.batch:BatchHandler',
'tests.test_app:AnotherBatchHandler',
'tests.test_app:MockBatchHandler'])
with patch.object(
mod,
"load_entry_points",
return_value={
"mock": MockBatchHandler,
"another": AnotherBatchHandler,
},
):
specs = self.app.get_batch_handler_specs("foo")
self.assertEqual(
specs,
[
"wuttjamaican.batch:BatchHandler",
"tests.test_app:AnotherBatchHandler",
"tests.test_app:MockBatchHandler",
],
)
def test_get_db_handler(self):
try:
@ -653,15 +702,15 @@ app_title = WuttaTest
def test_send_email(self):
from wuttjamaican.email import EmailHandler
with patch.object(EmailHandler, 'send_email') as send_email:
self.app.send_email('foo')
send_email.assert_called_once_with('foo')
with patch.object(EmailHandler, "send_email") as send_email:
self.app.send_email("foo")
send_email.assert_called_once_with("foo")
class TestAppProvider(TestCase):
def setUp(self):
self.config = WuttaConfig(appname='wuttatest')
self.config = WuttaConfig(appname="wuttatest")
self.app = mod.AppHandler(self.config)
self.config._app = self.app
@ -671,11 +720,11 @@ class TestAppProvider(TestCase):
provider = mod.AppProvider(self.config)
self.assertIs(provider.config, self.config)
self.assertIs(provider.app, self.app)
self.assertEqual(provider.appname, 'wuttatest')
self.assertEqual(provider.appname, "wuttatest")
# but can pass app handler instead
with warnings.catch_warnings():
warnings.filterwarnings('ignore', category=DeprecationWarning)
warnings.filterwarnings("ignore", category=DeprecationWarning)
provider = mod.AppProvider(self.app)
self.assertIs(provider.config, self.config)
self.assertIs(provider.app, self.app)
@ -686,17 +735,17 @@ class TestAppProvider(TestCase):
pass
# nb. we specify *classes* here
fake_providers = {'fake': FakeProvider}
fake_providers = {"fake": FakeProvider}
with patch('wuttjamaican.app.load_entry_points') as load_entry_points:
with patch("wuttjamaican.app.load_entry_points") as load_entry_points:
load_entry_points.return_value = fake_providers
# sanity check, we get *instances* back from this
providers = self.app.get_all_providers()
load_entry_points.assert_called_once_with('wutta.app.providers')
load_entry_points.assert_called_once_with("wutta.app.providers")
self.assertEqual(len(providers), 1)
self.assertIn('fake', providers)
self.assertIsInstance(providers['fake'], FakeProvider)
self.assertIn("fake", providers)
self.assertIsInstance(providers["fake"], FakeProvider)
def test_hasattr(self):
@ -704,15 +753,15 @@ class TestAppProvider(TestCase):
def fake_foo(self):
pass
self.app.providers = {'fake': FakeProvider(self.config)}
self.app.providers = {"fake": FakeProvider(self.config)}
self.assertTrue(hasattr(self.app, 'fake_foo'))
self.assertFalse(hasattr(self.app, 'fake_method_does_not_exist'))
self.assertTrue(hasattr(self.app, "fake_foo"))
self.assertFalse(hasattr(self.app, "fake_method_does_not_exist"))
def test_getattr(self):
# enum
self.assertNotIn('enum', self.app.__dict__)
self.assertNotIn("enum", self.app.__dict__)
self.assertIs(self.app.enum, wuttjamaican.enum)
# now we test that providers are loaded...
@ -722,12 +771,12 @@ class TestAppProvider(TestCase):
return 42
# nb. using instances here
fake_providers = {'fake': FakeProvider(self.config)}
fake_providers = {"fake": FakeProvider(self.config)}
with patch.object(self.app, 'get_all_providers') as get_all_providers:
with patch.object(self.app, "get_all_providers") as get_all_providers:
get_all_providers.return_value = fake_providers
self.assertNotIn('providers', self.app.__dict__)
self.assertNotIn("providers", self.app.__dict__)
self.assertIs(self.app.providers, fake_providers)
get_all_providers.assert_called_once_with()
@ -738,27 +787,27 @@ class TestAppProvider(TestCase):
pytest.skip("test not relevant without sqlalchemy")
# model
self.assertNotIn('model', self.app.__dict__)
self.assertNotIn("model", self.app.__dict__)
self.assertIs(self.app.model, wuttjamaican.db.model)
def test_getattr_providers(self):
# collection of providers is loaded on demand
self.assertNotIn('providers', self.app.__dict__)
self.assertNotIn("providers", self.app.__dict__)
self.assertIsNotNone(self.app.providers)
# custom attr does not exist yet
self.assertRaises(AttributeError, getattr, self.app, 'foo_value')
self.assertRaises(AttributeError, getattr, self.app, "foo_value")
# but provider can supply the attr
self.app.providers['mytest'] = MagicMock(foo_value='bar')
self.assertEqual(self.app.foo_value, 'bar')
self.app.providers["mytest"] = MagicMock(foo_value="bar")
self.assertEqual(self.app.foo_value, "bar")
class TestGenericHandler(ConfigTestCase):
def make_config(self, **kw):
kw.setdefault('appname', 'wuttatest')
kw.setdefault("appname", "wuttatest")
return super().make_config(**kw)
def make_handler(self, **kwargs):
@ -768,34 +817,36 @@ class TestGenericHandler(ConfigTestCase):
handler = mod.GenericHandler(self.config)
self.assertIs(handler.config, self.config)
self.assertIs(handler.app, self.app)
self.assertEqual(handler.appname, 'wuttatest')
self.assertEqual(handler.appname, "wuttatest")
def test_get_spec(self):
self.assertEqual(mod.GenericHandler.get_spec(), 'wuttjamaican.app:GenericHandler')
self.assertEqual(
mod.GenericHandler.get_spec(), "wuttjamaican.app:GenericHandler"
)
def test_get_provider_modules(self):
# no providers, no email modules
with patch.object(self.app, 'providers', new={}):
with patch.object(self.app, "providers", new={}):
handler = self.make_handler()
self.assertEqual(handler.get_provider_modules('email'), [])
self.assertEqual(handler.get_provider_modules("email"), [])
# provider may specify modules as list
providers = {
'wuttatest': MagicMock(email_modules=['wuttjamaican.app']),
"wuttatest": MagicMock(email_modules=["wuttjamaican.app"]),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
modules = handler.get_provider_modules('email')
modules = handler.get_provider_modules("email")
self.assertEqual(len(modules), 1)
self.assertIs(modules[0], mod)
# provider may specify modules as string
providers = {
'wuttatest': MagicMock(email_modules='wuttjamaican.app'),
"wuttatest": MagicMock(email_modules="wuttjamaican.app"),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
modules = handler.get_provider_modules('email')
modules = handler.get_provider_modules("email")
self.assertEqual(len(modules), 1)
self.assertIs(modules[0], mod)

View file

@ -11,7 +11,6 @@ except ImportError:
pass
else:
class TestAuthHandler(TestCase):
def setUp(self):
@ -19,7 +18,7 @@ else:
self.app = self.config.get_app()
self.handler = self.make_handler()
self.engine = sa.create_engine('sqlite://')
self.engine = sa.create_engine("sqlite://")
self.app.model.Base.metadata.create_all(bind=self.engine)
self.session = self.make_session()
@ -35,37 +34,37 @@ else:
def test_authenticate_user(self):
model = self.app.model
barney = model.User(username='barney')
self.handler.set_user_password(barney, 'goodpass')
barney = model.User(username="barney")
self.handler.set_user_password(barney, "goodpass")
self.session.add(barney)
self.session.commit()
# login ok
user = self.handler.authenticate_user(self.session, 'barney', 'goodpass')
user = self.handler.authenticate_user(self.session, "barney", "goodpass")
self.assertIs(user, barney)
# can also pass user instead of username
user = self.handler.authenticate_user(self.session, barney, 'goodpass')
user = self.handler.authenticate_user(self.session, barney, "goodpass")
self.assertIs(user, barney)
# bad password
user = self.handler.authenticate_user(self.session, 'barney', 'BADPASS')
user = self.handler.authenticate_user(self.session, "barney", "BADPASS")
self.assertIsNone(user)
# bad username
user = self.handler.authenticate_user(self.session, 'NOBODY', 'goodpass')
user = self.handler.authenticate_user(self.session, "NOBODY", "goodpass")
self.assertIsNone(user)
# inactive user
user = self.handler.authenticate_user(self.session, 'barney', 'goodpass')
user = self.handler.authenticate_user(self.session, "barney", "goodpass")
self.assertIs(user, barney)
barney.active = False
user = self.handler.authenticate_user(self.session, 'barney', 'goodpass')
user = self.handler.authenticate_user(self.session, "barney", "goodpass")
self.assertIsNone(user)
def test_authenticate_user_token(self):
model = self.app.model
barney = model.User(username='barney')
barney = model.User(username="barney")
self.session.add(barney)
token = self.handler.add_api_token(barney, "test token")
self.session.commit()
@ -73,32 +72,38 @@ else:
user = self.handler.authenticate_user_token(self.session, None)
self.assertIsNone(user)
user = self.handler.authenticate_user_token(self.session, token.token_string)
user = self.handler.authenticate_user_token(
self.session, token.token_string
)
self.assertIs(user, barney)
barney.active = False
self.session.flush()
user = self.handler.authenticate_user_token(self.session, token.token_string)
user = self.handler.authenticate_user_token(
self.session, token.token_string
)
self.assertIsNone(user)
barney.active = True
self.session.flush()
user = self.handler.authenticate_user_token(self.session, token.token_string)
user = self.handler.authenticate_user_token(
self.session, token.token_string
)
self.assertIs(user, barney)
user = self.handler.authenticate_user_token(self.session, 'bad-token')
user = self.handler.authenticate_user_token(self.session, "bad-token")
self.assertIsNone(user)
def test_check_user_password(self):
model = self.app.model
barney = model.User(username='barney')
self.handler.set_user_password(barney, 'goodpass')
barney = model.User(username="barney")
self.handler.set_user_password(barney, "goodpass")
self.session.add(barney)
self.session.commit()
# basics
self.assertTrue(self.handler.check_user_password(barney, 'goodpass'))
self.assertFalse(self.handler.check_user_password(barney, 'BADPASS'))
self.assertTrue(self.handler.check_user_password(barney, "goodpass"))
self.assertFalse(self.handler.check_user_password(barney, "BADPASS"))
def test_get_role(self):
model = self.app.model
@ -120,17 +125,17 @@ else:
# key may be represented within a setting
self.config.usedb = True
role = self.handler.get_role(self.session, 'mykey')
role = self.handler.get_role(self.session, "mykey")
self.assertIsNone(role)
setting = model.Setting(name='wutta.role.mykey', value=myrole.uuid.hex)
setting = model.Setting(name="wutta.role.mykey", value=myrole.uuid.hex)
self.session.add(setting)
self.session.commit()
role = self.handler.get_role(self.session, 'mykey')
role = self.handler.get_role(self.session, "mykey")
self.assertIs(role, myrole)
def test_get_user(self):
model = self.app.model
myuser = model.User(username='myuser')
myuser = model.User(username="myuser")
self.session.add(myuser)
self.session.commit()
@ -155,7 +160,7 @@ else:
self.assertIs(user, myuser)
# find user from person
myperson = model.Person(full_name='My Name')
myperson = model.Person(full_name="My Name")
self.session.add(myperson)
user.person = myperson
self.session.commit()
@ -173,11 +178,11 @@ else:
self.assertIsNone(person.full_name)
self.assertNotIn(person, self.session)
person = handler.make_person(first_name='Barney', last_name='Rubble')
person = handler.make_person(first_name="Barney", last_name="Rubble")
self.assertIsInstance(person, model.Person)
self.assertEqual(person.first_name, 'Barney')
self.assertEqual(person.last_name, 'Rubble')
self.assertEqual(person.full_name, 'Barney Rubble')
self.assertEqual(person.first_name, "Barney")
self.assertEqual(person.last_name, "Rubble")
self.assertEqual(person.full_name, "Barney Rubble")
self.assertNotIn(person, self.session)
def test_make_user(self):
@ -197,13 +202,13 @@ else:
# default username
# nb. this behavior requires a session
user = self.handler.make_user(session=self.session)
self.assertEqual(user.username, 'newuser')
self.assertEqual(user.username, "newuser")
def test_delete_user(self):
model = self.app.model
# basics
myuser = model.User(username='myuser')
myuser = model.User(username="myuser")
self.session.add(myuser)
self.session.commit()
user = self.session.query(model.User).one()
@ -217,67 +222,67 @@ else:
# default
name = self.handler.make_preferred_username(self.session)
self.assertEqual(name, 'newuser')
self.assertEqual(name, "newuser")
# person/first+last
person = model.Person(first_name='Barney', last_name='Rubble')
person = model.Person(first_name="Barney", last_name="Rubble")
name = self.handler.make_preferred_username(self.session, person=person)
self.assertEqual(name, 'barney.rubble')
self.assertEqual(name, "barney.rubble")
# person/first
person = model.Person(first_name='Barney')
person = model.Person(first_name="Barney")
name = self.handler.make_preferred_username(self.session, person=person)
self.assertEqual(name, 'barney')
self.assertEqual(name, "barney")
# person/last
person = model.Person(last_name='Rubble')
person = model.Person(last_name="Rubble")
name = self.handler.make_preferred_username(self.session, person=person)
self.assertEqual(name, 'rubble')
self.assertEqual(name, "rubble")
def test_make_unique_username(self):
model = self.app.model
# default
name = self.handler.make_unique_username(self.session)
self.assertEqual(name, 'newuser')
self.assertEqual(name, "newuser")
user = model.User(username=name)
self.session.add(user)
self.session.commit()
# counter invoked if name exists
name = self.handler.make_unique_username(self.session)
self.assertEqual(name, 'newuser01')
self.assertEqual(name, "newuser01")
user = model.User(username=name)
self.session.add(user)
self.session.commit()
# starts by getting preferred name
person = model.Person(first_name='Barney', last_name='Rubble')
person = model.Person(first_name="Barney", last_name="Rubble")
name = self.handler.make_unique_username(self.session, person=person)
self.assertEqual(name, 'barney.rubble')
self.assertEqual(name, "barney.rubble")
user = model.User(username=name)
self.session.add(user)
self.session.commit()
# counter invoked if name exists
name = self.handler.make_unique_username(self.session, person=person)
self.assertEqual(name, 'barney.rubble01')
self.assertEqual(name, "barney.rubble01")
def test_set_user_password(self):
model = self.app.model
myuser = model.User(username='myuser')
myuser = model.User(username="myuser")
self.session.add(myuser)
# basics
self.assertIsNone(myuser.password)
self.handler.set_user_password(myuser, 'goodpass')
self.handler.set_user_password(myuser, "goodpass")
self.session.commit()
self.assertIsNotNone(myuser.password)
# nb. password is hashed
self.assertNotEqual(myuser.password, 'goodpass')
self.assertNotEqual(myuser.password, "goodpass")
# confirm login works with new password
user = self.handler.authenticate_user(self.session, 'myuser', 'goodpass')
user = self.handler.authenticate_user(self.session, "myuser", "goodpass")
self.assertIs(user, myuser)
def test_get_role_administrator(self):
@ -337,15 +342,15 @@ else:
self.assertEqual(len(perms), 0)
# role perms
myrole = model.Role(name='My Role')
myrole = model.Role(name="My Role")
self.session.add(myrole)
self.handler.grant_permission(myrole, 'foo')
self.handler.grant_permission(myrole, "foo")
self.session.commit()
perms = self.handler.get_permissions(self.session, myrole)
self.assertEqual(perms, {'foo'})
self.assertEqual(perms, {"foo"})
# user perms
myuser = model.User(username='myuser')
myuser = model.User(username="myuser")
self.session.add(myuser)
self.session.commit()
perms = self.handler.get_permissions(self.session, myuser)
@ -353,7 +358,7 @@ else:
myuser.roles.append(myrole)
self.session.commit()
perms = self.handler.get_permissions(self.session, myuser)
self.assertEqual(perms, {'foo'})
self.assertEqual(perms, {"foo"})
# invalid principal
perms = self.handler.get_permissions(self.session, RuntimeError)
@ -368,39 +373,41 @@ else:
# false default for role
role = model.Role()
self.assertFalse(self.handler.has_permission(self.session, role, 'foo'))
self.assertFalse(self.handler.has_permission(self.session, role, "foo"))
# empty default for user
user = model.User()
self.assertFalse(self.handler.has_permission(self.session, user, 'foo'))
self.assertFalse(self.handler.has_permission(self.session, user, "foo"))
# role perms
myrole = model.Role(name='My Role')
myrole = model.Role(name="My Role")
self.session.add(myrole)
self.session.commit()
self.assertFalse(self.handler.has_permission(self.session, myrole, 'foo'))
self.handler.grant_permission(myrole, 'foo')
self.assertFalse(self.handler.has_permission(self.session, myrole, "foo"))
self.handler.grant_permission(myrole, "foo")
self.session.commit()
self.assertTrue(self.handler.has_permission(self.session, myrole, 'foo'))
self.assertTrue(self.handler.has_permission(self.session, myrole, "foo"))
# user perms
myuser = model.User(username='myuser')
myuser = model.User(username="myuser")
self.session.add(myuser)
self.session.commit()
self.assertFalse(self.handler.has_permission(self.session, myuser, 'foo'))
self.assertFalse(self.handler.has_permission(self.session, myuser, "foo"))
myuser.roles.append(myrole)
self.session.commit()
self.assertTrue(self.handler.has_permission(self.session, myuser, 'foo'))
self.assertTrue(self.handler.has_permission(self.session, myuser, "foo"))
# invalid principal
self.assertFalse(self.handler.has_permission(self.session, RuntimeError, 'foo'))
self.assertFalse(
self.handler.has_permission(self.session, RuntimeError, "foo")
)
# missing principal
self.assertFalse(self.handler.has_permission(self.session, None, 'foo'))
self.assertFalse(self.handler.has_permission(self.session, None, "foo"))
def test_grant_permission(self):
model = self.app.model
myrole = model.Role(name='My Role')
myrole = model.Role(name="My Role")
self.session.add(myrole)
self.session.commit()
@ -408,38 +415,38 @@ else:
self.assertEqual(self.session.query(model.Permission).count(), 0)
# grant one perm, and confirm
self.handler.grant_permission(myrole, 'foo')
self.handler.grant_permission(myrole, "foo")
self.session.commit()
self.assertEqual(self.session.query(model.Permission).count(), 1)
perm = self.session.query(model.Permission).one()
self.assertIs(perm.role, myrole)
self.assertEqual(perm.permission, 'foo')
self.assertEqual(perm.permission, "foo")
# grant same perm again, confirm just one exists
self.handler.grant_permission(myrole, 'foo')
self.handler.grant_permission(myrole, "foo")
self.session.commit()
self.assertEqual(self.session.query(model.Permission).count(), 1)
perm = self.session.query(model.Permission).one()
self.assertIs(perm.role, myrole)
self.assertEqual(perm.permission, 'foo')
self.assertEqual(perm.permission, "foo")
def test_revoke_permission(self):
model = self.app.model
myrole = model.Role(name='My Role')
myrole = model.Role(name="My Role")
self.session.add(myrole)
self.handler.grant_permission(myrole, 'foo')
self.handler.grant_permission(myrole, "foo")
self.session.commit()
# just the one perm
self.assertEqual(self.session.query(model.Permission).count(), 1)
# revoke it, then confirm
self.handler.revoke_permission(myrole, 'foo')
self.handler.revoke_permission(myrole, "foo")
self.session.commit()
self.assertEqual(self.session.query(model.Permission).count(), 0)
# revoke again, confirm
self.handler.revoke_permission(myrole, 'foo')
self.handler.revoke_permission(myrole, "foo")
self.session.commit()
self.assertEqual(self.session.query(model.Permission).count(), 0)
@ -450,7 +457,7 @@ else:
def test_add_api_token(self):
model = self.app.model
barney = model.User(username='barney')
barney = model.User(username="barney")
self.session.add(barney)
token = self.handler.add_api_token(barney, "test token")
@ -461,7 +468,7 @@ else:
def test_delete_api_token(self):
model = self.app.model
barney = model.User(username='barney')
barney = model.User(username="barney")
self.session.add(barney)
token = self.handler.add_api_token(barney, "test token")
self.session.commit()

View file

@ -14,10 +14,10 @@ except ImportError:
else:
class MockBatch(model.BatchMixin, model.Base):
__tablename__ = 'testing_batch_mock'
__tablename__ = "testing_batch_mock"
class MockBatchRow(model.BatchRowMixin, model.Base):
__tablename__ = 'testing_batch_mock_row'
__tablename__ = "testing_batch_mock_row"
__batch_class__ = MockBatch
class MockBatchHandler(mod.BatchHandler):
@ -30,12 +30,12 @@ else:
def test_model_class(self):
handler = mod.BatchHandler(self.config)
self.assertRaises(NotImplementedError, getattr, handler, 'model_class')
self.assertRaises(NotImplementedError, getattr, handler, "model_class")
def test_batch_type(self):
with patch.object(mod.BatchHandler, 'model_class', new=MockBatch):
with patch.object(mod.BatchHandler, "model_class", new=MockBatch):
handler = mod.BatchHandler(self.config)
self.assertEqual(handler.batch_type, 'testing_batch_mock')
self.assertEqual(handler.batch_type, "testing_batch_mock")
def test_make_batch(self):
handler = self.make_handler()
@ -50,25 +50,30 @@ else:
self.assertEqual(second, first + 1)
third = handler.consume_batch_id(self.session, as_str=True)
self.assertEqual(third, f'{first + 2:08d}')
self.assertEqual(third, f"{first + 2:08d}")
def test_get_data_path(self):
model = self.app.model
user = model.User(username='barney')
user = model.User(username="barney")
self.session.add(user)
with patch.object(mod.BatchHandler, 'model_class', new=MockBatch):
with patch.object(mod.BatchHandler, "model_class", new=MockBatch):
handler = self.make_handler()
# root storage (default)
with patch.object(self.app, 'get_appdir', return_value=self.tempdir):
with patch.object(self.app, "get_appdir", return_value=self.tempdir):
path = handler.get_data_path()
self.assertEqual(path, os.path.join(self.tempdir, 'data', 'batch', 'testing_batch_mock'))
self.assertEqual(
path,
os.path.join(
self.tempdir, "data", "batch", "testing_batch_mock"
),
)
# root storage (configured)
self.config.setdefault('wutta.batch.storage_path', self.tempdir)
self.config.setdefault("wutta.batch.storage_path", self.tempdir)
path = handler.get_data_path()
self.assertEqual(path, os.path.join(self.tempdir, 'testing_batch_mock'))
self.assertEqual(path, os.path.join(self.tempdir, "testing_batch_mock"))
batch = handler.make_batch(self.session, created_by=user)
self.session.add(batch)
@ -78,11 +83,18 @@ else:
path = handler.get_data_path(batch)
uuid = batch.uuid.hex
final = os.path.join(uuid[-2:], uuid[:-2])
self.assertEqual(path, os.path.join(self.tempdir, 'testing_batch_mock', final))
self.assertEqual(
path, os.path.join(self.tempdir, "testing_batch_mock", final)
)
# with filename
path = handler.get_data_path(batch, 'input.csv')
self.assertEqual(path, os.path.join(self.tempdir, 'testing_batch_mock', final, 'input.csv'))
path = handler.get_data_path(batch, "input.csv")
self.assertEqual(
path,
os.path.join(
self.tempdir, "testing_batch_mock", final, "input.csv"
),
)
# makedirs
path = handler.get_data_path(batch)
@ -118,7 +130,7 @@ else:
def test_remove_row(self):
model = self.app.model
handler = self.make_handler()
user = model.User(username='barney')
user = model.User(username="barney")
self.session.add(user)
batch = handler.make_batch(self.session, created_by=user)
self.session.add(batch)
@ -134,7 +146,7 @@ else:
model = self.app.model
handler = self.make_handler()
user = model.User(username='barney')
user = model.User(username="barney")
self.session.add(user)
batch = handler.make_batch(self.session, created_by=user)
self.session.add(batch)
@ -152,7 +164,7 @@ else:
def test_do_execute(self):
model = self.app.model
user = model.User(username='barney')
user = model.User(username="barney")
self.session.add(user)
handler = self.make_handler()
@ -161,7 +173,7 @@ else:
self.session.flush()
# error if execution not allowed
with patch.object(handler, 'why_not_execute', return_value="bad batch"):
with patch.object(handler, "why_not_execute", return_value="bad batch"):
self.assertRaises(RuntimeError, handler.do_execute, batch, user)
# nb. coverage only; tests nothing
@ -178,7 +190,7 @@ else:
model = self.app.model
handler = self.make_handler()
user = model.User(username='barney')
user = model.User(username="barney")
self.session.add(user)
# simple delete
@ -201,13 +213,13 @@ else:
self.assertEqual(self.session.query(MockBatch).count(), 0)
# delete w/ files
self.config.setdefault('wutta.batch.storage_path', self.tempdir)
self.config.setdefault("wutta.batch.storage_path", self.tempdir)
batch = handler.make_batch(self.session, created_by=user)
self.session.add(batch)
self.session.flush()
path = handler.get_data_path(batch, 'data.txt', makedirs=True)
with open(path, 'wt') as f:
f.write('foo=bar')
path = handler.get_data_path(batch, "data.txt", makedirs=True)
with open(path, "wt") as f:
f.write("foo=bar")
self.assertEqual(self.session.query(MockBatch).count(), 1)
path = handler.get_data_path(batch)
self.assertTrue(os.path.exists(path))
@ -216,13 +228,13 @@ else:
self.assertFalse(os.path.exists(path))
# delete w/ files (dry-run)
self.config.setdefault('wutta.batch.storage_path', self.tempdir)
self.config.setdefault("wutta.batch.storage_path", self.tempdir)
batch = handler.make_batch(self.session, created_by=user)
self.session.add(batch)
self.session.flush()
path = handler.get_data_path(batch, 'data.txt', makedirs=True)
with open(path, 'wt') as f:
f.write('foo=bar')
path = handler.get_data_path(batch, "data.txt", makedirs=True)
with open(path, "wt") as f:
f.write("foo=bar")
self.assertEqual(self.session.query(MockBatch).count(), 1)
path = handler.get_data_path(batch)
self.assertTrue(os.path.exists(path))

File diff suppressed because it is too large Load diff

View file

@ -18,7 +18,7 @@ class TestEmailSetting(ConfigTestCase):
setting = mod.EmailSetting(self.config)
self.assertIs(setting.config, self.config)
self.assertIs(setting.app, self.app)
self.assertEqual(setting.key, 'EmailSetting')
self.assertEqual(setting.key, "EmailSetting")
def test_sample_data(self):
setting = mod.EmailSetting(self.config)
@ -34,23 +34,23 @@ class TestMessage(FileTestCase):
msg = self.make_message()
# set as list
recips = msg.get_recips(['sally@example.com'])
self.assertEqual(recips, ['sally@example.com'])
recips = msg.get_recips(["sally@example.com"])
self.assertEqual(recips, ["sally@example.com"])
# set as tuple
recips = msg.get_recips(('barney@example.com',))
self.assertEqual(recips, ['barney@example.com'])
recips = msg.get_recips(("barney@example.com",))
self.assertEqual(recips, ["barney@example.com"])
# set as string
recips = msg.get_recips('wilma@example.com')
self.assertEqual(recips, ['wilma@example.com'])
recips = msg.get_recips("wilma@example.com")
self.assertEqual(recips, ["wilma@example.com"])
# set as null
recips = msg.get_recips(None)
self.assertEqual(recips, [])
# otherwise error
self.assertRaises(ValueError, msg.get_recips, {'foo': 'foo@example.com'})
self.assertRaises(ValueError, msg.get_recips, {"foo": "foo@example.com"})
def test_as_string(self):
@ -59,38 +59,44 @@ class TestMessage(FileTestCase):
self.assertRaises(ValueError, msg.as_string)
# txt body
msg = self.make_message(sender='bob@example.com',
txt_body="hello world")
msg = self.make_message(sender="bob@example.com", txt_body="hello world")
complete = msg.as_string()
self.assertIn('From: bob@example.com', complete)
self.assertIn("From: bob@example.com", complete)
# html body
msg = self.make_message(sender='bob@example.com',
html_body="<p>hello world</p>")
msg = self.make_message(
sender="bob@example.com", html_body="<p>hello world</p>"
)
complete = msg.as_string()
self.assertIn('From: bob@example.com', complete)
self.assertIn("From: bob@example.com", complete)
# txt + html body
msg = self.make_message(sender='bob@example.com',
txt_body="hello world",
html_body="<p>hello world</p>")
msg = self.make_message(
sender="bob@example.com",
txt_body="hello world",
html_body="<p>hello world</p>",
)
complete = msg.as_string()
self.assertIn('From: bob@example.com', complete)
self.assertIn("From: bob@example.com", complete)
# html + attachment
csv_part = MIMEText("foo,bar\n1,2", 'csv', 'utf_8')
msg = self.make_message(sender='bob@example.com',
html_body="<p>hello world</p>",
attachments=[csv_part])
csv_part = MIMEText("foo,bar\n1,2", "csv", "utf_8")
msg = self.make_message(
sender="bob@example.com",
html_body="<p>hello world</p>",
attachments=[csv_part],
)
complete = msg.as_string()
self.assertIn('Content-Type: multipart/mixed; boundary=', complete)
self.assertIn("Content-Type: multipart/mixed; boundary=", complete)
self.assertIn('Content-Type: text/csv; charset="utf_8"', complete)
# error if improper attachment
csv_path = self.write_file('data.csv', "foo,bar\n1,2")
msg = self.make_message(sender='bob@example.com',
html_body="<p>hello world</p>",
attachments=[csv_path])
csv_path = self.write_file("data.csv", "foo,bar\n1,2")
msg = self.make_message(
sender="bob@example.com",
html_body="<p>hello world</p>",
attachments=[csv_path],
)
self.assertRaises(ValueError, msg.as_string)
try:
msg.as_string()
@ -98,27 +104,30 @@ class TestMessage(FileTestCase):
self.assertIn("must specify valid MIME attachments", str(err))
# everything
msg = self.make_message(sender='bob@example.com',
subject='meeting follow-up',
to='sally@example.com',
cc='marketing@example.com',
bcc='bob@example.com',
replyto='sales@example.com',
txt_body="hello world",
html_body="<p>hello world</p>")
msg = self.make_message(
sender="bob@example.com",
subject="meeting follow-up",
to="sally@example.com",
cc="marketing@example.com",
bcc="bob@example.com",
replyto="sales@example.com",
txt_body="hello world",
html_body="<p>hello world</p>",
)
complete = msg.as_string()
self.assertIn('From: bob@example.com', complete)
self.assertIn('Subject: meeting follow-up', complete)
self.assertIn('To: sally@example.com', complete)
self.assertIn('Cc: marketing@example.com', complete)
self.assertIn('Bcc: bob@example.com', complete)
self.assertIn('Reply-To: sales@example.com', complete)
self.assertIn("From: bob@example.com", complete)
self.assertIn("Subject: meeting follow-up", complete)
self.assertIn("To: sally@example.com", complete)
self.assertIn("Cc: marketing@example.com", complete)
self.assertIn("Bcc: bob@example.com", complete)
self.assertIn("Reply-To: sales@example.com", complete)
class mock_foo(mod.EmailSetting):
default_subject = "MOCK FOO!"
def sample_data(self):
return {'foo': 'mock'}
return {"foo": "mock"}
class TestEmailHandler(ConfigTestCase):
@ -129,43 +138,43 @@ class TestEmailHandler(ConfigTestCase):
def test_constructor_lookups(self):
# empty lookup paths by default, if no providers
with patch.object(self.app, 'providers', new={}):
with patch.object(self.app, "providers", new={}):
handler = self.make_handler()
self.assertEqual(handler.txt_templates.directories, [])
self.assertEqual(handler.html_templates.directories, [])
# provider may specify paths as list
providers = {
'wuttatest': MagicMock(email_templates=['wuttjamaican:email-templates']),
"wuttatest": MagicMock(email_templates=["wuttjamaican:email-templates"]),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
path = resource_path('wuttjamaican:email-templates')
path = resource_path("wuttjamaican:email-templates")
self.assertEqual(handler.txt_templates.directories, [path])
self.assertEqual(handler.html_templates.directories, [path])
# provider may specify paths as string
providers = {
'wuttatest': MagicMock(email_templates='wuttjamaican:email-templates'),
"wuttatest": MagicMock(email_templates="wuttjamaican:email-templates"),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
path = resource_path('wuttjamaican:email-templates')
path = resource_path("wuttjamaican:email-templates")
self.assertEqual(handler.txt_templates.directories, [path])
self.assertEqual(handler.html_templates.directories, [path])
def test_get_email_modules(self):
# no providers, no email modules
with patch.object(self.app, 'providers', new={}):
with patch.object(self.app, "providers", new={}):
handler = self.make_handler()
self.assertEqual(handler.get_email_modules(), [])
# provider may specify modules as list
providers = {
'wuttatest': MagicMock(email_modules=['wuttjamaican.email']),
"wuttatest": MagicMock(email_modules=["wuttjamaican.email"]),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
modules = handler.get_email_modules()
self.assertEqual(len(modules), 1)
@ -173,9 +182,9 @@ class TestEmailHandler(ConfigTestCase):
# provider may specify modules as string
providers = {
'wuttatest': MagicMock(email_modules='wuttjamaican.email'),
"wuttatest": MagicMock(email_modules="wuttjamaican.email"),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
modules = handler.get_email_modules()
self.assertEqual(len(modules), 1)
@ -184,36 +193,36 @@ class TestEmailHandler(ConfigTestCase):
def test_get_email_settings(self):
# no providers, no email settings
with patch.object(self.app, 'providers', new={}):
with patch.object(self.app, "providers", new={}):
handler = self.make_handler()
self.assertEqual(handler.get_email_settings(), {})
# provider may define email settings (via modules)
providers = {
'wuttatest': MagicMock(email_modules=['tests.test_email']),
"wuttatest": MagicMock(email_modules=["tests.test_email"]),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
settings = handler.get_email_settings()
self.assertEqual(len(settings), 1)
self.assertIn('mock_foo', settings)
self.assertIn("mock_foo", settings)
def test_get_email_setting(self):
providers = {
'wuttatest': MagicMock(email_modules=['tests.test_email']),
"wuttatest": MagicMock(email_modules=["tests.test_email"]),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
# as instance
setting = handler.get_email_setting('mock_foo')
setting = handler.get_email_setting("mock_foo")
self.assertIsInstance(setting, mod.EmailSetting)
self.assertIsInstance(setting, mock_foo)
# as class
setting = handler.get_email_setting('mock_foo', instance=False)
setting = handler.get_email_setting("mock_foo", instance=False)
self.assertTrue(issubclass(setting, mod.EmailSetting))
self.assertIs(setting, mock_foo)
@ -229,10 +238,10 @@ class TestEmailHandler(ConfigTestCase):
# self.assertRaises(ConfigurationError, handler.make_auto_message, 'foo')
# message is empty by default
msg = handler.make_auto_message('foo')
msg = handler.make_auto_message("foo")
self.assertIsInstance(msg, mod.Message)
self.assertEqual(msg.key, 'foo')
self.assertEqual(msg.sender, 'root@localhost')
self.assertEqual(msg.key, "foo")
self.assertEqual(msg.sender, "root@localhost")
self.assertEqual(msg.subject, "Automated message")
self.assertEqual(msg.to, [])
self.assertEqual(msg.cc, [])
@ -242,14 +251,14 @@ class TestEmailHandler(ConfigTestCase):
self.assertIsNone(msg.html_body)
# override defaults
self.config.setdefault('wutta.email.default.sender', 'bob@example.com')
self.config.setdefault('wutta.email.default.subject', 'Attention required')
self.config.setdefault("wutta.email.default.sender", "bob@example.com")
self.config.setdefault("wutta.email.default.subject", "Attention required")
# message is empty by default
msg = handler.make_auto_message('foo')
msg = handler.make_auto_message("foo")
self.assertIsInstance(msg, mod.Message)
self.assertEqual(msg.key, 'foo')
self.assertEqual(msg.sender, 'bob@example.com')
self.assertEqual(msg.key, "foo")
self.assertEqual(msg.sender, "bob@example.com")
self.assertEqual(msg.subject, "Attention required")
self.assertEqual(msg.to, [])
self.assertEqual(msg.cc, [])
@ -260,15 +269,15 @@ class TestEmailHandler(ConfigTestCase):
# but if there is a proper email profile configured for key,
# then we should get back a more complete message
self.config.setdefault('wutta.email.test_foo.subject', "hello foo")
self.config.setdefault('wutta.email.test_foo.to', 'sally@example.com')
self.config.setdefault('wutta.email.templates', 'tests:email-templates')
self.config.setdefault("wutta.email.test_foo.subject", "hello foo")
self.config.setdefault("wutta.email.test_foo.to", "sally@example.com")
self.config.setdefault("wutta.email.templates", "tests:email-templates")
handler = self.make_handler()
msg = handler.make_auto_message('test_foo')
self.assertEqual(msg.key, 'test_foo')
self.assertEqual(msg.sender, 'bob@example.com')
msg = handler.make_auto_message("test_foo")
self.assertEqual(msg.key, "test_foo")
self.assertEqual(msg.sender, "bob@example.com")
self.assertEqual(msg.subject, "hello foo")
self.assertEqual(msg.to, ['sally@example.com'])
self.assertEqual(msg.to, ["sally@example.com"])
self.assertEqual(msg.cc, [])
self.assertEqual(msg.bcc, [])
self.assertIsNone(msg.replyto)
@ -279,160 +288,162 @@ class TestEmailHandler(ConfigTestCase):
# kwarg at all; others get skipped if kwarg is empty
# sender
with patch.object(handler, 'get_auto_sender') as get_auto_sender:
msg = handler.make_auto_message('foo', sender=None)
with patch.object(handler, "get_auto_sender") as get_auto_sender:
msg = handler.make_auto_message("foo", sender=None)
get_auto_sender.assert_not_called()
msg = handler.make_auto_message('foo')
get_auto_sender.assert_called_once_with('foo')
msg = handler.make_auto_message("foo")
get_auto_sender.assert_called_once_with("foo")
# subject
with patch.object(handler, 'get_auto_subject') as get_auto_subject:
msg = handler.make_auto_message('foo', subject=None)
with patch.object(handler, "get_auto_subject") as get_auto_subject:
msg = handler.make_auto_message("foo", subject=None)
get_auto_subject.assert_not_called()
msg = handler.make_auto_message('foo')
get_auto_subject.assert_called_once_with('foo', {}, default=None)
msg = handler.make_auto_message("foo")
get_auto_subject.assert_called_once_with("foo", {}, default=None)
# to
with patch.object(handler, 'get_auto_to') as get_auto_to:
msg = handler.make_auto_message('foo', to=None)
with patch.object(handler, "get_auto_to") as get_auto_to:
msg = handler.make_auto_message("foo", to=None)
get_auto_to.assert_not_called()
get_auto_to.return_value = None
msg = handler.make_auto_message('foo')
get_auto_to.assert_called_once_with('foo')
msg = handler.make_auto_message("foo")
get_auto_to.assert_called_once_with("foo")
# cc
with patch.object(handler, 'get_auto_cc') as get_auto_cc:
msg = handler.make_auto_message('foo', cc=None)
with patch.object(handler, "get_auto_cc") as get_auto_cc:
msg = handler.make_auto_message("foo", cc=None)
get_auto_cc.assert_not_called()
get_auto_cc.return_value = None
msg = handler.make_auto_message('foo')
get_auto_cc.assert_called_once_with('foo')
msg = handler.make_auto_message("foo")
get_auto_cc.assert_called_once_with("foo")
# bcc
with patch.object(handler, 'get_auto_bcc') as get_auto_bcc:
msg = handler.make_auto_message('foo', bcc=None)
with patch.object(handler, "get_auto_bcc") as get_auto_bcc:
msg = handler.make_auto_message("foo", bcc=None)
get_auto_bcc.assert_not_called()
get_auto_bcc.return_value = None
msg = handler.make_auto_message('foo')
get_auto_bcc.assert_called_once_with('foo')
msg = handler.make_auto_message("foo")
get_auto_bcc.assert_called_once_with("foo")
# txt_body
with patch.object(handler, 'get_auto_txt_body') as get_auto_txt_body:
msg = handler.make_auto_message('foo', txt_body=None)
with patch.object(handler, "get_auto_txt_body") as get_auto_txt_body:
msg = handler.make_auto_message("foo", txt_body=None)
get_auto_txt_body.assert_not_called()
msg = handler.make_auto_message('foo')
get_auto_txt_body.assert_called_once_with('foo', {})
msg = handler.make_auto_message("foo")
get_auto_txt_body.assert_called_once_with("foo", {})
# html_body
with patch.object(handler, 'get_auto_html_body') as get_auto_html_body:
msg = handler.make_auto_message('foo', html_body=None)
with patch.object(handler, "get_auto_html_body") as get_auto_html_body:
msg = handler.make_auto_message("foo", html_body=None)
get_auto_html_body.assert_not_called()
msg = handler.make_auto_message('foo')
get_auto_html_body.assert_called_once_with('foo', {})
msg = handler.make_auto_message("foo")
get_auto_html_body.assert_called_once_with("foo", {})
def test_get_auto_sender(self):
handler = self.make_handler()
# basic global default
self.assertEqual(handler.get_auto_sender('foo'), 'root@localhost')
self.assertEqual(handler.get_auto_sender("foo"), "root@localhost")
# can set global default
self.config.setdefault('wutta.email.default.sender', 'bob@example.com')
self.assertEqual(handler.get_auto_sender('foo'), 'bob@example.com')
self.config.setdefault("wutta.email.default.sender", "bob@example.com")
self.assertEqual(handler.get_auto_sender("foo"), "bob@example.com")
# can set for key
self.config.setdefault('wutta.email.foo.sender', 'sally@example.com')
self.assertEqual(handler.get_auto_sender('foo'), 'sally@example.com')
self.config.setdefault("wutta.email.foo.sender", "sally@example.com")
self.assertEqual(handler.get_auto_sender("foo"), "sally@example.com")
def test_get_auto_replyto(self):
handler = self.make_handler()
# null by default
self.assertIsNone(handler.get_auto_replyto('foo'))
self.assertIsNone(handler.get_auto_replyto("foo"))
# can set global default
self.config.setdefault('wutta.email.default.replyto', 'george@example.com')
self.assertEqual(handler.get_auto_replyto('foo'), 'george@example.com')
self.config.setdefault("wutta.email.default.replyto", "george@example.com")
self.assertEqual(handler.get_auto_replyto("foo"), "george@example.com")
# can set for key
self.config.setdefault('wutta.email.foo.replyto', 'kathy@example.com')
self.assertEqual(handler.get_auto_replyto('foo'), 'kathy@example.com')
self.config.setdefault("wutta.email.foo.replyto", "kathy@example.com")
self.assertEqual(handler.get_auto_replyto("foo"), "kathy@example.com")
def test_get_auto_subject_template(self):
handler = self.make_handler()
# global default
template = handler.get_auto_subject_template('foo')
template = handler.get_auto_subject_template("foo")
self.assertEqual(template, "Automated message")
# can configure alternate global default
self.config.setdefault('wutta.email.default.subject', "Wutta Message")
template = handler.get_auto_subject_template('foo')
self.config.setdefault("wutta.email.default.subject", "Wutta Message")
template = handler.get_auto_subject_template("foo")
self.assertEqual(template, "Wutta Message")
# can configure just for key
self.config.setdefault('wutta.email.foo.subject', "Foo Message")
template = handler.get_auto_subject_template('foo')
self.config.setdefault("wutta.email.foo.subject", "Foo Message")
template = handler.get_auto_subject_template("foo")
self.assertEqual(template, "Foo Message")
# EmailSetting can provide default subject
providers = {
'wuttatest': MagicMock(email_modules=['tests.test_email']),
"wuttatest": MagicMock(email_modules=["tests.test_email"]),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
template = handler.get_auto_subject_template('mock_foo')
template = handler.get_auto_subject_template("mock_foo")
self.assertEqual(template, "MOCK FOO!")
# caller can provide default subject
template = handler.get_auto_subject_template('mock_foo', default="whatever is clever")
template = handler.get_auto_subject_template(
"mock_foo", default="whatever is clever"
)
self.assertEqual(template, "whatever is clever")
def test_get_auto_subject(self):
handler = self.make_handler()
# global default
subject = handler.get_auto_subject('foo')
subject = handler.get_auto_subject("foo")
self.assertEqual(subject, "Automated message")
# can configure alternate global default
self.config.setdefault('wutta.email.default.subject', "Wutta Message")
subject = handler.get_auto_subject('foo')
self.config.setdefault("wutta.email.default.subject", "Wutta Message")
subject = handler.get_auto_subject("foo")
self.assertEqual(subject, "Wutta Message")
# caller can provide default subject
subject = handler.get_auto_subject('foo', default="whatever is clever")
subject = handler.get_auto_subject("foo", default="whatever is clever")
self.assertEqual(subject, "whatever is clever")
# can configure just for key
self.config.setdefault('wutta.email.foo.subject', "Foo Message")
subject = handler.get_auto_subject('foo')
self.config.setdefault("wutta.email.foo.subject", "Foo Message")
subject = handler.get_auto_subject("foo")
self.assertEqual(subject, "Foo Message")
# proper template is rendered
self.config.setdefault('wutta.email.bar.subject', "${foo} Message")
subject = handler.get_auto_subject('bar', {'foo': "FOO"})
self.config.setdefault("wutta.email.bar.subject", "${foo} Message")
subject = handler.get_auto_subject("bar", {"foo": "FOO"})
self.assertEqual(subject, "FOO Message")
# unless we ask it not to
subject = handler.get_auto_subject('bar', {'foo': "FOO"}, rendered=False)
subject = handler.get_auto_subject("bar", {"foo": "FOO"}, rendered=False)
self.assertEqual(subject, "${foo} Message")
def test_get_auto_recips(self):
handler = self.make_handler()
# error if bad type requested
self.assertRaises(ValueError, handler.get_auto_recips, 'foo', 'doesnotexist')
self.assertRaises(ValueError, handler.get_auto_recips, "foo", "doesnotexist")
# can configure global default
self.config.setdefault('wutta.email.default.to', 'admin@example.com')
recips = handler.get_auto_recips('foo', 'to')
self.assertEqual(recips, ['admin@example.com'])
self.config.setdefault("wutta.email.default.to", "admin@example.com")
recips = handler.get_auto_recips("foo", "to")
self.assertEqual(recips, ["admin@example.com"])
# can configure just for key
self.config.setdefault('wutta.email.foo.to', 'bob@example.com')
recips = handler.get_auto_recips('foo', 'to')
self.assertEqual(recips, ['bob@example.com'])
self.config.setdefault("wutta.email.foo.to", "bob@example.com")
recips = handler.get_auto_recips("foo", "to")
self.assertEqual(recips, ["bob@example.com"])
def test_get_auto_body_template(self):
from mako.template import Template
@ -440,88 +451,88 @@ class TestEmailHandler(ConfigTestCase):
handler = self.make_handler()
# error if bad request
self.assertRaises(ValueError, handler.get_auto_body_template, 'foo', 'BADTYPE')
self.assertRaises(ValueError, handler.get_auto_body_template, "foo", "BADTYPE")
# empty by default
template = handler.get_auto_body_template('foo', 'txt')
template = handler.get_auto_body_template("foo", "txt")
self.assertIsNone(template)
# but returns a template if it exists
providers = {
'wuttatest': MagicMock(email_templates=['tests:email-templates']),
"wuttatest": MagicMock(email_templates=["tests:email-templates"]),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
template = handler.get_auto_body_template('test_foo', 'txt')
template = handler.get_auto_body_template("test_foo", "txt")
self.assertIsInstance(template, Template)
self.assertEqual(template.uri, 'test_foo.txt.mako')
self.assertEqual(template.uri, "test_foo.txt.mako")
def test_get_auto_txt_body(self):
handler = self.make_handler()
# empty by default
body = handler.get_auto_txt_body('some-random-email')
body = handler.get_auto_txt_body("some-random-email")
self.assertIsNone(body)
# but returns body if template exists
providers = {
'wuttatest': MagicMock(email_templates=['tests:email-templates']),
"wuttatest": MagicMock(email_templates=["tests:email-templates"]),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
body = handler.get_auto_txt_body('test_foo')
self.assertEqual(body, 'hello from foo txt template\n')
body = handler.get_auto_txt_body("test_foo")
self.assertEqual(body, "hello from foo txt template\n")
def test_get_auto_html_body(self):
handler = self.make_handler()
# empty by default
body = handler.get_auto_html_body('some-random-email')
body = handler.get_auto_html_body("some-random-email")
self.assertIsNone(body)
# but returns body if template exists
providers = {
'wuttatest': MagicMock(email_templates=['tests:email-templates']),
"wuttatest": MagicMock(email_templates=["tests:email-templates"]),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
body = handler.get_auto_html_body('test_foo')
self.assertEqual(body, '<p>hello from foo html template</p>\n')
body = handler.get_auto_html_body("test_foo")
self.assertEqual(body, "<p>hello from foo html template</p>\n")
def test_get_notes(self):
handler = self.make_handler()
# null by default
self.assertIsNone(handler.get_notes('foo'))
self.assertIsNone(handler.get_notes("foo"))
# configured notes
self.config.setdefault('wutta.email.foo.notes', 'hello world')
self.assertEqual(handler.get_notes('foo'), 'hello world')
self.config.setdefault("wutta.email.foo.notes", "hello world")
self.assertEqual(handler.get_notes("foo"), "hello world")
def test_is_enabled(self):
handler = self.make_handler()
# enabled by default
self.assertTrue(handler.is_enabled('default'))
self.assertTrue(handler.is_enabled('foo'))
self.assertTrue(handler.is_enabled("default"))
self.assertTrue(handler.is_enabled("foo"))
# specific type disabled
self.config.setdefault('wutta.email.foo.enabled', 'false')
self.assertFalse(handler.is_enabled('foo'))
self.config.setdefault("wutta.email.foo.enabled", "false")
self.assertFalse(handler.is_enabled("foo"))
# default is disabled
self.assertTrue(handler.is_enabled('bar'))
self.config.setdefault('wutta.email.default.enabled', 'false')
self.assertFalse(handler.is_enabled('bar'))
self.assertTrue(handler.is_enabled("bar"))
self.config.setdefault("wutta.email.default.enabled", "false")
self.assertFalse(handler.is_enabled("bar"))
def test_deliver_message(self):
handler = self.make_handler()
msg = handler.make_message(sender='bob@example.com', to='sally@example.com')
with patch.object(msg, 'as_string', return_value='msg-str'):
msg = handler.make_message(sender="bob@example.com", to="sally@example.com")
with patch.object(msg, "as_string", return_value="msg-str"):
# no smtp session since sending email is disabled by default
with patch.object(mod, 'smtplib') as smtplib:
with patch.object(mod, "smtplib") as smtplib:
session = MagicMock()
smtplib.SMTP.return_value = session
handler.deliver_message(msg)
@ -530,85 +541,99 @@ class TestEmailHandler(ConfigTestCase):
session.sendmail.assert_not_called()
# now let's enable sending
self.config.setdefault('wutta.mail.send_emails', 'true')
self.config.setdefault("wutta.mail.send_emails", "true")
# smtp login not attempted by default
with patch.object(mod, 'smtplib') as smtplib:
with patch.object(mod, "smtplib") as smtplib:
session = MagicMock()
smtplib.SMTP.return_value = session
handler.deliver_message(msg)
smtplib.SMTP.assert_called_once_with('localhost')
smtplib.SMTP.assert_called_once_with("localhost")
session.login.assert_not_called()
session.sendmail.assert_called_once_with('bob@example.com', {'sally@example.com'}, 'msg-str')
session.sendmail.assert_called_once_with(
"bob@example.com", {"sally@example.com"}, "msg-str"
)
# but login attempted if config has credentials
self.config.setdefault('wutta.mail.smtp.username', 'bob')
self.config.setdefault('wutta.mail.smtp.password', 'seekrit')
with patch.object(mod, 'smtplib') as smtplib:
self.config.setdefault("wutta.mail.smtp.username", "bob")
self.config.setdefault("wutta.mail.smtp.password", "seekrit")
with patch.object(mod, "smtplib") as smtplib:
session = MagicMock()
smtplib.SMTP.return_value = session
handler.deliver_message(msg)
smtplib.SMTP.assert_called_once_with('localhost')
session.login.assert_called_once_with('bob', 'seekrit')
session.sendmail.assert_called_once_with('bob@example.com', {'sally@example.com'}, 'msg-str')
smtplib.SMTP.assert_called_once_with("localhost")
session.login.assert_called_once_with("bob", "seekrit")
session.sendmail.assert_called_once_with(
"bob@example.com", {"sally@example.com"}, "msg-str"
)
# error if no sender
msg = handler.make_message(to='sally@example.com')
msg = handler.make_message(to="sally@example.com")
self.assertRaises(ValueError, handler.deliver_message, msg)
# error if no recips
msg = handler.make_message(sender='bob@example.com')
msg = handler.make_message(sender="bob@example.com")
self.assertRaises(ValueError, handler.deliver_message, msg)
# can set recips as list
msg = handler.make_message(sender='bob@example.com')
with patch.object(msg, 'as_string', return_value='msg-str'):
with patch.object(mod, 'smtplib') as smtplib:
msg = handler.make_message(sender="bob@example.com")
with patch.object(msg, "as_string", return_value="msg-str"):
with patch.object(mod, "smtplib") as smtplib:
session = MagicMock()
smtplib.SMTP.return_value = session
handler.deliver_message(msg, recips=['sally@example.com'])
smtplib.SMTP.assert_called_once_with('localhost')
session.sendmail.assert_called_once_with('bob@example.com', {'sally@example.com'}, 'msg-str')
handler.deliver_message(msg, recips=["sally@example.com"])
smtplib.SMTP.assert_called_once_with("localhost")
session.sendmail.assert_called_once_with(
"bob@example.com", {"sally@example.com"}, "msg-str"
)
# can set recips as string
msg = handler.make_message(sender='bob@example.com')
with patch.object(msg, 'as_string', return_value='msg-str'):
with patch.object(mod, 'smtplib') as smtplib:
msg = handler.make_message(sender="bob@example.com")
with patch.object(msg, "as_string", return_value="msg-str"):
with patch.object(mod, "smtplib") as smtplib:
session = MagicMock()
smtplib.SMTP.return_value = session
handler.deliver_message(msg, recips='sally@example.com')
smtplib.SMTP.assert_called_once_with('localhost')
session.sendmail.assert_called_once_with('bob@example.com', {'sally@example.com'}, 'msg-str')
handler.deliver_message(msg, recips="sally@example.com")
smtplib.SMTP.assert_called_once_with("localhost")
session.sendmail.assert_called_once_with(
"bob@example.com", {"sally@example.com"}, "msg-str"
)
# can set recips via to
msg = handler.make_message(sender='bob@example.com', to='sally@example.com')
with patch.object(msg, 'as_string', return_value='msg-str'):
with patch.object(mod, 'smtplib') as smtplib:
msg = handler.make_message(sender="bob@example.com", to="sally@example.com")
with patch.object(msg, "as_string", return_value="msg-str"):
with patch.object(mod, "smtplib") as smtplib:
session = MagicMock()
smtplib.SMTP.return_value = session
handler.deliver_message(msg)
smtplib.SMTP.assert_called_once_with('localhost')
session.sendmail.assert_called_once_with('bob@example.com', {'sally@example.com'}, 'msg-str')
smtplib.SMTP.assert_called_once_with("localhost")
session.sendmail.assert_called_once_with(
"bob@example.com", {"sally@example.com"}, "msg-str"
)
# can set recips via cc
msg = handler.make_message(sender='bob@example.com', cc='sally@example.com')
with patch.object(msg, 'as_string', return_value='msg-str'):
with patch.object(mod, 'smtplib') as smtplib:
msg = handler.make_message(sender="bob@example.com", cc="sally@example.com")
with patch.object(msg, "as_string", return_value="msg-str"):
with patch.object(mod, "smtplib") as smtplib:
session = MagicMock()
smtplib.SMTP.return_value = session
handler.deliver_message(msg)
smtplib.SMTP.assert_called_once_with('localhost')
session.sendmail.assert_called_once_with('bob@example.com', {'sally@example.com'}, 'msg-str')
smtplib.SMTP.assert_called_once_with("localhost")
session.sendmail.assert_called_once_with(
"bob@example.com", {"sally@example.com"}, "msg-str"
)
# can set recips via bcc
msg = handler.make_message(sender='bob@example.com', bcc='sally@example.com')
with patch.object(msg, 'as_string', return_value='msg-str'):
with patch.object(mod, 'smtplib') as smtplib:
msg = handler.make_message(sender="bob@example.com", bcc="sally@example.com")
with patch.object(msg, "as_string", return_value="msg-str"):
with patch.object(mod, "smtplib") as smtplib:
session = MagicMock()
smtplib.SMTP.return_value = session
handler.deliver_message(msg)
smtplib.SMTP.assert_called_once_with('localhost')
session.sendmail.assert_called_once_with('bob@example.com', {'sally@example.com'}, 'msg-str')
smtplib.SMTP.assert_called_once_with("localhost")
session.sendmail.assert_called_once_with(
"bob@example.com", {"sally@example.com"}, "msg-str"
)
def test_sending_is_enabled(self):
handler = self.make_handler()
@ -617,12 +642,12 @@ class TestEmailHandler(ConfigTestCase):
self.assertFalse(handler.sending_is_enabled())
# but can be turned on
self.config.setdefault('wutta.mail.send_emails', 'true')
self.config.setdefault("wutta.mail.send_emails", "true")
self.assertTrue(handler.sending_is_enabled())
def test_send_email(self):
handler = self.make_handler()
with patch.object(handler, 'deliver_message') as deliver_message:
with patch.object(handler, "deliver_message") as deliver_message:
# specify message w/ no body
msg = handler.make_message()
@ -631,7 +656,7 @@ class TestEmailHandler(ConfigTestCase):
# again, but also specify key
msg = handler.make_message()
self.assertRaises(ValueError, handler.send_email, 'foo', message=msg)
self.assertRaises(ValueError, handler.send_email, "foo", message=msg)
self.assertFalse(deliver_message.called)
# specify complete message
@ -643,7 +668,7 @@ class TestEmailHandler(ConfigTestCase):
# again, but also specify key
deliver_message.reset_mock()
msg = handler.make_message(txt_body="hello world")
handler.send_email('foo', message=msg)
handler.send_email("foo", message=msg)
deliver_message.assert_called_once_with(msg, recips=None)
# no key, no message
@ -652,25 +677,27 @@ class TestEmailHandler(ConfigTestCase):
# auto-create message w/ no template
deliver_message.reset_mock()
self.assertRaises(RuntimeError, handler.send_email, 'foo', sender='foo@example.com')
self.assertRaises(
RuntimeError, handler.send_email, "foo", sender="foo@example.com"
)
self.assertFalse(deliver_message.called)
# auto create w/ body
deliver_message.reset_mock()
handler.send_email('foo', sender='foo@example.com', txt_body="hello world")
handler.send_email("foo", sender="foo@example.com", txt_body="hello world")
self.assertTrue(deliver_message.called)
# type is disabled
deliver_message.reset_mock()
self.config.setdefault('wutta.email.foo.enabled', False)
handler.send_email('foo', sender='foo@example.com', txt_body="hello world")
self.config.setdefault("wutta.email.foo.enabled", False)
handler.send_email("foo", sender="foo@example.com", txt_body="hello world")
self.assertFalse(deliver_message.called)
# default is disabled
deliver_message.reset_mock()
handler.send_email('bar', sender='bar@example.com', txt_body="hello world")
handler.send_email("bar", sender="bar@example.com", txt_body="hello world")
self.assertTrue(deliver_message.called)
deliver_message.reset_mock()
self.config.setdefault('wutta.email.default.enabled', False)
handler.send_email('bar', sender='bar@example.com', txt_body="hello world")
self.config.setdefault("wutta.email.default.enabled", False)
handler.send_email("bar", sender="bar@example.com", txt_body="hello world")
self.assertFalse(deliver_message.called)

View file

@ -18,16 +18,16 @@ class TestInstallHandler(ConfigTestCase):
def test_constructor(self):
handler = self.make_handler()
self.assertEqual(handler.pkg_name, 'poser')
self.assertEqual(handler.app_title, 'poser')
self.assertEqual(handler.pypi_name, 'poser')
self.assertEqual(handler.egg_name, 'poser')
self.assertEqual(handler.pkg_name, "poser")
self.assertEqual(handler.app_title, "poser")
self.assertEqual(handler.pypi_name, "poser")
self.assertEqual(handler.egg_name, "poser")
def test_run(self):
handler = self.make_handler()
with patch.object(handler, 'show_welcome') as show_welcome:
with patch.object(handler, 'sanity_check') as sanity_check:
with patch.object(handler, 'do_install_steps') as do_install_steps:
with patch.object(handler, "show_welcome") as show_welcome:
with patch.object(handler, "sanity_check") as sanity_check:
with patch.object(handler, "do_install_steps") as do_install_steps:
handler.run()
show_welcome.assert_called_once_with()
sanity_check.assert_called_once_with()
@ -35,9 +35,9 @@ class TestInstallHandler(ConfigTestCase):
def test_show_welcome(self):
handler = self.make_handler()
with patch.object(mod, 'sys') as sys:
with patch.object(handler, 'rprint') as rprint:
with patch.object(handler, 'prompt_bool') as prompt_bool:
with patch.object(mod, "sys") as sys:
with patch.object(handler, "rprint") as rprint:
with patch.object(handler, "prompt_bool") as prompt_bool:
# user continues
prompt_bool.return_value = True
@ -51,9 +51,9 @@ class TestInstallHandler(ConfigTestCase):
def test_sanity_check(self):
handler = self.make_handler()
with patch.object(mod, 'sys') as sys:
with patch.object(mod, 'os') as os:
with patch.object(handler, 'rprint') as rprint:
with patch.object(mod, "sys") as sys:
with patch.object(mod, "os") as os:
with patch.object(handler, "rprint") as rprint:
# pretend appdir does not exist
os.path.exists.return_value = False
@ -67,24 +67,26 @@ class TestInstallHandler(ConfigTestCase):
def test_do_install_steps(self):
handler = self.make_handler()
handler.templates = TemplateLookup(directories=[
self.app.resource_path('wuttjamaican:templates/install'),
])
handler.templates = TemplateLookup(
directories=[
self.app.resource_path("wuttjamaican:templates/install"),
]
)
dbinfo = {
'dburl': f'sqlite:///{self.tempdir}/poser.sqlite',
"dburl": f"sqlite:///{self.tempdir}/poser.sqlite",
}
with patch.object(handler, 'get_dbinfo', return_value=dbinfo):
with patch.object(handler, 'make_appdir') as make_appdir:
with patch.object(handler, 'install_db_schema') as install_db_schema:
with patch.object(handler, "get_dbinfo", return_value=dbinfo):
with patch.object(handler, "make_appdir") as make_appdir:
with patch.object(handler, "install_db_schema") as install_db_schema:
# nb. just for sanity/coverage
install_db_schema.return_value = True
self.assertFalse(hasattr(handler, 'schema_installed'))
self.assertFalse(hasattr(handler, "schema_installed"))
handler.do_install_steps()
self.assertTrue(make_appdir.called)
self.assertTrue(handler.schema_installed)
install_db_schema.assert_called_once_with(dbinfo['dburl'])
install_db_schema.assert_called_once_with(dbinfo["dburl"])
def test_get_dbinfo(self):
try:
@ -97,16 +99,16 @@ class TestInstallHandler(ConfigTestCase):
handler = self.make_handler()
def prompt_generic(info, default=None, is_password=False):
if info in ('db name', 'db user'):
return 'poser'
if info in ("db name", "db user"):
return "poser"
if is_password:
return 'seekrit'
return "seekrit"
return default
with patch.object(mod, 'sys') as sys:
with patch.object(handler, 'prompt_generic', side_effect=prompt_generic):
with patch.object(handler, 'test_db_connection') as test_db_connection:
with patch.object(handler, 'rprint') as rprint:
with patch.object(mod, "sys") as sys:
with patch.object(handler, "prompt_generic", side_effect=prompt_generic):
with patch.object(handler, "test_db_connection") as test_db_connection:
with patch.object(handler, "rprint") as rprint:
# bad dbinfo
test_db_connection.return_value = "bad dbinfo"
@ -114,7 +116,7 @@ class TestInstallHandler(ConfigTestCase):
self.assertRaises(RuntimeError, handler.get_dbinfo)
sys.exit.assert_called_once_with(1)
seekrit = '***' if SA2 else 'seekrit'
seekrit = "***" if SA2 else "seekrit"
# good dbinfo
sys.exit.reset_mock()
@ -122,8 +124,10 @@ class TestInstallHandler(ConfigTestCase):
dbinfo = handler.get_dbinfo()
self.assertFalse(sys.exit.called)
rprint.assert_called_with("[bold green]good[/bold green]")
self.assertEqual(str(dbinfo['dburl']),
f'postgresql+psycopg2://poser:{seekrit}@localhost:5432/poser')
self.assertEqual(
str(dbinfo["dburl"]),
f"postgresql+psycopg2://poser:{seekrit}@localhost:5432/poser",
)
def test_make_db_url(self):
try:
@ -134,13 +138,21 @@ class TestInstallHandler(ConfigTestCase):
from wuttjamaican.db.util import SA2
handler = self.make_handler()
seekrit = '***' if SA2 else 'seekrit'
seekrit = "***" if SA2 else "seekrit"
url = handler.make_db_url('postgresql', 'localhost', '5432', 'poser', 'poser', 'seekrit')
self.assertEqual(str(url), f'postgresql+psycopg2://poser:{seekrit}@localhost:5432/poser')
url = handler.make_db_url(
"postgresql", "localhost", "5432", "poser", "poser", "seekrit"
)
self.assertEqual(
str(url), f"postgresql+psycopg2://poser:{seekrit}@localhost:5432/poser"
)
url = handler.make_db_url('mysql', 'localhost', '3306', 'poser', 'poser', 'seekrit')
self.assertEqual(str(url), f'mysql+mysqlconnector://poser:{seekrit}@localhost:3306/poser')
url = handler.make_db_url(
"mysql", "localhost", "3306", "poser", "poser", "seekrit"
)
self.assertEqual(
str(url), f"mysql+mysqlconnector://poser:{seekrit}@localhost:3306/poser"
)
def test_test_db_connection(self):
try:
@ -151,11 +163,11 @@ class TestInstallHandler(ConfigTestCase):
handler = self.make_handler()
# db does not exist
result = handler.test_db_connection('sqlite:///bad/url/should/not/exist')
self.assertIn('unable to open database file', result)
result = handler.test_db_connection("sqlite:///bad/url/should/not/exist")
self.assertIn("unable to open database file", result)
# db is setup
url = f'sqlite:///{self.tempdir}/db.sqlite'
url = f"sqlite:///{self.tempdir}/db.sqlite"
engine = sa.create_engine(url)
with engine.begin() as cxn:
cxn.execute(sa.text("create table whatever (id int primary key);"))
@ -163,27 +175,29 @@ class TestInstallHandler(ConfigTestCase):
def test_make_template_context(self):
handler = self.make_handler()
dbinfo = {'dburl': 'sqlite:///poser.sqlite'}
dbinfo = {"dburl": "sqlite:///poser.sqlite"}
context = handler.make_template_context(dbinfo)
self.assertEqual(context['envdir'], sys.prefix)
self.assertEqual(context['pkg_name'], 'poser')
self.assertEqual(context['app_title'], 'poser')
self.assertEqual(context['pypi_name'], 'poser')
self.assertEqual(context['egg_name'], 'poser')
self.assertEqual(context['appdir'], os.path.join(sys.prefix, 'app'))
self.assertEqual(context['db_url'], 'sqlite:///poser.sqlite')
self.assertEqual(context["envdir"], sys.prefix)
self.assertEqual(context["pkg_name"], "poser")
self.assertEqual(context["app_title"], "poser")
self.assertEqual(context["pypi_name"], "poser")
self.assertEqual(context["egg_name"], "poser")
self.assertEqual(context["appdir"], os.path.join(sys.prefix, "app"))
self.assertEqual(context["db_url"], "sqlite:///poser.sqlite")
def test_make_appdir(self):
handler = self.make_handler()
handler.templates = TemplateLookup(directories=[
self.app.resource_path('wuttjamaican:templates/install'),
])
dbinfo = {'dburl': 'sqlite:///poser.sqlite'}
handler.templates = TemplateLookup(
directories=[
self.app.resource_path("wuttjamaican:templates/install"),
]
)
dbinfo = {"dburl": "sqlite:///poser.sqlite"}
context = handler.make_template_context(dbinfo)
handler.make_appdir(context, appdir=self.tempdir)
wutta_conf = os.path.join(self.tempdir, 'wutta.conf')
with open(wutta_conf, 'rt') as f:
self.assertIn('default.url = sqlite:///poser.sqlite', f.read())
wutta_conf = os.path.join(self.tempdir, "wutta.conf")
with open(wutta_conf, "rt") as f:
self.assertIn("default.url = sqlite:///poser.sqlite", f.read())
def test_install_db_schema(self):
try:
@ -192,89 +206,105 @@ class TestInstallHandler(ConfigTestCase):
pytest.skip("test is not relevant without sqlalchemy")
handler = self.make_handler()
db_url = f'sqlite:///{self.tempdir}/poser.sqlite'
db_url = f"sqlite:///{self.tempdir}/poser.sqlite"
wutta_conf = self.write_file('wutta.conf', f"""
wutta_conf = self.write_file(
"wutta.conf",
f"""
[wutta.db]
default.url = {db_url}
""")
""",
)
# convert to proper URL object
db_url = sa.create_engine(db_url).url
with patch.object(mod, 'subprocess') as subprocess:
with patch.object(mod, "subprocess") as subprocess:
# user declines offer to install schema
with patch.object(handler, 'prompt_bool', return_value=False):
with patch.object(handler, "prompt_bool", return_value=False):
self.assertFalse(handler.install_db_schema(db_url, appdir=self.tempdir))
# user agrees to install schema
with patch.object(handler, 'prompt_bool', return_value=True):
with patch.object(handler, "prompt_bool", return_value=True):
self.assertTrue(handler.install_db_schema(db_url, appdir=self.tempdir))
subprocess.check_call.assert_called_once_with([
os.path.join(sys.prefix, 'bin', 'alembic'),
'-c', wutta_conf, 'upgrade', 'heads'])
subprocess.check_call.assert_called_once_with(
[
os.path.join(sys.prefix, "bin", "alembic"),
"-c",
wutta_conf,
"upgrade",
"heads",
]
)
def test_show_goodbye(self):
handler = self.make_handler()
with patch.object(handler, 'rprint') as rprint:
with patch.object(handler, "rprint") as rprint:
handler.schema_installed = True
handler.show_goodbye()
rprint.assert_any_call("\n\t[bold green]initial setup is complete![/bold green]")
rprint.assert_any_call(
"\n\t[bold green]initial setup is complete![/bold green]"
)
rprint.assert_any_call("\t[blue]bin/wutta -c app/web.conf webapp -r[/blue]")
def test_require_prompt_toolkit_installed(self):
# nb. this assumes we *do* have prompt_toolkit installed
handler = self.make_handler()
with patch.object(mod, 'subprocess') as subprocess:
handler.require_prompt_toolkit(answer='Y')
with patch.object(mod, "subprocess") as subprocess:
handler.require_prompt_toolkit(answer="Y")
self.assertFalse(subprocess.check_call.called)
def test_require_prompt_toolkit_missing(self):
handler = self.make_handler()
orig_import = __import__
stuff = {'attempts': 0}
stuff = {"attempts": 0}
def mock_import(name, globals=None, locals=None, fromlist=(), level=0):
if name == 'prompt_toolkit':
if name == "prompt_toolkit":
# nb. pretend this is not installed
raise ImportError
return orig_import(name, globals, locals, fromlist, level)
# prompt_toolkit not installed, and user declines offer to install
with patch('builtins.__import__', side_effect=mock_import):
with patch.object(mod, 'subprocess') as subprocess:
with patch.object(mod, 'sys') as sys:
with patch("builtins.__import__", side_effect=mock_import):
with patch.object(mod, "subprocess") as subprocess:
with patch.object(mod, "sys") as sys:
sys.exit.side_effect = RuntimeError
self.assertRaises(RuntimeError, handler.require_prompt_toolkit, answer='N')
self.assertRaises(
RuntimeError, handler.require_prompt_toolkit, answer="N"
)
self.assertFalse(subprocess.check_call.called)
sys.stderr.write.assert_called_once_with("prompt_toolkit is required; aborting\n")
sys.stderr.write.assert_called_once_with(
"prompt_toolkit is required; aborting\n"
)
sys.exit.assert_called_once_with(1)
def test_require_prompt_toolkit_missing_then_installed(self):
handler = self.make_handler()
orig_import = __import__
stuff = {'attempts': 0}
stuff = {"attempts": 0}
def mock_import(name, globals=None, locals=None, fromlist=(), level=0):
if name == 'prompt_toolkit':
stuff['attempts'] += 1
if stuff['attempts'] == 1:
if name == "prompt_toolkit":
stuff["attempts"] += 1
if stuff["attempts"] == 1:
# nb. pretend this is not installed
raise ImportError
return orig_import('prompt_toolkit')
return orig_import("prompt_toolkit")
return orig_import(name, globals, locals, fromlist, level)
# prompt_toolkit not installed, and user declines offer to install
with patch('builtins.__import__', side_effect=mock_import):
with patch.object(mod, 'subprocess') as subprocess:
with patch.object(mod, 'sys') as sys:
sys.executable = 'python'
handler.require_prompt_toolkit(answer='Y')
subprocess.check_call.assert_called_once_with(['python', '-m', 'pip',
'install', 'prompt_toolkit'])
with patch("builtins.__import__", side_effect=mock_import):
with patch.object(mod, "subprocess") as subprocess:
with patch.object(mod, "sys") as sys:
sys.executable = "python"
handler.require_prompt_toolkit(answer="Y")
subprocess.check_call.assert_called_once_with(
["python", "-m", "pip", "install", "prompt_toolkit"]
)
self.assertFalse(sys.exit.called)
self.assertEqual(stuff['attempts'], 2)
self.assertEqual(stuff["attempts"], 2)
def test_prompt_generic(self):
handler = self.make_handler()
@ -283,86 +313,94 @@ default.url = {db_url}
mock_prompt = MagicMock()
def mock_import(name, globals=None, locals=None, fromlist=(), level=0):
if name == 'prompt_toolkit':
if fromlist == ('prompt',):
if name == "prompt_toolkit":
if fromlist == ("prompt",):
return MagicMock(prompt=mock_prompt)
return orig_import(name, globals, locals, fromlist, level)
with patch('builtins.__import__', side_effect=mock_import):
with patch.object(handler, 'get_prompt_style', return_value=style):
with patch.object(handler, 'rprint') as rprint:
with patch("builtins.__import__", side_effect=mock_import):
with patch.object(handler, "get_prompt_style", return_value=style):
with patch.object(handler, "rprint") as rprint:
# no input or default value
mock_prompt.return_value = ''
result = handler.prompt_generic('foo')
mock_prompt.return_value = ""
result = handler.prompt_generic("foo")
self.assertIsNone(result)
mock_prompt.assert_called_once_with([('', '\n'),
('class:bold', 'foo'),
('', ': ')],
style=style, is_password=False)
mock_prompt.assert_called_once_with(
[("", "\n"), ("class:bold", "foo"), ("", ": ")],
style=style,
is_password=False,
)
# fallback to default value
mock_prompt.reset_mock()
mock_prompt.return_value = ''
result = handler.prompt_generic('foo', default='baz')
self.assertEqual(result, 'baz')
mock_prompt.assert_called_once_with([('', '\n'),
('class:bold', 'foo'),
('', ' [baz]: ')],
style=style, is_password=False)
mock_prompt.return_value = ""
result = handler.prompt_generic("foo", default="baz")
self.assertEqual(result, "baz")
mock_prompt.assert_called_once_with(
[("", "\n"), ("class:bold", "foo"), ("", " [baz]: ")],
style=style,
is_password=False,
)
# text input value
mock_prompt.reset_mock()
mock_prompt.return_value = 'bar'
result = handler.prompt_generic('foo')
self.assertEqual(result, 'bar')
mock_prompt.assert_called_once_with([('', '\n'),
('class:bold', 'foo'),
('', ': ')],
style=style, is_password=False)
mock_prompt.return_value = "bar"
result = handler.prompt_generic("foo")
self.assertEqual(result, "bar")
mock_prompt.assert_called_once_with(
[("", "\n"), ("class:bold", "foo"), ("", ": ")],
style=style,
is_password=False,
)
# bool value (no default; true input)
mock_prompt.reset_mock()
mock_prompt.return_value = 'Y'
result = handler.prompt_generic('foo', is_bool=True)
mock_prompt.return_value = "Y"
result = handler.prompt_generic("foo", is_bool=True)
self.assertTrue(result)
mock_prompt.assert_called_once_with([('', '\n'),
('class:bold', 'foo'),
('', ': ')],
style=style, is_password=False)
mock_prompt.assert_called_once_with(
[("", "\n"), ("class:bold", "foo"), ("", ": ")],
style=style,
is_password=False,
)
# bool value (no default; false input)
mock_prompt.reset_mock()
mock_prompt.return_value = 'N'
result = handler.prompt_generic('foo', is_bool=True)
mock_prompt.return_value = "N"
result = handler.prompt_generic("foo", is_bool=True)
self.assertFalse(result)
mock_prompt.assert_called_once_with([('', '\n'),
('class:bold', 'foo'),
('', ': ')],
style=style, is_password=False)
mock_prompt.assert_called_once_with(
[("", "\n"), ("class:bold", "foo"), ("", ": ")],
style=style,
is_password=False,
)
# bool value (default; no input)
mock_prompt.reset_mock()
mock_prompt.return_value = ''
result = handler.prompt_generic('foo', is_bool=True, default=True)
mock_prompt.return_value = ""
result = handler.prompt_generic("foo", is_bool=True, default=True)
self.assertTrue(result)
mock_prompt.assert_called_once_with([('', '\n'),
('class:bold', 'foo'),
('', ' [Y]: ')],
style=style, is_password=False)
mock_prompt.assert_called_once_with(
[("", "\n"), ("class:bold", "foo"), ("", " [Y]: ")],
style=style,
is_password=False,
)
# bool value (bad input)
mock_prompt.reset_mock()
counter = {'attempts': 0}
counter = {"attempts": 0}
def omg(*args, **kwargs):
counter['attempts'] += 1
if counter['attempts'] == 1:
counter["attempts"] += 1
if counter["attempts"] == 1:
# nb. bad input first time we ask
return 'doesnotmakesense'
return "doesnotmakesense"
# nb. but good input after that
return 'N'
return "N"
mock_prompt.side_effect = omg
result = handler.prompt_generic('foo', is_bool=True)
result = handler.prompt_generic("foo", is_bool=True)
self.assertFalse(result)
# nb. user was prompted twice
self.assertEqual(mock_prompt.call_count, 2)
@ -370,32 +408,34 @@ default.url = {db_url}
# Ctrl+C
mock_prompt.reset_mock()
mock_prompt.side_effect = KeyboardInterrupt
with patch.object(mod, 'sys') as sys:
with patch.object(mod, "sys") as sys:
sys.exit.side_effect = RuntimeError
self.assertRaises(RuntimeError, handler.prompt_generic, 'foo')
self.assertRaises(RuntimeError, handler.prompt_generic, "foo")
sys.exit.assert_called_once_with(1)
# Ctrl+D
mock_prompt.reset_mock()
mock_prompt.side_effect = EOFError
with patch.object(mod, 'sys') as sys:
with patch.object(mod, "sys") as sys:
sys.exit.side_effect = RuntimeError
self.assertRaises(RuntimeError, handler.prompt_generic, 'foo')
self.assertRaises(RuntimeError, handler.prompt_generic, "foo")
sys.exit.assert_called_once_with(1)
# missing required value
mock_prompt.reset_mock()
counter = {'attempts': 0}
counter = {"attempts": 0}
def omg(*args, **kwargs):
counter['attempts'] += 1
if counter['attempts'] == 1:
counter["attempts"] += 1
if counter["attempts"] == 1:
# nb. no input first time we ask
return ''
return ""
# nb. but good input after that
return 'bar'
return "bar"
mock_prompt.side_effect = omg
result = handler.prompt_generic('foo', required=True)
self.assertEqual(result, 'bar')
result = handler.prompt_generic("foo", required=True)
self.assertEqual(result, "bar")
# nb. user was prompted twice
self.assertEqual(mock_prompt.call_count, 2)
@ -405,47 +445,49 @@ default.url = {db_url}
mock_prompt = MagicMock()
def mock_import(name, globals=None, locals=None, fromlist=(), level=0):
if name == 'prompt_toolkit':
if fromlist == ('prompt',):
if name == "prompt_toolkit":
if fromlist == ("prompt",):
return MagicMock(prompt=mock_prompt)
return orig_import(name, globals, locals, fromlist, level)
with patch('builtins.__import__', side_effect=mock_import):
with patch.object(handler, 'rprint') as rprint:
with patch("builtins.__import__", side_effect=mock_import):
with patch.object(handler, "rprint") as rprint:
# no default; true input
mock_prompt.reset_mock()
mock_prompt.return_value = 'Y'
result = handler.prompt_bool('foo')
mock_prompt.return_value = "Y"
result = handler.prompt_bool("foo")
self.assertTrue(result)
mock_prompt.assert_called_once()
# no default; false input
mock_prompt.reset_mock()
mock_prompt.return_value = 'N'
result = handler.prompt_bool('foo')
mock_prompt.return_value = "N"
result = handler.prompt_bool("foo")
self.assertFalse(result)
mock_prompt.assert_called_once()
# default; no input
mock_prompt.reset_mock()
mock_prompt.return_value = ''
result = handler.prompt_bool('foo', default=True)
mock_prompt.return_value = ""
result = handler.prompt_bool("foo", default=True)
self.assertTrue(result)
mock_prompt.assert_called_once()
# bad input
mock_prompt.reset_mock()
counter = {'attempts': 0}
counter = {"attempts": 0}
def omg(*args, **kwargs):
counter['attempts'] += 1
if counter['attempts'] == 1:
counter["attempts"] += 1
if counter["attempts"] == 1:
# nb. bad input first time we ask
return 'doesnotmakesense'
return "doesnotmakesense"
# nb. but good input after that
return 'N'
return "N"
mock_prompt.side_effect = omg
result = handler.prompt_bool('foo')
result = handler.prompt_bool("foo")
self.assertFalse(result)
# nb. user was prompted twice
self.assertEqual(mock_prompt.call_count, 2)

View file

@ -9,7 +9,6 @@ except ImportError:
pass
else:
class TestPeopleHandler(DataTestCase):
def make_handler(self):
@ -17,7 +16,7 @@ else:
def test_get_person(self):
model = self.app.model
myperson = model.Person(full_name='Barny Rubble')
myperson = model.Person(full_name="Barny Rubble")
self.session.add(myperson)
self.session.commit()
handler = self.make_handler()
@ -31,7 +30,7 @@ else:
self.assertIs(person, myperson)
# find person from user
myuser = model.User(username='barney', person=myperson)
myuser = model.User(username="barney", person=myperson)
self.session.add(myuser)
self.session.commit()
person = handler.get_person(myuser)
@ -48,9 +47,9 @@ else:
self.assertIsNone(person.full_name)
self.assertNotIn(person, self.session)
person = handler.make_person(first_name='Barney', last_name='Rubble')
person = handler.make_person(first_name="Barney", last_name="Rubble")
self.assertIsInstance(person, model.Person)
self.assertEqual(person.first_name, 'Barney')
self.assertEqual(person.last_name, 'Rubble')
self.assertEqual(person.full_name, 'Barney Rubble')
self.assertEqual(person.first_name, "Barney")
self.assertEqual(person.last_name, "Rubble")
self.assertEqual(person.full_name, "Barney Rubble")
self.assertNotIn(person, self.session)

View file

@ -14,15 +14,15 @@ class TestProblemCheck(ConfigTestCase):
def test_system_key(self):
check = self.make_check()
self.assertRaises(AttributeError, getattr, check, 'system_key')
self.assertRaises(AttributeError, getattr, check, "system_key")
def test_problem_key(self):
check = self.make_check()
self.assertRaises(AttributeError, getattr, check, 'problem_key')
self.assertRaises(AttributeError, getattr, check, "problem_key")
def test_title(self):
check = self.make_check()
self.assertRaises(AttributeError, getattr, check, 'title')
self.assertRaises(AttributeError, getattr, check, "title")
def test_find_problems(self):
check = self.make_check()
@ -44,8 +44,8 @@ class TestProblemCheck(ConfigTestCase):
class FakeProblemCheck(mod.ProblemCheck):
system_key = 'wuttatest'
problem_key = 'fake_check'
system_key = "wuttatest"
problem_key = "fake_check"
title = "Fake problem check"
# def find_problems(self):
@ -69,7 +69,7 @@ class TestProblemHandler(ConfigTestCase):
self.assertEqual(len(checks), 0)
# but let's configure our fake check
self.config.setdefault('wutta.problems.modules', 'tests.test_problems')
self.config.setdefault("wutta.problems.modules", "tests.test_problems")
checks = self.handler.get_all_problem_checks()
self.assertIsInstance(checks, list)
self.assertEqual(len(checks), 1)
@ -82,27 +82,31 @@ class TestProblemHandler(ConfigTestCase):
self.assertEqual(len(checks), 0)
# but let's configure our fake check
self.config.setdefault('wutta.problems.modules', 'tests.test_problems')
self.config.setdefault("wutta.problems.modules", "tests.test_problems")
checks = self.handler.filter_problem_checks()
self.assertIsInstance(checks, list)
self.assertEqual(len(checks), 1)
# filter by system_key
checks = self.handler.filter_problem_checks(systems=['wuttatest'])
checks = self.handler.filter_problem_checks(systems=["wuttatest"])
self.assertEqual(len(checks), 1)
checks = self.handler.filter_problem_checks(systems=['something_else'])
checks = self.handler.filter_problem_checks(systems=["something_else"])
self.assertEqual(len(checks), 0)
# filter by problem_key
checks = self.handler.filter_problem_checks(problems=['fake_check'])
checks = self.handler.filter_problem_checks(problems=["fake_check"])
self.assertEqual(len(checks), 1)
checks = self.handler.filter_problem_checks(problems=['something_else'])
checks = self.handler.filter_problem_checks(problems=["something_else"])
self.assertEqual(len(checks), 0)
# filter by both
checks = self.handler.filter_problem_checks(systems=['wuttatest'], problems=['fake_check'])
checks = self.handler.filter_problem_checks(
systems=["wuttatest"], problems=["fake_check"]
)
self.assertEqual(len(checks), 1)
checks = self.handler.filter_problem_checks(systems=['wuttatest'], problems=['bad_check'])
checks = self.handler.filter_problem_checks(
systems=["wuttatest"], problems=["bad_check"]
)
self.assertEqual(len(checks), 0)
def test_get_supported_systems(self):
@ -113,14 +117,14 @@ class TestProblemHandler(ConfigTestCase):
self.assertEqual(len(systems), 0)
# but let's configure our fake check
self.config.setdefault('wutta.problems.modules', 'tests.test_problems')
self.config.setdefault("wutta.problems.modules", "tests.test_problems")
systems = self.handler.get_supported_systems()
self.assertIsInstance(systems, list)
self.assertEqual(systems, ['wuttatest'])
self.assertEqual(systems, ["wuttatest"])
def test_get_system_title(self):
title = self.handler.get_system_title('wutta')
self.assertEqual(title, 'wutta')
title = self.handler.get_system_title("wutta")
self.assertEqual(title, "wutta")
def test_is_enabled(self):
check = FakeProblemCheck(self.config)
@ -129,7 +133,7 @@ class TestProblemHandler(ConfigTestCase):
self.assertTrue(self.handler.is_enabled(check))
# config can disable
self.config.setdefault('wutta.problems.wuttatest.fake_check.enabled', 'false')
self.config.setdefault("wutta.problems.wuttatest.fake_check.enabled", "false")
self.assertFalse(self.handler.is_enabled(check))
def test_should_run_for_weekday(self):
@ -140,8 +144,8 @@ class TestProblemHandler(ConfigTestCase):
self.assertTrue(self.handler.should_run_for_weekday(check, weekday))
# config can disable, e.g. for weekends
self.config.setdefault('wutta.problems.wuttatest.fake_check.day5', 'false')
self.config.setdefault('wutta.problems.wuttatest.fake_check.day6', 'false')
self.config.setdefault("wutta.problems.wuttatest.fake_check.day5", "false")
self.config.setdefault("wutta.problems.wuttatest.fake_check.day6", "false")
for weekday in range(5):
self.assertTrue(self.handler.should_run_for_weekday(check, weekday))
for weekday in (5, 6):
@ -152,10 +156,10 @@ class TestProblemHandler(ConfigTestCase):
organized = self.handler.organize_problem_checks(checks)
self.assertIsInstance(organized, dict)
self.assertEqual(list(organized), ['wuttatest'])
self.assertIsInstance(organized['wuttatest'], dict)
self.assertEqual(list(organized['wuttatest']), ['fake_check'])
self.assertIs(organized['wuttatest']['fake_check'], FakeProblemCheck)
self.assertEqual(list(organized), ["wuttatest"])
self.assertIsInstance(organized["wuttatest"], dict)
self.assertEqual(list(organized["wuttatest"]), ["fake_check"])
self.assertIs(organized["wuttatest"]["fake_check"], FakeProblemCheck)
def test_find_problems(self):
check = FakeProblemCheck(self.config)
@ -165,7 +169,7 @@ class TestProblemHandler(ConfigTestCase):
def test_get_email_key(self):
check = FakeProblemCheck(self.config)
key = self.handler.get_email_key(check)
self.assertEqual(key, 'wuttatest_problems_fake_check')
self.assertEqual(key, "wuttatest_problems_fake_check")
def test_get_global_email_context(self):
context = self.handler.get_global_email_context()
@ -175,44 +179,53 @@ class TestProblemHandler(ConfigTestCase):
check = FakeProblemCheck(self.config)
problems = []
context = self.handler.get_check_email_context(check, problems)
self.assertEqual(context, {'system_title': 'wuttatest'})
self.assertEqual(context, {"system_title": "wuttatest"})
def test_send_problem_report(self):
check = FakeProblemCheck(self.config)
problems = []
with patch.object(self.app, 'send_email') as send_email:
with patch.object(self.app, "send_email") as send_email:
self.handler.send_problem_report(check, problems)
send_email.assert_called_once_with('wuttatest_problems_fake_check', {
'system_title': 'wuttatest',
'config': self.config,
'app': self.app,
'check': check,
'problems': problems,
}, default_subject="Fake problem check", attachments=None)
send_email.assert_called_once_with(
"wuttatest_problems_fake_check",
{
"system_title": "wuttatest",
"config": self.config,
"app": self.app,
"check": check,
"problems": problems,
},
default_subject="Fake problem check",
attachments=None,
)
def test_run_problem_check(self):
with patch.object(FakeProblemCheck, 'find_problems') as find_problems:
with patch.object(self.handler, 'send_problem_report') as send_problem_report:
with patch.object(FakeProblemCheck, "find_problems") as find_problems:
with patch.object(
self.handler, "send_problem_report"
) as send_problem_report:
# check runs by default
find_problems.return_value = [{'foo': 'bar'}]
find_problems.return_value = [{"foo": "bar"}]
problems = self.handler.run_problem_check(FakeProblemCheck)
self.assertEqual(problems, [{'foo': 'bar'}])
self.assertEqual(problems, [{"foo": "bar"}])
find_problems.assert_called_once_with()
send_problem_report.assert_called_once()
# does not run if generally disabled
find_problems.reset_mock()
send_problem_report.reset_mock()
with patch.object(self.handler, 'is_enabled', return_value=False):
with patch.object(self.handler, "is_enabled", return_value=False):
problems = self.handler.run_problem_check(FakeProblemCheck)
self.assertIsNone(problems)
find_problems.assert_not_called()
send_problem_report.assert_not_called()
# unless caller gives force flag
problems = self.handler.run_problem_check(FakeProblemCheck, force=True)
self.assertEqual(problems, [{'foo': 'bar'}])
problems = self.handler.run_problem_check(
FakeProblemCheck, force=True
)
self.assertEqual(problems, [{"foo": "bar"}])
find_problems.assert_called_once_with()
send_problem_report.assert_called_once()
@ -220,7 +233,9 @@ class TestProblemHandler(ConfigTestCase):
find_problems.reset_mock()
send_problem_report.reset_mock()
weekday = datetime.date.today().weekday()
self.config.setdefault(f'wutta.problems.wuttatest.fake_check.day{weekday}', 'false')
self.config.setdefault(
f"wutta.problems.wuttatest.fake_check.day{weekday}", "false"
)
problems = self.handler.run_problem_check(FakeProblemCheck)
self.assertIsNone(problems)
find_problems.assert_not_called()
@ -228,16 +243,18 @@ class TestProblemHandler(ConfigTestCase):
# unless caller gives force flag
problems = self.handler.run_problem_check(FakeProblemCheck, force=True)
self.assertEqual(problems, [{'foo': 'bar'}])
self.assertEqual(problems, [{"foo": "bar"}])
find_problems.assert_called_once_with()
send_problem_report.assert_called_once()
def test_run_problem_checks(self):
with patch.object(FakeProblemCheck, 'find_problems') as find_problems:
with patch.object(self.handler, 'send_problem_report') as send_problem_report:
with patch.object(FakeProblemCheck, "find_problems") as find_problems:
with patch.object(
self.handler, "send_problem_report"
) as send_problem_report:
# check runs by default
find_problems.return_value = [{'foo': 'bar'}]
find_problems.return_value = [{"foo": "bar"}]
self.handler.run_problem_checks([FakeProblemCheck])
find_problems.assert_called_once_with()
send_problem_report.assert_called_once()
@ -245,7 +262,7 @@ class TestProblemHandler(ConfigTestCase):
# does not run if generally disabled
find_problems.reset_mock()
send_problem_report.reset_mock()
with patch.object(self.handler, 'is_enabled', return_value=False):
with patch.object(self.handler, "is_enabled", return_value=False):
self.handler.run_problem_checks([FakeProblemCheck])
find_problems.assert_not_called()
send_problem_report.assert_not_called()
@ -259,7 +276,9 @@ class TestProblemHandler(ConfigTestCase):
find_problems.reset_mock()
send_problem_report.reset_mock()
weekday = datetime.date.today().weekday()
self.config.setdefault(f'wutta.problems.wuttatest.fake_check.day{weekday}', 'false')
self.config.setdefault(
f"wutta.problems.wuttatest.fake_check.day{weekday}", "false"
)
self.handler.run_problem_checks([FakeProblemCheck])
find_problems.assert_not_called()
send_problem_report.assert_not_called()

View file

@ -10,7 +10,7 @@ class TestProgressBase(TestCase):
def test_basic(self):
# sanity / coverage check
prog = mod.ProgressBase('testing', 2)
prog = mod.ProgressBase("testing", 2)
prog.update(1)
prog.update(2)
prog.finish()
@ -21,7 +21,7 @@ class TestConsoleProgress(TestCase):
def test_basic(self):
# sanity / coverage check
prog = mod.ConsoleProgress('testing', 2)
prog = mod.ConsoleProgress("testing", 2)
prog.update(1)
prog.update(2)
prog.finish()

View file

@ -7,12 +7,12 @@ from wuttjamaican.testing import ConfigTestCase
class MockFooReport(mod.Report):
report_key = 'mock_foo'
report_key = "mock_foo"
report_title = "MOCK Report"
def make_data(self, params, **kwargs):
return [
{'foo': 'bar'},
{"foo": "bar"},
]
@ -35,15 +35,15 @@ class TestReportHandler(ConfigTestCase):
def test_get_report_modules(self):
# no providers, no report modules
with patch.object(self.app, 'providers', new={}):
with patch.object(self.app, "providers", new={}):
handler = self.make_handler()
self.assertEqual(handler.get_report_modules(), [])
# provider may specify modules as list
providers = {
'wuttatest': MagicMock(report_modules=['wuttjamaican.reports']),
"wuttatest": MagicMock(report_modules=["wuttjamaican.reports"]),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
modules = handler.get_report_modules()
self.assertEqual(len(modules), 1)
@ -51,9 +51,9 @@ class TestReportHandler(ConfigTestCase):
# provider may specify modules as string
providers = {
'wuttatest': MagicMock(report_modules='wuttjamaican.reports'),
"wuttatest": MagicMock(report_modules="wuttjamaican.reports"),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
modules = handler.get_report_modules()
self.assertEqual(len(modules), 1)
@ -62,54 +62,54 @@ class TestReportHandler(ConfigTestCase):
def test_get_reports(self):
# no providers, no reports
with patch.object(self.app, 'providers', new={}):
with patch.object(self.app, "providers", new={}):
handler = self.make_handler()
self.assertEqual(handler.get_reports(), {})
# provider may define reports (via modules)
providers = {
'wuttatest': MagicMock(report_modules=['tests.test_reports']),
"wuttatest": MagicMock(report_modules=["tests.test_reports"]),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
reports = handler.get_reports()
self.assertEqual(len(reports), 1)
self.assertIn('mock_foo', reports)
self.assertIn("mock_foo", reports)
def test_get_report(self):
providers = {
'wuttatest': MagicMock(report_modules=['tests.test_reports']),
"wuttatest": MagicMock(report_modules=["tests.test_reports"]),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
# as instance
report = handler.get_report('mock_foo')
report = handler.get_report("mock_foo")
self.assertIsInstance(report, mod.Report)
self.assertIsInstance(report, MockFooReport)
# as class
report = handler.get_report('mock_foo', instance=False)
report = handler.get_report("mock_foo", instance=False)
self.assertTrue(issubclass(report, mod.Report))
self.assertIs(report, MockFooReport)
# not found
report = handler.get_report('unknown')
report = handler.get_report("unknown")
self.assertIsNone(report)
def test_make_report_data(self):
providers = {
'wuttatest': MagicMock(report_modules=['tests.test_reports']),
"wuttatest": MagicMock(report_modules=["tests.test_reports"]),
}
with patch.object(self.app, 'providers', new=providers):
with patch.object(self.app, "providers", new=providers):
handler = self.make_handler()
report = handler.get_report('mock_foo')
report = handler.get_report("mock_foo")
data = handler.make_report_data(report)
self.assertEqual(len(data), 2)
self.assertIn('output_title', data)
self.assertEqual(data['output_title'], "MOCK Report")
self.assertIn('data', data)
self.assertEqual(data['data'], [{'foo': 'bar'}])
self.assertIn("output_title", data)
self.assertEqual(data["output_title"], "MOCK Report")
self.assertIn("data", data)
self.assertEqual(data["data"], [{"foo": "bar"}])

View file

@ -10,9 +10,17 @@ from wuttjamaican import util as mod
from wuttjamaican.progress import ProgressBase
class A: pass
class B(A): pass
class C(B): pass
class A:
pass
class B(A):
pass
class C(B):
pass
class TestGetClassHierarchy(TestCase):
@ -35,15 +43,15 @@ class TestLoadEntryPoints(TestCase):
def test_empty(self):
# empty set returned for unknown group
result = mod.load_entry_points('this_should_never_exist!!!!!!')
result = mod.load_entry_points("this_should_never_exist!!!!!!")
self.assertEqual(result, {})
def test_basic(self):
# load some entry points which should "always" be present,
# even in a testing environment. basic sanity check
result = mod.load_entry_points('console_scripts', ignore_errors=True)
result = mod.load_entry_points("console_scripts", ignore_errors=True)
self.assertTrue(len(result) >= 1)
self.assertIn('pip', result)
self.assertIn("pip", result)
def test_basic_pre_python_3_10(self):
@ -54,6 +62,7 @@ class TestLoadEntryPoints(TestCase):
pytest.skip("this test is not relevant before python 3.10")
import importlib.metadata
real_entry_points = importlib.metadata.entry_points()
class FakeEntryPoints(dict):
@ -63,13 +72,13 @@ class TestLoadEntryPoints(TestCase):
importlib = MagicMock()
importlib.metadata.entry_points.return_value = FakeEntryPoints()
with patch.dict('sys.modules', **{'importlib': importlib}):
with patch.dict("sys.modules", **{"importlib": importlib}):
# load some entry points which should "always" be present,
# even in a testing environment. basic sanity check
result = mod.load_entry_points('console_scripts', ignore_errors=True)
result = mod.load_entry_points("console_scripts", ignore_errors=True)
self.assertTrue(len(result) >= 1)
self.assertIn('pytest', result)
self.assertIn("pytest", result)
def test_basic_pre_python_3_8(self):
@ -80,11 +89,12 @@ class TestLoadEntryPoints(TestCase):
pytest.skip("this test is not relevant before python 3.8")
from importlib.metadata import entry_points
real_entry_points = entry_points()
class FakeEntryPoints(dict):
def get(self, group, default):
if hasattr(real_entry_points, 'select'):
if hasattr(real_entry_points, "select"):
return real_entry_points.select(group=group)
return real_entry_points.get(group, [])
@ -94,19 +104,19 @@ class TestLoadEntryPoints(TestCase):
orig_import = __import__
def mock_import(name, *args, **kwargs):
if name == 'importlib.metadata':
if name == "importlib.metadata":
raise ImportError
if name == 'importlib_metadata':
if name == "importlib_metadata":
return importlib_metadata
return orig_import(name, *args, **kwargs)
with patch('builtins.__import__', side_effect=mock_import):
with patch("builtins.__import__", side_effect=mock_import):
# load some entry points which should "always" be present,
# even in a testing environment. basic sanity check
result = mod.load_entry_points('console_scripts', ignore_errors=True)
result = mod.load_entry_points("console_scripts", ignore_errors=True)
self.assertTrue(len(result) >= 1)
self.assertIn('pytest', result)
self.assertIn("pytest", result)
def test_error(self):
@ -123,22 +133,24 @@ class TestLoadEntryPoints(TestCase):
importlib = MagicMock()
importlib.metadata.entry_points.return_value = entry_points
with patch.dict('sys.modules', **{'importlib': importlib}):
with patch.dict("sys.modules", **{"importlib": importlib}):
# empty set returned if errors suppressed
result = mod.load_entry_points('wuttatest.thingers', ignore_errors=True)
result = mod.load_entry_points("wuttatest.thingers", ignore_errors=True)
self.assertEqual(result, {})
importlib.metadata.entry_points.assert_called_once_with()
entry_points.select.assert_called_once_with(group='wuttatest.thingers')
entry_points.select.assert_called_once_with(group="wuttatest.thingers")
entry_point.load.assert_called_once_with()
# error is raised, if not suppressed
importlib.metadata.entry_points.reset_mock()
entry_points.select.reset_mock()
entry_point.load.reset_mock()
self.assertRaises(NotImplementedError, mod.load_entry_points, 'wuttatest.thingers')
self.assertRaises(
NotImplementedError, mod.load_entry_points, "wuttatest.thingers"
)
importlib.metadata.entry_points.assert_called_once_with()
entry_points.select.assert_called_once_with(group='wuttatest.thingers')
entry_points.select.assert_called_once_with(group="wuttatest.thingers")
entry_point.load.assert_called_once_with()
@ -148,7 +160,7 @@ class TestLoadObject(TestCase):
self.assertRaises(ValueError, mod.load_object, None)
def test_basic(self):
result = mod.load_object('unittest:TestCase')
result = mod.load_object("unittest:TestCase")
self.assertIs(result, TestCase)
@ -169,20 +181,20 @@ class TestParseBool(TestCase):
self.assertFalse(mod.parse_bool(False))
def test_string_true(self):
self.assertTrue(mod.parse_bool('true'))
self.assertTrue(mod.parse_bool('yes'))
self.assertTrue(mod.parse_bool('y'))
self.assertTrue(mod.parse_bool('on'))
self.assertTrue(mod.parse_bool('1'))
self.assertTrue(mod.parse_bool("true"))
self.assertTrue(mod.parse_bool("yes"))
self.assertTrue(mod.parse_bool("y"))
self.assertTrue(mod.parse_bool("on"))
self.assertTrue(mod.parse_bool("1"))
def test_string_false(self):
self.assertFalse(mod.parse_bool('false'))
self.assertFalse(mod.parse_bool('no'))
self.assertFalse(mod.parse_bool('n'))
self.assertFalse(mod.parse_bool('off'))
self.assertFalse(mod.parse_bool('0'))
self.assertFalse(mod.parse_bool("false"))
self.assertFalse(mod.parse_bool("no"))
self.assertFalse(mod.parse_bool("n"))
self.assertFalse(mod.parse_bool("off"))
self.assertFalse(mod.parse_bool("0"))
# nb. assume false for unrecognized input
self.assertFalse(mod.parse_bool('whatever-else'))
self.assertFalse(mod.parse_bool("whatever-else"))
class TestParseList(TestCase):
@ -198,76 +210,82 @@ class TestParseList(TestCase):
self.assertIs(value, mylist)
def test_single_value(self):
value = mod.parse_list('foo')
value = mod.parse_list("foo")
self.assertEqual(len(value), 1)
self.assertEqual(value[0], 'foo')
self.assertEqual(value[0], "foo")
def test_single_value_padded_by_spaces(self):
value = mod.parse_list(' foo ')
value = mod.parse_list(" foo ")
self.assertEqual(len(value), 1)
self.assertEqual(value[0], 'foo')
self.assertEqual(value[0], "foo")
def test_slash_is_not_a_separator(self):
value = mod.parse_list('/dev/null')
value = mod.parse_list("/dev/null")
self.assertEqual(len(value), 1)
self.assertEqual(value[0], '/dev/null')
self.assertEqual(value[0], "/dev/null")
def test_multiple_values_separated_by_whitespace(self):
value = mod.parse_list('foo bar baz')
value = mod.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')
self.assertEqual(value[0], "foo")
self.assertEqual(value[1], "bar")
self.assertEqual(value[2], "baz")
def test_multiple_values_separated_by_commas(self):
value = mod.parse_list('foo,bar,baz')
value = mod.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')
self.assertEqual(value[0], "foo")
self.assertEqual(value[1], "bar")
self.assertEqual(value[2], "baz")
def test_multiple_values_separated_by_whitespace_and_commas(self):
value = mod.parse_list(' foo, bar baz')
value = mod.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')
self.assertEqual(value[0], "foo")
self.assertEqual(value[1], "bar")
self.assertEqual(value[2], "baz")
def test_multiple_values_separated_by_whitespace_and_commas_with_some_quoting(self):
value = mod.parse_list("""
value = mod.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')
self.assertEqual(value[0], "foo")
self.assertEqual(value[1], "C:\\some path\\with spaces\\and, a comma")
self.assertEqual(value[2], "baz")
def test_multiple_values_separated_by_whitespace_and_commas_with_single_quotes(self):
value = mod.parse_list("""
def test_multiple_values_separated_by_whitespace_and_commas_with_single_quotes(
self,
):
value = mod.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')
self.assertEqual(value[0], "foo")
self.assertEqual(value[1], "C:\\some path\\with spaces\\and, a comma")
self.assertEqual(value[2], "baz")
class TestMakeTitle(TestCase):
def test_basic(self):
text = mod.make_title('foo_bar')
text = mod.make_title("foo_bar")
self.assertEqual(text, "Foo Bar")
class TestMakeFullName(TestCase):
def test_basic(self):
name = mod.make_full_name('Fred', '', 'Flintstone', '')
self.assertEqual(name, 'Fred Flintstone')
name = mod.make_full_name("Fred", "", "Flintstone", "")
self.assertEqual(name, "Fred Flintstone")
class TestProgressLoop(TestCase):
@ -278,12 +296,10 @@ class TestProgressLoop(TestCase):
pass
# with progress
mod.progress_loop(act, [1, 2, 3], ProgressBase,
message="whatever")
mod.progress_loop(act, [1, 2, 3], ProgressBase, message="whatever")
# without progress
mod.progress_loop(act, [1, 2, 3], None,
message="whatever")
mod.progress_loop(act, [1, 2, 3], None, message="whatever")
class TestResourcePath(TestCase):
@ -291,11 +307,13 @@ class TestResourcePath(TestCase):
def test_basic(self):
# package spec is resolved to path
path = mod.resource_path('wuttjamaican:util.py')
self.assertTrue(path.endswith('wuttjamaican/util.py'))
path = mod.resource_path("wuttjamaican:util.py")
self.assertTrue(path.endswith("wuttjamaican/util.py"))
# absolute path returned as-is
self.assertEqual(mod.resource_path('/tmp/doesnotexist.txt'), '/tmp/doesnotexist.txt')
self.assertEqual(
mod.resource_path("/tmp/doesnotexist.txt"), "/tmp/doesnotexist.txt"
)
def test_basic_pre_python_3_9(self):
@ -310,20 +328,22 @@ class TestResourcePath(TestCase):
orig_import = __import__
def mock_import(name, globals=None, locals=None, fromlist=(), level=0):
if name == 'importlib.resources':
if name == "importlib.resources":
raise ImportError
if name == 'importlib_resources':
if name == "importlib_resources":
return MagicMock(files=files, as_file=as_file)
return orig_import(name, globals, locals, fromlist, level)
with patch('builtins.__import__', side_effect=mock_import):
with patch("builtins.__import__", side_effect=mock_import):
# package spec is resolved to path
path = mod.resource_path('wuttjamaican:util.py')
self.assertTrue(path.endswith('wuttjamaican/util.py'))
path = mod.resource_path("wuttjamaican:util.py")
self.assertTrue(path.endswith("wuttjamaican/util.py"))
# absolute path returned as-is
self.assertEqual(mod.resource_path('/tmp/doesnotexist.txt'), '/tmp/doesnotexist.txt')
self.assertEqual(
mod.resource_path("/tmp/doesnotexist.txt"), "/tmp/doesnotexist.txt"
)
class TestSimpleError(TestCase):