Pass mypy type verifications

Change-Id: If5b0a9902bd3cb65068541dce0cfe1ce35b72afb
This commit is contained in:
Federico Ressi 2019-11-02 18:14:37 +01:00
parent f4658cbfb9
commit 3afec15af3
17 changed files with 92 additions and 91 deletions

View File

@ -52,11 +52,11 @@ class TobikoException(Exception):
:attribute message: the message to be printed out. :attribute message: the message to be printed out.
""" """
message = None message = "unknown reason"
def __init__(self, message=None, **properties): def __init__(self, message=None, **properties):
# pylint: disable=exception-message-attribute # pylint: disable=exception-message-attribute
message = message or self.message or "unknown reason" message = message or self.message
if properties: if properties:
message = message.format(**properties) message = message.format(**properties)
self.message = message self.message = message

View File

@ -54,7 +54,8 @@ class Selection(list):
return '{!s}({!r})'.format(type(self).__name__, list(self)) return '{!s}({!r})'.format(type(self).__name__, list(self))
select = Selection.create def select(objects):
return Selection.create(objects)
def filter_by_attributes(objects, exclude=False, **attributes): def filter_by_attributes(objects, exclude=False, **attributes):

View File

@ -16,13 +16,14 @@ from __future__ import absolute_import
import functools import functools
import inspect import inspect
import unittest import unittest
import typing # noqa
import testtools import testtools
from tobiko.common import _fixture from tobiko.common import _fixture
SkipException = testtools.TestCase.skipException SkipException = testtools.TestCase.skipException # type: typing.Type
def skip(reason, *args, **kwargs): def skip(reason, *args, **kwargs):

View File

@ -17,6 +17,7 @@ import importlib
import itertools import itertools
import logging import logging
import os import os
import typing # noqa
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log from oslo_log import log
@ -82,7 +83,7 @@ class GlobalConfig(object):
# this is a singletone # this is a singletone
_instance = None _instance = None
_sources = {} _sources = {} # type: typing.Dict[str, typing.Any]
def __new__(cls): def __new__(cls):
if cls._instance is None: if cls._instance is None:

View File

@ -42,10 +42,10 @@ def setup_http_session(session, ssh_client=None):
# All known keyword arguments that could be provided to the pool manager, its # All known keyword arguments that could be provided to the pool manager, its
# pools, or the underlying connections. This is used to construct a pool key. # pools, or the underlying connections. This is used to construct a pool key.
_key_fields = poolmanager._key_fields + ('key_ssh_client',) _key_fields = tuple(poolmanager._key_fields) + ('key_ssh_client',)
class PoolKey(collections.namedtuple("PoolKey", _key_fields)): class PoolKey(collections.namedtuple("PoolKey", _key_fields)): # type: ignore
"""The namedtuple class used to construct keys for the connection pool. """The namedtuple class used to construct keys for the connection pool.
All custom key schemes should include the fields in this key at a minimum. All custom key schemes should include the fields in this key at a minimum.

View File

@ -70,9 +70,9 @@ class GlanceImageStatus(object):
class GlanceImageFixture(tobiko.SharedFixture): class GlanceImageFixture(tobiko.SharedFixture):
client = None client = None
image_name = None image_name = None # type: str
username = None username = None # type: str
password = None password = None # type: str
image = None image = None
wait_interval = 5. wait_interval = 5.
@ -319,7 +319,7 @@ class FileGlanceImageFixture(UploadGranceImageFixture):
class URLGlanceImageFixture(FileGlanceImageFixture): class URLGlanceImageFixture(FileGlanceImageFixture):
image_url = None image_url = None # type: str
def __init__(self, image_url=None, **kwargs): def __init__(self, image_url=None, **kwargs):
super(URLGlanceImageFixture, self).__init__(**kwargs) super(URLGlanceImageFixture, self).__init__(**kwargs)

View File

@ -30,3 +30,4 @@ HeatTemplateFixture = _template.HeatTemplateFixture
HeatTemplateFileFixture = _template.HeatTemplateFileFixture HeatTemplateFileFixture = _template.HeatTemplateFileFixture
HeatStackFixture = _stack.HeatStackFixture HeatStackFixture = _stack.HeatStackFixture
heat_stack_parameters = _stack.heat_stack_parameters

View File

@ -15,6 +15,7 @@ from __future__ import absolute_import
import collections import collections
import time import time
import typing # noqa
from heatclient import exc from heatclient import exc
from oslo_log import log from oslo_log import log
@ -42,15 +43,17 @@ DELETE_FAILED = 'DELETE_FAILED'
TEMPLATE_FILE_SUFFIX = '.yaml' TEMPLATE_FILE_SUFFIX = '.yaml'
def _stack_parameters(obj, stack=None): def heat_stack_parameters(obj, stack=None):
if obj is None or isinstance(obj, collections.Mapping): if isinstance(obj, HeatStackParametersFixture):
parameters = obj
elif obj is None or isinstance(obj, collections.Mapping):
parameters = HeatStackParametersFixture(stack, obj) parameters = HeatStackParametersFixture(stack, obj)
else: else:
parameters = tobiko.get_fixture(obj) parameters = tobiko.get_fixture(obj)
if not isinstance(parameters, HeatStackParametersFixture): tobiko.check_valid_type(parameters, HeatStackParametersFixture)
msg = "Object {!r} is not an HeatStackParametersFixture".format( if stack:
parameters) parameters.stack = parameters.stack or stack
raise TypeError(msg) tobiko.check_valid_type(parameters.stack, type(None), HeatStackFixture)
return parameters return parameters
@ -60,10 +63,10 @@ class HeatStackFixture(tobiko.SharedFixture):
client = None client = None
retry_create_stack = 1 retry_create_stack = 1
wait_interval = 5 wait_interval = 5
stack_name = None stack_name = None # type: str
template = None template = None # type: _template.HeatTemplateFixture
stack = None stack = None
parameters = None parameters = None # type: HeatStackParametersFixture
def __init__(self, stack_name=None, template=None, parameters=None, def __init__(self, stack_name=None, template=None, parameters=None,
wait_interval=None, client=None): wait_interval=None, client=None):
@ -73,7 +76,7 @@ class HeatStackFixture(tobiko.SharedFixture):
self.fixture_name) self.fixture_name)
self.template = _template.heat_template(template or self.template) self.template = _template.heat_template(template or self.template)
self.parameters = _stack_parameters( self.parameters = heat_stack_parameters(
stack=self, obj=(parameters or self.parameters)) stack=self, obj=(parameters or self.parameters))
self.client = client or self.client self.client = client or self.client
if config.get_bool_env('TOBIKO_PREVENT_CREATE'): if config.get_bool_env('TOBIKO_PREVENT_CREATE'):
@ -282,7 +285,7 @@ class HeatStackNamespaceFixture(tobiko.SharedFixture):
def __init__(self, stack): def __init__(self, stack):
super(HeatStackNamespaceFixture, self).__init__() super(HeatStackNamespaceFixture, self).__init__()
if not isinstance(stack, HeatStackFixture): if stack and not isinstance(stack, HeatStackFixture):
message = "Object {!r} is not an HeatStackFixture".format(stack) message = "Object {!r} is not an HeatStackFixture".format(stack)
raise TypeError(message) raise TypeError(message)
self.stack = stack self.stack = stack

View File

@ -16,6 +16,7 @@ from __future__ import absolute_import
import collections import collections
import os import os
import sys import sys
import typing # noqa
from heatclient.common import template_utils from heatclient.common import template_utils
import yaml import yaml
@ -30,7 +31,7 @@ TEMPLATE_DIRS = list(sys.path)
class HeatTemplateFixture(tobiko.SharedFixture): class HeatTemplateFixture(tobiko.SharedFixture):
template = None template = None # type: typing.Dict[str, typing.Any]
template_files = None template_files = None
template_yaml = None template_yaml = None
@ -68,8 +69,6 @@ class HeatTemplateFileFixture(HeatTemplateFixture):
template_file = None template_file = None
template_dirs = None template_dirs = None
template_files = None template_files = None
template = None
template_yaml = None
def __init__(self, template_file=None, template_dirs=None): def __init__(self, template_file=None, template_dirs=None):
super(HeatTemplateFileFixture, self).__init__() super(HeatTemplateFileFixture, self).__init__()

View File

@ -30,10 +30,8 @@ JSON_SUFFIXES = ('.json',)
CLOUDS_FILE_SUFFIXES = JSON_SUFFIXES + YAML_SUFFIXES CLOUDS_FILE_SUFFIXES = JSON_SUFFIXES + YAML_SUFFIXES
try: class CloudsFileNotFoundError(tobiko.TobikoException):
FileNotFound = FileNotFoundError message = "No such clouds file(s): {clouds_files!s}"
except NameError:
FileNotFound = OSError
class DefaultCloudsFileConfig(tobiko.SharedFixture): class DefaultCloudsFileConfig(tobiko.SharedFixture):
@ -198,22 +196,18 @@ class CloudsFileKeystoneCredentialsFixture(
def _get_clouds_file(self): def _get_clouds_file(self):
clouds_file = self.clouds_file clouds_file = self.clouds_file
if not clouds_file: if clouds_file:
clouds_files = self.clouds_files clouds_files = [self.clouds_file]
for filename in clouds_files: else:
if os.path.exists(filename): clouds_files = list(self.clouds_files)
LOG.debug('Found clouds file at %r', filename)
self.clouds_file = clouds_file = filename
break
else:
message = 'No such clouds file: {!s}'.format(
', '.join(repr(f) for f in clouds_files))
raise FileNotFound(message)
if not os.path.exists(clouds_file):
message = 'Cloud file not found: {!r}'.format(clouds_file)
raise FileNotFound(message)
for filename in clouds_files:
if os.path.exists(filename):
LOG.debug('Found clouds file at %r', filename)
self.clouds_file = clouds_file = filename
break
else:
raise CloudsFileNotFoundError(clouds_files=', '.join(clouds_files))
return clouds_file return clouds_file

View File

@ -16,6 +16,7 @@
from __future__ import absolute_import from __future__ import absolute_import
import os import os
import typing # noqa
import six import six
@ -118,7 +119,7 @@ class ServerStackFixture(heat.HeatStackFixture):
port_security_enabled = False port_security_enabled = False
#: Security groups to be associated to network ports #: Security groups to be associated to network ports
security_groups = [] security_groups = [] # type: typing.List[str]
@property @property
def key_name(self): def key_name(self):

View File

@ -24,9 +24,27 @@ from oslo_log import log
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
PING_PARAMETER_NAMES = ['host', 'count', 'deadline', 'fragmentation', class PingParameters(collections.namedtuple('PingParameters',
'interval', 'ip_version', 'packet_size', 'source', ['host',
'timeout', 'network_namespace'] 'count',
'deadline',
'fragmentation',
'interval',
'ip_version',
'packet_size',
'source',
'timeout',
'network_namespace'])):
"""Recollect parameters to be used to format ping command line
PingParameters class is a data model recollecting parameters used to
create a ping command line. It provides the feature of copying default
values from another instance of PingParameters passed using constructor
parameter 'default'.
"""
PING_PARAMETERS_NAMES = PingParameters._fields
def get_ping_parameters(default=None, **ping_params): def get_ping_parameters(default=None, **ping_params):
@ -122,17 +140,6 @@ def default_ping_parameters():
timeout=CONF.tobiko.ping.timeout) timeout=CONF.tobiko.ping.timeout)
class PingParameters(collections.namedtuple('PingParameters',
PING_PARAMETER_NAMES)):
"""Recollect parameters to be used to format ping command line
PingParameters class is a data model recollecting parameters used to
create a ping command line. It provides the feature of copying default
values from another instance of PingParameters passed using constructor
parameter 'default'.
"""
def get_ping_ip_version(parameters): def get_ping_ip_version(parameters):
ip_version = parameters.ip_version ip_version = parameters.ip_version
if ip_version is not None: if ip_version is not None:

View File

@ -15,8 +15,6 @@
# under the License. # under the License.
from __future__ import absolute_import from __future__ import absolute_import
import collections
from oslo_log import log from oslo_log import log
import tobiko import tobiko
@ -27,18 +25,11 @@ LOG = log.getLogger(__name__)
class ExecutePathFixture(tobiko.SharedFixture): class ExecutePathFixture(tobiko.SharedFixture):
executable_dirs = None
environ = None
def __init__(self, executable_dirs=None, environ=None): def __init__(self, executable_dirs=None, environ=None):
super(ExecutePathFixture, self).__init__() super(ExecutePathFixture, self).__init__()
if executable_dirs: self.executable_dirs = list(executable_dirs or
self.executable_dirs = tuple(executable_dirs) []) # type: typing.List[str]
tobiko.check_valid_type(self.executable_dirs, collections.Iterable) self.environ = dict(environ or {}) # type: typing.Dict[str, str]
if environ is not None:
self.environ = environ
tobiko.check_valid_type(self.environ, collections.Mapping)
def setup_fixture(self): def setup_fixture(self):
missing_dirs = [] missing_dirs = []

View File

@ -138,11 +138,7 @@ class SSHTunnelForwarderFixture(tobiko.SharedFixture):
# pylint: disable=protected-access # pylint: disable=protected-access
SSHForwardHandler = sshtunnel._ForwardHandler class SSHUnixForwardHandler(sshtunnel._ForwardHandler):
# pylint: enable=protected-access
class SSHUnixForwardHandler(SSHForwardHandler):
transport = None transport = None
@ -178,6 +174,8 @@ class SSHUnixForwardHandler(SSHForwardHandler):
self.logger.log(sshtunnel.TRACE_LEVEL, self.logger.log(sshtunnel.TRACE_LEVEL,
'{0} connection closed.'.format(self.info)) '{0} connection closed.'.format(self.info))
# pylint: enable=protected-access
class SSHTunnelForwarder(sshtunnel.SSHTunnelForwarder): class SSHTunnelForwarder(sshtunnel.SSHTunnelForwarder):

View File

@ -29,7 +29,7 @@ from tobiko.tests.unit import openstack
class MyStack(heat.HeatStackFixture): class MyStack(heat.HeatStackFixture):
template = {'template': 'from-class'} template = heat.heat_template({'template': 'from-class'})
class MyStackWithStackName(MyStack): class MyStackWithStackName(MyStack):
@ -37,7 +37,7 @@ class MyStackWithStackName(MyStack):
class MyStackWithParameters(MyStack): class MyStackWithParameters(MyStack):
parameters = {'param': 'from-class'} parameters = heat.heat_stack_parameters({'param': 'from-class'})
class MyStackWithWaitInterval(MyStack): class MyStackWithWaitInterval(MyStack):
@ -73,7 +73,8 @@ class HeatStackFixtureTest(openstack.OpenstackTest):
self.assertIsInstance(stack.parameters, self.assertIsInstance(stack.parameters,
_stack.HeatStackParametersFixture) _stack.HeatStackParametersFixture)
self.assertEqual(parameters or fixture_class.parameters or {}, self.assertEqual(parameters or getattr(fixture_class.parameters,
'parameters', {}),
stack.parameters.parameters) stack.parameters.parameters)
self.assertEqual(wait_interval or fixture_class.wait_interval, self.assertEqual(wait_interval or fixture_class.wait_interval,
stack.wait_interval) stack.wait_interval)
@ -95,7 +96,7 @@ class HeatStackFixtureTest(openstack.OpenstackTest):
self.test_init(parameters={'my': 'value'}) self.test_init(parameters={'my': 'value'})
def test_init_with_parameters_from_class(self): def test_init_with_parameters_from_class(self):
self.test_init(fixture_class=MyStackWithParameters, ) self.test_init(fixture_class=MyStackWithParameters)
def test_init_with_wait_interval(self): def test_init_with_wait_interval(self):
self.test_init(wait_interval=20) self.test_init(wait_interval=20)
@ -144,7 +145,10 @@ class HeatStackFixtureTest(openstack.OpenstackTest):
else: else:
client.stacks.delete.assert_not_called() client.stacks.delete.assert_not_called()
parameters = parameters or fixture_class.parameters or {} parameters = (parameters or
(fixture_class.parameters and
fixture_class.parameters.values) or
{})
self.assertEqual(parameters, stack.parameters.values) self.assertEqual(parameters, stack.parameters.values)
if call_create: if call_create:
client.stacks.create.assert_called_once_with( client.stacks.create.assert_called_once_with(

View File

@ -17,6 +17,7 @@ from __future__ import absolute_import
import json import json
import os import os
import tempfile import tempfile
import typing # noqa
import yaml import yaml
@ -38,9 +39,9 @@ def make_clouds_content(cloud_name, api_version=None, auth=None):
class CloudsFileFixture(tobiko.SharedFixture): class CloudsFileFixture(tobiko.SharedFixture):
cloud_name = None cloud_name = None # type: str
api_version = None api_version = None # type: str
auth = None auth = None # type: typing.Dict[str, typing.Any]
clouds_content = None clouds_content = None
clouds_file = None clouds_file = None
suffix = '.yaml' suffix = '.yaml'
@ -298,15 +299,15 @@ class CloudsFileKeystoneCredentialsFixtureTest(openstack.OpenstackTest):
self.patch(self.config, 'clouds_files', ['/a', '/b', '/c']) self.patch(self.config, 'clouds_files', ['/a', '/b', '/c'])
fixture = keystone.CloudsFileKeystoneCredentialsFixture( fixture = keystone.CloudsFileKeystoneCredentialsFixture(
cloud_name='cloud-name') cloud_name='cloud-name')
ex = self.assertRaises(_clouds_file.FileNotFound, tobiko.setup_fixture, ex = self.assertRaises(_clouds_file.CloudsFileNotFoundError,
fixture) tobiko.setup_fixture, fixture)
self.assertEqual('cloud-name', fixture.cloud_name) self.assertEqual('cloud-name', fixture.cloud_name)
self.assertEqual("No such clouds file: '/a', '/b', '/c'", str(ex)) self.assertEqual("No such clouds file(s): /a, /b, /c", str(ex))
def test_setup_with_non_existing_clouds_file(self): def test_setup_with_non_existing_clouds_file(self):
fixture = keystone.CloudsFileKeystoneCredentialsFixture( fixture = keystone.CloudsFileKeystoneCredentialsFixture(
clouds_file='/a.yaml', clouds_file='/a.yaml',
cloud_name='cloud-name') cloud_name='cloud-name')
ex = self.assertRaises(_clouds_file.FileNotFound, tobiko.setup_fixture, ex = self.assertRaises(_clouds_file.CloudsFileNotFoundError,
fixture) tobiko.setup_fixture, fixture)
self.assertEqual("Cloud file not found: '/a.yaml'", str(ex)) self.assertEqual("No such clouds file(s): /a.yaml", str(ex))

View File

@ -1,7 +1,6 @@
- job: - job:
name: tobiko-tox-mypy name: tobiko-tox-mypy
parent: openstack-tox parent: openstack-tox
voting: False
description: | description: |
Run static mypy type checker for Tobiko project. Run static mypy type checker for Tobiko project.
vars: vars: