Add support for Python 3.10

Change-Id: I42a3558899c1262b3edb61c177e8856af71529bd
This commit is contained in:
Federico Ressi 2022-01-03 15:19:37 +01:00
parent 5667949dc9
commit 143cf01645
13 changed files with 45 additions and 35 deletions

View File

@ -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

View File

@ -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)

View File

@ -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:

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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:

View File

@ -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))

View File

@ -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:

View File

@ -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):

View File

@ -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:

View File

@ -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(

View File

@ -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)