mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Reorganizing plugin unit tests and adding start of strategy tests (v2)
This commit is contained in:
parent
2e07567c16
commit
21fa385ce7
14 changed files with 339 additions and 5 deletions
|
@ -61,7 +61,6 @@ class StrategyBase:
|
||||||
self._inventory = tqm.get_inventory()
|
self._inventory = tqm.get_inventory()
|
||||||
self._workers = tqm.get_workers()
|
self._workers = tqm.get_workers()
|
||||||
self._notified_handlers = tqm.get_notified_handlers()
|
self._notified_handlers = tqm.get_notified_handlers()
|
||||||
#self._callback = tqm.get_callback()
|
|
||||||
self._variable_manager = tqm.get_variable_manager()
|
self._variable_manager = tqm.get_variable_manager()
|
||||||
self._loader = tqm.get_loader()
|
self._loader = tqm.get_loader()
|
||||||
self._final_q = tqm._final_q
|
self._final_q = tqm._final_q
|
||||||
|
@ -80,8 +79,6 @@ class StrategyBase:
|
||||||
num_failed = len(self._tqm._failed_hosts)
|
num_failed = len(self._tqm._failed_hosts)
|
||||||
num_unreachable = len(self._tqm._unreachable_hosts)
|
num_unreachable = len(self._tqm._unreachable_hosts)
|
||||||
|
|
||||||
#debug("running the cleanup portion of the play")
|
|
||||||
#result &= self.cleanup(iterator, connection_info)
|
|
||||||
debug("running handlers")
|
debug("running handlers")
|
||||||
result &= self.run_handlers(iterator, connection_info)
|
result &= self.run_handlers(iterator, connection_info)
|
||||||
|
|
||||||
|
@ -99,6 +96,7 @@ class StrategyBase:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def get_hosts_remaining(self, play):
|
def get_hosts_remaining(self, play):
|
||||||
|
print("inventory get hosts: %s" % self._inventory.get_hosts(play.hosts))
|
||||||
return [host for host in self._inventory.get_hosts(play.hosts) if host.name not in self._tqm._failed_hosts and host.name not in self._tqm._unreachable_hosts]
|
return [host for host in self._inventory.get_hosts(play.hosts) if host.name not in self._tqm._failed_hosts and host.name not in self._tqm._unreachable_hosts]
|
||||||
|
|
||||||
def get_failed_hosts(self, play):
|
def get_failed_hosts(self, play):
|
||||||
|
@ -119,13 +117,12 @@ class StrategyBase:
|
||||||
if self._cur_worker >= len(self._workers):
|
if self._cur_worker >= len(self._workers):
|
||||||
self._cur_worker = 0
|
self._cur_worker = 0
|
||||||
|
|
||||||
self._pending_results += 1
|
|
||||||
|
|
||||||
# create a dummy object with plugin loaders set as an easier
|
# create a dummy object with plugin loaders set as an easier
|
||||||
# way to share them with the forked processes
|
# way to share them with the forked processes
|
||||||
shared_loader_obj = SharedPluginLoaderObj()
|
shared_loader_obj = SharedPluginLoaderObj()
|
||||||
|
|
||||||
main_q.put((host, task, self._loader.get_basedir(), task_vars, connection_info, shared_loader_obj), block=False)
|
main_q.put((host, task, self._loader.get_basedir(), task_vars, connection_info, shared_loader_obj), block=False)
|
||||||
|
self._pending_results += 1
|
||||||
except (EOFError, IOError, AssertionError) as e:
|
except (EOFError, IOError, AssertionError) as e:
|
||||||
# most likely an abort
|
# most likely an abort
|
||||||
debug("got an error while queuing: %s" % e)
|
debug("got an error while queuing: %s" % e)
|
||||||
|
|
21
test/units/plugins/action/__init__.py
Normal file
21
test/units/plugins/action/__init__.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||||
|
#
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Make coding more python3-ish
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
21
test/units/plugins/cache/__init__.py
vendored
Normal file
21
test/units/plugins/cache/__init__.py
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||||
|
#
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Make coding more python3-ish
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
21
test/units/plugins/callback/__init__.py
Normal file
21
test/units/plugins/callback/__init__.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||||
|
#
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Make coding more python3-ish
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
21
test/units/plugins/connections/__init__.py
Normal file
21
test/units/plugins/connections/__init__.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||||
|
#
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Make coding more python3-ish
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
21
test/units/plugins/filter/__init__.py
Normal file
21
test/units/plugins/filter/__init__.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||||
|
#
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Make coding more python3-ish
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
21
test/units/plugins/inventory/__init__.py
Normal file
21
test/units/plugins/inventory/__init__.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||||
|
#
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Make coding more python3-ish
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
21
test/units/plugins/lookup/__init__.py
Normal file
21
test/units/plugins/lookup/__init__.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||||
|
#
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Make coding more python3-ish
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
21
test/units/plugins/shell/__init__.py
Normal file
21
test/units/plugins/shell/__init__.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||||
|
#
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Make coding more python3-ish
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
21
test/units/plugins/strategies/__init__.py
Normal file
21
test/units/plugins/strategies/__init__.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||||
|
#
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Make coding more python3-ish
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
127
test/units/plugins/strategies/test_strategy_base.py
Normal file
127
test/units/plugins/strategies/test_strategy_base.py
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||||
|
#
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Make coding more python3-ish
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
from ansible.compat.tests import unittest
|
||||||
|
from ansible.compat.tests.mock import patch, MagicMock
|
||||||
|
|
||||||
|
from ansible.plugins.strategies import StrategyBase
|
||||||
|
from ansible.executor.task_queue_manager import TaskQueueManager
|
||||||
|
|
||||||
|
from units.mock.loader import DictDataLoader
|
||||||
|
|
||||||
|
class TestVariableManager(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_strategy_base_init(self):
|
||||||
|
mock_tqm = MagicMock(TaskQueueManager)
|
||||||
|
mock_tqm._final_q = MagicMock()
|
||||||
|
strategy_base = StrategyBase(tqm=mock_tqm)
|
||||||
|
|
||||||
|
def test_strategy_base_run(self):
|
||||||
|
mock_tqm = MagicMock(TaskQueueManager)
|
||||||
|
mock_tqm._final_q = MagicMock()
|
||||||
|
mock_tqm._stats = MagicMock()
|
||||||
|
mock_tqm.send_callback.return_value = None
|
||||||
|
|
||||||
|
mock_iterator = MagicMock()
|
||||||
|
mock_iterator._play = MagicMock()
|
||||||
|
mock_iterator._play.handlers = []
|
||||||
|
|
||||||
|
mock_conn_info = MagicMock()
|
||||||
|
|
||||||
|
mock_tqm._failed_hosts = []
|
||||||
|
mock_tqm._unreachable_hosts = []
|
||||||
|
strategy_base = StrategyBase(tqm=mock_tqm)
|
||||||
|
|
||||||
|
self.assertEqual(strategy_base.run(iterator=mock_iterator, connection_info=mock_conn_info), 0)
|
||||||
|
self.assertEqual(strategy_base.run(iterator=mock_iterator, connection_info=mock_conn_info, result=False), 1)
|
||||||
|
mock_tqm._failed_hosts = ["host1"]
|
||||||
|
self.assertEqual(strategy_base.run(iterator=mock_iterator, connection_info=mock_conn_info, result=False), 2)
|
||||||
|
mock_tqm._unreachable_hosts = ["host1"]
|
||||||
|
self.assertEqual(strategy_base.run(iterator=mock_iterator, connection_info=mock_conn_info, result=False), 3)
|
||||||
|
|
||||||
|
def test_strategy_base_get_hosts(self):
|
||||||
|
mock_hosts = []
|
||||||
|
for i in range(0, 5):
|
||||||
|
mock_host = MagicMock()
|
||||||
|
mock_host.name = "host%02d" % (i+1)
|
||||||
|
mock_hosts.append(mock_host)
|
||||||
|
|
||||||
|
mock_inventory = MagicMock()
|
||||||
|
mock_inventory.get_hosts.return_value = mock_hosts
|
||||||
|
|
||||||
|
mock_tqm = MagicMock()
|
||||||
|
mock_tqm._final_q = MagicMock()
|
||||||
|
mock_tqm.get_inventory.return_value = mock_inventory
|
||||||
|
|
||||||
|
mock_play = MagicMock()
|
||||||
|
mock_play.hosts = ["host%02d" % (i+1) for i in range(0, 5)]
|
||||||
|
|
||||||
|
strategy_base = StrategyBase(tqm=mock_tqm)
|
||||||
|
|
||||||
|
mock_tqm._failed_hosts = []
|
||||||
|
mock_tqm._unreachable_hosts = []
|
||||||
|
self.assertEqual(strategy_base.get_hosts_remaining(play=mock_play), mock_hosts)
|
||||||
|
|
||||||
|
mock_tqm._failed_hosts = ["host01"]
|
||||||
|
self.assertEqual(strategy_base.get_hosts_remaining(play=mock_play), mock_hosts[1:])
|
||||||
|
self.assertEqual(strategy_base.get_failed_hosts(play=mock_play), [mock_hosts[0]])
|
||||||
|
|
||||||
|
mock_tqm._unreachable_hosts = ["host02"]
|
||||||
|
self.assertEqual(strategy_base.get_hosts_remaining(play=mock_play), mock_hosts[2:])
|
||||||
|
|
||||||
|
def test_strategy_base_queue_task(self):
|
||||||
|
fake_loader = DictDataLoader()
|
||||||
|
|
||||||
|
workers = []
|
||||||
|
for i in range(0, 3):
|
||||||
|
worker_main_q = MagicMock()
|
||||||
|
worker_main_q.put.return_value = None
|
||||||
|
worker_result_q = MagicMock()
|
||||||
|
workers.append([i, worker_main_q, worker_result_q])
|
||||||
|
|
||||||
|
mock_tqm = MagicMock()
|
||||||
|
mock_tqm._final_q = MagicMock()
|
||||||
|
mock_tqm.get_workers.return_value = workers
|
||||||
|
mock_tqm.get_loader.return_value = fake_loader
|
||||||
|
|
||||||
|
strategy_base = StrategyBase(tqm=mock_tqm)
|
||||||
|
strategy_base._cur_worker = 0
|
||||||
|
strategy_base._pending_results = 0
|
||||||
|
strategy_base._queue_task(host=MagicMock(), task=MagicMock(), task_vars=dict(), connection_info=MagicMock())
|
||||||
|
self.assertEqual(strategy_base._cur_worker, 1)
|
||||||
|
self.assertEqual(strategy_base._pending_results, 1)
|
||||||
|
strategy_base._queue_task(host=MagicMock(), task=MagicMock(), task_vars=dict(), connection_info=MagicMock())
|
||||||
|
self.assertEqual(strategy_base._cur_worker, 2)
|
||||||
|
self.assertEqual(strategy_base._pending_results, 2)
|
||||||
|
strategy_base._queue_task(host=MagicMock(), task=MagicMock(), task_vars=dict(), connection_info=MagicMock())
|
||||||
|
self.assertEqual(strategy_base._cur_worker, 0)
|
||||||
|
self.assertEqual(strategy_base._pending_results, 3)
|
||||||
|
workers[0][1].put.side_effect = EOFError
|
||||||
|
strategy_base._queue_task(host=MagicMock(), task=MagicMock(), task_vars=dict(), connection_info=MagicMock())
|
||||||
|
self.assertEqual(strategy_base._cur_worker, 1)
|
||||||
|
self.assertEqual(strategy_base._pending_results, 3)
|
||||||
|
|
21
test/units/plugins/vars/__init__.py
Normal file
21
test/units/plugins/vars/__init__.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||||
|
#
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Make coding more python3-ish
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
Loading…
Reference in a new issue