Bump Python version used for linters to 3.9

We should have done this ages ago. Do it now. The main change is that
this lets us use the newly subscriptable 'type' [1], 'list' [2], and
'frozenset' [3] introduced in this version.

[1] https://docs.python.org/3/library/typing.html#typing.Type
[2] https://docs.python.org/3/library/typing.html#typing.List
[3] https://docs.python.org/3/library/typing.html#typing.FrozenSet

Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
Change-Id: Idf13dd34c54534a6572beaa4675498d7e9a3be52
This commit is contained in:
Stephen Finucane
2025-05-07 12:24:37 +01:00
parent 1c1de17ed5
commit ec28703dc3
19 changed files with 38 additions and 45 deletions

View File

@@ -93,7 +93,7 @@ class FairSemaphore:
def __exit__(
self,
exc_type: ty.Optional[ty.Type[BaseException]],
exc_type: ty.Optional[type[BaseException]],
exc_value: ty.Optional[BaseException],
traceback: ty.Optional[types.TracebackType],
) -> None:

View File

@@ -57,7 +57,7 @@ class AccessInfo:
Provides helper methods for extracting useful values from that token.
"""
_service_catalog_class: ty.Type[service_catalog.ServiceCatalog]
_service_catalog_class: type[service_catalog.ServiceCatalog]
_data: ty.Any
def __init__(

View File

@@ -10,7 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import typing as ty
from keystoneauth1.extras import _saml2
from keystoneauth1 import loading
@@ -19,7 +18,7 @@ from keystoneauth1.loading import opts
class Saml2Password(loading.BaseFederationLoader[_saml2.V3Saml2Password]):
@property
def plugin_class(self) -> ty.Type[_saml2.V3Saml2Password]:
def plugin_class(self) -> type[_saml2.V3Saml2Password]:
return _saml2.V3Saml2Password
@property
@@ -51,7 +50,7 @@ class Saml2Password(loading.BaseFederationLoader[_saml2.V3Saml2Password]):
class ADFSPassword(loading.BaseFederationLoader[_saml2.V3ADFSPassword]):
@property
def plugin_class(self) -> ty.Type[_saml2.V3ADFSPassword]:
def plugin_class(self) -> type[_saml2.V3ADFSPassword]:
return _saml2.V3ADFSPassword
@property

View File

@@ -20,7 +20,7 @@ from keystoneauth1.loading import opts
class Kerberos(loading.BaseV3Loader[kerberos.Kerberos]):
@property
def plugin_class(self) -> ty.Type[kerberos.Kerberos]:
def plugin_class(self) -> type[kerberos.Kerberos]:
return kerberos.Kerberos
@property
@@ -59,7 +59,7 @@ class Kerberos(loading.BaseV3Loader[kerberos.Kerberos]):
class MappedKerberos(loading.BaseFederationLoader[kerberos.MappedKerberos]):
@property
def plugin_class(self) -> ty.Type[kerberos.MappedKerberos]:
def plugin_class(self) -> type[kerberos.MappedKerberos]:
return kerberos.MappedKerberos
@property

View File

@@ -10,7 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import typing as ty
from keystoneauth1.extras.oauth1 import v3
from keystoneauth1 import loading
@@ -21,7 +20,7 @@ from keystoneauth1.loading import opts
# include the scoping options like project-id in the option list
class V3OAuth1(loading.BaseIdentityLoader[v3.OAuth1]):
@property
def plugin_class(self) -> ty.Type[v3.OAuth1]:
def plugin_class(self) -> type[v3.OAuth1]:
return v3.OAuth1
@property

View File

@@ -362,7 +362,7 @@ class AuthMethod(metaclass=abc.ABCMeta):
@ty.runtime_checkable
class SupportsMultiFactor(ty.Protocol):
_auth_method_class: ty.ClassVar[ty.Type[AuthMethod]]
_auth_method_class: ty.ClassVar[type[AuthMethod]]
class AuthConstructor(Auth, metaclass=abc.ABCMeta):
@@ -376,7 +376,7 @@ class AuthConstructor(Auth, metaclass=abc.ABCMeta):
creates the auth plugin with only that authentication method.
"""
_auth_method_class: ty.ClassVar[ty.Type[AuthMethod]]
_auth_method_class: ty.ClassVar[type[AuthMethod]]
def __init__(
self,

View File

@@ -10,7 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import typing as ty
from keystoneauth1 import loading
from keystoneauth1.loading import opts
@@ -31,7 +30,7 @@ class AdminToken(loading.BaseLoader[token_endpoint.Token]):
"""
@property
def plugin_class(self) -> ty.Type[token_endpoint.Token]:
def plugin_class(self) -> type[token_endpoint.Token]:
return token_endpoint.Token
def get_options(self) -> list[opts.Opt]:

View File

@@ -10,7 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import typing as ty
from keystoneauth1 import http_basic
from keystoneauth1 import loading
@@ -30,7 +29,7 @@ class HTTPBasicAuth(loading.BaseLoader[http_basic.HTTPBasicAuth]):
"""
@property
def plugin_class(self) -> ty.Type[http_basic.HTTPBasicAuth]:
def plugin_class(self) -> type[http_basic.HTTPBasicAuth]:
return http_basic.HTTPBasicAuth
def get_options(self) -> list[opts.Opt]:

View File

@@ -10,7 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import typing as ty
from keystoneauth1 import identity
from keystoneauth1 import loading
@@ -31,7 +30,7 @@ class Token(loading.BaseGenericLoader[identity.Token]):
"""
@property
def plugin_class(self) -> ty.Type[identity.Token]:
def plugin_class(self) -> type[identity.Token]:
return identity.Token
def get_options(self) -> list[opts.Opt]:
@@ -60,7 +59,7 @@ class Password(loading.BaseGenericLoader[identity.Password]):
"""
@property
def plugin_class(self) -> ty.Type[identity.Password]:
def plugin_class(self) -> type[identity.Password]:
return identity.Password
def get_options(self) -> list[opts.Opt]:

View File

@@ -10,7 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import typing as ty
from keystoneauth1 import identity
from keystoneauth1 import loading
@@ -27,7 +26,7 @@ class Token(loading.BaseV2Loader[identity.V2Token]):
"""
@property
def plugin_class(self) -> ty.Type[identity.V2Token]:
def plugin_class(self) -> type[identity.V2Token]:
return identity.V2Token
def get_options(self) -> list[opts.Opt]:
@@ -46,7 +45,7 @@ class Password(loading.BaseV2Loader[identity.V2Password]):
"""
@property
def plugin_class(self) -> ty.Type[identity.V2Password]:
def plugin_class(self) -> type[identity.V2Password]:
return identity.V2Password
def get_options(self) -> list[opts.Opt]:

View File

@@ -54,7 +54,7 @@ class Password(loading.BaseV3Loader[identity.V3Password]):
"""
@property
def plugin_class(self) -> ty.Type[identity.V3Password]:
def plugin_class(self) -> type[identity.V3Password]:
return identity.V3Password
def get_options(self) -> list[opts.Opt]:
@@ -90,7 +90,7 @@ class Token(loading.BaseV3Loader[identity.V3Token]):
"""
@property
def plugin_class(self) -> ty.Type[identity.V3Token]:
def plugin_class(self) -> type[identity.V3Token]:
return identity.V3Token
def get_options(self) -> list[opts.Opt]:
@@ -177,7 +177,7 @@ class OpenIDConnectClientCredentials(
"""Authenticate with the OIDC Client Credentials flow."""
@property
def plugin_class(self) -> ty.Type[identity.V3OidcClientCredentials]:
def plugin_class(self) -> type[identity.V3OidcClientCredentials]:
return identity.V3OidcClientCredentials
def get_options(self) -> list[opts.Opt]:
@@ -190,7 +190,7 @@ class OpenIDConnectPassword(_OpenIDConnectBase[identity.V3OidcPassword]):
"""Authenticate with the OIDC Resource Owner Password Credentials flow."""
@property
def plugin_class(self) -> ty.Type[identity.V3OidcPassword]:
def plugin_class(self) -> type[identity.V3OidcPassword]:
return identity.V3OidcPassword
def get_options(self) -> list[opts.Opt]:
@@ -220,7 +220,7 @@ class OpenIDConnectAuthorizationCode(
"""Authenticate with the OIDC Authorization Code flow."""
@property
def plugin_class(self) -> ty.Type[identity.V3OidcAuthorizationCode]:
def plugin_class(self) -> type[identity.V3OidcAuthorizationCode]:
return identity.V3OidcAuthorizationCode
def get_options(self) -> list[opts.Opt]:
@@ -250,7 +250,7 @@ class OpenIDConnectAccessToken(
"""Authenticate with the OIDC Access Token flow."""
@property
def plugin_class(self) -> ty.Type[identity.V3OidcAccessToken]:
def plugin_class(self) -> type[identity.V3OidcAccessToken]:
return identity.V3OidcAccessToken
def get_options(self) -> list[opts.Opt]:
@@ -275,7 +275,7 @@ class OpenIDConnectDeviceAuthorization(
"""Authenticate with the OAuth 2.0 Device Authorization flow."""
@property
def plugin_class(self) -> ty.Type[identity.V3OidcDeviceAuthorization]:
def plugin_class(self) -> type[identity.V3OidcDeviceAuthorization]:
return identity.V3OidcDeviceAuthorization
def get_options(self) -> list[opts.Opt]:
@@ -312,7 +312,7 @@ class TOTP(loading.BaseV3Loader[identity.V3TOTP]):
"""
@property
def plugin_class(self) -> ty.Type[identity.V3TOTP]:
def plugin_class(self) -> type[identity.V3TOTP]:
return identity.V3TOTP
def get_options(self) -> list[opts.Opt]:
@@ -342,7 +342,7 @@ class TokenlessAuth(loading.BaseLoader[identity.V3TokenlessAuth]):
"""Authenticate without a token, using an X.509 certificate."""
@property
def plugin_class(self) -> ty.Type[identity.V3TokenlessAuth]:
def plugin_class(self) -> type[identity.V3TokenlessAuth]:
return identity.V3TokenlessAuth
def get_options(self) -> list[opts.Opt]:
@@ -407,7 +407,7 @@ class ApplicationCredential(
"""
@property
def plugin_class(self) -> ty.Type[identity.V3ApplicationCredential]:
def plugin_class(self) -> type[identity.V3ApplicationCredential]:
return identity.V3ApplicationCredential
def get_options(self) -> list[opts.Opt]:
@@ -466,7 +466,7 @@ class MultiFactor(loading.BaseV3Loader[identity.V3MultiFactor]):
self._methods = None
@property
def plugin_class(self) -> ty.Type[identity.V3MultiFactor]:
def plugin_class(self) -> type[identity.V3MultiFactor]:
return identity.V3MultiFactor
def get_options(self) -> list[opts.Opt]:
@@ -508,7 +508,7 @@ class OAuth2ClientCredential(
"""Authenticate with an OAuth2.0 client credential."""
@property
def plugin_class(self) -> ty.Type[identity.V3OAuth2ClientCredential]:
def plugin_class(self) -> type[identity.V3OAuth2ClientCredential]:
return identity.V3OAuth2ClientCredential
def get_options(self) -> list[opts.Opt]:
@@ -558,7 +558,7 @@ class OAuth2mTlsClientCredential(
"""Authenticate with an OAuth2.0 mTLS client credential."""
@property
def plugin_class(self) -> ty.Type[identity.V3OAuth2mTlsClientCredential]:
def plugin_class(self) -> type[identity.V3OAuth2mTlsClientCredential]:
return identity.V3OAuth2mTlsClientCredential
def get_options(self) -> list[opts.Opt]:

View File

@@ -10,7 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import typing as ty
from keystoneauth1 import loading
from keystoneauth1.loading import opts
@@ -30,7 +29,7 @@ class NoAuth(loading.BaseLoader[noauth.NoAuth]):
"""
@property
def plugin_class(self) -> ty.Type[noauth.NoAuth]:
def plugin_class(self) -> type[noauth.NoAuth]:
return noauth.NoAuth
def get_options(self) -> list[opts.Opt]:

View File

@@ -34,7 +34,7 @@ __all__ = (
class Adapter(base._BaseLoader[adapter.Adapter]):
@property
def plugin_class(self) -> ty.Type[adapter.Adapter]:
def plugin_class(self) -> type[adapter.Adapter]:
return adapter.Adapter
def get_options(self) -> list['opts.Opt']:

View File

@@ -42,7 +42,7 @@ def _auth_plugin_available(ext: extension.Extension) -> bool:
return ty.cast(bool, ext.obj.available)
def get_available_plugin_names() -> ty.FrozenSet[str]:
def get_available_plugin_names() -> frozenset[str]:
"""Get the names of all the plugins that are available on the system.
This is particularly useful for help and error text to prompt a user for
@@ -116,7 +116,7 @@ def get_plugin_options(name: str) -> list['opts.Opt']:
class _BaseLoader(ty.Generic[T], metaclass=abc.ABCMeta):
@property
def plugin_class(self) -> ty.Type[T]:
def plugin_class(self) -> type[T]:
raise NotImplementedError()
def create_plugin(self, **kwargs: ty.Any) -> T:

View File

@@ -66,7 +66,7 @@ class Opt:
def __init__(
self,
name: str,
type: ty.Type[ty.Any] = str,
type: type[ty.Any] = str,
help: ty.Optional[str] = None,
secret: bool = False,
dest: ty.Optional[str] = None,
@@ -141,7 +141,7 @@ class Opt:
return [f'--os-{o.name}' for o in self._all_opts]
@property
def argparse_envvars(self) -> ty.List[str]:
def argparse_envvars(self) -> list[str]:
return [
'OS_{}'.format(o.name.replace('-', '_').upper())
for o in self._all_opts

View File

@@ -51,7 +51,7 @@ def _positive_non_zero_float(
class Session(base._BaseLoader[session.Session]):
@property
def plugin_class(self) -> ty.Type[session.Session]:
def plugin_class(self) -> type[session.Session]:
return session.Session
def get_options(self) -> list['opts.Opt']:

View File

@@ -35,7 +35,7 @@ BaseAuthPluginT = ty.TypeVar(
class ConnectionParams(ty.TypedDict):
# https://github.com/python/typeshed/blob/24c78b9e0/stubs/requests/requests/sessions.pyi#L82
cert: ty_ext.NotRequired[ty.Union[str, ty.Tuple[str, str], None]]
cert: ty_ext.NotRequired[ty.Union[str, tuple[str, str], None]]
# https://github.com/python/typeshed/blob/24c78b9e0/stubs/requests/requests/sessions.pyi#L108
verify: ty_ext.NotRequired[ty.Union[bool, str, None]]

View File

@@ -118,7 +118,7 @@ class NoOpSemaphore:
def __exit__(
self,
exc_type: ty.Optional[ty.Type[BaseException]],
exc_type: ty.Optional[type[BaseException]],
exc_value: ty.Optional[BaseException],
traceback: ty.Optional[types.TracebackType],
) -> None:

View File

@@ -42,7 +42,7 @@ disallow_untyped_calls = false
[tool.ruff]
line-length = 79
target-version = "py38"
target-version = "py39"
[tool.ruff.lint]
# enable the following rule classes: