Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-keystoneauth1 for 
openSUSE:Factory checked in at 2023-03-21 17:40:51
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-keystoneauth1 (Old)
 and      /work/SRC/openSUSE:Factory/.python-keystoneauth1.new.31432 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-keystoneauth1"

Tue Mar 21 17:40:51 2023 rev:17 rq:1073019 version:5.1.2

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-keystoneauth1/python-keystoneauth1.changes    
    2022-08-11 18:31:57.202210444 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-keystoneauth1.new.31432/python-keystoneauth1.changes
     2023-03-21 17:40:52.477642751 +0100
@@ -1,0 +2,11 @@
+Mon Mar  6 15:53:59 UTC 2023 - [email protected]
+
+- update to version 5.1.2
+  - OAuth2.0 Client Credentials Grant Flow Support
+  - Update python testing as per zed cycle teting runtime
+  - Enforce scope mutual exclusion for system
+  - Allow passing of version header
+  - Fix docs build for tox4
+  - Fix linters and bindep on jammy
+
+-------------------------------------------------------------------

Old:
----
  keystoneauth1-4.6.0.tar.gz

New:
----
  keystoneauth1-5.1.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-keystoneauth1.spec ++++++
--- /var/tmp/diff_new_pack.Fu9YtP/_old  2023-03-21 17:40:53.133645889 +0100
+++ /var/tmp/diff_new_pack.Fu9YtP/_new  2023-03-21 17:40:53.141645927 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-keystoneauth1
 #
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,13 +17,13 @@
 
 
 Name:           python-keystoneauth1
-Version:        4.6.0
+Version:        5.1.2
 Release:        0
 Summary:        OpenStack authenticating tools
 License:        Apache-2.0
 Group:          Development/Languages/Python
 URL:            https://docs.openstack.org/keystoneauth
-Source0:        
https://files.pythonhosted.org/packages/source/k/keystoneauth1/keystoneauth1-4.6.0.tar.gz
+Source0:        
https://files.pythonhosted.org/packages/source/k/keystoneauth1/keystoneauth1-5.1.2.tar.gz
 BuildRequires:  openstack-macros
 BuildRequires:  python3-PyYAML
 BuildRequires:  python3-betamax
@@ -100,7 +100,7 @@
 
 %check
 rm -v keystoneauth1/tests/unit/test_hacking_checks.py
-python3 -m stestr.cli run
+%{openstack_stestr_run}
 
 %files -n python3-keystoneauth1
 %license LICENSE

++++++ keystoneauth1-4.6.0.tar.gz -> keystoneauth1-5.1.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keystoneauth1-4.6.0/.zuul.yaml 
new/keystoneauth1-5.1.2/.zuul.yaml
--- old/keystoneauth1-4.6.0/.zuul.yaml  2022-05-20 14:26:02.000000000 +0200
+++ new/keystoneauth1-5.1.2/.zuul.yaml  2023-02-13 16:48:53.000000000 +0100
@@ -2,7 +2,7 @@
     templates:
       - check-requirements
       - lib-forward-testing-python3
-      - openstack-python3-ussuri-jobs
+      - openstack-python3-zed-jobs
       - openstacksdk-functional-tips
       - openstacksdk-tox-tips
       - osc-tox-unit-tips
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keystoneauth1-4.6.0/AUTHORS 
new/keystoneauth1-5.1.2/AUTHORS
--- old/keystoneauth1-4.6.0/AUTHORS     2022-05-20 14:26:32.000000000 +0200
+++ new/keystoneauth1-5.1.2/AUTHORS     2023-02-13 16:49:31.000000000 +0100
@@ -75,6 +75,7 @@
 Guang Yee <[email protected]>
 Haiwei Xu <[email protected]>
 Henry Nash <[email protected]>
+Hervé Beraud <[email protected]>
 Ian Cordasco <[email protected]>
 Ian Cordasco <[email protected]>
 Ihar Hrachyshka <[email protected]>
@@ -179,6 +180,7 @@
 XiaojueGuan <[email protected]>
 YangLei <[email protected]>
 Yatin Kumbhare <[email protected]>
+Yi Feng <[email protected]>
 Yolanda Robla <[email protected]>
 Zhenguo Niu <[email protected]>
 ZhiQiang Fan <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keystoneauth1-4.6.0/ChangeLog 
new/keystoneauth1-5.1.2/ChangeLog
--- old/keystoneauth1-4.6.0/ChangeLog   2022-05-20 14:26:32.000000000 +0200
+++ new/keystoneauth1-5.1.2/ChangeLog   2023-02-13 16:49:31.000000000 +0100
@@ -1,6 +1,28 @@
 CHANGES
 =======
 
+5.1.2
+-----
+
+* Fix docs build for tox4
+
+5.1.1
+-----
+
+* Allow passing of version header
+* Enforce scope mutual exclusion for system
+* Fix linters and bindep on jammy
+
+5.1.0
+-----
+
+* OAuth2.0 Client Credentials Grant Flow Support
+
+5.0.0
+-----
+
+* Update python testing as per zed cycle teting runtime
+
 4.6.0
 -----
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keystoneauth1-4.6.0/PKG-INFO 
new/keystoneauth1-5.1.2/PKG-INFO
--- old/keystoneauth1-4.6.0/PKG-INFO    2022-05-20 14:26:32.638197700 +0200
+++ new/keystoneauth1-5.1.2/PKG-INFO    2023-02-13 16:49:32.015777300 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: keystoneauth1
-Version: 4.6.0
+Version: 5.1.2
 Summary: Authentication Library for OpenStack Identity
 Home-page: https://docs.openstack.org/keystoneauth/latest/
 Author: OpenStack
@@ -54,9 +54,8 @@
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: 3 :: Only
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
 Provides-Extra: betamax
 Provides-Extra: kerberos
 Provides-Extra: oauth1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keystoneauth1-4.6.0/bindep.txt 
new/keystoneauth1-5.1.2/bindep.txt
--- old/keystoneauth1-4.6.0/bindep.txt  2022-05-20 14:26:02.000000000 +0200
+++ new/keystoneauth1-5.1.2/bindep.txt  2023-02-13 16:48:53.000000000 +0100
@@ -2,7 +2,7 @@
 # see https://docs.openstack.org/infra/bindep/ for additional information.
 
 build-essential [platform:dpkg test]
-python-dev [platform:dpkg test]
+python3-dev [platform:dpkg test]
 python3-devel [platform:rpm test]
 libkrb5-dev [platform:dpkg test]
 krb5-devel [platform:rpm test]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keystoneauth1-4.6.0/keystoneauth1/discover.py 
new/keystoneauth1-5.1.2/keystoneauth1/discover.py
--- old/keystoneauth1-4.6.0/keystoneauth1/discover.py   2022-05-20 
14:26:02.000000000 +0200
+++ new/keystoneauth1-5.1.2/keystoneauth1/discover.py   2023-02-13 
16:48:53.000000000 +0100
@@ -58,7 +58,7 @@
     return LATEST if val == 'latest' or val == LATEST else int(val)
 
 
-def get_version_data(session, url, authenticated=None):
+def get_version_data(session, url, authenticated=None, version_header=None):
     """Retrieve raw version data from a url.
 
     The return is a list of dicts of the form::
@@ -93,10 +93,15 @@
     :param string url: Endpoint or discovery URL from which to retrieve data.
     :param bool authenticated: Include a token in the discovery call.
                                (optional) Defaults to None.
+    :param string version_header: provide the OpenStack-API-Version header
+        for services which don't return version information without it, for
+        backward compatibility.
     :return: A list of dicts containing version information.
     :rtype: list(dict)
     """
     headers = {'Accept': 'application/json'}
+    if version_header:
+        headers['OpenStack-API-Version'] = version_header
 
     try:
         resp = session.get(url, headers=headers, authenticated=authenticated)
@@ -197,7 +202,7 @@
         Examples: (1,), [1, 2], ('12', '34', '56'), (LATEST,), (2, 'latest')
     :return: A tuple of len >= 2 comprising integers and/or LATEST.
     :raises TypeError: If the input version cannot be interpreted.
-    """
+    """  # noqa: D412
     # Copy the input var so the error presents the original value
     ver = version
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystoneauth1-4.6.0/keystoneauth1/identity/__init__.py 
new/keystoneauth1-5.1.2/keystoneauth1/identity/__init__.py
--- old/keystoneauth1-4.6.0/keystoneauth1/identity/__init__.py  2022-05-20 
14:26:02.000000000 +0200
+++ new/keystoneauth1-5.1.2/keystoneauth1/identity/__init__.py  2023-02-13 
16:48:53.000000000 +0100
@@ -61,6 +61,9 @@
 V3MultiFactor = v3.MultiFactor
 """See :class:`keystoneauth1.identity.v3.MultiFactor`"""
 
+V3OAuth2ClientCredential = v3.OAuth2ClientCredential
+"""See :class:`keystoneauth1.identity.v3.OAuth2ClientCredential`"""
+
 __all__ = ('BaseIdentityPlugin',
            'Password',
            'Token',
@@ -74,4 +77,5 @@
            'V3TOTP',
            'V3TokenlessAuth',
            'V3ApplicationCredential',
-           'V3MultiFactor')
+           'V3MultiFactor',
+           'V3OAuth2ClientCredential')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystoneauth1-4.6.0/keystoneauth1/identity/v3/__init__.py 
new/keystoneauth1-5.1.2/keystoneauth1/identity/v3/__init__.py
--- old/keystoneauth1-4.6.0/keystoneauth1/identity/v3/__init__.py       
2022-05-20 14:26:02.000000000 +0200
+++ new/keystoneauth1-5.1.2/keystoneauth1/identity/v3/__init__.py       
2023-02-13 16:48:53.000000000 +0100
@@ -23,6 +23,7 @@
 from keystoneauth1.identity.v3.token import *  # noqa
 from keystoneauth1.identity.v3.totp import *  # noqa
 from keystoneauth1.identity.v3.tokenless_auth import *  # noqa
+from keystoneauth1.identity.v3.oauth2_client_credential import *  # noqa
 
 
 __all__ = ('ApplicationCredential',
@@ -55,4 +56,7 @@
 
            'ReceiptMethod',
 
-           'MultiFactor', )
+           'MultiFactor',
+
+           'OAuth2ClientCredential',
+           'OAuth2ClientCredentialMethod',)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystoneauth1-4.6.0/keystoneauth1/identity/v3/base.py 
new/keystoneauth1-5.1.2/keystoneauth1/identity/v3/base.py
--- old/keystoneauth1-4.6.0/keystoneauth1/identity/v3/base.py   2022-05-20 
14:26:02.000000000 +0200
+++ new/keystoneauth1-5.1.2/keystoneauth1/identity/v3/base.py   2023-02-13 
16:48:53.000000000 +0100
@@ -137,13 +137,14 @@
         mutual_exclusion = [bool(self.domain_id or self.domain_name),
                             bool(self.project_id or self.project_name),
                             bool(self.trust_id),
+                            bool(self.system_scope),
                             bool(self.unscoped)]
 
         if sum(mutual_exclusion) > 1:
             raise exceptions.AuthorizationFailure(
                 message='Authentication cannot be scoped to multiple'
                         ' targets. Pick one of: project, domain, '
-                        'trust or unscoped')
+                        'trust, system or unscoped')
 
         if self.domain_id:
             body['auth']['scope'] = {'domain': {'id': self.domain_id}}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystoneauth1-4.6.0/keystoneauth1/identity/v3/oauth2_client_credential.py 
new/keystoneauth1-5.1.2/keystoneauth1/identity/v3/oauth2_client_credential.py
--- 
old/keystoneauth1-4.6.0/keystoneauth1/identity/v3/oauth2_client_credential.py   
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/keystoneauth1-5.1.2/keystoneauth1/identity/v3/oauth2_client_credential.py   
    2023-02-13 16:48:53.000000000 +0100
@@ -0,0 +1,127 @@
+# Copyright 2022 OpenStack Foundation
+#
+# 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 requests.auth
+
+from keystoneauth1.exceptions import ClientException
+from keystoneauth1.identity.v3 import base
+
+__all__ = ('OAuth2ClientCredentialMethod', 'OAuth2ClientCredential')
+
+
+class OAuth2ClientCredentialMethod(base.AuthMethod):
+    """An auth method to fetch a token via an OAuth2.0 client credential.
+
+    :param string oauth2_endpoint: OAuth2.0 endpoint.
+    :param string oauth2_client_id: OAuth2.0 client credential id.
+    :param string oauth2_client_secret: OAuth2.0 client credential secret.
+    """
+
+    _method_parameters = [
+        'oauth2_endpoint',
+        'oauth2_client_id',
+        'oauth2_client_secret'
+    ]
+
+    def get_auth_data(self, session, auth, headers, **kwargs):
+        """Return the authentication section of an auth plugin.
+
+        :param session: The communication session.
+        :type session: keystoneauth1.session.Session
+        :param base.Auth auth: The auth plugin calling the method.
+        :param dict headers: The headers that will be sent with the auth
+                             request if a plugin needs to add to them.
+        :return: The identifier of this plugin and a dict of authentication
+                 data for the auth type.
+        :rtype: tuple(string, dict)
+        """
+        auth_data = {
+            'id': self.oauth2_client_id,
+            'secret': self.oauth2_client_secret
+        }
+        return 'application_credential', auth_data
+
+    def get_cache_id_elements(self):
+        """Get the elements for this auth method that make it unique.
+
+        These elements will be used as part of the
+        :py:meth:`keystoneauth1.plugin.BaseIdentityPlugin.get_cache_id` to
+        allow caching of the auth plugin.
+
+        Plugins should override this if they want to allow caching of their
+        state.
+
+        To avoid collision or overrides the keys of the returned dictionary
+        should be prefixed with the plugin identifier. For example the password
+        plugin returns its username value as 'password_username'.
+        """
+        return dict(('oauth2_client_credential_%s' % p, getattr(self, p))
+                    for p in self._method_parameters)
+
+
+class OAuth2ClientCredential(base.AuthConstructor):
+    """A plugin for authenticating via an OAuth2.0 client credential.
+
+    :param string auth_url: Identity service endpoint for authentication.
+    :param string oauth2_endpoint: OAuth2.0 endpoint.
+    :param string oauth2_client_id: OAuth2.0 client credential id.
+    :param string oauth2_client_secret: OAuth2.0 client credential secret.
+    """
+
+    _auth_method_class = OAuth2ClientCredentialMethod
+
+    def __init__(self, auth_url, *args, **kwargs):
+        super(OAuth2ClientCredential, self).__init__(auth_url, *args, **kwargs)
+        self._oauth2_endpoint = kwargs['oauth2_endpoint']
+        self._oauth2_client_id = kwargs['oauth2_client_id']
+        self._oauth2_client_secret = kwargs['oauth2_client_secret']
+
+    def get_headers(self, session, **kwargs):
+        """Fetch authentication headers for message.
+
+        :param session: The session object that the auth_plugin belongs to.
+        :type session: keystoneauth1.session.Session
+
+        :returns: Headers that are set to authenticate a message or None for
+                  failure. Note that when checking this value that the empty
+                  dict is a valid, non-failure response.
+        :rtype: dict
+        """
+        # get headers for X-Auth-Token
+        headers = super(OAuth2ClientCredential, self).get_headers(
+            session, **kwargs)
+
+        # Get OAuth2.0 access token and add the field 'Authorization'
+        data = {"grant_type": "client_credentials"}
+        auth = requests.auth.HTTPBasicAuth(self._oauth2_client_id,
+                                           self._oauth2_client_secret)
+        resp = session.request(self._oauth2_endpoint,
+                               "POST",
+                               authenticated=False,
+                               raise_exc=False,
+                               data=data,
+                               requests_auth=auth)
+        if resp.status_code == 200:
+            oauth2 = resp.json()
+            oauth2_token = oauth2["access_token"]
+            if headers:
+                headers['Authorization'] = f'Bearer {oauth2_token}'
+            else:
+                headers = {'Authorization': f'Bearer {oauth2_token}'}
+        else:
+            error = resp.json()
+            msg = error.get("error_description")
+            raise ClientException(msg)
+
+        return headers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystoneauth1-4.6.0/keystoneauth1/identity/v3/oidc.py 
new/keystoneauth1-5.1.2/keystoneauth1/identity/v3/oidc.py
--- old/keystoneauth1-4.6.0/keystoneauth1/identity/v3/oidc.py   2022-05-20 
14:26:02.000000000 +0200
+++ new/keystoneauth1-5.1.2/keystoneauth1/identity/v3/oidc.py   2023-02-13 
16:48:53.000000000 +0100
@@ -452,7 +452,7 @@
         self.access_token = access_token
 
     def get_payload(self, session):
-        """OidcAccessToken does not require a payload."""
+        """OidcAccessToken does not require a payload."""  # noqa: D403
         return {}
 
     def get_unscoped_auth_ref(self, session):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystoneauth1-4.6.0/keystoneauth1/loading/_plugins/identity/v3.py 
new/keystoneauth1-5.1.2/keystoneauth1/loading/_plugins/identity/v3.py
--- old/keystoneauth1-4.6.0/keystoneauth1/loading/_plugins/identity/v3.py       
2022-05-20 14:26:02.000000000 +0200
+++ new/keystoneauth1-5.1.2/keystoneauth1/loading/_plugins/identity/v3.py       
2023-02-13 16:48:53.000000000 +0100
@@ -338,3 +338,44 @@
         self._methods = kwargs['auth_methods']
 
         return super(MultiFactor, self).load_from_options(**kwargs)
+
+
+class OAuth2ClientCredential(loading.BaseV3Loader):
+
+    @property
+    def plugin_class(self):
+        return identity.V3OAuth2ClientCredential
+
+    def get_options(self):
+        options = super(OAuth2ClientCredential, self).get_options()
+        options.extend([
+            loading.Opt('oauth2_endpoint',
+                        required=True,
+                        help='Endpoint for OAuth2.0'),
+        ]),
+        options.extend([
+            loading.Opt('oauth2_client_id',
+                        required=True,
+                        help='Client id for OAuth2.0'),
+        ]),
+        options.extend([
+            loading.Opt('oauth2_client_secret',
+                        secret=True,
+                        required=True,
+                        help='Client secret for OAuth2.0'),
+        ])
+
+        return options
+
+    def load_from_options(self, **kwargs):
+        if not kwargs.get('oauth2_endpoint'):
+            m = 'You must provide an OAuth2.0 endpoint.'
+            raise exceptions.OptionError(m)
+        if not kwargs.get('oauth2_client_id'):
+            m = 'You must provide an OAuth2.0 client credential ID.'
+            raise exceptions.OptionError(m)
+        if not kwargs.get('oauth2_client_secret'):
+            m = 'You must provide an OAuth2.0 client credential auth secret.'
+            raise exceptions.OptionError(m)
+
+        return super(OAuth2ClientCredential, self).load_from_options(**kwargs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystoneauth1-4.6.0/keystoneauth1/tests/unit/identity/test_identity_v3.py 
new/keystoneauth1-5.1.2/keystoneauth1/tests/unit/identity/test_identity_v3.py
--- 
old/keystoneauth1-4.6.0/keystoneauth1/tests/unit/identity/test_identity_v3.py   
    2022-05-20 14:26:02.000000000 +0200
+++ 
new/keystoneauth1-5.1.2/keystoneauth1/tests/unit/identity/test_identity_v3.py   
    2023-02-13 16:48:53.000000000 +0100
@@ -13,11 +13,13 @@
 import copy
 import json
 import time
+import unittest
 import uuid
 
 from keystoneauth1 import _utils as ksa_utils
 from keystoneauth1 import access
 from keystoneauth1 import exceptions
+from keystoneauth1.exceptions import ClientException
 from keystoneauth1 import fixture
 from keystoneauth1.identity import v3
 from keystoneauth1.identity.v3 import base as v3_base
@@ -37,6 +39,9 @@
     TEST_APP_CRED_ID = 'appcredid'
     TEST_APP_CRED_SECRET = 'secret'
 
+    TEST_CLIENT_CRED_ID = 'clientcredid'
+    TEST_CLIENT_CRED_SECRET = 'secret'
+
     TEST_SERVICE_CATALOG = [{
         "endpoints": [{
             "url": "http://cdn.admin-nets.local:8774/v1.0/";,
@@ -822,3 +827,261 @@
         self.assertRequestHeaderEqual('Content-Type', 'application/json')
         self.assertRequestHeaderEqual('Accept', 'application/json')
         self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN)
+
+    def test_oauth2_client_credential_method_http(self):
+        base_http = self.TEST_URL
+        oauth2_endpoint = f'{self.TEST_URL}/oauth_token'
+        oauth2_token = 'HW9bB6oYWJywz6mAN_KyIBXlof15Pk'
+        self.stub_auth(json=self.TEST_APP_CRED_TOKEN_RESPONSE)
+        client_cre = v3.OAuth2ClientCredential(
+            base_http,
+            oauth2_endpoint=oauth2_endpoint,
+            oauth2_client_id=self.TEST_CLIENT_CRED_ID,
+            oauth2_client_secret=self.TEST_CLIENT_CRED_SECRET
+        )
+        oauth2_resp = {
+            'status_code': 200,
+            'json': {
+                'access_token': oauth2_token,
+                'expires_in': 3600,
+                'token_type': 'Bearer'
+            }
+        }
+        self.requests_mock.post(oauth2_endpoint,
+                                [oauth2_resp])
+
+        sess = session.Session(auth=client_cre)
+        initial_cache_id = client_cre.get_cache_id()
+
+        auth_head = sess.get_auth_headers()
+        self.assertEqual(self.TEST_TOKEN, auth_head['X-Auth-Token'])
+        self.assertEqual(f'Bearer {oauth2_token}', auth_head['Authorization'])
+
+        self.assertEqual(sess.auth.auth_ref.auth_token, self.TEST_TOKEN)
+        self.assertEqual(initial_cache_id, client_cre.get_cache_id())
+
+        resp_ok = {
+            'status_code': 200
+        }
+        self.requests_mock.post(f'{base_http}/test_api',
+                                [resp_ok])
+        resp = sess.post(f'{base_http}/test_api', authenticated=True)
+        self.assertRequestHeaderEqual('Authorization',
+                                      f'Bearer {oauth2_token}')
+        self.assertRequestHeaderEqual('X-Auth-Token', self.TEST_TOKEN)
+        self.assertEqual(200, resp.status_code)
+
+    def test_oauth2_client_credential_method_https(self):
+        self.TEST_URL = self.TEST_URL.replace('http:', 'https:')
+        base_https = self.TEST_URL
+        oauth2_endpoint = f'{base_https}/oauth_token'
+        oauth2_token = 'HW9bB6oYWJywz6mAN_KyIBXlof15Pk'
+        self.stub_auth(json=self.TEST_APP_CRED_TOKEN_RESPONSE)
+        client_cre = v3.OAuth2ClientCredential(
+            base_https,
+            oauth2_endpoint=oauth2_endpoint,
+            oauth2_client_id=self.TEST_CLIENT_CRED_ID,
+            oauth2_client_secret=self.TEST_CLIENT_CRED_SECRET
+        )
+        oauth2_resp = {
+            'status_code': 200,
+            'json': {
+                'access_token': oauth2_token,
+                'expires_in': 3600,
+                'token_type': 'Bearer'
+            }
+        }
+        self.requests_mock.post(oauth2_endpoint,
+                                [oauth2_resp])
+
+        sess = session.Session(auth=client_cre)
+        initial_cache_id = client_cre.get_cache_id()
+
+        auth_head = sess.get_auth_headers()
+        self.assertEqual(self.TEST_TOKEN, auth_head['X-Auth-Token'])
+        self.assertEqual(f'Bearer {oauth2_token}', auth_head['Authorization'])
+
+        self.assertEqual(sess.auth.auth_ref.auth_token, self.TEST_TOKEN)
+        self.assertEqual(initial_cache_id, client_cre.get_cache_id())
+
+        resp_ok = {
+            'status_code': 200
+        }
+        self.requests_mock.post(f'{base_https}/test_api',
+                                [resp_ok])
+        resp = sess.post(f'{base_https}/test_api', authenticated=True)
+        self.assertRequestHeaderEqual('Authorization',
+                                      f'Bearer {oauth2_token}')
+        self.assertRequestHeaderEqual('X-Auth-Token', self.TEST_TOKEN)
+        self.assertEqual(200, resp.status_code)
+
+    def test_oauth2_client_credential_method_base_header_none(self):
+        base_https = self.TEST_URL.replace('http:', 'https:')
+        oauth2_endpoint = f'{base_https}/oauth_token'
+        oauth2_token = 'HW9bB6oYWJywz6mAN_KyIBXlof15Pk'
+        with unittest.mock.patch(
+                'keystoneauth1.plugin.BaseAuthPlugin.'
+                'get_headers') as co_mock:
+            co_mock.return_value = None
+            client_cre = v3.OAuth2ClientCredential(
+                base_https,
+                oauth2_endpoint=oauth2_endpoint,
+                oauth2_client_id=self.TEST_CLIENT_CRED_ID,
+                oauth2_client_secret=self.TEST_CLIENT_CRED_SECRET
+            )
+            oauth2_resp = {
+                'status_code': 200,
+                'json': {
+                    'access_token': oauth2_token,
+                    'expires_in': 3600,
+                    'token_type': 'Bearer'
+                }
+            }
+            self.requests_mock.post(oauth2_endpoint,
+                                    [oauth2_resp])
+
+            sess = session.Session(auth=client_cre)
+            auth_head = sess.get_auth_headers()
+            self.assertNotIn('X-Auth-Token', auth_head)
+            self.assertEqual(f'Bearer {oauth2_token}',
+                             auth_head['Authorization'])
+
+    def test_oauth2_client_credential_method_rm_auth(self):
+        base_https = self.TEST_URL.replace('http:', 'https:')
+        base_http = self.TEST_URL
+        oauth2_endpoint = f'{base_https}/oauth_token'
+        oauth2_token = 'HW9bB6oYWJywz6mAN_KyIBXlof15Pk'
+        self.stub_auth(json=self.TEST_APP_CRED_TOKEN_RESPONSE)
+        client_cre = v3.OAuth2ClientCredential(
+            base_http,
+            oauth2_endpoint=oauth2_endpoint,
+            oauth2_client_id=self.TEST_CLIENT_CRED_ID,
+            oauth2_client_secret=self.TEST_CLIENT_CRED_SECRET
+        )
+        oauth2_resp = {
+            'status_code': 200,
+            'json': {
+                'access_token': oauth2_token,
+                'expires_in': 3600,
+                'token_type': 'Bearer'
+            }
+        }
+        self.requests_mock.post(oauth2_endpoint,
+                                [oauth2_resp])
+
+        sess = session.Session(auth=client_cre)
+        initial_cache_id = client_cre.get_cache_id()
+
+        auth_head = sess.get_auth_headers()
+        self.assertEqual(self.TEST_TOKEN, auth_head['X-Auth-Token'])
+        self.assertEqual(f'Bearer {oauth2_token}', auth_head['Authorization'])
+
+        self.assertEqual(sess.auth.auth_ref.auth_token, self.TEST_TOKEN)
+        self.assertEqual(initial_cache_id, client_cre.get_cache_id())
+
+        resp_ok = {
+            'status_code': 200
+        }
+        self.requests_mock.post(f'{base_http}/test_api',
+                                [resp_ok])
+        resp = sess.post(f'{base_http}/test_api', authenticated=True)
+        self.assertRequestHeaderEqual('Authorization',
+                                      f'Bearer {oauth2_token}')
+        self.assertRequestHeaderEqual('X-Auth-Token', self.TEST_TOKEN)
+        self.assertEqual(200, resp.status_code)
+
+    def test_oauth2_client_credential_method_other_not_rm_auth(self):
+        base_https = self.TEST_URL.replace('http:', 'https:')
+        other_auth_token = 'HW9bB6oYWJywz6mAN_KyIBXlof15Pk'
+        self.stub_auth(json=self.TEST_APP_CRED_TOKEN_RESPONSE)
+        with unittest.mock.patch(
+                'keystoneauth1.identity.v3.Password.get_headers') as co_mock:
+            co_mock.return_value = {
+                'X-Auth-Token': self.TEST_TOKEN,
+                'Authorization': other_auth_token
+            }
+            pass_auth = v3.Password(base_https,
+                                    username=self.TEST_USER,
+                                    password=self.TEST_PASS,
+                                    include_catalog=False)
+            sess = session.Session(auth=pass_auth)
+
+            resp_ok = {
+                'status_code': 200
+            }
+            self.requests_mock.post(f'{base_https}/test_api',
+                                    [resp_ok])
+            resp = sess.post(f'{base_https}/test_api', authenticated=True)
+            self.assertRequestHeaderEqual('Authorization', other_auth_token)
+            self.assertRequestHeaderEqual('X-Auth-Token', self.TEST_TOKEN)
+            self.assertEqual(200, resp.status_code)
+
+    def test_oauth2_client_credential_method_500(self):
+        self.TEST_URL = self.TEST_URL.replace('http:', 'https:')
+        base_https = self.TEST_URL
+        oauth2_endpoint = f'{base_https}/oauth_token'
+        self.stub_auth(json=self.TEST_APP_CRED_TOKEN_RESPONSE)
+        client_cre = v3.OAuth2ClientCredential(
+            base_https,
+            oauth2_endpoint=oauth2_endpoint,
+            oauth2_client_id=self.TEST_CLIENT_CRED_ID,
+            oauth2_client_secret=self.TEST_CLIENT_CRED_SECRET
+        )
+        oauth2_resp = {
+            'status_code': 500,
+            'json': {
+                'error': 'other_error',
+                'error_description':
+                    'Unknown error is occur.'
+            }
+        }
+        self.requests_mock.post(oauth2_endpoint,
+                                [oauth2_resp])
+
+        sess = session.Session(auth=client_cre)
+        err = self.assertRaises(ClientException, sess.get_auth_headers)
+        self.assertEqual('Unknown error is occur.',
+                         str(err))
+
+    def test_oauth2_client_credential_reauth_called_https(self):
+        base_https = self.TEST_URL.replace('http:', 'https:')
+        oauth2_endpoint = f'{base_https}/oauth_token'
+        oauth2_token = 'HW9bB6oYWJywz6mAN_KyIBXlof15Pk'
+        auth = v3.OAuth2ClientCredential(
+            base_https,
+            oauth2_endpoint=oauth2_endpoint,
+            oauth2_client_id='clientcredid',
+            oauth2_client_secret='secret'
+        )
+        oauth2_resp = {
+            'status_code': 200,
+            'json': {
+                'access_token': oauth2_token,
+                'expires_in': 3600,
+                'token_type': 'Bearer'
+            }
+        }
+        self.requests_mock.post(oauth2_endpoint,
+                                [oauth2_resp])
+
+        sess = session.Session(auth=auth)
+
+        resp_text = json.dumps(self.TEST_APP_CRED_TOKEN_RESPONSE)
+        resp_ok = {
+            'status_code': 200,
+            'headers': {
+                'Content-Type': 'application/json',
+                'x-subject-token': self.TEST_TOKEN
+            },
+            'text': resp_text
+        }
+        self.requests_mock.post(f'{base_https}/auth/tokens',
+                                [resp_ok,
+                                 {'text': 'Failed', 'status_code': 401},
+                                 resp_ok])
+
+        resp = sess.post(f'{base_https}/auth/tokens', authenticated=True)
+        self.assertRequestHeaderEqual('Authorization',
+                                      f'Bearer {oauth2_token}')
+        self.assertEqual(200, resp.status_code)
+        self.assertEqual(resp_text, resp.text)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystoneauth1-4.6.0/keystoneauth1/tests/unit/loading/test_v3.py 
new/keystoneauth1-5.1.2/keystoneauth1/tests/unit/loading/test_v3.py
--- old/keystoneauth1-4.6.0/keystoneauth1/tests/unit/loading/test_v3.py 
2022-05-20 14:26:02.000000000 +0200
+++ new/keystoneauth1-5.1.2/keystoneauth1/tests/unit/loading/test_v3.py 
2023-02-13 16:48:53.000000000 +0100
@@ -486,3 +486,56 @@
                           username=uuid.uuid4().hex,
                           project_name=uuid.uuid4().hex,
                           project_domain_id=uuid.uuid4().hex)
+
+
+class V3Oauth2ClientCredentialTests(utils.TestCase):
+
+    def setUp(self):
+        super(V3Oauth2ClientCredentialTests, self).setUp()
+
+        self.auth_url = uuid.uuid4().hex
+
+    def create(self, **kwargs):
+        kwargs.setdefault('auth_url', self.auth_url)
+        loader = loading.get_plugin_loader('v3oauth2clientcredential')
+        return loader.load_from_options(**kwargs)
+
+    def test_basic(self):
+        id = uuid.uuid4().hex
+        secret = uuid.uuid4().hex
+        oauth2_endpoint = "https://localhost/token";
+
+        client_cred = self.create(oauth2_endpoint=oauth2_endpoint,
+                                  oauth2_client_id=id,
+                                  oauth2_client_secret=secret)
+
+        client_method = client_cred.auth_methods[0]
+        self.assertEqual(id, client_method.oauth2_client_id)
+        self.assertEqual(secret, client_method.oauth2_client_secret)
+        self.assertEqual(oauth2_endpoint, client_method.oauth2_endpoint)
+
+        self.assertEqual(id, client_cred._oauth2_client_id)
+        self.assertEqual(secret, client_cred._oauth2_client_secret)
+        self.assertEqual(oauth2_endpoint, client_cred._oauth2_endpoint)
+
+    def test_without_oauth2_endpoint(self):
+        id = uuid.uuid4().hex
+        secret = uuid.uuid4().hex
+        self.assertRaises(exceptions.OptionError,
+                          self.create,
+                          oauth2_client_id=id,
+                          oauth2_client_secret=secret)
+
+    def test_without_client_id(self):
+        oauth2_endpoint = "https://localhost/token";
+        self.assertRaises(exceptions.OptionError,
+                          self.create,
+                          oauth2_endpoint=oauth2_endpoint,
+                          oauth2_client_secret=uuid.uuid4().hex)
+
+    def test_without_secret(self):
+        oauth2_endpoint = "https://localhost/token";
+        self.assertRaises(exceptions.OptionError,
+                          self.create,
+                          oauth2_endpoint=oauth2_endpoint,
+                          oauth2_client_id=uuid.uuid4().hex)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystoneauth1-4.6.0/keystoneauth1/tests/unit/test_discovery.py 
new/keystoneauth1-5.1.2/keystoneauth1/tests/unit/test_discovery.py
--- old/keystoneauth1-4.6.0/keystoneauth1/tests/unit/test_discovery.py  
2022-05-20 14:26:02.000000000 +0200
+++ new/keystoneauth1-5.1.2/keystoneauth1/tests/unit/test_discovery.py  
2023-02-13 16:48:53.000000000 +0100
@@ -1321,7 +1321,8 @@
 
     def test_run_discovery_auth(self):
         url = 'https://example.com'
-        headers = {'Accept': 'application/json'}
+        headers = {'Accept': 'application/json',
+                   'OpenStack-API-Version': 'version header test'}
 
         session = mock.Mock()
         session.get.side_effect = [
@@ -1332,7 +1333,8 @@
         ]
 
         try:
-            discover.get_version_data(session, url)
+            discover.get_version_data(
+                session, url, version_header='version header test')
         except exceptions.BadRequest:
             pass
         # Only one call with 'url'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keystoneauth1-4.6.0/keystoneauth1.egg-info/PKG-INFO 
new/keystoneauth1-5.1.2/keystoneauth1.egg-info/PKG-INFO
--- old/keystoneauth1-4.6.0/keystoneauth1.egg-info/PKG-INFO     2022-05-20 
14:26:32.000000000 +0200
+++ new/keystoneauth1-5.1.2/keystoneauth1.egg-info/PKG-INFO     2023-02-13 
16:49:31.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: keystoneauth1
-Version: 4.6.0
+Version: 5.1.2
 Summary: Authentication Library for OpenStack Identity
 Home-page: https://docs.openstack.org/keystoneauth/latest/
 Author: OpenStack
@@ -54,9 +54,8 @@
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: 3 :: Only
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
 Provides-Extra: betamax
 Provides-Extra: kerberos
 Provides-Extra: oauth1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystoneauth1-4.6.0/keystoneauth1.egg-info/SOURCES.txt 
new/keystoneauth1-5.1.2/keystoneauth1.egg-info/SOURCES.txt
--- old/keystoneauth1-4.6.0/keystoneauth1.egg-info/SOURCES.txt  2022-05-20 
14:26:32.000000000 +0200
+++ new/keystoneauth1-5.1.2/keystoneauth1.egg-info/SOURCES.txt  2023-02-13 
16:49:31.000000000 +0100
@@ -99,6 +99,7 @@
 keystoneauth1/identity/v3/federation.py
 keystoneauth1/identity/v3/k2k.py
 keystoneauth1/identity/v3/multi_factor.py
+keystoneauth1/identity/v3/oauth2_client_credential.py
 keystoneauth1/identity/v3/oidc.py
 keystoneauth1/identity/v3/password.py
 keystoneauth1/identity/v3/receipt.py
@@ -213,6 +214,7 @@
 releasenotes/notes/api-sig-error-guideline-handler.yaml
 releasenotes/notes/basic-http-auth-45bea4298209df75.yaml
 releasenotes/notes/bp-application-credentials-416a1f8bb2311e04.yaml
+releasenotes/notes/bp-oauth2-client-credentials-ext-06271700d4f33a7e.yaml
 releasenotes/notes/bp-system-scope-29e9c597039ddb1e.yaml
 releasenotes/notes/bug-1582774-49af731b6dfc6f2f.yaml
 releasenotes/notes/bug-1614688-c4a1bd54f4ba5644.yaml
@@ -229,6 +231,7 @@
 releasenotes/notes/client-side-rate-limiting-dec43fc9b54f5b70.yaml
 releasenotes/notes/collect-timing-85f007f0d86c8b26.yaml
 releasenotes/notes/drop-py-2-7-f90c67a5db0dfeb8.yaml
+releasenotes/notes/drop-python-3-6-and-3-7-c407d5898c5eafec.yaml
 releasenotes/notes/drop-python-3.5-362bb9d47f830353.yaml
 releasenotes/notes/expose-endpoint-status-6195a6b76d8a8de8.yaml
 releasenotes/notes/filter-versions-service-type-763af68092344b7a.yaml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystoneauth1-4.6.0/keystoneauth1.egg-info/entry_points.txt 
new/keystoneauth1-5.1.2/keystoneauth1.egg-info/entry_points.txt
--- old/keystoneauth1-4.6.0/keystoneauth1.egg-info/entry_points.txt     
2022-05-20 14:26:32.000000000 +0200
+++ new/keystoneauth1-5.1.2/keystoneauth1.egg-info/entry_points.txt     
2023-02-13 16:49:31.000000000 +0100
@@ -12,6 +12,7 @@
 v3kerberos = keystoneauth1.extras.kerberos._loading:Kerberos
 v3multifactor = keystoneauth1.loading._plugins.identity.v3:MultiFactor
 v3oauth1 = keystoneauth1.extras.oauth1._loading:V3OAuth1
+v3oauth2clientcredential = 
keystoneauth1.loading._plugins.identity.v3:OAuth2ClientCredential
 v3oidcaccesstoken = 
keystoneauth1.loading._plugins.identity.v3:OpenIDConnectAccessToken
 v3oidcauthcode = 
keystoneauth1.loading._plugins.identity.v3:OpenIDConnectAuthorizationCode
 v3oidcclientcredentials = 
keystoneauth1.loading._plugins.identity.v3:OpenIDConnectClientCredentials
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keystoneauth1-4.6.0/keystoneauth1.egg-info/pbr.json 
new/keystoneauth1-5.1.2/keystoneauth1.egg-info/pbr.json
--- old/keystoneauth1-4.6.0/keystoneauth1.egg-info/pbr.json     2022-05-20 
14:26:32.000000000 +0200
+++ new/keystoneauth1-5.1.2/keystoneauth1.egg-info/pbr.json     2023-02-13 
16:49:31.000000000 +0100
@@ -1 +1 @@
-{"git_version": "f194e6a", "is_release": true}
\ No newline at end of file
+{"git_version": "6ee21bd", "is_release": true}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystoneauth1-4.6.0/keystoneauth1.egg-info/requires.txt 
new/keystoneauth1-5.1.2/keystoneauth1.egg-info/requires.txt
--- old/keystoneauth1-4.6.0/keystoneauth1.egg-info/requires.txt 2022-05-20 
14:26:32.000000000 +0200
+++ new/keystoneauth1-5.1.2/keystoneauth1.egg-info/requires.txt 2023-02-13 
16:49:31.000000000 +0100
@@ -25,15 +25,14 @@
 betamax>=0.7.0
 coverage!=4.4,>=4.0
 fixtures>=3.0.0
-flake8-docstrings==0.2.1.post1
+flake8-docstrings~=1.6.0
 flake8-import-order>=0.17.1
-hacking<3.1.0,>=3.0.1
+hacking~=4.1.0
 lxml>=4.2.0
 oauthlib>=0.6.2
 oslo.config>=5.2.0
 oslo.utils>=3.33.0
 oslotest>=3.2.0
-pycodestyle<2.6.0,>=2.0.0
 reno>=3.1.0
 requests-kerberos>=0.8.0
 requests-mock>=1.2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystoneauth1-4.6.0/releasenotes/notes/bp-oauth2-client-credentials-ext-06271700d4f33a7e.yaml
 
new/keystoneauth1-5.1.2/releasenotes/notes/bp-oauth2-client-credentials-ext-06271700d4f33a7e.yaml
--- 
old/keystoneauth1-4.6.0/releasenotes/notes/bp-oauth2-client-credentials-ext-06271700d4f33a7e.yaml
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/keystoneauth1-5.1.2/releasenotes/notes/bp-oauth2-client-credentials-ext-06271700d4f33a7e.yaml
   2023-02-13 16:48:53.000000000 +0100
@@ -0,0 +1,10 @@
+---
+features:
+  - |
+    [`blueprint oauth2-client-credentials-ext 
<https://blueprints.launchpad.net/keystone/+spec/oauth2-client-credentials-ext>`_]
+    Added a new OAuth2ClientCredential plugin, accessible via the
+    'v3oauth2clientcredential' entry point, making possible to authenticate
+    using an application credentials as an OAuth2.0 client credentials.
+    Keystoneauth can now be used to access the OpenStack APIs that use the
+    keystone middleware to support OAuth2.0 client credentials authentication
+    through the keystone identity server.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystoneauth1-4.6.0/releasenotes/notes/drop-python-3-6-and-3-7-c407d5898c5eafec.yaml
 
new/keystoneauth1-5.1.2/releasenotes/notes/drop-python-3-6-and-3-7-c407d5898c5eafec.yaml
--- 
old/keystoneauth1-4.6.0/releasenotes/notes/drop-python-3-6-and-3-7-c407d5898c5eafec.yaml
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/keystoneauth1-5.1.2/releasenotes/notes/drop-python-3-6-and-3-7-c407d5898c5eafec.yaml
    2023-02-13 16:48:53.000000000 +0100
@@ -0,0 +1,5 @@
+---
+upgrade:
+  - |
+    Python 3.6 & 3.7 support has been dropped. The minimum version of Python
+    now supported is Python 3.8.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keystoneauth1-4.6.0/setup.cfg 
new/keystoneauth1-5.1.2/setup.cfg
--- old/keystoneauth1-4.6.0/setup.cfg   2022-05-20 14:26:32.638197700 +0200
+++ new/keystoneauth1-5.1.2/setup.cfg   2023-02-13 16:49:32.015777300 +0100
@@ -6,7 +6,7 @@
 author = OpenStack
 author_email = [email protected]
 home_page = https://docs.openstack.org/keystoneauth/latest/
-python_equires = >=3.6
+python_equires = >=3.8
 classifier = 
        Environment :: OpenStack
        Intended Audience :: Information Technology
@@ -17,9 +17,8 @@
        Programming Language :: Python :: Implementation :: CPython
        Programming Language :: Python :: 3 :: Only
        Programming Language :: Python :: 3
-       Programming Language :: Python :: 3.6
-       Programming Language :: Python :: 3.7
        Programming Language :: Python :: 3.8
+       Programming Language :: Python :: 3.9
 
 [files]
 packages = 
@@ -61,6 +60,7 @@
        v3samlpassword = keystoneauth1.extras._saml2._loading:Saml2Password
        v3applicationcredential = 
keystoneauth1.loading._plugins.identity.v3:ApplicationCredential
        v3multifactor = keystoneauth1.loading._plugins.identity.v3:MultiFactor
+       v3oauth2clientcredential = 
keystoneauth1.loading._plugins.identity.v3:OAuth2ClientCredential
 
 [egg_info]
 tag_build = 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keystoneauth1-4.6.0/test-requirements.txt 
new/keystoneauth1-5.1.2/test-requirements.txt
--- old/keystoneauth1-4.6.0/test-requirements.txt       2022-05-20 
14:26:02.000000000 +0200
+++ new/keystoneauth1-5.1.2/test-requirements.txt       2023-02-13 
16:48:53.000000000 +0100
@@ -2,10 +2,9 @@
 # of appearance. Changing the order has an impact on the overall integration
 # process, which may cause wedges in the gate later.
 
-hacking>=3.0.1,<3.1.0 # Apache-2.0
-flake8-docstrings==0.2.1.post1 # MIT
+hacking~=4.1.0 # Apache-2.0
+flake8-docstrings~=1.6.0 # MIT
 flake8-import-order>=0.17.1 #LGPLv3
-pycodestyle>=2.0.0,<2.6.0 # MIT
 
 bandit<1.6.0,>=1.1.0 # Apache-2.0
 coverage!=4.4,>=4.0 # Apache-2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keystoneauth1-4.6.0/tox.ini 
new/keystoneauth1-5.1.2/tox.ini
--- old/keystoneauth1-4.6.0/tox.ini     2022-05-20 14:26:02.000000000 +0200
+++ new/keystoneauth1-5.1.2/tox.ini     2023-02-13 16:48:53.000000000 +0100
@@ -1,7 +1,6 @@
 [tox]
 minversion = 3.1.1
-skipsdist = True
-envlist = py38,pep8,releasenotes
+envlist = py3,pep8,releasenotes
 ignore_basepython_conflict = True
 
 [testenv]
@@ -14,7 +13,7 @@
     -r{toxinidir}/test-requirements.txt
     -r{toxinidir}/requirements.txt
 commands = stestr run {posargs}
-whitelist_externals =
+allowlist_externals =
   bash
 basepython = python3
 
@@ -53,10 +52,12 @@
 # D102: Missing docstring in public method
 # D103: Missing docstring in public function
 # D104: Missing docstring in public package
+# D107: Missing docstring in __init__
 # D203: 1 blank line required before class docstring (deprecated in pep257)
+# D401: First line should be in imperative mood; try rephrasing
 # W503 line break before binary operator
 # W504 line break after binary operator
-ignore = D100,D101,D102,D103,D104,D203,W503,W504
+ignore = D100,D101,D102,D103,D104,D107,D203,D401,W503,W504
 # H106: Don’t put vim configuration in source files
 # H203: Use assertIs(Not)None to check for None
 enable-extensions=H106,H203
@@ -83,7 +84,7 @@
     SPHINX_APIDOC_OPTIONS=noindex,members,undoc-members,show-inheritance
 envdir = {toxworkdir}/docs
 deps = {[testenv:docs]deps}
-whitelist_externals =
+allowlist_externals =
   make
   rm
 commands =

Reply via email to