Skip to content

Commit 8a6c3af

Browse files
committed
typing: Add hints to common commands
Change-Id: I433ffc933fef92a879fac9143402519649788f64 Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
1 parent 467f72c commit 8a6c3af

12 files changed

Lines changed: 182 additions & 99 deletions

openstackclient/common/availability_zone.py

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313

1414
"""Availability Zone action implementations"""
1515

16+
import argparse
1617
import copy
1718
import logging
19+
from collections.abc import Iterable, Sequence
20+
from typing import Any
1821

1922
from openstack import exceptions as sdk_exceptions
2023
from openstack import utils as sdk_utils
@@ -27,8 +30,10 @@
2730
LOG = logging.getLogger(__name__)
2831

2932

30-
def _xform_compute_availability_zone(az, include_extra):
31-
result = []
33+
def _xform_compute_availability_zone(
34+
az: Any, include_extra: bool
35+
) -> list[dict[str, str]]:
36+
result: list[dict[str, str]] = []
3237
zone_info = {
3338
'zone_name': az.name,
3439
'zone_status': (
@@ -62,8 +67,8 @@ def _xform_compute_availability_zone(az, include_extra):
6267
return result
6368

6469

65-
def _xform_network_availability_zone(az):
66-
result = []
70+
def _xform_network_availability_zone(az: Any) -> list[dict[str, str]]:
71+
result: list[dict[str, str]] = []
6772
zone_info = {}
6873
zone_info['zone_name'] = az.name
6974
zone_info['zone_status'] = az.state
@@ -74,8 +79,8 @@ def _xform_network_availability_zone(az):
7479
return result
7580

7681

77-
def _xform_volume_availability_zone(az):
78-
result = []
82+
def _xform_volume_availability_zone(az: Any) -> list[dict[str, str]]:
83+
result: list[dict[str, str]] = []
7984
zone_info = {
8085
'zone_name': az.name,
8186
'zone_status': (
@@ -89,7 +94,7 @@ def _xform_volume_availability_zone(az):
8994
class ListAvailabilityZone(command.Lister):
9095
_description = _("List availability zones and their status")
9196

92-
def get_parser(self, prog_name):
97+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
9398
parser = super().get_parser(prog_name)
9499
parser.add_argument(
95100
'--compute',
@@ -117,7 +122,9 @@ def get_parser(self, prog_name):
117122
)
118123
return parser
119124

120-
def _get_compute_availability_zones(self, parsed_args):
125+
def _get_compute_availability_zones(
126+
self, parsed_args: argparse.Namespace
127+
) -> list[dict[str, str]]:
121128
compute_client = self.app.client_manager.compute
122129
try:
123130
data = list(compute_client.availability_zones(details=True))
@@ -132,7 +139,9 @@ def _get_compute_availability_zones(self, parsed_args):
132139
result += _xform_compute_availability_zone(zone, parsed_args.long)
133140
return result
134141

135-
def _get_network_availability_zones(self, parsed_args):
142+
def _get_network_availability_zones(
143+
self, parsed_args: argparse.Namespace
144+
) -> list[dict[str, str]]:
136145
network_client = self.app.client_manager.network
137146
try:
138147
# Verify that the extension exists.
@@ -153,7 +162,9 @@ def _get_network_availability_zones(self, parsed_args):
153162
result += _xform_network_availability_zone(zone)
154163
return result
155164

156-
def _get_volume_availability_zones(self, parsed_args):
165+
def _get_volume_availability_zones(
166+
self, parsed_args: argparse.Namespace
167+
) -> list[dict[str, str]]:
157168
volume_client = sdk_utils.ensure_service_version(
158169
self.app.client_manager.sdk_connection.volume, '3'
159170
)
@@ -174,7 +185,9 @@ def _get_volume_availability_zones(self, parsed_args):
174185
result += _xform_volume_availability_zone(zone)
175186
return result
176187

177-
def take_action(self, parsed_args):
188+
def take_action(
189+
self, parsed_args: argparse.Namespace
190+
) -> tuple[Sequence[str], Iterable[tuple[Any, ...]]]:
178191
columns: tuple[str, ...] = ('Zone Name', 'Zone Status')
179192
if parsed_args.long:
180193
columns += (

openstackclient/common/clientmanager.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@ class ClientManager(clientmanager.ClientManager):
7070

7171
def __init__(
7272
self,
73-
cli_options=None,
74-
api_version=None,
75-
pw_func=None,
76-
):
73+
cli_options: Any = None,
74+
api_version: Any = None,
75+
pw_func: Any = None,
76+
) -> None:
7777
super().__init__(
7878
cli_options=cli_options,
7979
api_version=api_version,
@@ -89,7 +89,7 @@ def __init__(
8989
# store original auth_type
9090
self._original_auth_type = cli_options.auth_type
9191

92-
def setup_auth(self):
92+
def setup_auth(self) -> None:
9393
"""Set up authentication"""
9494

9595
if self._auth_setup_completed:
@@ -125,7 +125,7 @@ def setup_auth(self):
125125

126126
return super().setup_auth()
127127

128-
def _fallback_load_auth_plugin(self, e):
128+
def _fallback_load_auth_plugin(self, e: Exception) -> None:
129129
# NOTES(RuiChen): Hack to avoid auth plugins choking on data they don't
130130
# expect, delete fake token and endpoint, then try to
131131
# load auth plugin again with user specified options.
@@ -150,20 +150,20 @@ def _fallback_load_auth_plugin(self, e):
150150
else:
151151
raise e
152152

153-
def is_network_endpoint_enabled(self):
153+
def is_network_endpoint_enabled(self) -> bool:
154154
"""Check if the network endpoint is enabled"""
155155
# NOTE(dtroyer): is_service_available() can also return None if
156156
# there is no Service Catalog, callers here are
157157
# not expecting that so fold None into True to
158158
# use Network API by default
159159
return self.is_service_available('network') is not False
160160

161-
def is_compute_endpoint_enabled(self):
161+
def is_compute_endpoint_enabled(self) -> bool:
162162
"""Check if Compute endpoint is enabled"""
163163
return self.is_service_available('compute') is not False
164164

165165
# TODO(stephenfin): Drop volume_client argument in OSC 8.0 or later.
166-
def is_volume_endpoint_enabled(self, volume_client=None):
166+
def is_volume_endpoint_enabled(self, volume_client: Any = None) -> bool:
167167
"""Check if volume endpoint is enabled"""
168168
# We check against the service type and all aliases defined by the
169169
# Service Types Authority
@@ -195,7 +195,7 @@ class PluginModule(Protocol):
195195

196196

197197
def _on_load_failure_callback(
198-
manager: stevedore.ExtensionManager,
198+
manager: stevedore.ExtensionManager[PluginModule],
199199
ep: importlib.metadata.EntryPoint,
200200
err: BaseException,
201201
) -> None:
@@ -204,7 +204,7 @@ def _on_load_failure_callback(
204204
)
205205

206206

207-
def get_plugin_modules(group):
207+
def get_plugin_modules(group: str) -> list[Any]:
208208
"""Find plugin entry points"""
209209
mod_list = []
210210
mgr: stevedore.ExtensionManager[PluginModule]
@@ -238,7 +238,9 @@ def get_plugin_modules(group):
238238
return mod_list
239239

240240

241-
def build_plugin_option_parser(parser):
241+
def build_plugin_option_parser(
242+
parser: ArgumentParserT,
243+
) -> ArgumentParserT:
242244
"""Add plugin options to the parser"""
243245

244246
# Loop through extensions to get parser additions

openstackclient/common/configuration.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313

1414
"""Configuration action implementations"""
1515

16+
import argparse
17+
from collections.abc import Iterable, Sequence
18+
from typing import Any
19+
1620
from keystoneauth1.loading import base
1721

1822
from openstackclient import command
@@ -26,7 +30,7 @@ class ShowConfiguration(command.ShowOne):
2630

2731
auth_required = False
2832

29-
def get_parser(self, prog_name):
33+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
3034
parser = super().get_parser(prog_name)
3135
mask_group = parser.add_mutually_exclusive_group()
3236
mask_group.add_argument(
@@ -44,7 +48,9 @@ def get_parser(self, prog_name):
4448
)
4549
return parser
4650

47-
def take_action(self, parsed_args):
51+
def take_action(
52+
self, parsed_args: argparse.Namespace
53+
) -> tuple[Sequence[str], Iterable[Any]]:
4854
info = self.app.client_manager.get_configuration()
4955

5056
# Assume a default secret list in case we do not have an auth_plugin
@@ -68,4 +74,5 @@ def take_action(self, parsed_args):
6874
if secret_opt in info:
6975
info[secret_opt] = REDACTED
7076

71-
return zip(*sorted(info.items()))
77+
col_headers, col_data = zip(*sorted(info.items()))
78+
return col_headers, col_data

openstackclient/common/envvars.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from openstackclient.i18n import _
1616

1717

18-
def bool_from_str(value, strict=False):
18+
def bool_from_str(value: bool | str, strict: bool = False) -> bool:
1919
true_strings = ('1', 't', 'true', 'on', 'y', 'yes')
2020
false_strings = ('0', 'f', 'false', 'off', 'n', 'no')
2121

@@ -39,7 +39,7 @@ def bool_from_str(value, strict=False):
3939
raise ValueError(msg)
4040

4141

42-
def boolenv(*vars, default=False):
42+
def boolenv(*vars: str, default: bool = False) -> bool:
4343
"""Search for the first defined of possibly many bool-like env vars.
4444
4545
Returns the first environment variable defined in vars, or returns the

openstackclient/common/extension.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515

1616
"""Extension action implementations"""
1717

18+
import argparse
1819
import logging
20+
from collections.abc import Iterable, Sequence
21+
from typing import Any
1922

2023
from osc_lib import utils
2124

@@ -25,7 +28,9 @@
2528
LOG = logging.getLogger(__name__)
2629

2730

28-
def _get_extension_columns(item):
31+
def _get_extension_columns(
32+
item: Any,
33+
) -> tuple[tuple[str, ...], tuple[str, ...]]:
2934
column_map = {
3035
'updated': 'updated_at',
3136
}
@@ -38,7 +43,7 @@ def _get_extension_columns(item):
3843
class ListExtension(command.Lister):
3944
_description = _("List API extensions")
4045

41-
def get_parser(self, prog_name):
46+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
4247
parser = super().get_parser(prog_name)
4348
parser.add_argument(
4449
'--compute',
@@ -72,7 +77,9 @@ def get_parser(self, prog_name):
7277
)
7378
return parser
7479

75-
def take_action(self, parsed_args):
80+
def take_action(
81+
self, parsed_args: argparse.Namespace
82+
) -> tuple[Sequence[str], Iterable[tuple[Any, ...]]]:
7683
columns: tuple[str, ...] = ('Name', 'Alias', 'Description')
7784
if parsed_args.long:
7885
columns += ('Namespace', 'Updated At', 'Links')
@@ -139,7 +146,7 @@ def take_action(self, parsed_args):
139146
class ShowExtension(command.ShowOne):
140147
_description = _("Show API extension")
141148

142-
def get_parser(self, prog_name):
149+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
143150
parser = super().get_parser(prog_name)
144151
parser.add_argument(
145152
'extension',
@@ -152,7 +159,9 @@ def get_parser(self, prog_name):
152159
)
153160
return parser
154161

155-
def take_action(self, parsed_args):
162+
def take_action(
163+
self, parsed_args: argparse.Namespace
164+
) -> tuple[Sequence[str], Iterable[Any]]:
156165
client = self.app.client_manager.network
157166

158167
extension = client.find_extension(

openstackclient/common/limits.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515

1616
"""Limits Action Implementation"""
1717

18+
import argparse
1819
import itertools
20+
from collections.abc import Iterable, Sequence
21+
from typing import Any
1922

2023
from osc_lib import utils
2124

@@ -24,8 +27,8 @@
2427
from openstackclient.identity import common as identity_common
2528

2629

27-
def _format_absolute_limit(absolute_limits):
28-
info = {}
30+
def _format_absolute_limit(absolute_limits: Any) -> dict[str, Any]:
31+
info: dict[str, Any] = {}
2932

3033
for key in set(absolute_limits):
3134
if key in ('id', 'name', 'location'):
@@ -36,7 +39,7 @@ def _format_absolute_limit(absolute_limits):
3639
return info
3740

3841

39-
def _format_rate_limit(rate_limits):
42+
def _format_rate_limit(rate_limits: Any) -> Any:
4043
# flatten this:
4144
#
4245
# {'uri': '<uri>', 'limit': [{'value': '<value>', ...], ...}
@@ -52,7 +55,7 @@ def _format_rate_limit(rate_limits):
5255
class ShowLimits(command.Lister):
5356
_description = _("Show compute and block storage limits")
5457

55-
def get_parser(self, prog_name):
58+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
5659
parser = super().get_parser(prog_name)
5760
type_group = parser.add_mutually_exclusive_group(required=True)
5861
type_group.add_argument(
@@ -100,7 +103,9 @@ def get_parser(self, prog_name):
100103
)
101104
return parser
102105

103-
def take_action(self, parsed_args):
106+
def take_action(
107+
self, parsed_args: argparse.Namespace
108+
) -> tuple[Sequence[str], Iterable[tuple[Any, ...]]]:
104109
project_id = None
105110
if parsed_args.project is not None:
106111
identity_client = self.app.client_manager.identity

0 commit comments

Comments
 (0)