[SEBA-450] (part 2)

Add tox testing support on additional XOS library modules:

- xos-api
- xos-kafka (has no tests)
- xos-migrate (has no tests)
- xos-synchronizer

Change-Id: I98195bc9747971d3515882d517affe058dd86ac5
diff --git a/lib/xos-synchronizer/xos-synchronizer-tests/test_diffs.py b/lib/xos-synchronizer/xos-synchronizer-tests/test_diffs.py
index 9e09c0f..9e0b9d9 100644
--- a/lib/xos-synchronizer/xos-synchronizer-tests/test_diffs.py
+++ b/lib/xos-synchronizer/xos-synchronizer-tests/test_diffs.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import
 import unittest
 from mock import patch, call, Mock, PropertyMock
 import json
@@ -24,6 +25,7 @@
 xos_dir = os.path.join(test_path, "..", "..", "..", "xos")
 services_dir = os.path.join(xos_dir, "../../xos_services")
 
+
 class TestDiffs(unittest.TestCase):
 
     """ These tests are for the mock modelaccessor, to make sure it behaves like the real one """
@@ -39,9 +41,7 @@
         Config.init(config, "synchronizer-config-schema.yaml")
         # END Setting up the config module
 
-        from xossynchronizer.mock_modelaccessor_build import (
-            build_mock_modelaccessor,
-        )
+        from xossynchronizer.mock_modelaccessor_build import build_mock_modelaccessor
 
         # FIXME this is to get jenkins to pass the tests, somehow it is running tests in a different order
         # and apparently it is not overriding the generated model accessor
@@ -52,9 +52,7 @@
         for (
             k,
             v,
-        ) in (
-            xossynchronizer.modelaccessor.model_accessor.all_model_classes.items()
-        ):
+        ) in xossynchronizer.modelaccessor.model_accessor.all_model_classes.items():
             globals()[k] = v
 
         self.log = Mock()
@@ -68,7 +66,7 @@
         self.assertEqual(site.is_new, True)
         self.assertEqual(site._dict, {"name": "mysite"})
         self.assertEqual(site.diff, {})
-        self.assertEqual(site.changed_fields, ["name"])
+        self.assertEqual(list(site.changed_fields), ["name"])
         self.assertEqual(site.has_field_changed("name"), False)
         self.assertEqual(site.has_field_changed("login_base"), False)
 
@@ -93,7 +91,7 @@
         self.assertEqual(site.is_new, False)
         self.assertEqual(site._dict, {"id": 1, "name": "mysite", "login_base": "foo"})
         self.assertEqual(site.diff, {})
-        self.assertEqual(site.changed_fields, [])
+        self.assertEqual(list(site.changed_fields), [])
         self.assertEqual(site.has_field_changed("name"), False)
         self.assertEqual(site.has_field_changed("login_base"), False)
 
diff --git a/lib/xos-synchronizer/xos-synchronizer-tests/test_event_engine.py b/lib/xos-synchronizer/xos-synchronizer-tests/test_event_engine.py
index bc1cb97..352c7e3 100644
--- a/lib/xos-synchronizer/xos-synchronizer-tests/test_event_engine.py
+++ b/lib/xos-synchronizer/xos-synchronizer-tests/test_event_engine.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import, print_function
 import confluent_kafka
 import functools
 import unittest
@@ -28,7 +29,7 @@
 sync_lib_dir = os.path.join(test_path, "..", "xossynchronizer")
 xos_dir = os.path.join(test_path, "..", "..", "..", "xos")
 
-print os.getcwd()
+print(os.getcwd())
 
 def config_get_mock(orig, overrides, key):
     if key in overrides:
diff --git a/lib/xos-synchronizer/xos-synchronizer-tests/test_event_steps/event_step.py b/lib/xos-synchronizer/xos-synchronizer-tests/test_event_steps/event_step.py
index 372d6d3..77402ba 100644
--- a/lib/xos-synchronizer/xos-synchronizer-tests/test_event_steps/event_step.py
+++ b/lib/xos-synchronizer/xos-synchronizer-tests/test_event_steps/event_step.py
@@ -13,6 +13,7 @@
 # limitations under the License.
 
 from __future__ import print_function
+from __future__ import absolute_import
 from xossynchronizer.event_steps.eventstep import EventStep
 from mock_modelaccessor import *
 
diff --git a/lib/xos-synchronizer/xos-synchronizer-tests/test_load.py b/lib/xos-synchronizer/xos-synchronizer-tests/test_load.py
index 774bc97..73ea213 100644
--- a/lib/xos-synchronizer/xos-synchronizer-tests/test_load.py
+++ b/lib/xos-synchronizer/xos-synchronizer-tests/test_load.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import
 import unittest
 from mock import patch
 import mock
@@ -21,6 +22,12 @@
 import os
 import sys
 
+try:
+    # Python 2: "reload" is built-in
+    reload  # pylint: disable=reload-builtin
+except NameError:
+    from importlib import reload
+
 test_path = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
 sync_lib_dir = os.path.join(test_path, "..", "xossynchronizer")
 xos_dir = os.path.join(test_path, "..", "..", "..", "xos")
@@ -77,10 +84,8 @@
         self.synchronizer.load_sync_steps()
         model_to_step = self.synchronizer.model_to_step
         step_lookup = self.synchronizer.step_lookup
-        self.assertIn(
-            ("Port", ["SyncPort"]), model_to_step.items()
-        )
-        self.assertIn(("Image", ["SyncImages"]), model_to_step.items())
+        self.assertIn(("Port", ["SyncPort"]), list(model_to_step.items()))
+        self.assertIn(("Image", ["SyncImages"]), list(model_to_step.items()))
 
         for k, v in model_to_step.items():
             val = v[0]
diff --git a/lib/xos-synchronizer/xos-synchronizer-tests/test_loadmodels.py b/lib/xos-synchronizer/xos-synchronizer-tests/test_loadmodels.py
index 6353104..ddb88f3 100644
--- a/lib/xos-synchronizer/xos-synchronizer-tests/test_loadmodels.py
+++ b/lib/xos-synchronizer/xos-synchronizer-tests/test_loadmodels.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import
 import unittest
 from mock import patch, Mock, MagicMock
 
@@ -20,6 +21,15 @@
 import os
 import sys
 
+# Python 3 renamed __builtin__ -> builtins
+# py_builtins is used to help with mocking 'open'
+try:
+    import builtins
+    py_builtins = "builtins"
+except ImportError:
+    import __builtin__ as builtins
+    py_builtins = "__builtin__"
+
 test_path = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
 
 
@@ -30,7 +40,7 @@
 
 def mock_exists(file_map, fn):
     """ mock os.path.exists() """
-    return (fn in file_map)
+    return fn in file_map
 
 
 def mock_open(orig_open, file_map, fn, *args, **kwargs):
@@ -79,6 +89,7 @@
 
         from xossynchronizer import loadmodels
         from xossynchronizer.loadmodels import ModelLoadClient
+
         self.loadmodels = loadmodels
 
         self.api = MagicMock()
@@ -90,22 +101,31 @@
         os.chdir(self.cwd_save)
 
     def test_upload_models(self):
-        dir_map = {"models_dir": ["models.xproto", "models.py"],
-                   "models_dir/convenience": ["convenience1.py"],
-                   "models_dir/../migrations": ["migration1.py", "migration2.py"]}
+        dir_map = {
+            "models_dir": ["models.xproto", "models.py"],
+            "models_dir/convenience": ["convenience1.py"],
+            "models_dir/../migrations": ["migration1.py", "migration2.py"],
+        }
 
-        file_map = {"models_dir/models.xproto": u"some xproto",
-                    "models_dir/models.py": u"print `python models file`",
-                    "models_dir/convenience": u"directory",
-                    "models_dir/convenience/convenience1.py": u"print `python convenience file`",
-                    "models_dir/../migrations": u"directory",
-                    "models_dir/../migrations/migration1.py": u"print `first migration`",
-                    "models_dir/../migrations/migration2.py": u"print `second migration`"}
+        file_map = {
+            "models_dir/models.xproto": u"some xproto",
+            "models_dir/models.py": u"print `python models file`",
+            "models_dir/convenience": u"directory",
+            "models_dir/convenience/convenience1.py": u"print `python convenience file`",
+            "models_dir/../migrations": u"directory",
+            "models_dir/../migrations/migration1.py": u"print `first migration`",
+            "models_dir/../migrations/migration2.py": u"print `second migration`",
+        }
 
-        orig_open = open
-        with patch("os.listdir", side_effect=functools.partial(mock_listdir, dir_map)), \
-                patch("os.path.exists", side_effect=functools.partial(mock_exists, file_map)), \
-                patch("__builtin__.open", side_effect=functools.partial(mock_open, orig_open, file_map)):
+        orig_open = builtins.open
+        with patch(
+            "os.listdir", side_effect=functools.partial(mock_listdir, dir_map)
+        ), patch(
+            "os.path.exists", side_effect=functools.partial(mock_exists, file_map)
+        ), patch(
+            py_builtins + ".open",
+            side_effect=functools.partial(mock_open, orig_open, file_map),
+        ):
             self.loader.upload_models("myservice", "models_dir", "1.2")
 
             request = self.api.dynamicload.LoadModels.call_args[0][0]
@@ -118,17 +138,28 @@
 
             self.assertEqual(len(request.decls.items), 1)
             self.assertEqual(request.decls.items[0].filename, "models.py")
-            self.assertEqual(request.decls.items[0].contents, u"print `python models file`")
+            self.assertEqual(
+                request.decls.items[0].contents, u"print `python models file`"
+            )
 
             self.assertEqual(len(request.convenience_methods.items), 1)
-            self.assertEqual(request.convenience_methods.items[0].filename, "convenience1.py")
-            self.assertEqual(request.convenience_methods.items[0].contents, u"print `python convenience file`")
+            self.assertEqual(
+                request.convenience_methods.items[0].filename, "convenience1.py"
+            )
+            self.assertEqual(
+                request.convenience_methods.items[0].contents,
+                u"print `python convenience file`",
+            )
 
             self.assertEqual(len(request.migrations.items), 2)
             self.assertEqual(request.migrations.items[0].filename, "migration1.py")
-            self.assertEqual(request.migrations.items[0].contents, u"print `first migration`")
+            self.assertEqual(
+                request.migrations.items[0].contents, u"print `first migration`"
+            )
             self.assertEqual(request.migrations.items[1].filename, "migration2.py")
-            self.assertEqual(request.migrations.items[1].contents, u"print `second migration`")
+            self.assertEqual(
+                request.migrations.items[1].contents, u"print `second migration`"
+            )
 
 
 if __name__ == "__main__":
diff --git a/lib/xos-synchronizer/xos-synchronizer-tests/test_run.py b/lib/xos-synchronizer/xos-synchronizer-tests/test_run.py
index a9c6c19..f21428e 100644
--- a/lib/xos-synchronizer/xos-synchronizer-tests/test_run.py
+++ b/lib/xos-synchronizer/xos-synchronizer-tests/test_run.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import
 import json
 import unittest
 import mock
@@ -19,6 +20,12 @@
 import os
 import sys
 
+try:
+    # Python 2: "reload" is built-in
+    reload  # pylint: disable=reload-builtin
+except NameError:
+    from importlib import reload
+
 test_path = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
 sync_lib_dir = os.path.join(test_path, "..", "xossynchronizer")
 xos_dir = os.path.join(test_path, "..", "..", "..", "xos")
@@ -47,13 +54,15 @@
         Config.clear()
         Config.init(config, "synchronizer-config-schema.yaml")
 
-        from xossynchronizer.mock_modelaccessor_build import (
-            build_mock_modelaccessor,
+        from xossynchronizer.mock_modelaccessor_build import build_mock_modelaccessor
+
+        build_mock_modelaccessor(
+            sync_lib_dir, xos_dir, services_dir=None, service_xprotos=[]
         )
 
-        build_mock_modelaccessor(sync_lib_dir, xos_dir, services_dir=None, service_xprotos=[])
-
-        os.chdir(os.path.join(test_path, ".."))  # config references xos-synchronizer-tests/model-deps
+        os.chdir(
+            os.path.join(test_path, "..")
+        )  # config references xos-synchronizer-tests/model-deps
 
         import xossynchronizer.event_loop
 
@@ -72,7 +81,9 @@
         b = xossynchronizer.backend.Backend(model_accessor=model_accessor)
         steps_dir = Config.get("steps_dir")
         self.steps = b.load_sync_step_modules(steps_dir)
-        self.synchronizer = xossynchronizer.event_loop.XOSObserver(self.steps, model_accessor)
+        self.synchronizer = xossynchronizer.event_loop.XOSObserver(
+            self.steps, model_accessor
+        )
         try:
             os.remove("/tmp/sync_ports")
         except OSError:
diff --git a/lib/xos-synchronizer/xos-synchronizer-tests/test_scheduler.py b/lib/xos-synchronizer/xos-synchronizer-tests/test_scheduler.py
index 0aa5334..1dc8fdf 100644
--- a/lib/xos-synchronizer/xos-synchronizer-tests/test_scheduler.py
+++ b/lib/xos-synchronizer/xos-synchronizer-tests/test_scheduler.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import
 import unittest
 from mock import patch
 import mock
@@ -21,12 +22,18 @@
 import os
 import sys
 
+try:
+    # Python 2: "reload" is built-in
+    reload  # pylint: disable=reload-builtin
+except NameError:
+    from importlib import reload
+
 test_path = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
 sync_lib_dir = os.path.join(test_path, "..", "xossynchronizer")
 xos_dir = os.path.join(test_path, "..", "..", "..", "xos")
 
-class TestScheduling(unittest.TestCase):
 
+class TestScheduling(unittest.TestCase):
     def setUp(self):
         global mock_enumerator, event_loop
 
@@ -39,15 +46,18 @@
         Config.clear()
         Config.init(config, "synchronizer-config-schema.yaml")
 
-        from xossynchronizer.mock_modelaccessor_build import (
-            build_mock_modelaccessor,
+        from xossynchronizer.mock_modelaccessor_build import build_mock_modelaccessor
+
+        build_mock_modelaccessor(
+            sync_lib_dir, xos_dir, services_dir=None, service_xprotos=[]
         )
 
-        build_mock_modelaccessor(sync_lib_dir, xos_dir, services_dir=None, service_xprotos=[])
-
-        os.chdir(os.path.join(test_path, ".."))  # config references xos-synchronizer-tests/model-deps
+        os.chdir(
+            os.path.join(test_path, "..")
+        )  # config references xos-synchronizer-tests/model-deps
 
         import xossynchronizer.event_loop
+
         event_loop = xossynchronizer.event_loop
 
         reload(xossynchronizer.event_loop)
@@ -64,7 +74,9 @@
         b = xossynchronizer.backend.Backend(model_accessor=model_accessor)
         steps_dir = Config.get("steps_dir")
         self.steps = b.load_sync_step_modules(steps_dir)
-        self.synchronizer = xossynchronizer.event_loop.XOSObserver(self.steps, model_accessor)
+        self.synchronizer = xossynchronizer.event_loop.XOSObserver(
+            self.steps, model_accessor
+        )
 
     def tearDown(self):
         sys.path = self.sys_path_save
@@ -106,6 +118,7 @@
         self.assertTrue(verdict)
         self.assertEqual(edge_type, event_loop.DIRECT_EDGE)
 
+
     def test_concrete_object_path_distant(self):
         p = ComputeServiceInstance()
         s = Slice()
diff --git a/lib/xos-synchronizer/xos-synchronizer-tests/test_services.py b/lib/xos-synchronizer/xos-synchronizer-tests/test_services.py
index 3ff1c43..96fd534 100644
--- a/lib/xos-synchronizer/xos-synchronizer-tests/test_services.py
+++ b/lib/xos-synchronizer/xos-synchronizer-tests/test_services.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import
 import unittest
 from mock import patch
 import mock
@@ -21,6 +22,12 @@
 import os
 import sys
 
+try:
+    # Python 2: "reload" is built-in
+    reload  # pylint: disable=reload-builtin
+except NameError:
+    from importlib import reload
+
 test_path = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
 sync_lib_dir = os.path.join(test_path, "..", "xossynchronizer")
 xos_dir = os.path.join(test_path, "..", "..", "..", "xos")
@@ -37,13 +44,15 @@
         Config.clear()
         Config.init(config, "synchronizer-config-schema.yaml")
 
-        from xossynchronizer.mock_modelaccessor_build import (
-            build_mock_modelaccessor,
+        from xossynchronizer.mock_modelaccessor_build import build_mock_modelaccessor
+
+        build_mock_modelaccessor(
+            sync_lib_dir, xos_dir, services_dir=None, service_xprotos=[]
         )
 
-        build_mock_modelaccessor(sync_lib_dir, xos_dir, services_dir=None, service_xprotos=[])
-
-        os.chdir(os.path.join(test_path, ".."))  # config references xos-synchronizer-tests/model-deps
+        os.chdir(
+            os.path.join(test_path, "..")
+        )  # config references xos-synchronizer-tests/model-deps
 
         import xossynchronizer.event_loop
 
@@ -60,7 +69,9 @@
         b = xossynchronizer.backend.Backend(model_accessor=model_accessor)
         steps_dir = Config.get("steps_dir")
         self.steps = b.load_sync_step_modules(steps_dir)
-        self.synchronizer = xossynchronizer.event_loop.XOSObserver(self.steps, model_accessor)
+        self.synchronizer = xossynchronizer.event_loop.XOSObserver(
+            self.steps, model_accessor
+        )
 
     def tearDown(self):
         sys.path = self.sys_path_save
diff --git a/lib/xos-synchronizer/xos-synchronizer-tests/test_steps/sync_images.py b/lib/xos-synchronizer/xos-synchronizer-tests/test_steps/sync_images.py
index b3ed9bd..2ed1e40 100644
--- a/lib/xos-synchronizer/xos-synchronizer-tests/test_steps/sync_images.py
+++ b/lib/xos-synchronizer/xos-synchronizer-tests/test_steps/sync_images.py
@@ -13,8 +13,10 @@
 # limitations under the License.
 
 
+from __future__ import absolute_import
 from xossynchronizer.steps.syncstep import SyncStep
 
+
 class SyncImages(SyncStep):
     requested_interval = 0
     observes = ["Image"]
diff --git a/lib/xos-synchronizer/xos-synchronizer-tests/test_steps/sync_ports.py b/lib/xos-synchronizer/xos-synchronizer-tests/test_steps/sync_ports.py
index a7eb7d1..1fbbbf5 100644
--- a/lib/xos-synchronizer/xos-synchronizer-tests/test_steps/sync_ports.py
+++ b/lib/xos-synchronizer/xos-synchronizer-tests/test_steps/sync_ports.py
@@ -13,6 +13,7 @@
 # limitations under the License.
 
 
+from __future__ import absolute_import
 import os
 import base64
 from xossynchronizer.steps.syncstep import SyncStep