feat: add support for Wutta <-> Wutta import/export
This commit is contained in:
parent
bfc45bd0f0
commit
ae282ab468
25 changed files with 719 additions and 21 deletions
|
|
@ -25,19 +25,55 @@ class TestImportCommandHandler(DataTestCase):
|
|||
# as spec
|
||||
handler = self.make_handler(import_handler=FromCsvToWutta.get_spec())
|
||||
self.assertIsInstance(handler.import_handler, FromCsvToWutta)
|
||||
self.assertFalse(hasattr(handler, "foo"))
|
||||
self.assertFalse(hasattr(handler.import_handler, "foo"))
|
||||
|
||||
# as spec, w/ kwargs
|
||||
handler = self.make_handler(import_handler=FromCsvToWutta.get_spec(), foo="bar")
|
||||
self.assertIsInstance(handler.import_handler, FromCsvToWutta)
|
||||
self.assertFalse(hasattr(handler, "foo"))
|
||||
self.assertTrue(hasattr(handler.import_handler, "foo"))
|
||||
self.assertEqual(handler.import_handler.foo, "bar")
|
||||
|
||||
# as factory
|
||||
handler = self.make_handler(import_handler=FromCsvToWutta)
|
||||
self.assertIsInstance(handler.import_handler, FromCsvToWutta)
|
||||
self.assertFalse(hasattr(handler, "foo"))
|
||||
self.assertFalse(hasattr(handler.import_handler, "foo"))
|
||||
|
||||
# as factory, w/ kwargs
|
||||
handler = self.make_handler(import_handler=FromCsvToWutta, foo="bar")
|
||||
self.assertIsInstance(handler.import_handler, FromCsvToWutta)
|
||||
self.assertFalse(hasattr(handler, "foo"))
|
||||
self.assertTrue(hasattr(handler.import_handler, "foo"))
|
||||
self.assertEqual(handler.import_handler.foo, "bar")
|
||||
|
||||
# as instance
|
||||
myhandler = FromCsvToWutta(self.config)
|
||||
handler = self.make_handler(import_handler=myhandler)
|
||||
self.assertIs(handler.import_handler, myhandler)
|
||||
self.assertFalse(hasattr(handler, "foo"))
|
||||
self.assertFalse(hasattr(handler.import_handler, "foo"))
|
||||
|
||||
# as instance, w/ kwargs (which are ignored)
|
||||
myhandler = FromCsvToWutta(self.config)
|
||||
handler = self.make_handler(import_handler=myhandler, foo="bar")
|
||||
self.assertIs(handler.import_handler, myhandler)
|
||||
self.assertFalse(hasattr(handler, "foo"))
|
||||
self.assertFalse(hasattr(handler.import_handler, "foo"))
|
||||
|
||||
# as key
|
||||
handler = self.make_handler(key="import.to_wutta.from_csv")
|
||||
self.assertIsInstance(handler.import_handler, FromCsvToWutta)
|
||||
self.assertFalse(hasattr(handler, "foo"))
|
||||
self.assertFalse(hasattr(handler.import_handler, "foo"))
|
||||
|
||||
# as key, w/ kwargs
|
||||
handler = self.make_handler(key="import.to_wutta.from_csv", foo="bar")
|
||||
self.assertIsInstance(handler.import_handler, FromCsvToWutta)
|
||||
self.assertFalse(hasattr(handler, "foo"))
|
||||
self.assertTrue(hasattr(handler.import_handler, "foo"))
|
||||
self.assertEqual(handler.import_handler.foo, "bar")
|
||||
|
||||
def test_run(self):
|
||||
handler = self.make_handler(
|
||||
|
|
|
|||
23
tests/cli/test_export_wutta.py
Normal file
23
tests/cli/test_export_wutta.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
from unittest import TestCase
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from wuttasync.cli import export_wutta as mod, ImportCommandHandler
|
||||
|
||||
|
||||
class TestExportWutta(TestCase):
|
||||
|
||||
def test_basic(self):
|
||||
params = {
|
||||
"dbkey": "another",
|
||||
"models": [],
|
||||
"create": True,
|
||||
"update": True,
|
||||
"delete": False,
|
||||
"dry_run": True,
|
||||
}
|
||||
ctx = MagicMock(params=params)
|
||||
with patch.object(ImportCommandHandler, "run") as run:
|
||||
mod.export_wutta(ctx)
|
||||
run.assert_called_once_with(ctx)
|
||||
23
tests/cli/test_import_wutta.py
Normal file
23
tests/cli/test_import_wutta.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
from unittest import TestCase
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from wuttasync.cli import import_wutta as mod, ImportCommandHandler
|
||||
|
||||
|
||||
class TestImportWutta(TestCase):
|
||||
|
||||
def test_basic(self):
|
||||
params = {
|
||||
"dbkey": "another",
|
||||
"models": [],
|
||||
"create": True,
|
||||
"update": True,
|
||||
"delete": False,
|
||||
"dry_run": True,
|
||||
}
|
||||
ctx = MagicMock(params=params)
|
||||
with patch.object(ImportCommandHandler, "run") as run:
|
||||
mod.import_wutta(ctx)
|
||||
run.assert_called_once_with(ctx)
|
||||
|
|
@ -19,6 +19,17 @@ class TestImportHandler(DataTestCase):
|
|||
def make_handler(self, **kwargs):
|
||||
return mod.ImportHandler(self.config, **kwargs)
|
||||
|
||||
def test_constructor(self):
|
||||
|
||||
# attr missing by default
|
||||
handler = self.make_handler()
|
||||
self.assertFalse(hasattr(handler, "some_foo_attr"))
|
||||
|
||||
# but constructor can set it
|
||||
handler = self.make_handler(some_foo_attr="bar")
|
||||
self.assertTrue(hasattr(handler, "some_foo_attr"))
|
||||
self.assertEqual(handler.some_foo_attr, "bar")
|
||||
|
||||
def test_str(self):
|
||||
handler = self.make_handler()
|
||||
self.assertEqual(str(handler), "None → None")
|
||||
|
|
|
|||
|
|
@ -1,3 +1,134 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from wuttjamaican.testing import DataTestCase
|
||||
|
||||
from wuttasync.importing import wutta as mod
|
||||
from wuttasync.importing import ToWutta
|
||||
|
||||
|
||||
class TestFromWuttaMirror(DataTestCase):
|
||||
|
||||
def make_importer(self, **kwargs):
|
||||
return mod.FromWuttaMirror(self.config, **kwargs)
|
||||
|
||||
def test_basic(self):
|
||||
importer = self.make_importer()
|
||||
self.assertIsInstance(importer, mod.FromWuttaMirror)
|
||||
|
||||
|
||||
class TestFromWuttaToWuttaBase(DataTestCase):
|
||||
|
||||
def make_handler(self, **kwargs):
|
||||
return mod.FromWuttaToWuttaBase(self.config, **kwargs)
|
||||
|
||||
def test_dbkey(self):
|
||||
|
||||
# null by default
|
||||
handler = self.make_handler()
|
||||
self.assertIsNone(handler.dbkey)
|
||||
|
||||
# but caller can specify
|
||||
handler = self.make_handler(dbkey="another")
|
||||
self.assertEqual(handler.dbkey, "another")
|
||||
|
||||
def test_make_importer_factory(self):
|
||||
model = self.app.model
|
||||
handler = self.make_handler()
|
||||
|
||||
# returns a typical importer
|
||||
factory = handler.make_importer_factory(model.User, "User")
|
||||
self.assertTrue(issubclass(factory, mod.FromWuttaMirror))
|
||||
self.assertTrue(issubclass(factory, ToWutta))
|
||||
self.assertIs(factory.model_class, model.User)
|
||||
self.assertEqual(factory.__name__, "UserImporter")
|
||||
|
||||
def test_define_importers(self):
|
||||
handler = self.make_handler()
|
||||
|
||||
# all models are included
|
||||
importers = handler.define_importers()
|
||||
self.assertIn("Setting", importers)
|
||||
self.assertIn("Person", importers)
|
||||
self.assertIn("Role", importers)
|
||||
self.assertIn("Permission", importers)
|
||||
self.assertIn("User", importers)
|
||||
self.assertIn("UserRole", importers)
|
||||
self.assertIn("UserAPIToken", importers)
|
||||
self.assertIn("Upgrade", importers)
|
||||
self.assertNotIn("BatchMixin", importers)
|
||||
self.assertNotIn("BatchRowMixin", importers)
|
||||
self.assertNotIn("Base", importers)
|
||||
|
||||
# also, dependencies are implied by sort order
|
||||
models = list(importers)
|
||||
self.assertLess(models.index("Person"), models.index("User"))
|
||||
self.assertLess(models.index("User"), models.index("UserRole"))
|
||||
self.assertLess(models.index("User"), models.index("Upgrade"))
|
||||
|
||||
|
||||
class TestFromWuttaToWuttaImport(DataTestCase):
|
||||
|
||||
def make_handler(self, **kwargs):
|
||||
return mod.FromWuttaToWuttaImport(self.config, **kwargs)
|
||||
|
||||
def test_make_source_session(self):
|
||||
|
||||
# error if null dbkey
|
||||
handler = self.make_handler()
|
||||
self.assertIsNone(handler.dbkey)
|
||||
self.assertRaises(ValueError, handler.make_source_session)
|
||||
|
||||
# error if dbkey not found
|
||||
handler = self.make_handler(dbkey="another")
|
||||
self.assertEqual(handler.dbkey, "another")
|
||||
self.assertNotIn("another", self.config.appdb_engines)
|
||||
self.assertRaises(ValueError, handler.make_source_session)
|
||||
|
||||
# error if dbkey is 'default'
|
||||
handler = self.make_handler(dbkey="default")
|
||||
self.assertEqual(handler.dbkey, "default")
|
||||
self.assertIn("default", self.config.appdb_engines)
|
||||
self.assertRaises(ValueError, handler.make_source_session)
|
||||
|
||||
# expected behavior
|
||||
another_engine = sa.create_engine("sqlite://")
|
||||
handler = self.make_handler(dbkey="another")
|
||||
with patch.dict(self.config.appdb_engines, {"another": another_engine}):
|
||||
session = handler.make_source_session()
|
||||
self.assertIs(session.bind, another_engine)
|
||||
|
||||
|
||||
class TestFromWuttaToWuttaExport(DataTestCase):
|
||||
|
||||
def make_handler(self, **kwargs):
|
||||
return mod.FromWuttaToWuttaExport(self.config, **kwargs)
|
||||
|
||||
def test_make_target_session(self):
|
||||
|
||||
# error if null dbkey
|
||||
handler = self.make_handler()
|
||||
self.assertIsNone(handler.dbkey)
|
||||
self.assertRaises(ValueError, handler.make_target_session)
|
||||
|
||||
# error if dbkey not found
|
||||
handler = self.make_handler(dbkey="another")
|
||||
self.assertEqual(handler.dbkey, "another")
|
||||
self.assertNotIn("another", self.config.appdb_engines)
|
||||
self.assertRaises(ValueError, handler.make_target_session)
|
||||
|
||||
# error if dbkey is 'default'
|
||||
handler = self.make_handler(dbkey="default")
|
||||
self.assertEqual(handler.dbkey, "default")
|
||||
self.assertIn("default", self.config.appdb_engines)
|
||||
self.assertRaises(ValueError, handler.make_target_session)
|
||||
|
||||
# expected behavior
|
||||
another_engine = sa.create_engine("sqlite://")
|
||||
handler = self.make_handler(dbkey="another")
|
||||
with patch.dict(self.config.appdb_engines, {"another": another_engine}):
|
||||
session = handler.make_target_session()
|
||||
self.assertIs(session.bind, another_engine)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,18 @@ class TestWuttaSyncAppProvider(ConfigTestCase):
|
|||
self.assertIn(FromCsvToWutta, handlers)
|
||||
self.assertIn(FromFooToBar, handlers)
|
||||
|
||||
# now for something completely different..here we pretend there
|
||||
# are multiple handler entry points with same key. all should
|
||||
# be returned, including both which share the key.
|
||||
entry_points = {
|
||||
"import.to_baz.from_foo": [FromFooToBaz1, FromFooToBaz2],
|
||||
}
|
||||
with patch.object(mod, "load_entry_points", return_value=entry_points):
|
||||
handlers = self.app.get_all_import_handlers()
|
||||
self.assertEqual(len(handlers), 2)
|
||||
self.assertIn(FromFooToBaz1, handlers)
|
||||
self.assertIn(FromFooToBaz2, handlers)
|
||||
|
||||
def test_get_designated_import_handler_spec(self):
|
||||
|
||||
# fetch of unknown key returns none
|
||||
|
|
@ -139,6 +151,14 @@ class TestWuttaSyncAppProvider(ConfigTestCase):
|
|||
handler = self.app.get_import_handler("import.to_wutta.from_csv")
|
||||
self.assertIsInstance(handler, FromCsvToWutta)
|
||||
self.assertIsInstance(handler, FromCsvToPoser)
|
||||
self.assertFalse(hasattr(handler, "foo_attr"))
|
||||
|
||||
# can pass extra kwargs
|
||||
handler = self.app.get_import_handler(
|
||||
"import.to_wutta.from_csv", foo_attr="whatever"
|
||||
)
|
||||
self.assertTrue(hasattr(handler, "foo_attr"))
|
||||
self.assertEqual(handler.foo_attr, "whatever")
|
||||
|
||||
# unknown importer cannot be found
|
||||
handler = self.app.get_import_handler("bogus")
|
||||
|
|
|
|||
39
tests/test_conf.py
Normal file
39
tests/test_conf.py
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
from wuttjamaican.testing import ConfigTestCase
|
||||
|
||||
from wuttasync import conf as mod
|
||||
|
||||
|
||||
class TestWuttaSyncConfig(ConfigTestCase):
|
||||
|
||||
def make_extension(self):
|
||||
return mod.WuttaSyncConfig()
|
||||
|
||||
def test_default_import_handlers(self):
|
||||
|
||||
# base config has no default handlers
|
||||
spec = self.config.get(
|
||||
"wuttasync.importing.import.to_wutta.from_wutta.default_handler"
|
||||
)
|
||||
self.assertIsNone(spec)
|
||||
spec = self.config.get(
|
||||
"wuttasync.importing.export.to_wutta.from_wutta.default_handler"
|
||||
)
|
||||
self.assertIsNone(spec)
|
||||
|
||||
# extend config
|
||||
ext = self.make_extension()
|
||||
ext.configure(self.config)
|
||||
|
||||
# config now has default handlers
|
||||
spec = self.config.get(
|
||||
"wuttasync.importing.import.to_wutta.from_wutta.default_handler"
|
||||
)
|
||||
self.assertIsNotNone(spec)
|
||||
self.assertEqual(spec, "wuttasync.importing.wutta:FromWuttaToWuttaImport")
|
||||
spec = self.config.get(
|
||||
"wuttasync.importing.export.to_wutta.from_wutta.default_handler"
|
||||
)
|
||||
self.assertIsNotNone(spec)
|
||||
self.assertEqual(spec, "wuttasync.importing.wutta:FromWuttaToWuttaExport")
|
||||
|
|
@ -5,6 +5,7 @@ from wuttjamaican.testing import ConfigTestCase
|
|||
from wuttasync import emails as mod
|
||||
from wuttasync.importing import ImportHandler
|
||||
from wuttasync.testing import ImportExportWarningTestCase
|
||||
from wuttasync.conf import WuttaSyncConfig
|
||||
|
||||
|
||||
class FromFooToWutta(ImportHandler):
|
||||
|
|
@ -74,8 +75,21 @@ class TestImportExportWarning(ConfigTestCase):
|
|||
|
||||
class TestEmailSettings(ImportExportWarningTestCase):
|
||||
|
||||
def make_config(self, files=None, **kwargs):
|
||||
config = super().make_config(files, **kwargs)
|
||||
|
||||
# need this to ensure default import/export handlers. since
|
||||
# behavior can vary depending on what packages are installed.
|
||||
ext = WuttaSyncConfig()
|
||||
ext.configure(config)
|
||||
|
||||
return config
|
||||
|
||||
def test_import_to_versions_from_wutta_warning(self):
|
||||
self.do_test_preview("import_to_versions_from_wutta_warning")
|
||||
|
||||
def test_import_to_wutta_from_csv_warning(self):
|
||||
self.do_test_preview("import_to_wutta_from_csv_warning")
|
||||
|
||||
def test_import_to_wutta_from_wutta_warning(self):
|
||||
self.do_test_preview("import_to_wutta_from_wutta_warning")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue