Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-osc-lib for openSUSE:Factory 
checked in at 2026-05-19 17:48:21
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-osc-lib (Old)
 and      /work/SRC/openSUSE:Factory/.python-osc-lib.new.1966 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-osc-lib"

Tue May 19 17:48:21 2026 rev:26 rq:1353845 version:4.6.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-osc-lib/python-osc-lib.changes    
2026-03-09 16:31:57.279780392 +0100
+++ /work/SRC/openSUSE:Factory/.python-osc-lib.new.1966/python-osc-lib.changes  
2026-05-19 17:48:26.979849058 +0200
@@ -1,0 +2,16 @@
+Mon May 18 13:23:09 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 4.6.0:
+  * clientmanager: Add filters for
+    ClientManger.is_service_available
+  * fix: unbound variable when both values are false
+  * typing: union-attrs on find_project()
+  * typing: Use objects from typing
+  * typing: Use objects from collections.abc
+  * typing: Broaden return type of
+    OpenStackShell.build_option_parser
+  * ruff: Configure hacking as external linter
+  * Return list from sort_items
+  * Update master for stable/2026.1
+
+-------------------------------------------------------------------

Old:
----
  osc_lib-4.4.0.tar.gz

New:
----
  osc_lib-4.6.0.tar.gz

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

Other differences:
------------------
++++++ python-osc-lib.spec ++++++
--- /var/tmp/diff_new_pack.MERVkv/_old  2026-05-19 17:48:27.679878015 +0200
+++ /var/tmp/diff_new_pack.MERVkv/_new  2026-05-19 17:48:27.679878015 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           python-osc-lib
-Version:        4.4.0
+Version:        4.6.0
 Release:        0
 Summary:        OpenStackClient Library
 License:        Apache-2.0
@@ -27,13 +27,15 @@
 BuildRequires:  %{python_module cliff >= 4.9.0}
 BuildRequires:  %{python_module fixtures}
 BuildRequires:  %{python_module keystoneauth1 >= 5.10.0}
-BuildRequires:  %{python_module openstacksdk >= 4.7.1}
+BuildRequires:  %{python_module openstacksdk >= 4.12.0}
 BuildRequires:  %{python_module oslo.i18n >= 6.6.0}
 BuildRequires:  %{python_module oslo.utils >= 9.1.0}
 BuildRequires:  %{python_module oslotest}
 BuildRequires:  %{python_module osprofiler}
+BuildRequires:  %{python_module pbr >= 6.1.1}
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module platformdirs}
+BuildRequires:  %{python_module requests >= 2.14.2}
 BuildRequires:  %{python_module requests-mock}
 BuildRequires:  %{python_module simplejson}
 BuildRequires:  %{python_module stestr}
@@ -43,11 +45,12 @@
 BuildRequires:  openstack-macros
 Requires:       python-cliff >= 4.9.0
 Requires:       python-keystoneauth1 >= 5.10.0
-Requires:       python-openstacksdk >= 4.7.1
+Requires:       python-openstacksdk >= 4.12.0
 Requires:       python-oslo.i18n >= 6.6.0
 Requires:       python-oslo.utils >= 9.1.0
 Requires:       python-pbr >= 2.0.0
 Requires:       python-platformdirs
+Requires:       python-requests >= 2.14.2
 Requires:       python-simplejson
 Requires:       python-stevedore >= 1.20.0
 %if "python%{python_nodots_ver}" == "%{primary_python}"

++++++ osc_lib-4.4.0.tar.gz -> osc_lib-4.6.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/AUTHORS new/osc_lib-4.6.0/AUTHORS
--- old/osc_lib-4.4.0/AUTHORS   2026-02-17 15:51:27.000000000 +0100
+++ new/osc_lib-4.6.0/AUTHORS   2026-05-05 13:36:39.000000000 +0200
@@ -42,6 +42,7 @@
 Dean Troyer <[email protected]>
 Dina Belova <[email protected]>
 Dmitry Tantsur <[email protected]>
+Doug Goldstein <[email protected]>
 Doug Hellmann <[email protected]>
 Doug Hellmann <[email protected]>
 Dougal Matthews <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/ChangeLog new/osc_lib-4.6.0/ChangeLog
--- old/osc_lib-4.4.0/ChangeLog 2026-02-17 15:51:27.000000000 +0100
+++ new/osc_lib-4.6.0/ChangeLog 2026-05-05 13:36:39.000000000 +0200
@@ -1,6 +1,23 @@
 CHANGES
 =======
 
+4.6.0
+-----
+
+* clientmanager: Add filters for ClientManger.is\_service\_available
+* fix: unbound variable when both values are false
+* typing: union-attrs on find\_project()
+
+4.5.0
+-----
+
+* typing: Use objects from typing
+* typing: Use objects from collections.abc
+* typing: Broaden return type of OpenStackShell.build\_option\_parser
+* ruff: Configure hacking as external linter
+* Return list from sort\_items
+* Update master for stable/2026.1
+
 4.4.0
 -----
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/PKG-INFO new/osc_lib-4.6.0/PKG-INFO
--- old/osc_lib-4.4.0/PKG-INFO  2026-02-17 15:51:27.580233800 +0100
+++ new/osc_lib-4.6.0/PKG-INFO  2026-05-05 13:36:39.612447000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: osc-lib
-Version: 4.4.0
+Version: 4.6.0
 Summary: OpenStackClient Library
 Author-email: OpenStack <[email protected]>
 License: Apache-2.0
@@ -24,7 +24,7 @@
 License-File: LICENSE
 Requires-Dist: cliff>=4.9.0
 Requires-Dist: keystoneauth1>=5.10.0
-Requires-Dist: openstacksdk>=0.15.0
+Requires-Dist: openstacksdk>=4.12.0
 Requires-Dist: oslo.i18n>=3.15.3
 Requires-Dist: oslo.utils>=3.33.0
 Requires-Dist: pbr!=2.1.0,>=2.0.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/api/api.py 
new/osc_lib-4.6.0/osc_lib/api/api.py
--- old/osc_lib-4.4.0/osc_lib/api/api.py        2026-02-17 15:50:51.000000000 
+0100
+++ new/osc_lib-4.6.0/osc_lib/api/api.py        2026-05-05 13:36:12.000000000 
+0200
@@ -14,7 +14,7 @@
 """Base API Library"""
 
 import builtins
-import typing as ty
+from typing import Any, NoReturn
 import warnings
 
 from keystoneauth1 import exceptions as ksa_exceptions
@@ -50,7 +50,7 @@
         session: ksa_session.Session | None = None,
         service_type: str | None = None,
         endpoint: str | None = None,
-        **kwargs: ty.Any,
+        **kwargs: Any,
     ) -> None:
         """Base object that contains some common API objects and methods
 
@@ -109,7 +109,7 @@
         method: str,
         url: str,
         session: ksa_session.Session | None = None,
-        **kwargs: ty.Any,
+        **kwargs: Any,
     ) -> requests.Response:
         """Perform call into session
 
@@ -161,8 +161,8 @@
         url: str,
         session: ksa_session.Session | None = None,
         method: str | None = None,
-        **params: ty.Any,
-    ) -> requests.Response | ty.Any:
+        **params: Any,
+    ) -> requests.Response | Any:
         """Create a new resource
 
         :param string url:
@@ -186,7 +186,7 @@
         self,
         url: str,
         session: ksa_session.Session | None = None,
-        **params: ty.Any,
+        **params: Any,
     ) -> requests.Response:
         """Delete a resource
 
@@ -202,11 +202,11 @@
         self,
         path: str,
         session: ksa_session.Session | None = None,
-        body: ty.Any = None,
+        body: Any = None,
         detailed: bool = False,
         headers: dict[str, str] | None = None,
-        **params: ty.Any,
-    ) -> requests.Response | ty.Any:
+        **params: Any,
+    ) -> requests.Response | Any:
         """Return a list of resources
 
         GET ${ENDPOINT}/${PATH}?${PARAMS}
@@ -261,7 +261,7 @@
         value: str | None = None,
         attr: str | None = None,
         resource: str | None = None,
-    ) -> ty.Any:
+    ) -> Any:
         """Find a resource via attribute or ID
 
         Most APIs return a list wrapped by a dict with the resource
@@ -291,7 +291,7 @@
         if resource is None:
             resource = path
 
-        def getlist(kw: dict[str, ty.Any]) -> ty.Any:
+        def getlist(kw: dict[str, Any]) -> Any:
             """Do list call, unwrap resource dict if present"""
             ret = self.list(path, **kw)
             if isinstance(ret, dict) and resource in ret:
@@ -325,8 +325,8 @@
         self,
         path: str,
         headers: dict[str, str] | None = None,
-        **kwargs: ty.Any,
-    ) -> builtins.list[ty.Any]:
+        **kwargs: Any,
+    ) -> builtins.list[Any]:
         """Bulk load and filter locally
 
         :param string path:
@@ -356,7 +356,7 @@
 
         return ret
 
-    def find_one(self, path: str, **kwargs: ty.Any) -> ty.Any:
+    def find_one(self, path: str, **kwargs: Any) -> Any:
         """Find a resource by name or ID
 
         :param string path:
@@ -381,7 +381,7 @@
         value: str | None = None,
         attr: str | None = None,
         headers: dict[str, str] | None = None,
-    ) -> ty.Any:
+    ) -> Any:
         """Find a single resource by name or ID
 
         :param string path:
@@ -394,7 +394,7 @@
             Headers dictionary to pass to requests
         """
 
-        def raise_not_found() -> ty.NoReturn:
+        def raise_not_found() -> NoReturn:
             msg = _("%s not found") % value
             raise exceptions.NotFound(404, msg)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/api/auth.py 
new/osc_lib-4.6.0/osc_lib/api/auth.py
--- old/osc_lib-4.4.0/osc_lib/api/auth.py       2026-02-17 15:50:51.000000000 
+0100
+++ new/osc_lib-4.6.0/osc_lib/api/auth.py       2026-05-05 13:36:12.000000000 
+0200
@@ -14,7 +14,7 @@
 """Authentication Library"""
 
 import argparse
-import typing as ty
+from typing import TYPE_CHECKING, TypedDict, TypeVar
 
 from keystoneauth1.identity import base as identity_base
 from keystoneauth1.identity.v3 import k2k
@@ -24,7 +24,7 @@
 from osc_lib.i18n import _
 from osc_lib import utils
 
-if ty.TYPE_CHECKING:
+if TYPE_CHECKING:
     from openstack.config import cloud_region
 
 
@@ -33,7 +33,7 @@
 PLUGIN_LIST: frozenset[str] | None = None
 
 
-class _OptionDict(ty.TypedDict):
+class _OptionDict(TypedDict):
     env: str
     help: str
 
@@ -154,9 +154,7 @@
         )
 
 
-_ArgumentParserT = ty.TypeVar(
-    '_ArgumentParserT', bound=argparse.ArgumentParser
-)
+_ArgumentParserT = TypeVar('_ArgumentParserT', bound=argparse.ArgumentParser)
 
 
 def build_auth_plugins_option_parser(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/api/utils.py 
new/osc_lib-4.6.0/osc_lib/api/utils.py
--- old/osc_lib-4.4.0/osc_lib/api/utils.py      2026-02-17 15:50:51.000000000 
+0100
+++ new/osc_lib-4.6.0/osc_lib/api/utils.py      2026-05-05 13:36:12.000000000 
+0200
@@ -13,10 +13,10 @@
 
 """API Utilities Library"""
 
-import typing as ty
+from typing import Any, TypeVar
 
 
-_T = ty.TypeVar('_T', bound=list[ty.Any])
+_T = TypeVar('_T', bound=list[Any])
 
 
 def simple_filter(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/cli/client_config.py 
new/osc_lib-4.6.0/osc_lib/cli/client_config.py
--- old/osc_lib-4.4.0/osc_lib/cli/client_config.py      2026-02-17 
15:50:51.000000000 +0100
+++ new/osc_lib-4.6.0/osc_lib/cli/client_config.py      2026-05-05 
13:36:12.000000000 +0200
@@ -14,7 +14,7 @@
 """OpenStackConfig subclass for argument compatibility"""
 
 import logging
-import typing as ty
+from typing import Any
 
 from keystoneauth1 import loading as ksa_loading
 from openstack.config import exceptions as sdk_exceptions
@@ -27,10 +27,10 @@
 
 # Subclass OpenStackConfig in order to munge config values
 # before auth plugins are loaded
-class OSC_Config(config.OpenStackConfig):  # type: ignore
+class OSC_Config(config.OpenStackConfig):
     def _auth_select_default_plugin(
-        self, config: dict[str, ty.Any]
-    ) -> dict[str, ty.Any]:
+        self, config: dict[str, Any]
+    ) -> dict[str, Any]:
         """Select a default plugin based on supplied arguments
 
         Migrated from auth.select_auth_plugin()
@@ -63,9 +63,7 @@
         LOG.debug("Auth plugin {} selected".format(config['auth_type']))
         return config
 
-    def _auth_v2_arguments(
-        self, config: dict[str, ty.Any]
-    ) -> dict[str, ty.Any]:
+    def _auth_v2_arguments(self, config: dict[str, Any]) -> dict[str, Any]:
         """Set up v2-required arguments from v3 info
 
         Migrated from auth.build_auth_params()
@@ -78,9 +76,7 @@
                 config['auth']['tenant_name'] = config['auth']['project_name']
         return config
 
-    def _auth_v2_ignore_v3(
-        self, config: dict[str, ty.Any]
-    ) -> dict[str, ty.Any]:
+    def _auth_v2_ignore_v3(self, config: dict[str, Any]) -> dict[str, Any]:
         """Remove v3 arguments if present for v2 plugin
 
         Migrated from clientmanager.setup_auth()
@@ -118,9 +114,7 @@
                     )
         return config
 
-    def _auth_default_domain(
-        self, config: dict[str, ty.Any]
-    ) -> dict[str, ty.Any]:
+    def _auth_default_domain(self, config: dict[str, Any]) -> dict[str, Any]:
         """Set a default domain from available arguments
 
         Migrated from clientmanager.setup_auth()
@@ -161,7 +155,7 @@
                 config['auth']['user_domain_id'] = default_domain
         return config
 
-    def auth_config_hook(self, config: dict[str, ty.Any]) -> dict[str, ty.Any]:
+    def auth_config_hook(self, config: dict[str, Any]) -> dict[str, Any]:
         """Allow examination of config values before loading auth plugin
 
         OpenStackClient will override this to perform additional checks
@@ -181,9 +175,9 @@
 
     def _validate_auth(
         self,
-        config: dict[str, ty.Any],
-        loader: ksa_loading.BaseLoader[ty.Any],
-    ) -> dict[str, ty.Any]:
+        config: dict[str, Any],
+        loader: ksa_loading.BaseLoader[Any],
+    ) -> dict[str, Any]:
         """Validate auth plugin arguments"""
         # May throw a keystoneauth1.exceptions.NoMatchingPlugin
 
@@ -256,7 +250,7 @@
         return config
 
     # TODO(stephenfin): Add type once we have typing for SDK
-    def load_auth_plugin(self, config: dict[str, ty.Any]) -> ty.Any:
+    def load_auth_plugin(self, config: dict[str, Any]) -> Any:
         """Get auth plugin and validate args"""
 
         loader = self._get_auth_loader(config)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/cli/format_columns.py 
new/osc_lib-4.6.0/osc_lib/cli/format_columns.py
--- old/osc_lib-4.4.0/osc_lib/cli/format_columns.py     2026-02-17 
15:50:51.000000000 +0100
+++ new/osc_lib-4.6.0/osc_lib/cli/format_columns.py     2026-05-05 
13:36:12.000000000 +0200
@@ -15,50 +15,50 @@
 
 """Formattable column for specify content type"""
 
-import typing as ty
+from typing import Any
 
 from cliff import columns
 
 from osc_lib import utils
 
 
-class DictColumn(columns.FormattableColumn[dict[str, ty.Any]]):
+class DictColumn(columns.FormattableColumn[dict[str, Any]]):
     """Format column for dict content"""
 
     def human_readable(self) -> str:
         return utils.format_dict(self._value)
 
-    def machine_readable(self) -> dict[str, ty.Any]:
+    def machine_readable(self) -> dict[str, Any]:
         return dict(self._value or {})
 
 
-class DictListColumn(columns.FormattableColumn[dict[str, list[ty.Any]]]):
+class DictListColumn(columns.FormattableColumn[dict[str, list[Any]]]):
     """Format column for dict, key is string, value is list"""
 
     def human_readable(self) -> str:
         return utils.format_dict_of_list(self._value) or ''
 
-    def machine_readable(self) -> dict[str, list[ty.Any]]:
+    def machine_readable(self) -> dict[str, list[Any]]:
         return dict(self._value or {})
 
 
-class ListColumn(columns.FormattableColumn[list[ty.Any]]):
+class ListColumn(columns.FormattableColumn[list[Any]]):
     """Format column for list content"""
 
     def human_readable(self) -> str:
         return utils.format_list(self._value) or ''
 
-    def machine_readable(self) -> list[ty.Any]:
+    def machine_readable(self) -> list[Any]:
         return [x for x in self._value or []]
 
 
-class ListDictColumn(columns.FormattableColumn[list[dict[str, ty.Any]]]):
+class ListDictColumn(columns.FormattableColumn[list[dict[str, Any]]]):
     """Format column for list of dict content"""
 
     def human_readable(self) -> str:
         return utils.format_list_of_dicts(self._value) or ''
 
-    def machine_readable(self) -> list[dict[str, ty.Any]]:
+    def machine_readable(self) -> list[dict[str, Any]]:
         return [dict(x) for x in self._value or []]
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/cli/identity.py 
new/osc_lib-4.6.0/osc_lib/cli/identity.py
--- old/osc_lib-4.4.0/osc_lib/cli/identity.py   2026-02-17 15:50:51.000000000 
+0100
+++ new/osc_lib-4.6.0/osc_lib/cli/identity.py   2026-05-05 13:36:12.000000000 
+0200
@@ -16,6 +16,7 @@
 from openstack import connection
 from openstack import exceptions
 from openstack.identity.v3 import project
+from openstack import utils
 
 from osc_lib.i18n import _
 
@@ -66,15 +67,18 @@
     :rtype: `openstack.identity.v3.project.Project`
     """
     try:
+        identity_client = utils.ensure_service_version(
+            sdk_connection.identity, '3'
+        )
         if domain_name_or_id:
-            domain = sdk_connection.identity.find_domain(
+            domain = identity_client.find_domain(
                 domain_name_or_id, ignore_missing=False
             )
             domain_id = domain.id
         else:
             domain_id = None
 
-        return sdk_connection.identity.find_project(  # type: ignore
+        return identity_client.find_project(
             name_or_id, ignore_missing=False, domain_id=domain_id
         )
     # NOTE: OpenStack SDK raises HttpException for 403 response code.
@@ -82,5 +86,5 @@
     # HttpException and check the status code.
     except exceptions.HttpException as e:
         if e.status_code == 403:
-            return project.Project(id=name_or_id, name=name_or_id)  # type: 
ignore
+            return project.Project(id=name_or_id, name=name_or_id)
         raise
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/cli/parseractions.py 
new/osc_lib-4.6.0/osc_lib/cli/parseractions.py
--- old/osc_lib-4.4.0/osc_lib/cli/parseractions.py      2026-02-17 
15:50:51.000000000 +0100
+++ new/osc_lib-4.6.0/osc_lib/cli/parseractions.py      2026-05-05 
13:36:12.000000000 +0200
@@ -16,12 +16,13 @@
 """argparse Custom Actions"""
 
 import argparse
-import collections.abc
-import typing as ty
+from collections.abc import Callable, Iterable
+from typing import Any, TypeVar
+from collections.abc import Sequence
 
 from osc_lib.i18n import _
 
-_T = ty.TypeVar('_T')
+_T = TypeVar('_T')
 
 
 class KeyValueAction(argparse.Action):
@@ -34,7 +35,7 @@
         self,
         parser: argparse.ArgumentParser,
         namespace: argparse.Namespace,
-        values: str | ty.Sequence[ty.Any] | None,
+        values: str | Sequence[Any] | None,
         option_string: str | None = None,
     ) -> None:
         if not isinstance(values, str):
@@ -68,7 +69,7 @@
         self,
         parser: argparse.ArgumentParser,
         namespace: argparse.Namespace,
-        values: str | ty.Sequence[ty.Any] | None,
+        values: str | Sequence[Any] | None,
         option_string: str | None = None,
     ) -> None:
         if not isinstance(values, str):
@@ -108,15 +109,15 @@
 
     def __init__(
         self,
-        option_strings: ty.Sequence[str],
+        option_strings: Sequence[str],
         dest: str,
         nargs: int | str | None = None,
-        required_keys: ty.Sequence[str] | None = None,
-        optional_keys: ty.Sequence[str] | None = None,
+        required_keys: Sequence[str] | None = None,
+        optional_keys: Sequence[str] | None = None,
         const: _T | None = None,
         default: _T | str | None = None,
-        type: collections.abc.Callable[[str], _T] | None = None,
-        choices: collections.abc.Iterable[_T] | None = None,
+        type: Callable[[str], _T] | None = None,
+        choices: Iterable[_T] | None = None,
         required: bool = False,
         help: str | None = None,
         metavar: str | tuple[str, ...] | None = None,
@@ -160,7 +161,7 @@
             raise TypeError(msg)
         self.optional_keys = set(optional_keys or [])
 
-    def validate_keys(self, keys: ty.Sequence[str]) -> None:
+    def validate_keys(self, keys: Sequence[str]) -> None:
         """Validate the provided keys.
 
         :param keys: A list of keys to validate.
@@ -203,7 +204,7 @@
         self,
         parser: argparse.ArgumentParser,
         namespace: argparse.Namespace,
-        values: str | ty.Sequence[ty.Any] | None,
+        values: str | Sequence[Any] | None,
         option_string: str | None = None,
     ) -> None:
         if not isinstance(values, str):
@@ -249,7 +250,7 @@
         self,
         parser: argparse.ArgumentParser,
         namespace: argparse.Namespace,
-        values: str | ty.Sequence[ty.Any] | None,
+        values: str | Sequence[Any] | None,
         option_string: str | None = None,
     ) -> None:
         """Overwrite the __call__ function of MultiKeyValueAction
@@ -308,7 +309,7 @@
         self,
         parser: argparse.ArgumentParser,
         namespace: argparse.Namespace,
-        values: str | ty.Sequence[ty.Any] | None,
+        values: str | Sequence[Any] | None,
         option_string: str | None = None,
     ) -> None:
         if not isinstance(values, str):
@@ -352,7 +353,7 @@
         self,
         parser: argparse.ArgumentParser,
         namespace: argparse.Namespace,
-        values: str | ty.Sequence[ty.Any] | None,
+        values: str | Sequence[Any] | None,
         option_string: str | None = None,
     ) -> None:
         if not isinstance(values, str | int | float):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/clientmanager.py 
new/osc_lib-4.6.0/osc_lib/clientmanager.py
--- old/osc_lib-4.4.0/osc_lib/clientmanager.py  2026-02-17 15:50:51.000000000 
+0100
+++ new/osc_lib-4.6.0/osc_lib/clientmanager.py  2026-05-05 13:36:12.000000000 
+0200
@@ -17,7 +17,7 @@
 
 import copy
 import logging
-import typing as ty
+from typing import Any, Protocol, cast
 import warnings
 
 from keystoneauth1 import access as ksa_access
@@ -36,7 +36,7 @@
 class ClientCache:
     """Descriptor class for caching created client handles."""
 
-    def __init__(self, factory: ty.Any) -> None:
+    def __init__(self, factory: Any) -> None:
         warnings.warn(
             "The ClientCache class is deprecated for removal as it has no "
             "users.",
@@ -46,7 +46,7 @@
         self.factory = factory
         self._handle = None
 
-    def __get__(self, instance: ty.Any, owner: ty.Any) -> ty.Any:
+    def __get__(self, instance: Any, owner: Any) -> Any:
         # Tell the ClientManager to login to keystone
         if self._handle is None:
             try:
@@ -58,7 +58,7 @@
         return self._handle
 
 
-class _PasswordHelper(ty.Protocol):
+class _PasswordHelper(Protocol):
     def __call__(self, prompt: str | None = None) -> str: ...
 
 
@@ -240,9 +240,14 @@
 
     def _override_for(self, service_type: str) -> str | None:
         key = '{}_endpoint_override'.format(service_type.replace('-', '_'))
-        return ty.cast(str | None, self._cli_options.config.get(key))
+        return cast(str | None, self._cli_options.config.get(key))
 
-    def is_service_available(self, service_type: str) -> bool | None:
+    def is_service_available(
+        self,
+        service_type: str,
+        region_name: str | None = None,
+        interface: str = 'public',
+    ) -> bool | None:
         """Check if a service type is in the current Service Catalog"""
         # If there is an override, assume the service is available
         if self._override_for(service_type):
@@ -255,7 +260,11 @@
         # Assume that the network endpoint is enabled.
         service_available = None
         if service_catalog:
-            if service_type in service_catalog.get_endpoints():
+            if service_type in service_catalog.get_endpoints(
+                service_type=service_type,
+                region_name=region_name,
+                interface=interface,
+            ):
                 service_available = True
                 LOG.debug("%s endpoint in service catalog", service_type)
             else:
@@ -279,6 +288,8 @@
 
         if not interface:
             interface = 'public'
+
+        endpoint = None
         # See if we are using password flow auth, i.e. we have a
         # service catalog to select endpoints from
         if self.auth_ref:
@@ -293,7 +304,8 @@
                 self.session,
                 interface=interface,
             )
+
         return endpoint
 
-    def get_configuration(self) -> dict[str, ty.Any]:
+    def get_configuration(self) -> dict[str, Any]:
         return copy.deepcopy(self._cli_options.config)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/command/command.py 
new/osc_lib-4.6.0/osc_lib/command/command.py
--- old/osc_lib-4.4.0/osc_lib/command/command.py        2026-02-17 
15:50:51.000000000 +0100
+++ new/osc_lib-4.6.0/osc_lib/command/command.py        2026-05-05 
13:36:12.000000000 +0200
@@ -15,7 +15,7 @@
 import abc
 import argparse
 import logging
-import typing as ty
+from typing import Any, TYPE_CHECKING
 
 from cliff import command
 from cliff import lister
@@ -24,7 +24,7 @@
 from osc_lib import exceptions
 from osc_lib.i18n import _
 
-if ty.TYPE_CHECKING:
+if TYPE_CHECKING:
     from osc_lib import shell
 
 
@@ -32,8 +32,8 @@
     def __new__(
         mcs: type['CommandMeta'],
         name: str,
-        bases: tuple[type[ty.Any], ...],
-        namespace: dict[str, ty.Any],
+        bases: tuple[type[Any], ...],
+        namespace: dict[str, Any],
     ) -> 'CommandMeta':
         if 'log' not in namespace:
             namespace['log'] = logging.getLogger(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/command/timing.py 
new/osc_lib-4.6.0/osc_lib/command/timing.py
--- old/osc_lib-4.4.0/osc_lib/command/timing.py 2026-02-17 15:50:51.000000000 
+0100
+++ new/osc_lib-4.6.0/osc_lib/command/timing.py 2026-05-05 13:36:12.000000000 
+0200
@@ -14,7 +14,7 @@
 """Timing Implementation"""
 
 import argparse
-import typing as ty
+from typing import Any
 
 from osc_lib.command import command
 
@@ -24,7 +24,7 @@
 
     def take_action(
         self, parsed_args: argparse.Namespace
-    ) -> tuple[tuple[str, ...], list[ty.Any]]:
+    ) -> tuple[tuple[str, ...], list[Any]]:
         column_headers = (
             'URL',
             'Seconds',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/logs.py 
new/osc_lib-4.6.0/osc_lib/logs.py
--- old/osc_lib-4.4.0/osc_lib/logs.py   2026-02-17 15:50:51.000000000 +0100
+++ new/osc_lib-4.6.0/osc_lib/logs.py   2026-05-05 13:36:12.000000000 +0200
@@ -14,10 +14,10 @@
 """Application logging"""
 
 import argparse
-import collections.abc
+from collections.abc import Mapping
 import logging
 import sys
-import typing as ty
+from typing import Any
 import warnings
 
 from openstack.config import cloud_region
@@ -57,7 +57,7 @@
     return log_level
 
 
-def log_level_from_config(config: collections.abc.Mapping[str, ty.Any]) -> int:
+def log_level_from_config(config: Mapping[str, Any]) -> int:
     # Check the command line option
     verbose_level_from_config = config.get('verbose_level')
     if config.get('debug', False):
@@ -101,7 +101,7 @@
         self,
         options: argparse.Namespace | None = None,
         config: cloud_region.CloudRegion | None = None,
-        **kwargs: ty.Any,
+        **kwargs: Any,
     ) -> None:
         context = {}
         if options:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/shell.py 
new/osc_lib-4.6.0/osc_lib/shell.py
--- old/osc_lib-4.4.0/osc_lib/shell.py  2026-02-17 15:50:51.000000000 +0100
+++ new/osc_lib-4.6.0/osc_lib/shell.py  2026-05-05 13:36:12.000000000 +0200
@@ -16,13 +16,13 @@
 
 """Command-line interface to the OpenStack APIs"""
 
+import argparse
 import getpass
 import logging
 import sys
 import traceback
-import typing as ty
+from typing import Any, TextIO
 
-from cliff import _argparse
 from cliff import app
 from cliff import command
 from cliff import commandmanager
@@ -82,7 +82,7 @@
     client_manager: clientmanager.ClientManager
 
     log = logging.getLogger(__name__)
-    timing_data: list[ty.Any] = []
+    timing_data: list[Any] = []
     api_version: dict[str, str]
 
     def __init__(
@@ -90,9 +90,9 @@
         description: str | None = None,
         version: str | None = None,
         command_manager: commandmanager.CommandManager | None = None,
-        stdin: ty.TextIO | None = None,
-        stdout: ty.TextIO | None = None,
-        stderr: ty.TextIO | None = None,
+        stdin: TextIO | None = None,
+        stdout: TextIO | None = None,
+        stderr: TextIO | None = None,
         interactive_app_factory: type['interactive.InteractiveApp']
         | None = None,
         deferred_help: bool = True,
@@ -204,8 +204,8 @@
         self,
         description: str | None,
         version: str | None,
-        argparse_kwargs: dict[str, ty.Any] | None = None,
-    ) -> _argparse.ArgumentParser:
+        argparse_kwargs: dict[str, Any] | None = None,
+    ) -> argparse.ArgumentParser:
         parser = super().build_option_parser(
             description,
             version,
@@ -439,7 +439,7 @@
         # https://review.opendev.org/c/openstack/oslo.utils/+/967979
         self.log.debug(
             "options: %s",
-            strutils.mask_password(self.options),  # type: ignore
+            strutils.mask_password(self.options),
         )
 
         # Callout for stuff between superclass init and o-c-c
@@ -478,7 +478,7 @@
         # https://review.opendev.org/c/openstack/oslo.utils/+/967979
         self.log.debug(
             "cloud cfg: %s",
-            strutils.mask_password(self.cloud.config),  # type: ignore
+            strutils.mask_password(self.cloud.config),
         )
 
         self._load_plugins()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/test/base.py 
new/osc_lib-4.6.0/osc_lib/test/base.py
--- old/osc_lib-4.4.0/osc_lib/test/base.py      2026-02-17 15:50:51.000000000 
+0100
+++ new/osc_lib-4.6.0/osc_lib/test/base.py      2026-05-05 13:36:12.000000000 
+0200
@@ -19,7 +19,7 @@
 from cliff import columns as cliff_columns
 from cliff import command as cliff_command
 import fixtures
-import testtools  # type: ignore
+import testtools
 
 from osc_lib.test import fakes
 
@@ -28,7 +28,7 @@
     pass
 
 
-class TestCase(testtools.TestCase):  # type: ignore
+class TestCase(testtools.TestCase):
     # provide additional context for failures
     maxDiff = None
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/tests/cli/test_identity.py 
new/osc_lib-4.6.0/osc_lib/tests/cli/test_identity.py
--- old/osc_lib-4.4.0/osc_lib/tests/cli/test_identity.py        2026-02-17 
15:50:51.000000000 +0100
+++ new/osc_lib-4.6.0/osc_lib/tests/cli/test_identity.py        2026-05-05 
13:36:12.000000000 +0200
@@ -33,6 +33,7 @@
 
     def test_find_project(self):
         sdk_connection = mock.Mock()
+        sdk_connection.identity.api_version = '3'
         sdk_find_project = sdk_connection.identity.find_project
         sdk_find_project.return_value = mock.sentinel.project1
 
@@ -47,6 +48,7 @@
         domain1.id = 'id-domain1'
 
         sdk_connection = mock.Mock()
+        sdk_connection.identity.api_version = '3'
         sdk_find_domain = sdk_connection.identity.find_domain
         sdk_find_domain.return_value = domain1
         sdk_find_project = sdk_connection.identity.find_project
@@ -63,6 +65,7 @@
 
     def test_find_project_with_forbidden_exception(self):
         sdk_connection = mock.Mock()
+        sdk_connection.identity.api_version = '3'
         sdk_find_project = sdk_connection.identity.find_project
         exc = exceptions.HttpException()
         exc.status_code = 403
@@ -76,6 +79,7 @@
 
     def test_find_project_with_generic_exception(self):
         sdk_connection = mock.Mock()
+        sdk_connection.identity.api_version = '3'
         sdk_find_project = sdk_connection.identity.find_project
         exc = exceptions.HttpException()
         # Some value other than 403.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/utils/__init__.py 
new/osc_lib-4.6.0/osc_lib/utils/__init__.py
--- old/osc_lib-4.4.0/osc_lib/utils/__init__.py 2026-02-17 15:50:51.000000000 
+0100
+++ new/osc_lib-4.6.0/osc_lib/utils/__init__.py 2026-05-05 13:36:12.000000000 
+0200
@@ -16,14 +16,14 @@
 """Common client utilities"""
 
 import argparse
-import collections.abc
+from collections.abc import Callable, Mapping, MutableMapping, Sequence
 import copy
 import functools
 import getpass
 import logging
 import os
 import time
-import typing as ty
+from typing import Any, TextIO, TypeVar
 import uuid
 import warnings
 
@@ -36,7 +36,7 @@
 
 LOG = logging.getLogger(__name__)
 
-_T = ty.TypeVar('_T')
+_T = TypeVar('_T')
 
 
 def backward_compat_col_lister(
@@ -76,10 +76,10 @@
 
 
 def backward_compat_col_showone(
-    show_object: collections.abc.MutableMapping[str, _T],
+    show_object: MutableMapping[str, _T],
     columns: list[str],
     column_map: dict[str, str],
-) -> collections.abc.MutableMapping[str, _T]:
+) -> MutableMapping[str, _T]:
     """Convert the output object to keep column backward compatibility.
 
     Replace the new column name of output object by old name, so that
@@ -118,10 +118,10 @@
 
 
 def calculate_header_and_attrs(
-    column_headers: collections.abc.Sequence[str],
-    attrs: collections.abc.Sequence[str],
+    column_headers: Sequence[str],
+    attrs: Sequence[str],
     parsed_args: argparse.Namespace,
-) -> tuple[collections.abc.Sequence[str], collections.abc.Sequence[str]]:
+) -> tuple[Sequence[str], Sequence[str]]:
     """Calculate headers and attribute names based on parsed_args.column.
 
     When --column (-c) option is specified, this function calculates
@@ -156,7 +156,7 @@
         return column_headers, attrs
 
 
-def env(*vars: str, **kwargs: ty.Any) -> str | None:
+def env(*vars: str, **kwargs: Any) -> str | None:
     """Search for the first defined of possibly many env vars
 
     Returns the first environment variable defined in vars, or
@@ -174,10 +174,10 @@
 
 
 def find_min_match(
-    items: collections.abc.Sequence[_T],
+    items: Sequence[_T],
     sort_attr: str,
-    **kwargs: ty.Any,
-) -> collections.abc.Sequence[_T]:
+    **kwargs: Any,
+) -> Sequence[_T]:
     """Find all resources meeting the given minimum constraints
 
     :param items: A List of objects to consider
@@ -202,10 +202,10 @@
 # using generics? We should also deprecate this but there are a lot of users
 # still.
 def find_resource(
-    manager: ty.Any,
+    manager: Any,
     name_or_id: str,
-    **kwargs: ty.Any,
-) -> ty.Any:
+    **kwargs: Any,
+) -> Any:
     """Helper for the _find_* methods.
 
     :param manager: A client manager class
@@ -328,7 +328,7 @@
         raise exceptions.CommandError(msg % name_or_id)
 
 
-def format_dict(data: dict[str, ty.Any], prefix: str | None = None) -> str:
+def format_dict(data: dict[str, Any], prefix: str | None = None) -> str:
     """Return a formatted string of key value pairs
 
     :param data: a dict
@@ -357,7 +357,7 @@
 
 
 def format_dict_of_list(
-    data: dict[str, list[ty.Any]] | None, separator: str = '; '
+    data: dict[str, list[Any]] | None, separator: str = '; '
 ) -> str | None:
     """Return a formatted string of key value pair
 
@@ -383,9 +383,7 @@
     return separator.join(output)
 
 
-def format_list(
-    data: list[ty.Any] | None, separator: str = ', '
-) -> str | None:
+def format_list(data: list[Any] | None, separator: str = ', ') -> str | None:
     """Return a formatted strings
 
     :param data: a list of strings
@@ -399,7 +397,7 @@
 
 
 def format_list_of_dicts(
-    data: list[dict[str, ty.Any]] | None,
+    data: list[dict[str, Any]] | None,
 ) -> str | None:
     """Return a formatted string of key value pairs for each dict
 
@@ -445,7 +443,7 @@
     api_name: str,
     version: str | int | float,
     version_map: dict[str, str],
-) -> ty.Any:
+) -> Any:
     """Returns the client class for the requested API version
 
     :param api_name: the name of the API, e.g. 'compute', 'image', etc
@@ -482,16 +480,16 @@
 
 
 FormatterT = (
-    type[cliff_columns.FormattableColumn[ty.Any]] | functools.partial[ty.Any]
+    type[cliff_columns.FormattableColumn[Any]] | functools.partial[Any]
 )
 
 
 def get_dict_properties(
     item: dict[str, _T],
-    fields: collections.abc.Sequence[str],
-    mixed_case_fields: collections.abc.Sequence[str] | None = None,
-    formatters: collections.abc.Mapping[str, FormatterT] | None = None,
-) -> tuple[ty.Any, ...]:
+    fields: Sequence[str],
+    mixed_case_fields: Sequence[str] | None = None,
+    formatters: Mapping[str, FormatterT] | None = None,
+) -> tuple[Any, ...]:
     """Return a tuple containing the item properties.
 
     :param item: a single dict resource
@@ -512,7 +510,7 @@
             field_name = field.replace(' ', '_')
         else:
             field_name = field.lower().replace(' ', '_')
-        data: ty.Any = item[field_name] if field_name in item else ''
+        data: Any = item[field_name] if field_name in item else ''
         if field in formatters:
             formatter = formatters[field]
             # columns must be either a subclass of FormattableColumn
@@ -539,10 +537,10 @@
 
 def get_item_properties(
     item: dict[str, _T],
-    fields: collections.abc.Sequence[str],
-    mixed_case_fields: collections.abc.Sequence[str] | None = None,
-    formatters: collections.abc.Mapping[str, FormatterT] | None = None,
-) -> tuple[ty.Any, ...]:
+    fields: Sequence[str],
+    mixed_case_fields: Sequence[str] | None = None,
+    formatters: Mapping[str, FormatterT] | None = None,
+) -> tuple[Any, ...]:
     """Return a tuple containing the item properties.
 
     :param item: a single item resource (e.g. Server, Project, etc)
@@ -600,7 +598,7 @@
     return min_log_lvl
 
 
-def get_field(item: _T, field: str) -> ty.Any:
+def get_field(item: _T, field: str) -> Any:
     try:
         if isinstance(item, dict):
             return item[field]
@@ -612,7 +610,7 @@
 
 
 def get_password(
-    stdin: ty.TextIO,
+    stdin: TextIO,
     prompt: str | None = None,
     confirm: bool = True,
 ) -> str:
@@ -657,10 +655,10 @@
 
 
 def sort_items(
-    items: collections.abc.Sequence[_T],
+    items: Sequence[_T],
     sort_str: str,
-    sort_type: type[ty.Any] | None = None,
-) -> collections.abc.Sequence[_T]:
+    sort_type: type[Any] | None = None,
+) -> list[_T]:
     """Sort items based on sort keys and sort directions given by sort_str.
 
     :param items: a list or generator object of items
@@ -671,7 +669,9 @@
     :return: sorted items
     """
     if not sort_str:
-        return items
+        # wrap in list so we return a consistent type
+        return list(items)
+
     # items may be a generator object, transform it to a list
     items = list(items)
     sort_keys = sort_str.strip().split(',')
@@ -699,7 +699,7 @@
             if direction == 'desc':
                 reverse = True
 
-        def f(x: ty.Any) -> ty.Any:
+        def f(x: Any) -> Any:
             # Attempts to convert items to same 'sort_type' if provided.
             # This is due to Python 3 throwing TypeError if you attempt to
             # compare different types
@@ -718,14 +718,14 @@
 
 
 def wait_for_delete(
-    manager: ty.Any,
+    manager: Any,
     res_id: str,
     status_field: str = 'status',
-    error_status: collections.abc.Sequence[str] = ['error'],
-    exception_name: collections.abc.Sequence[str] = ['NotFound'],
+    error_status: Sequence[str] = ['error'],
+    exception_name: Sequence[str] = ['NotFound'],
     sleep_time: int = 5,
     timeout: int = 300,
-    callback: collections.abc.Callable[[int], None] | None = None,
+    callback: Callable[[int], None] | None = None,
 ) -> bool:
     """Wait for resource deletion
 
@@ -777,13 +777,13 @@
 
 
 def wait_for_status(
-    status_f: collections.abc.Callable[[str], object],
+    status_f: Callable[[str], object],
     res_id: str,
     status_field: str = 'status',
-    success_status: collections.abc.Sequence[str] = ['active'],
-    error_status: collections.abc.Sequence[str] = ['error'],
+    success_status: Sequence[str] = ['active'],
+    error_status: Sequence[str] = ['error'],
     sleep_time: int = 5,
-    callback: collections.abc.Callable[[int], None] | None = None,
+    callback: Callable[[int], None] | None = None,
 ) -> bool:
     """Wait for status change on a resource during a long-running operation
 
@@ -821,7 +821,7 @@
 def get_osc_show_columns_for_sdk_resource(
     sdk_resource: resource.Resource,
     osc_column_map: dict[str, str],
-    invisible_columns: collections.abc.Sequence[str] | None = None,
+    invisible_columns: Sequence[str] | None = None,
 ) -> tuple[tuple[str, ...], tuple[str, ...]]:
     """Get and filter the display and attribute columns for an SDK resource.
 
@@ -871,7 +871,7 @@
     return tuple(sorted_display_columns), tuple(attr_columns)
 
 
-def is_uuid_like(value: ty.Any) -> bool:
+def is_uuid_like(value: Any) -> bool:
     """Returns validation of a value as a UUID.
 
     :param val: Value to verify
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/utils/columns.py 
new/osc_lib-4.6.0/osc_lib/utils/columns.py
--- old/osc_lib-4.4.0/osc_lib/utils/columns.py  2026-02-17 15:50:51.000000000 
+0100
+++ new/osc_lib-4.6.0/osc_lib/utils/columns.py  2026-05-05 13:36:12.000000000 
+0200
@@ -11,7 +11,7 @@
 #   under the License.
 
 import operator
-import typing as ty
+from typing import Any
 
 LIST_BOTH = 'both'
 LIST_SHORT_ONLY = 'short_only'
@@ -77,7 +77,7 @@
 
 
 def get_columns(
-    item: dict[str, ty.Any],
+    item: dict[str, Any],
     attr_map: list[tuple[str, str, str]] | None = None,
 ) -> tuple[tuple[str, ...], tuple[str, ...]]:
     """Return pair of resource attributes and corresponding display names.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/utils/tags.py 
new/osc_lib-4.6.0/osc_lib/utils/tags.py
--- old/osc_lib-4.4.0/osc_lib/utils/tags.py     2026-02-17 15:50:51.000000000 
+0100
+++ new/osc_lib-4.6.0/osc_lib/utils/tags.py     2026-05-05 13:36:12.000000000 
+0200
@@ -11,8 +11,8 @@
 #   under the License.
 
 import argparse
-import collections.abc
-import typing as ty
+from collections.abc import Callable, Sequence
+from typing import Any
 
 from osc_lib.i18n import _
 
@@ -22,7 +22,7 @@
         self,
         parser: argparse.ArgumentParser,
         namespace: argparse.Namespace,
-        values: str | ty.Sequence[ty.Any] | None,
+        values: str | Sequence[Any] | None,
         option_string: str | None = None,
     ) -> None:
         if not isinstance(values, str):
@@ -33,7 +33,7 @@
 def add_tag_filtering_option_to_parser(
     parser: argparse.ArgumentParser,
     resource_name: str,
-    enhance_help: collections.abc.Callable[[str], str] = lambda _h: _h,
+    enhance_help: Callable[[str], str] = lambda _h: _h,
 ) -> None:
     """Add tag filtering options to a parser.
 
@@ -97,7 +97,7 @@
 
 def get_tag_filtering_args(
     parsed_args: argparse.Namespace,
-    args: dict[str, ty.Any],
+    args: dict[str, Any],
 ) -> None:
     """Adds the tag arguments to an args list.
 
@@ -120,7 +120,7 @@
 def add_tag_option_to_parser_for_create(
     parser: argparse.ArgumentParser,
     resource_name: str,
-    enhance_help: collections.abc.Callable[[str], str] = lambda _h: _h,
+    enhance_help: Callable[[str], str] = lambda _h: _h,
 ) -> None:
     """Add tag options to a parser for create commands.
 
@@ -153,7 +153,7 @@
 def add_tag_option_to_parser_for_set(
     parser: argparse.ArgumentParser,
     resource_name: str,
-    enhance_help: collections.abc.Callable[[str], str] = lambda _h: _h,
+    enhance_help: Callable[[str], str] = lambda _h: _h,
 ) -> None:
     """Add tag options to a parser for set commands.
 
@@ -191,7 +191,7 @@
 def add_tag_option_to_parser_for_unset(
     parser: argparse.ArgumentParser,
     resource_name: str,
-    enhance_help: collections.abc.Callable[[str], str] = lambda _h: _h,
+    enhance_help: Callable[[str], str] = lambda _h: _h,
 ) -> None:
     """Add tag options to a parser for set commands.
 
@@ -227,7 +227,7 @@
 
 
 def update_tags_for_set(
-    client: ty.Any, obj: ty.Any, parsed_args: argparse.Namespace
+    client: Any, obj: Any, parsed_args: argparse.Namespace
 ) -> None:
     """Set the tags on an object.
 
@@ -246,7 +246,7 @@
 
 
 def update_tags_for_unset(
-    client: ty.Any, obj: ty.Any, parsed_args: argparse.Namespace
+    client: Any, obj: Any, parsed_args: argparse.Namespace
 ) -> None:
     """Unset the tags on an object.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib/version.py 
new/osc_lib-4.6.0/osc_lib/version.py
--- old/osc_lib-4.4.0/osc_lib/version.py        2026-02-17 15:50:51.000000000 
+0100
+++ new/osc_lib-4.6.0/osc_lib/version.py        2026-05-05 13:36:12.000000000 
+0200
@@ -10,7 +10,7 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-import pbr.version  # type: ignore
+import pbr.version
 
 __all__ = ['version_info', 'version_string']
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib.egg-info/PKG-INFO 
new/osc_lib-4.6.0/osc_lib.egg-info/PKG-INFO
--- old/osc_lib-4.4.0/osc_lib.egg-info/PKG-INFO 2026-02-17 15:51:27.000000000 
+0100
+++ new/osc_lib-4.6.0/osc_lib.egg-info/PKG-INFO 2026-05-05 13:36:39.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: osc-lib
-Version: 4.4.0
+Version: 4.6.0
 Summary: OpenStackClient Library
 Author-email: OpenStack <[email protected]>
 License: Apache-2.0
@@ -24,7 +24,7 @@
 License-File: LICENSE
 Requires-Dist: cliff>=4.9.0
 Requires-Dist: keystoneauth1>=5.10.0
-Requires-Dist: openstacksdk>=0.15.0
+Requires-Dist: openstacksdk>=4.12.0
 Requires-Dist: oslo.i18n>=3.15.3
 Requires-Dist: oslo.utils>=3.33.0
 Requires-Dist: pbr!=2.1.0,>=2.0.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib.egg-info/SOURCES.txt 
new/osc_lib-4.6.0/osc_lib.egg-info/SOURCES.txt
--- old/osc_lib-4.4.0/osc_lib.egg-info/SOURCES.txt      2026-02-17 
15:51:27.000000000 +0100
+++ new/osc_lib-4.6.0/osc_lib.egg-info/SOURCES.txt      2026-05-05 
13:36:39.000000000 +0200
@@ -117,6 +117,7 @@
 releasenotes/source/2024.2.rst
 releasenotes/source/2025.1.rst
 releasenotes/source/2025.2.rst
+releasenotes/source/2026.1.rst
 releasenotes/source/conf.py
 releasenotes/source/index.rst
 releasenotes/source/newton.rst
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib.egg-info/pbr.json 
new/osc_lib-4.6.0/osc_lib.egg-info/pbr.json
--- old/osc_lib-4.4.0/osc_lib.egg-info/pbr.json 2026-02-17 15:51:27.000000000 
+0100
+++ new/osc_lib-4.6.0/osc_lib.egg-info/pbr.json 2026-05-05 13:36:39.000000000 
+0200
@@ -1 +1 @@
-{"git_version": "adeeb72", "is_release": true}
\ No newline at end of file
+{"git_version": "7bda488", "is_release": true}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/osc_lib.egg-info/requires.txt 
new/osc_lib-4.6.0/osc_lib.egg-info/requires.txt
--- old/osc_lib-4.4.0/osc_lib.egg-info/requires.txt     2026-02-17 
15:51:27.000000000 +0100
+++ new/osc_lib-4.6.0/osc_lib.egg-info/requires.txt     2026-05-05 
13:36:39.000000000 +0200
@@ -1,6 +1,6 @@
 cliff>=4.9.0
 keystoneauth1>=5.10.0
-openstacksdk>=0.15.0
+openstacksdk>=4.12.0
 oslo.i18n>=3.15.3
 oslo.utils>=3.33.0
 pbr!=2.1.0,>=2.0.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/pyproject.toml 
new/osc_lib-4.6.0/pyproject.toml
--- old/osc_lib-4.4.0/pyproject.toml    2026-02-17 15:50:51.000000000 +0100
+++ new/osc_lib-4.6.0/pyproject.toml    2026-05-05 13:36:12.000000000 +0200
@@ -44,13 +44,12 @@
 ]
 
 [tool.mypy]
+python_version = "3.10"
 show_column_numbers = true
 show_error_context = true
-# we set this to false since the typing situation of dependencies is rapidly
-# evolving right now
-warn_unused_ignores = false
 strict = true
-exclude = '(?x)(doc | releasenotes)'
+disable_error_code = ["import-untyped"]
+exclude = "(?x)(doc | releasenotes)"
 
 [[tool.mypy.overrides]]
 module = ["osc_lib.tests.*"]
@@ -65,6 +64,7 @@
 
 [tool.ruff.lint]
 select = ["E4", "E5", "E7", "E9", "F", "S", "UP"]
+external = ["H"]
 ignore = [
     # we only use asserts for type narrowing
     "S101",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/releasenotes/source/2026.1.rst 
new/osc_lib-4.6.0/releasenotes/source/2026.1.rst
--- old/osc_lib-4.4.0/releasenotes/source/2026.1.rst    1970-01-01 
01:00:00.000000000 +0100
+++ new/osc_lib-4.6.0/releasenotes/source/2026.1.rst    2026-05-05 
13:36:12.000000000 +0200
@@ -0,0 +1,6 @@
+===========================
+2026.1 Series Release Notes
+===========================
+
+.. release-notes::
+   :branch: stable/2026.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/releasenotes/source/index.rst 
new/osc_lib-4.6.0/releasenotes/source/index.rst
--- old/osc_lib-4.4.0/releasenotes/source/index.rst     2026-02-17 
15:50:51.000000000 +0100
+++ new/osc_lib-4.6.0/releasenotes/source/index.rst     2026-05-05 
13:36:12.000000000 +0200
@@ -6,6 +6,7 @@
    :maxdepth: 1
 
    unreleased
+   2026.1
    2025.2
    2025.1
    2024.2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc_lib-4.4.0/requirements.txt 
new/osc_lib-4.6.0/requirements.txt
--- old/osc_lib-4.4.0/requirements.txt  2026-02-17 15:50:51.000000000 +0100
+++ new/osc_lib-4.6.0/requirements.txt  2026-05-05 13:36:12.000000000 +0200
@@ -1,6 +1,6 @@
 cliff>=4.9.0 # Apache-2.0
 keystoneauth1>=5.10.0 # Apache-2.0
-openstacksdk>=0.15.0 # Apache-2.0
+openstacksdk>=4.12.0 # Apache-2.0
 oslo.i18n>=3.15.3 # Apache-2.0
 oslo.utils>=3.33.0 # Apache-2.0
 pbr!=2.1.0,>=2.0.0 # Apache-2.0

Reply via email to