Fix AttributeError in Python 3.8

The importlib-metadata package was imported to the core Python since
Python 3.8, and stevedore uses the standard library implementation
instead of the 3rd party package in Python 3.8 and later. However
the implementation available in Python 3.8 is quite old and especially
it does not include the change which added the module attribute[1].

This change makes sure we avoid referring to that attribute if it does
not exist, to avoid AttributeError in Python 3.8.

[1] dfc96137ac

Story: 2010095
Task: 45650
Change-Id: Ieba5f353b0fe8a9b187bac1f6ff1b3a8f3b896b3
This commit is contained in:
Takashi Kajinami 2022-06-20 10:50:26 +09:00
parent 27f7a81650
commit eec1f92bc0
2 changed files with 45 additions and 6 deletions

View File

@ -18,9 +18,17 @@ LOG = logging.getLogger(__name__)
def log_fail_msg(manager, entrypoint, exception):
LOG.warning('Encountered exception while loading %(module_name)s: '
'"%(message)s". Not using %(name)s.',
{'module_name': entrypoint.module,
'message': getattr(exception, 'message',
str(exception)),
'name': entrypoint.name})
# importlib.metadata in Python 3.8 is quite old and the EntryPoint class
# does not have module. This logic is required to workaround AttributeError
# caused by that old implementation.
if hasattr(entrypoint, 'module'):
LOG.warning('Encountered exception while loading %(module_name)s: '
'"%(message)s". Not using %(name)s.',
{'module_name': entrypoint.module,
'message': getattr(exception, 'message', str(exception)),
'name': entrypoint.name})
else:
LOG.warning('Encountered exception: "%(message)s". '
'Not using %(name)s.',
{'message': getattr(exception, 'message', str(exception)),
'name': entrypoint.name})

View File

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# 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 importlib.metadata as importlib_metadata
from unittest import mock
from heat.common import pluginutils
from heat.tests import common
class TestPluginUtil(common.HeatTestCase):
def test_log_fail_msg(self):
ep = importlib_metadata.EntryPoint(
name=None, group=None,
value='package.module:attr [extra1, extra2]')
exc = Exception('Something went wrong')
pluginutils.log_fail_msg(mock.Mock(), ep, exc)
self.assertIn("Something went wrong", self.LOG.output)