Coverage for watcher/api/controllers/base.py: 94%
57 statements
« prev ^ index » next coverage.py v7.8.2, created at 2025-06-17 12:22 +0000
« prev ^ index » next coverage.py v7.8.2, created at 2025-06-17 12:22 +0000
1# -*- encoding: utf-8 -*-
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12# implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
16import datetime
17import functools
19import microversion_parse
20from webob import exc
21import wsme
22from wsme import types as wtypes
25class APIBase(wtypes.Base):
27 created_at = wsme.wsattr(datetime.datetime, readonly=True)
28 """The time in UTC at which the object is created"""
30 updated_at = wsme.wsattr(datetime.datetime, readonly=True)
31 """The time in UTC at which the object is updated"""
33 deleted_at = wsme.wsattr(datetime.datetime, readonly=True)
34 """The time in UTC at which the object is deleted"""
36 def as_dict(self):
37 """Render this object as a dict of its fields."""
38 return dict((k, getattr(self, k))
39 for k in self.fields
40 if hasattr(self, k) and
41 getattr(self, k) != wsme.Unset)
43 def unset_fields_except(self, except_list=None):
44 """Unset fields so they don't appear in the message body.
46 :param except_list: A list of fields that won't be touched.
48 """
49 if except_list is None: 49 ↛ 50line 49 didn't jump to line 50 because the condition on line 49 was never true
50 except_list = []
52 for k in self.as_dict():
53 if k not in except_list:
54 setattr(self, k, wsme.Unset)
57@functools.total_ordering
58class Version(object):
59 """API Version object."""
61 string = 'OpenStack-API-Version'
62 """HTTP Header string carrying the requested version"""
64 min_string = 'OpenStack-API-Minimum-Version'
65 """HTTP response header"""
67 max_string = 'OpenStack-API-Maximum-Version'
68 """HTTP response header"""
70 def __init__(self, headers, default_version, latest_version):
71 """Create an API Version object from the supplied headers.
73 :param headers: webob headers
74 :param default_version: version to use if not specified in headers
75 :param latest_version: version to use if latest is requested
76 :raises: webob.HTTPNotAcceptable
78 """
79 (self.major, self.minor) = Version.parse_headers(
80 headers, default_version, latest_version)
82 def __repr__(self):
83 return '%s.%s' % (self.major, self.minor)
85 @staticmethod
86 def parse_headers(headers, default_version, latest_version):
87 """Determine the API version requested based on the headers supplied.
89 :param headers: webob headers
90 :param default_version: version to use if not specified in headers
91 :param latest_version: version to use if latest is requested
92 :returns: a tuple of (major, minor) version numbers
93 :raises: webob.HTTPNotAcceptable
95 """
96 version_str = microversion_parse.get_version(
97 headers,
98 service_type='infra-optim')
100 minimal_version = (1, 0)
102 if version_str is None:
103 # If requested header is wrong, Watcher answers with the minimal
104 # supported version.
105 return minimal_version
107 if version_str.lower() == 'latest':
108 parse_str = latest_version
109 else:
110 parse_str = version_str
112 try:
113 version = tuple(int(i) for i in parse_str.split('.'))
114 except ValueError:
115 version = minimal_version
117 # NOTE (alexchadin): Old python-watcherclient sends requests with
118 # value of version header is "1". It should be transformed to 1.0 as
119 # it was supposed to be.
120 if len(version) == 1 and version[0] == 1:
121 version = minimal_version
123 if len(version) != 2:
124 raise exc.HTTPNotAcceptable(
125 "Invalid value for %s header" % Version.string)
126 return version
128 def __gt__(self, other):
129 return (self.major, self.minor) > (other.major, other.minor)
131 def __eq__(self, other):
132 return (self.major, self.minor) == (other.major, other.minor)
134 def __ne__(self, other):
135 return not self.__eq__(other)