Add support for Python 3.10
Change-Id: I42a3558899c1262b3edb61c177e8856af71529bd
This commit is contained in:
parent
5667949dc9
commit
143cf01645
17
Dockerfile
17
Dockerfile
@ -1,9 +1,16 @@
|
|||||||
FROM python:3.9 as base
|
FROM python:3.10 as base
|
||||||
|
|
||||||
ENV TOBIKO_DIR=/tobiko
|
ENV TOBIKO_DIR=/tobiko
|
||||||
ENV WHEEL_DIR=/wheel
|
ENV WHEEL_DIR=/wheel
|
||||||
|
|
||||||
RUN apt update
|
ENV INSTALL_PACKAGES="apt install -y"
|
||||||
|
|
||||||
|
# Install binary dependencies
|
||||||
|
RUN apt update && \
|
||||||
|
${INSTALL_PACKAGES} git
|
||||||
|
|
||||||
|
RUN python3 -m ensurepip --upgrade && \
|
||||||
|
python3 -m pip install --upgrade setuptools wheel
|
||||||
|
|
||||||
|
|
||||||
FROM base as source
|
FROM base as source
|
||||||
@ -28,7 +35,7 @@ ADD tobiko/ ${TOBIKO_DIR}/tobiko/
|
|||||||
FROM source as build
|
FROM source as build
|
||||||
|
|
||||||
# Install binary dependencies
|
# Install binary dependencies
|
||||||
RUN apt install -y git
|
# RUN ${INSTALL_PACKAGES} gcc python3-devel
|
||||||
|
|
||||||
# Build wheel files
|
# Build wheel files
|
||||||
RUN python3 -m pip wheel -w ${WHEEL_DIR} \
|
RUN python3 -m pip wheel -w ${WHEEL_DIR} \
|
||||||
@ -44,13 +51,13 @@ FROM base as install
|
|||||||
# Install wheels
|
# Install wheels
|
||||||
RUN mkdir -p ${WHEEL_DIR}
|
RUN mkdir -p ${WHEEL_DIR}
|
||||||
COPY --from=build ${WHEEL_DIR} ${WHEEL_DIR}
|
COPY --from=build ${WHEEL_DIR} ${WHEEL_DIR}
|
||||||
RUN pip install ${WHEEL_DIR}/*.whl
|
RUN python3 -m pip install ${WHEEL_DIR}/*.whl
|
||||||
|
|
||||||
|
|
||||||
FROM source as tobiko
|
FROM source as tobiko
|
||||||
|
|
||||||
# Install packages
|
# Install packages
|
||||||
RUN apt install -y iperf3 iputils-ping ncat
|
RUN ${INSTALL_PACKAGES} iperf3 iputils-ping ncat
|
||||||
|
|
||||||
# Run tests variables
|
# Run tests variables
|
||||||
ENV PYTHONWARNINGS=ignore::Warning
|
ENV PYTHONWARNINGS=ignore::Warning
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
|
from collections import abc
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
import typing
|
import typing
|
||||||
@ -53,7 +54,7 @@ def heat_stack_parameters(obj,
|
|||||||
-> 'HeatStackParametersFixture':
|
-> 'HeatStackParametersFixture':
|
||||||
if isinstance(obj, HeatStackParametersFixture):
|
if isinstance(obj, HeatStackParametersFixture):
|
||||||
parameters = obj
|
parameters = obj
|
||||||
elif obj is None or isinstance(obj, collections.Mapping):
|
elif obj is None or isinstance(obj, abc.Mapping):
|
||||||
parameters = HeatStackParametersFixture(stack, obj)
|
parameters = HeatStackParametersFixture(stack, obj)
|
||||||
else:
|
else:
|
||||||
parameters = tobiko.get_fixture(obj)
|
parameters = tobiko.get_fixture(obj)
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import collections
|
from collections import abc
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import typing
|
import typing
|
||||||
@ -48,9 +48,9 @@ class HeatTemplateFixture(tobiko.SharedFixture):
|
|||||||
|
|
||||||
def setup_template(self):
|
def setup_template(self):
|
||||||
# Ensure main sections are dictionaries
|
# Ensure main sections are dictionaries
|
||||||
tobiko.check_valid_type(self.outputs, collections.Mapping)
|
tobiko.check_valid_type(self.outputs, abc.Mapping)
|
||||||
tobiko.check_valid_type(self.parameters, collections.Mapping)
|
tobiko.check_valid_type(self.parameters, abc.Mapping)
|
||||||
tobiko.check_valid_type(self.resources, collections.Mapping)
|
tobiko.check_valid_type(self.resources, abc.Mapping)
|
||||||
self.template_yaml = tobiko.dump_yaml(self.template)
|
self.template_yaml = tobiko.dump_yaml(self.template)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -98,7 +98,7 @@ HeatTemplateType = typing.Union[typing.Mapping[str, typing.Any],
|
|||||||
def heat_template(obj: HeatTemplateType,
|
def heat_template(obj: HeatTemplateType,
|
||||||
template_files: typing.Mapping = None) \
|
template_files: typing.Mapping = None) \
|
||||||
-> HeatTemplateFixture:
|
-> HeatTemplateFixture:
|
||||||
if isinstance(obj, collections.Mapping):
|
if isinstance(obj, abc.Mapping):
|
||||||
template = HeatTemplateFixture(template=obj,
|
template = HeatTemplateFixture(template=obj,
|
||||||
template_files=template_files)
|
template_files=template_files)
|
||||||
else:
|
else:
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import collections
|
from collections import abc
|
||||||
import re
|
import re
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ NeutronAgentType = typing.Dict[str, typing.Any]
|
|||||||
def list_agents(client=None, **params) \
|
def list_agents(client=None, **params) \
|
||||||
-> tobiko.Selection[NeutronAgentType]:
|
-> tobiko.Selection[NeutronAgentType]:
|
||||||
agents = _client.neutron_client(client).list_agents(**params)
|
agents = _client.neutron_client(client).list_agents(**params)
|
||||||
if isinstance(agents, collections.Mapping):
|
if isinstance(agents, abc.Mapping):
|
||||||
agents = agents['agents']
|
agents = agents['agents']
|
||||||
return tobiko.Selection[NeutronAgentType](agents)
|
return tobiko.Selection[NeutronAgentType](agents)
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ def list_agents(client=None, **params) \
|
|||||||
def list_l3_agent_hosting_routers(router, client=None, **params):
|
def list_l3_agent_hosting_routers(router, client=None, **params):
|
||||||
agents = _client.neutron_client(client).list_l3_agent_hosting_routers(
|
agents = _client.neutron_client(client).list_l3_agent_hosting_routers(
|
||||||
router, **params)
|
router, **params)
|
||||||
if isinstance(agents, collections.Mapping):
|
if isinstance(agents, abc.Mapping):
|
||||||
agents = agents['agents']
|
agents = agents['agents']
|
||||||
return tobiko.select(agents)
|
return tobiko.select(agents)
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ def find_l3_agent_hosting_router(router, client=None, unique=False,
|
|||||||
def list_dhcp_agent_hosting_network(network, client=None, **params):
|
def list_dhcp_agent_hosting_network(network, client=None, **params):
|
||||||
agents = _client.neutron_client(client).list_dhcp_agent_hosting_networks(
|
agents = _client.neutron_client(client).list_dhcp_agent_hosting_networks(
|
||||||
network, **params)
|
network, **params)
|
||||||
if isinstance(agents, collections.Mapping):
|
if isinstance(agents, abc.Mapping):
|
||||||
agents = agents['agents']
|
agents = agents['agents']
|
||||||
return tobiko.select(agents)
|
return tobiko.select(agents)
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import collections
|
from collections import abc
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
@ -147,7 +147,7 @@ def list_subnets(client=None, ip_version: typing.Optional[int] = None,
|
|||||||
if ip_version is not None:
|
if ip_version is not None:
|
||||||
params['ip_version'] = ip_version
|
params['ip_version'] = ip_version
|
||||||
subnets = neutron_client(client).list_subnets(**params)
|
subnets = neutron_client(client).list_subnets(**params)
|
||||||
if isinstance(subnets, collections.Mapping):
|
if isinstance(subnets, abc.Mapping):
|
||||||
subnets = subnets['subnets']
|
subnets = subnets['subnets']
|
||||||
return tobiko.select(subnets)
|
return tobiko.select(subnets)
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import collections
|
from collections import abc
|
||||||
|
|
||||||
import tobiko
|
import tobiko
|
||||||
from tobiko.openstack import keystone
|
from tobiko.openstack import keystone
|
||||||
@ -35,7 +35,7 @@ class NetworkingExtensionsFixture(tobiko.SharedFixture):
|
|||||||
|
|
||||||
def get_networking_extensions(self):
|
def get_networking_extensions(self):
|
||||||
extensions = self.client.list_extensions()
|
extensions = self.client.list_extensions()
|
||||||
if isinstance(extensions, collections.Mapping):
|
if isinstance(extensions, abc.Mapping):
|
||||||
extensions = extensions['extensions']
|
extensions = extensions['extensions']
|
||||||
ignore_extensions = set(
|
ignore_extensions = set(
|
||||||
tobiko.tobiko_config().neutron.ignore_extensions)
|
tobiko.tobiko_config().neutron.ignore_extensions)
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import collections
|
from collections import abc
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
@ -51,7 +51,7 @@ def combine_cloud_configs(objs):
|
|||||||
extra_params = {}
|
extra_params = {}
|
||||||
for obj in objs:
|
for obj in objs:
|
||||||
if obj:
|
if obj:
|
||||||
if not isinstance(obj, collections.abc.Mapping):
|
if not isinstance(obj, abc.Mapping):
|
||||||
obj = dict(obj)
|
obj = dict(obj)
|
||||||
for package in obj.pop('packages', []):
|
for package in obj.pop('packages', []):
|
||||||
if package and package not in packages:
|
if package and package not in packages:
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import collections
|
from collections import abc
|
||||||
import functools
|
import functools
|
||||||
import socket
|
import socket
|
||||||
import typing
|
import typing
|
||||||
@ -43,7 +43,7 @@ def list_addresses(obj,
|
|||||||
ip_version=ip_version,
|
ip_version=ip_version,
|
||||||
port=port,
|
port=port,
|
||||||
ssh_config=ssh_config))
|
ssh_config=ssh_config))
|
||||||
elif isinstance(obj, collections.Sequence):
|
elif isinstance(obj, abc.Sequence):
|
||||||
addresses = tobiko.Selection()
|
addresses = tobiko.Selection()
|
||||||
for item in iter(obj):
|
for item in iter(obj):
|
||||||
addresses.extend(list_addresses(item))
|
addresses.extend(list_addresses(item))
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
|
from collections import abc
|
||||||
import re
|
import re
|
||||||
import typing
|
import typing
|
||||||
from urllib import parse
|
from urllib import parse
|
||||||
@ -56,7 +57,7 @@ def list_openstack_nodes(topology: 'OpenStackTopology' = None,
|
|||||||
elif isinstance(group, PatternType):
|
elif isinstance(group, PatternType):
|
||||||
nodes = topology.get_groups(groups=[group])
|
nodes = topology.get_groups(groups=[group])
|
||||||
else:
|
else:
|
||||||
assert isinstance(group, collections.Iterable)
|
assert isinstance(group, abc.Iterable)
|
||||||
nodes = topology.get_groups(groups=group)
|
nodes = topology.get_groups(groups=group)
|
||||||
|
|
||||||
if hostnames:
|
if hostnames:
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
|
from collections import abc
|
||||||
import getpass
|
import getpass
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@ -29,7 +30,7 @@ Context = collections.namedtuple('Context', (
|
|||||||
Context.__new__.__defaults__ = (None, ) * len(Context._fields) # type: ignore
|
Context.__new__.__defaults__ = (None, ) * len(Context._fields) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
class Portal(collections.MutableMapping):
|
class Portal(abc.MutableMapping):
|
||||||
"""Expiring container for tunnels."""
|
"""Expiring container for tunnels."""
|
||||||
|
|
||||||
def __init__(self, sweap=25):
|
def __init__(self, sweap=25):
|
||||||
@ -98,7 +99,7 @@ class Portal(collections.MutableMapping):
|
|||||||
self._schedule_reaper()
|
self._schedule_reaper()
|
||||||
|
|
||||||
|
|
||||||
class Tunnel():
|
class Tunnel:
|
||||||
"""SSH tunnel."""
|
"""SSH tunnel."""
|
||||||
|
|
||||||
def __init__(self, context):
|
def __init__(self, context):
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import collections
|
from collections import abc
|
||||||
import contextlib
|
import contextlib
|
||||||
import getpass
|
import getpass
|
||||||
import io
|
import io
|
||||||
@ -163,7 +163,7 @@ def gather_ssh_connect_parameters(source=None, destination=None, schema=None,
|
|||||||
|
|
||||||
if source:
|
if source:
|
||||||
# gather from object
|
# gather from object
|
||||||
if isinstance(source, collections.Mapping):
|
if isinstance(source, abc.Mapping):
|
||||||
parameters.update(_items_from_mapping(mapping=source,
|
parameters.update(_items_from_mapping(mapping=source,
|
||||||
schema=schema))
|
schema=schema))
|
||||||
else:
|
else:
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import collections
|
from collections import abc
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from heatclient.v1 import client as heatclient
|
from heatclient.v1 import client as heatclient
|
||||||
@ -297,7 +297,7 @@ class HeatStackFixtureTest(openstack.OpenstackTest):
|
|||||||
expected_template = template or type(stack).template
|
expected_template = template or type(stack).template
|
||||||
if tobiko.is_fixture(expected_template):
|
if tobiko.is_fixture(expected_template):
|
||||||
self.assertIs(expected_template, stack.template)
|
self.assertIs(expected_template, stack.template)
|
||||||
elif isinstance(expected_template, collections.Mapping):
|
elif isinstance(expected_template, abc.Mapping):
|
||||||
self.assertEqual(expected_template, stack.template.template)
|
self.assertEqual(expected_template, stack.template.template)
|
||||||
else:
|
else:
|
||||||
message = "Unsupported template type: {!r}".format(
|
message = "Unsupported template type: {!r}".format(
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import collections
|
from collections import abc
|
||||||
import re
|
import re
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
@ -44,14 +44,14 @@ class SelectionTest(unit.TobikoUnitTest):
|
|||||||
objects: typing.Iterable[T] = tuple()) \
|
objects: typing.Iterable[T] = tuple()) \
|
||||||
-> tobiko.Selection[T]:
|
-> tobiko.Selection[T]:
|
||||||
reference = list(objects)
|
reference = list(objects)
|
||||||
if isinstance(objects, collections.Generator):
|
if isinstance(objects, abc.Generator):
|
||||||
# Can't reiterate the same generator twice
|
# Can't reiterate the same generator twice
|
||||||
objects = (o for o in reference)
|
objects = (o for o in reference)
|
||||||
assert isinstance(objects, collections.Generator)
|
assert isinstance(objects, abc.Generator)
|
||||||
elif isinstance(objects, collections.Iterator):
|
elif isinstance(objects, abc.Iterator):
|
||||||
# Can't reiterate the same iterator twice
|
# Can't reiterate the same iterator twice
|
||||||
objects = iter(reference)
|
objects = iter(reference)
|
||||||
assert isinstance(objects, collections.Iterator)
|
assert isinstance(objects, abc.Iterator)
|
||||||
|
|
||||||
selection = self.create_selection(objects)
|
selection = self.create_selection(objects)
|
||||||
self.assertIsInstance(selection, list)
|
self.assertIsInstance(selection, list)
|
||||||
|
Loading…
Reference in New Issue
Block a user