Fixed neutron-db-manage without neutron/tests installed
With 7c0f189309
in tree, we made
neutron-db-manage require neutron/tests/tools.py installed. Some
distributions, like RDO, may split the python package into core package
and the one that contains python code needed for testing only (anything
under neutron/tests/), and hence don't guarantee that all setups have
neutron.tests package available.
This fix moves the import_module_recursively function from
neutron.tests.tools into neutron.common.utils because it has non-testing
use cases. All existing cases where we use the function switched to the
new location. The old symbol still works, though triggers a deprecation
warning, and will be removed in the next cycle.
Change-Id: Ia8d91a1704c894bc1f6cf14e6cdd971fab255b62
Closes-Bug: #1612959
This commit is contained in:
parent
ca0d752d81
commit
5925364c9a
@ -22,9 +22,11 @@ import collections
|
|||||||
import decimal
|
import decimal
|
||||||
import errno
|
import errno
|
||||||
import functools
|
import functools
|
||||||
|
import importlib
|
||||||
import math
|
import math
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
import os
|
import os
|
||||||
|
import os.path
|
||||||
import random
|
import random
|
||||||
import signal
|
import signal
|
||||||
import socket
|
import socket
|
||||||
@ -46,6 +48,7 @@ from oslo_utils import importutils
|
|||||||
import six
|
import six
|
||||||
from stevedore import driver
|
from stevedore import driver
|
||||||
|
|
||||||
|
import neutron
|
||||||
from neutron._i18n import _, _LE
|
from neutron._i18n import _, _LE
|
||||||
from neutron.db import api as db_api
|
from neutron.db import api as db_api
|
||||||
|
|
||||||
@ -693,3 +696,33 @@ def extract_exc_details(e):
|
|||||||
if args is _NO_ARGS_MARKER:
|
if args is _NO_ARGS_MARKER:
|
||||||
return details
|
return details
|
||||||
return details % args
|
return details % args
|
||||||
|
|
||||||
|
|
||||||
|
def import_modules_recursively(topdir):
|
||||||
|
'''Import and return all modules below the topdir directory.'''
|
||||||
|
modules = []
|
||||||
|
for root, dirs, files in os.walk(topdir):
|
||||||
|
for file_ in files:
|
||||||
|
if file_[-3:] != '.py':
|
||||||
|
continue
|
||||||
|
|
||||||
|
module = file_[:-3]
|
||||||
|
if module == '__init__':
|
||||||
|
continue
|
||||||
|
|
||||||
|
import_base = root.replace('/', '.')
|
||||||
|
|
||||||
|
# NOTE(ihrachys): in Python3, or when we are not located in the
|
||||||
|
# directory containing neutron code, __file__ is absolute, so we
|
||||||
|
# should truncate it to exclude PYTHONPATH prefix
|
||||||
|
prefixlen = len(os.path.dirname(neutron.__file__))
|
||||||
|
import_base = 'neutron' + import_base[prefixlen:]
|
||||||
|
|
||||||
|
module = '.'.join([import_base, module])
|
||||||
|
if module not in sys.modules:
|
||||||
|
importlib.import_module(module)
|
||||||
|
modules.append(module)
|
||||||
|
|
||||||
|
for dir_ in dirs:
|
||||||
|
modules.extend(import_modules_recursively(dir_))
|
||||||
|
return modules
|
||||||
|
@ -21,10 +21,9 @@ Based on this comparison database can be healed with healing migration.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# TODO(ihrachys): move the module under neutron/tests
|
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
|
from neutron.common import utils
|
||||||
from neutron.db import address_scope_db # noqa
|
from neutron.db import address_scope_db # noqa
|
||||||
from neutron.db import agents_db # noqa
|
from neutron.db import agents_db # noqa
|
||||||
from neutron.db import agentschedulers_db # noqa
|
from neutron.db import agentschedulers_db # noqa
|
||||||
@ -63,10 +62,9 @@ from neutron.plugins.ml2 import models as ml2_models # noqa
|
|||||||
from neutron.services.auto_allocate import models as aa_models # noqa
|
from neutron.services.auto_allocate import models as aa_models # noqa
|
||||||
from neutron.services.segments import db # noqa
|
from neutron.services.segments import db # noqa
|
||||||
from neutron.services.trunk import models as trunk_models # noqa
|
from neutron.services.trunk import models as trunk_models # noqa
|
||||||
from neutron.tests import tools
|
|
||||||
|
|
||||||
|
|
||||||
tools.import_modules_recursively(os.path.dirname(models.__file__))
|
utils.import_modules_recursively(os.path.dirname(models.__file__))
|
||||||
|
|
||||||
|
|
||||||
def get_metadata():
|
def get_metadata():
|
||||||
|
@ -14,15 +14,14 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import importlib
|
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
import sys
|
|
||||||
import time
|
import time
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
from debtcollector import moves
|
||||||
import fixtures
|
import fixtures
|
||||||
import mock
|
import mock
|
||||||
import netaddr
|
import netaddr
|
||||||
@ -30,10 +29,10 @@ from neutron_lib import constants
|
|||||||
import six
|
import six
|
||||||
import unittest2
|
import unittest2
|
||||||
|
|
||||||
import neutron
|
|
||||||
from neutron.api.v2 import attributes
|
from neutron.api.v2 import attributes
|
||||||
from neutron.common import constants as n_const
|
from neutron.common import constants as n_const
|
||||||
from neutron.common import ipv6_utils
|
from neutron.common import ipv6_utils
|
||||||
|
from neutron.common import utils
|
||||||
from neutron.db import common_db_mixin
|
from neutron.db import common_db_mixin
|
||||||
|
|
||||||
|
|
||||||
@ -132,9 +131,6 @@ class CommonDbMixinHooksFixture(fixtures.Fixture):
|
|||||||
common_db_mixin.CommonDbMixin._model_query_hooks = self.original_hooks
|
common_db_mixin.CommonDbMixin._model_query_hooks = self.original_hooks
|
||||||
|
|
||||||
|
|
||||||
from neutron.common import utils
|
|
||||||
|
|
||||||
|
|
||||||
def setup_mock_calls(mocked_call, expected_calls_and_values):
|
def setup_mock_calls(mocked_call, expected_calls_and_values):
|
||||||
"""A convenient method to setup a sequence of mock calls.
|
"""A convenient method to setup a sequence of mock calls.
|
||||||
|
|
||||||
@ -204,36 +200,6 @@ class UnorderedList(list):
|
|||||||
return not self == other
|
return not self == other
|
||||||
|
|
||||||
|
|
||||||
def import_modules_recursively(topdir):
|
|
||||||
'''Import and return all modules below the topdir directory.'''
|
|
||||||
modules = []
|
|
||||||
for root, dirs, files in os.walk(topdir):
|
|
||||||
for file_ in files:
|
|
||||||
if file_[-3:] != '.py':
|
|
||||||
continue
|
|
||||||
|
|
||||||
module = file_[:-3]
|
|
||||||
if module == '__init__':
|
|
||||||
continue
|
|
||||||
|
|
||||||
import_base = root.replace('/', '.')
|
|
||||||
|
|
||||||
# NOTE(ihrachys): in Python3, or when we are not located in the
|
|
||||||
# directory containing neutron code, __file__ is absolute, so we
|
|
||||||
# should truncate it to exclude PYTHONPATH prefix
|
|
||||||
prefixlen = len(os.path.dirname(neutron.__file__))
|
|
||||||
import_base = 'neutron' + import_base[prefixlen:]
|
|
||||||
|
|
||||||
module = '.'.join([import_base, module])
|
|
||||||
if module not in sys.modules:
|
|
||||||
importlib.import_module(module)
|
|
||||||
modules.append(module)
|
|
||||||
|
|
||||||
for dir_ in dirs:
|
|
||||||
modules.extend(import_modules_recursively(dir_))
|
|
||||||
return modules
|
|
||||||
|
|
||||||
|
|
||||||
def get_random_string(n=10):
|
def get_random_string(n=10):
|
||||||
return ''.join(random.choice(string.ascii_lowercase) for _ in range(n))
|
return ''.join(random.choice(string.ascii_lowercase) for _ in range(n))
|
||||||
|
|
||||||
@ -333,3 +299,8 @@ def reset_random_seed():
|
|||||||
|
|
||||||
def get_random_ipv6_mode():
|
def get_random_ipv6_mode():
|
||||||
return random.choice(n_const.IPV6_MODES)
|
return random.choice(n_const.IPV6_MODES)
|
||||||
|
|
||||||
|
|
||||||
|
import_modules_recursively = moves.moved_function(
|
||||||
|
utils.import_modules_recursively, 'import_modules_recursively', __name__,
|
||||||
|
version='Newton', removal_version='Ocata')
|
||||||
|
@ -13,7 +13,9 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import errno
|
import errno
|
||||||
|
import os.path
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
import eventlet
|
import eventlet
|
||||||
import mock
|
import mock
|
||||||
@ -30,6 +32,7 @@ from neutron.plugins.common import constants as p_const
|
|||||||
from neutron.plugins.common import utils as plugin_utils
|
from neutron.plugins.common import utils as plugin_utils
|
||||||
from neutron.tests import base
|
from neutron.tests import base
|
||||||
from neutron.tests.common import helpers
|
from neutron.tests.common import helpers
|
||||||
|
from neutron.tests.unit import tests
|
||||||
|
|
||||||
|
|
||||||
class TestParseMappings(base.BaseTestCase):
|
class TestParseMappings(base.BaseTestCase):
|
||||||
@ -778,3 +781,14 @@ class TestExcDetails(base.BaseTestCase):
|
|||||||
def test_extract_exc_details_no_details_attached(self):
|
def test_extract_exc_details_no_details_attached(self):
|
||||||
self.assertIsInstance(
|
self.assertIsInstance(
|
||||||
utils.extract_exc_details(Exception()), six.text_type)
|
utils.extract_exc_details(Exception()), six.text_type)
|
||||||
|
|
||||||
|
|
||||||
|
class ImportModulesRecursivelyTestCase(base.BaseTestCase):
|
||||||
|
|
||||||
|
def test_object_modules(self):
|
||||||
|
example_module = 'neutron.tests.unit.tests.example.dir.example_module'
|
||||||
|
sys.modules.pop(example_module, None)
|
||||||
|
modules = utils.import_modules_recursively(
|
||||||
|
os.path.dirname(tests.__file__))
|
||||||
|
self.assertIn(example_module, modules)
|
||||||
|
self.assertIn(example_module, sys.modules)
|
||||||
|
@ -18,9 +18,9 @@ import pprint
|
|||||||
from oslo_versionedobjects import base as obj_base
|
from oslo_versionedobjects import base as obj_base
|
||||||
from oslo_versionedobjects import fixture
|
from oslo_versionedobjects import fixture
|
||||||
|
|
||||||
|
from neutron.common import utils
|
||||||
from neutron import objects
|
from neutron import objects
|
||||||
from neutron.tests import base as test_base
|
from neutron.tests import base as test_base
|
||||||
from neutron.tests import tools
|
|
||||||
|
|
||||||
|
|
||||||
# NOTE: The hashes in this list should only be changed if they come with a
|
# NOTE: The hashes in this list should only be changed if they come with a
|
||||||
@ -55,7 +55,7 @@ class TestObjectVersions(test_base.BaseTestCase):
|
|||||||
super(TestObjectVersions, self).setUp()
|
super(TestObjectVersions, self).setUp()
|
||||||
# NOTE(ihrachys): seed registry with all objects under neutron.objects
|
# NOTE(ihrachys): seed registry with all objects under neutron.objects
|
||||||
# before validating the hashes
|
# before validating the hashes
|
||||||
tools.import_modules_recursively(os.path.dirname(objects.__file__))
|
utils.import_modules_recursively(os.path.dirname(objects.__file__))
|
||||||
|
|
||||||
def test_versions(self):
|
def test_versions(self):
|
||||||
checker = fixture.ObjectVersionChecker(
|
checker = fixture.ObjectVersionChecker(
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from neutron.tests import base
|
|
||||||
from neutron.tests import tools
|
|
||||||
from neutron.tests.unit import tests # noqa
|
|
||||||
|
|
||||||
|
|
||||||
EXAMPLE_MODULE = 'neutron.tests.unit.tests.example.dir.example_module'
|
|
||||||
|
|
||||||
|
|
||||||
class ImportModulesRecursivelyTestCase(base.BaseTestCase):
|
|
||||||
|
|
||||||
def test_object_modules(self):
|
|
||||||
sys.modules.pop(EXAMPLE_MODULE, None)
|
|
||||||
modules = tools.import_modules_recursively(
|
|
||||||
os.path.dirname(tests.__file__))
|
|
||||||
self.assertIn(
|
|
||||||
'neutron.tests.unit.tests.example.dir.example_module',
|
|
||||||
modules)
|
|
||||||
self.assertIn(EXAMPLE_MODULE, sys.modules)
|
|
Loading…
Reference in New Issue
Block a user