258 lines
9.5 KiB
Python
258 lines
9.5 KiB
Python
# -*- coding: utf-8; -*-
|
|
|
|
from collections import OrderedDict
|
|
from unittest.mock import patch
|
|
|
|
from wuttjamaican.testing import DataTestCase
|
|
|
|
from wuttasync.importing import handlers as mod, Importer, ToSqlalchemy
|
|
|
|
|
|
class TestImportHandler(DataTestCase):
|
|
|
|
def make_handler(self, **kwargs):
|
|
return mod.ImportHandler(self.config, **kwargs)
|
|
|
|
def test_str(self):
|
|
handler = self.make_handler()
|
|
self.assertEqual(str(handler), "None → None")
|
|
|
|
handler.source_title = "CSV"
|
|
handler.target_title = "Wutta"
|
|
self.assertEqual(str(handler), "CSV → Wutta")
|
|
|
|
def test_actioning(self):
|
|
handler = self.make_handler()
|
|
self.assertEqual(handler.actioning, "importing")
|
|
|
|
handler.orientation = mod.Orientation.EXPORT
|
|
self.assertEqual(handler.actioning, "exporting")
|
|
|
|
def test_get_key(self):
|
|
handler = self.make_handler()
|
|
self.assertEqual(handler.get_key(), "to_None.from_None.import")
|
|
|
|
with patch.multiple(mod.ImportHandler, source_key="csv", target_key="wutta"):
|
|
self.assertEqual(handler.get_key(), "to_wutta.from_csv.import")
|
|
|
|
def test_get_spec(self):
|
|
handler = self.make_handler()
|
|
self.assertEqual(
|
|
handler.get_spec(), "wuttasync.importing.handlers:ImportHandler"
|
|
)
|
|
|
|
def test_get_title(self):
|
|
handler = self.make_handler()
|
|
self.assertEqual(handler.get_title(), "None → None")
|
|
|
|
handler.source_title = "CSV"
|
|
handler.target_title = "Wutta"
|
|
self.assertEqual(handler.get_title(), "CSV → Wutta")
|
|
|
|
def test_get_source_title(self):
|
|
handler = self.make_handler()
|
|
|
|
# null by default
|
|
self.assertIsNone(handler.get_source_title())
|
|
|
|
# which is really using source_key as fallback
|
|
handler.source_key = "csv"
|
|
self.assertEqual(handler.get_source_title(), "csv")
|
|
|
|
# can also use (defined) generic fallback
|
|
handler.generic_source_title = "CSV"
|
|
self.assertEqual(handler.get_source_title(), "CSV")
|
|
|
|
# or can set explicitly
|
|
handler.source_title = "XXX"
|
|
self.assertEqual(handler.get_source_title(), "XXX")
|
|
|
|
def test_get_target_title(self):
|
|
handler = self.make_handler()
|
|
|
|
# null by default
|
|
self.assertIsNone(handler.get_target_title())
|
|
|
|
# which is really using target_key as fallback
|
|
handler.target_key = "wutta"
|
|
self.assertEqual(handler.get_target_title(), "wutta")
|
|
|
|
# can also use (defined) generic fallback
|
|
handler.generic_target_title = "Wutta"
|
|
self.assertEqual(handler.get_target_title(), "Wutta")
|
|
|
|
# or can set explicitly
|
|
handler.target_title = "XXX"
|
|
self.assertEqual(handler.get_target_title(), "XXX")
|
|
|
|
def test_process_data(self):
|
|
model = self.app.model
|
|
handler = self.make_handler()
|
|
|
|
# empy/no-op should commit (not fail)
|
|
with patch.object(handler, "commit_transaction") as commit_transaction:
|
|
handler.process_data()
|
|
commit_transaction.assert_called_once_with()
|
|
|
|
# do that again with no patch, just for kicks
|
|
handler.process_data()
|
|
|
|
# dry-run should rollback
|
|
with patch.object(handler, "commit_transaction") as commit_transaction:
|
|
with patch.object(handler, "rollback_transaction") as rollback_transaction:
|
|
handler.process_data(dry_run=True)
|
|
self.assertFalse(commit_transaction.called)
|
|
rollback_transaction.assert_called_once_with()
|
|
|
|
# and do that with no patch, for kicks
|
|
handler.process_data(dry_run=True)
|
|
|
|
# outright error should cause rollback
|
|
with patch.object(handler, "commit_transaction") as commit_transaction:
|
|
with patch.object(handler, "rollback_transaction") as rollback_transaction:
|
|
with patch.object(handler, "get_importer", side_effect=RuntimeError):
|
|
self.assertRaises(RuntimeError, handler.process_data, "BlahBlah")
|
|
self.assertFalse(commit_transaction.called)
|
|
rollback_transaction.assert_called_once_with()
|
|
|
|
# fake importer class/data
|
|
mock_source_objects = [{"name": "foo", "value": "bar"}]
|
|
|
|
class SettingImporter(ToSqlalchemy):
|
|
model_class = model.Setting
|
|
target_session = self.session
|
|
|
|
def get_source_objects(self):
|
|
return mock_source_objects
|
|
|
|
# now for a "normal" one
|
|
handler.importers["Setting"] = SettingImporter
|
|
self.assertEqual(self.session.query(model.Setting).count(), 0)
|
|
handler.process_data("Setting")
|
|
self.assertEqual(self.session.query(model.Setting).count(), 1)
|
|
|
|
# then add another mock record
|
|
mock_source_objects.append({"name": "foo2", "value": "bar2"})
|
|
handler.process_data("Setting")
|
|
self.assertEqual(self.session.query(model.Setting).count(), 2)
|
|
|
|
# nb. even if dry-run, record is added
|
|
# (rollback would happen later in that case)
|
|
mock_source_objects.append({"name": "foo3", "value": "bar3"})
|
|
handler.process_data("Setting", dry_run=True)
|
|
self.assertEqual(self.session.query(model.Setting).count(), 3)
|
|
|
|
def test_consume_kwargs(self):
|
|
handler = self.make_handler()
|
|
|
|
# kwargs are returned as-is
|
|
kw = {}
|
|
result = handler.consume_kwargs(kw)
|
|
self.assertIs(result, kw)
|
|
|
|
# captures dry-run flag
|
|
self.assertFalse(handler.dry_run)
|
|
kw["dry_run"] = True
|
|
result = handler.consume_kwargs(kw)
|
|
self.assertIs(result, kw)
|
|
self.assertTrue(kw["dry_run"])
|
|
self.assertTrue(handler.dry_run)
|
|
|
|
def test_define_importers(self):
|
|
handler = self.make_handler()
|
|
importers = handler.define_importers()
|
|
self.assertEqual(importers, {})
|
|
self.assertIsInstance(importers, OrderedDict)
|
|
|
|
def test_get_importer(self):
|
|
model = self.app.model
|
|
handler = self.make_handler()
|
|
|
|
# normal
|
|
handler.importers["Setting"] = Importer
|
|
importer = handler.get_importer("Setting", model_class=model.Setting)
|
|
self.assertIsInstance(importer, Importer)
|
|
|
|
# specifying empty keys
|
|
handler.importers["Setting"] = Importer
|
|
importer = handler.get_importer("Setting", model_class=model.Setting, keys=None)
|
|
self.assertIsInstance(importer, Importer)
|
|
importer = handler.get_importer("Setting", model_class=model.Setting, keys="")
|
|
self.assertIsInstance(importer, Importer)
|
|
importer = handler.get_importer("Setting", model_class=model.Setting, keys=[])
|
|
self.assertIsInstance(importer, Importer)
|
|
|
|
# key not found
|
|
self.assertRaises(
|
|
KeyError, handler.get_importer, "BunchOfNonsense", model_class=model.Setting
|
|
)
|
|
|
|
|
|
class TestFromFileHandler(DataTestCase):
|
|
|
|
def make_handler(self, **kwargs):
|
|
return mod.FromFileHandler(self.config, **kwargs)
|
|
|
|
def test_process_data(self):
|
|
handler = self.make_handler()
|
|
path = self.write_file("data.txt", "")
|
|
with patch.object(mod.ImportHandler, "process_data") as process_data:
|
|
|
|
# bare
|
|
handler.process_data()
|
|
process_data.assert_called_once_with()
|
|
|
|
# with file path
|
|
process_data.reset_mock()
|
|
handler.process_data(input_file_path=path)
|
|
process_data.assert_called_once_with(input_file_path=path)
|
|
|
|
# with folder
|
|
process_data.reset_mock()
|
|
handler.process_data(input_file_path=self.tempdir)
|
|
process_data.assert_called_once_with(input_file_dir=self.tempdir)
|
|
|
|
|
|
class TestToSqlalchemyHandler(DataTestCase):
|
|
|
|
def make_handler(self, **kwargs):
|
|
return mod.ToSqlalchemyHandler(self.config, **kwargs)
|
|
|
|
def test_begin_target_transaction(self):
|
|
handler = self.make_handler()
|
|
with patch.object(handler, "make_target_session") as make_target_session:
|
|
make_target_session.return_value = self.session
|
|
self.assertIsNone(handler.target_session)
|
|
handler.begin_target_transaction()
|
|
make_target_session.assert_called_once_with()
|
|
|
|
def test_rollback_target_transaction(self):
|
|
handler = self.make_handler()
|
|
with patch.object(handler, "make_target_session") as make_target_session:
|
|
make_target_session.return_value = self.session
|
|
self.assertIsNone(handler.target_session)
|
|
handler.begin_target_transaction()
|
|
self.assertIs(handler.target_session, self.session)
|
|
handler.rollback_target_transaction()
|
|
self.assertIsNone(handler.target_session)
|
|
|
|
def test_commit_target_transaction(self):
|
|
handler = self.make_handler()
|
|
with patch.object(handler, "make_target_session") as make_target_session:
|
|
make_target_session.return_value = self.session
|
|
self.assertIsNone(handler.target_session)
|
|
handler.begin_target_transaction()
|
|
self.assertIs(handler.target_session, self.session)
|
|
handler.commit_target_transaction()
|
|
self.assertIsNone(handler.target_session)
|
|
|
|
def test_make_target_session(self):
|
|
handler = self.make_handler()
|
|
self.assertRaises(NotImplementedError, handler.make_target_session)
|
|
|
|
def test_get_importer_kwargs(self):
|
|
handler = self.make_handler()
|
|
handler.target_session = self.session
|
|
kw = handler.get_importer_kwargs("Setting")
|
|
self.assertIn("target_session", kw)
|
|
self.assertIs(kw["target_session"], self.session)
|