From b91aaaab9092acc97166d2cccdb11c5d1b2569b9 Mon Sep 17 00:00:00 2001 From: Charles Short Date: Fri, 9 Apr 2021 08:51:29 -0400 Subject: [PATCH] python3: Fix python3 compatibility issues - Replace 'range' with six.moves.range. - Replace 'zip' with six.moves.zip. - Replace 'map' with six.moves.map. - Replace dict.keys() with list(dict.keys()) to get a list on Python 3. On Python 3, dict.keys() now returns a view. - Fix 'TypeError: unorderable types: NoneType() < int()' for python3 - Python 3 changed the iso8601 module iso8601.iso8601.Utc() function to iso8601.UTC. This is compatible with Python2.7. Testing: 1. Built new fm-rest-api rpm package. 2. Built new ISO with newer fm-rest-api and installed fine. 3. Checked for an exception in the logs while running "fm event-list". 4. Ran "fm alarm-list" without a problem. Story: 2006729 Task: 42256 Signed-off-by: Charles Short Change-Id: I2d0f4c2c85ea8057258d56632a102b2eac7db388 --- fm-rest-api/fm/fm/api/controllers/v1/alarm.py | 4 ++-- fm-rest-api/fm/fm/api/controllers/v1/base.py | 2 +- fm-rest-api/fm/fm/api/controllers/v1/event_log.py | 2 +- fm-rest-api/fm/fm/api/controllers/v1/event_suppression.py | 2 +- fm-rest-api/fm/fm/api/controllers/v1/types.py | 1 + fm-rest-api/fm/fm/api/controllers/v1/utils.py | 7 +++++-- fm-rest-api/fm/fm/api/middleware/auth_token.py | 3 +-- fm-rest-api/fm/fm/objects/utils.py | 2 +- fm-rest-api/fm/fm/tests/api/test_root.py | 4 ++-- 9 files changed, 15 insertions(+), 12 deletions(-) diff --git a/fm-rest-api/fm/fm/api/controllers/v1/alarm.py b/fm-rest-api/fm/fm/api/controllers/v1/alarm.py index e8324e0c..b96e5b19 100644 --- a/fm-rest-api/fm/fm/api/controllers/v1/alarm.py +++ b/fm-rest-api/fm/fm/api/controllers/v1/alarm.py @@ -99,7 +99,7 @@ class Alarm(base.APIBase): "A list containing a self link and associated alarm links" def __init__(self, **kwargs): - self.fields = objects.alarm.fields.keys() + self.fields = list(objects.alarm.fields.keys()) for k in self.fields: setattr(self, k, kwargs.get(k)) @@ -284,7 +284,7 @@ class AlarmController(rest.RestController): :param alarm_dict: Dictionary obtained from an alarm object. """ event_log_dict = {} - for key in alarm_dict.keys(): + for key in list(alarm_dict.keys()): if key == 'alarm_id': event_log_dict['event_log_id'] = alarm_dict[key] elif key == 'alarm_state': diff --git a/fm-rest-api/fm/fm/api/controllers/v1/base.py b/fm-rest-api/fm/fm/api/controllers/v1/base.py index 9755b70b..761e3982 100644 --- a/fm-rest-api/fm/fm/api/controllers/v1/base.py +++ b/fm-rest-api/fm/fm/api/controllers/v1/base.py @@ -62,7 +62,7 @@ class APIBase(wtypes.Base): # Unset non-required fields so they do not appear # in the message body obj_dict.update(dict((k, wsme.Unset) - for k in obj_dict.keys() + for k in list(obj_dict.keys()) if fields and k not in fields)) return cls(**obj_dict) diff --git a/fm-rest-api/fm/fm/api/controllers/v1/event_log.py b/fm-rest-api/fm/fm/api/controllers/v1/event_log.py index ae78e195..e5d012d5 100644 --- a/fm-rest-api/fm/fm/api/controllers/v1/event_log.py +++ b/fm-rest-api/fm/fm/api/controllers/v1/event_log.py @@ -93,7 +93,7 @@ class EventLog(base.APIBase): def __init__(self, **kwargs): - self.fields = objects.event_log.fields.keys() + self.fields = list(objects.event_log.fields.keys()) for k in self.fields: setattr(self, k, kwargs.get(k)) diff --git a/fm-rest-api/fm/fm/api/controllers/v1/event_suppression.py b/fm-rest-api/fm/fm/api/controllers/v1/event_suppression.py index 3670dedb..8402256c 100644 --- a/fm-rest-api/fm/fm/api/controllers/v1/event_suppression.py +++ b/fm-rest-api/fm/fm/api/controllers/v1/event_suppression.py @@ -60,7 +60,7 @@ class EventSuppression(base.APIBase): "A list containing a self link and associated links" def __init__(self, **kwargs): - self.fields = objects.event_suppression.fields.keys() + self.fields = list(objects.event_suppression.fields.keys()) for k in self.fields: if not hasattr(self, k): continue diff --git a/fm-rest-api/fm/fm/api/controllers/v1/types.py b/fm-rest-api/fm/fm/api/controllers/v1/types.py index a553abb1..8b884507 100644 --- a/fm-rest-api/fm/fm/api/controllers/v1/types.py +++ b/fm-rest-api/fm/fm/api/controllers/v1/types.py @@ -29,6 +29,7 @@ import wsme from wsme import types as wtypes from oslo_utils import strutils from oslo_utils import uuidutils +from six.moves import map from fm.common.i18n import _ from fm.common import exceptions diff --git a/fm-rest-api/fm/fm/api/controllers/v1/utils.py b/fm-rest-api/fm/fm/api/controllers/v1/utils.py index e501c0d4..4370bdd7 100644 --- a/fm-rest-api/fm/fm/api/controllers/v1/utils.py +++ b/fm-rest-api/fm/fm/api/controllers/v1/utils.py @@ -49,14 +49,17 @@ def save_and_reraise_exception(): LOG.error(_('Original exception being dropped: %s'), traceback.format_exception(type_, value, tb)) raise - raise (type_, value, tb) + raise type_ def validate_limit(limit): if limit and limit < 0: raise wsme.exc.ClientSideError(_("Limit must be positive")) - return min(CONF.api.limit_max, limit) or CONF.api.limit_max + if limit: + return min(CONF.api.limit_max, limit) or CONF.api.limit_max + else: + return CONF.api_limit_max def validate_sort_dir(sort_dir): diff --git a/fm-rest-api/fm/fm/api/middleware/auth_token.py b/fm-rest-api/fm/fm/api/middleware/auth_token.py index 98c260d6..162c2ad5 100644 --- a/fm-rest-api/fm/fm/api/middleware/auth_token.py +++ b/fm-rest-api/fm/fm/api/middleware/auth_token.py @@ -57,8 +57,7 @@ class AuthTokenMiddleware(auth_token.AuthProtocol): # The information whether the API call is being performed against the # public API is required for some other components. Saving it to the # WSGI environment is reasonable thereby. - env['is_public_api'] = any(map(lambda pattern: re.match(pattern, path), - self.public_api_routes)) + env['is_public_api'] = any([re.match(pattern, path) for pattern in self.public_api_routes]) if env['is_public_api']: return self._app(env, start_response) diff --git a/fm-rest-api/fm/fm/objects/utils.py b/fm-rest-api/fm/fm/objects/utils.py index e8ab6117..5c24c537 100644 --- a/fm-rest-api/fm/fm/objects/utils.py +++ b/fm-rest-api/fm/fm/objects/utils.py @@ -38,7 +38,7 @@ def datetime_or_none(dt): # NOTE(danms): Legacy objects from sqlalchemy are stored in UTC, # but are returned without a timezone attached. # As a transitional aid, assume a tz-naive object is in UTC. - return dt.replace(tzinfo=iso8601.iso8601.Utc()) + return dt.replace(tzinfo=iso8601.UTC) else: return dt raise ValueError('A datetime.datetime is required here') diff --git a/fm-rest-api/fm/fm/tests/api/test_root.py b/fm-rest-api/fm/fm/tests/api/test_root.py index 802e41ae..1403689e 100644 --- a/fm-rest-api/fm/fm/tests/api/test_root.py +++ b/fm-rest-api/fm/fm/tests/api/test_root.py @@ -25,7 +25,7 @@ class TestRoot(base.FunctionalTest): data = self.get_json('/', path_prefix='') self.assertEqual(data['default_version']['id'], 'v1') # Check fields are not empty - [self.assertNotIn(f, ['', []]) for f in data.keys()] + [self.assertNotIn(f, ['', []]) for f in list(data.keys())] class TestV1Root(base.FunctionalTest): @@ -34,7 +34,7 @@ class TestV1Root(base.FunctionalTest): data = self.get_json('/') self.assertEqual(data['id'], 'v1') # Check fields are not empty - [self.assertNotIn(f, ['', []]) for f in data.keys()] + [self.assertNotIn(f, ['', []]) for f in list(data.keys())] # Check if the resources are present self.assertIn({'type': 'application/vnd.openstack.fm.v1+json', 'base': 'application/json'}, data['media_types'])