Skip to content

Commit 7ebdb7c

Browse files
authored
ref: Refactor baked/operation.py (#601)
1 parent 9f7ebc8 commit 7ebdb7c

File tree

1 file changed

+121
-18
lines changed

1 file changed

+121
-18
lines changed

linodecli/baked/operation.py

Lines changed: 121 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,27 @@
1111
from collections import defaultdict
1212
from getpass import getpass
1313
from os import environ, path
14-
from typing import Any, List, Tuple
14+
from typing import Any, Dict, List, Tuple
1515

16+
import openapi3.paths
1617
from openapi3.paths import Operation
1718

1819
from linodecli.baked.request import OpenAPIFilteringRequest, OpenAPIRequest
1920
from linodecli.baked.response import OpenAPIResponse
21+
from linodecli.output import OutputHandler
2022
from linodecli.overrides import OUTPUT_OVERRIDES
2123

2224

23-
def parse_boolean(value):
25+
def parse_boolean(value: str) -> bool:
2426
"""
2527
A helper to allow accepting booleans in from argparse. This is intended to
2628
be passed to the `type=` kwarg for ArgumentParser.add_argument.
29+
30+
:param value: The value to be parsed into boolean.
31+
:type value: str
32+
33+
:returns: The boolean value of the input.
34+
:rtype: bool
2735
"""
2836
if value.lower() in ("yes", "true", "y", "1"):
2937
return True
@@ -32,10 +40,16 @@ def parse_boolean(value):
3240
raise argparse.ArgumentTypeError("Expected a boolean value")
3341

3442

35-
def parse_dict(value):
43+
def parse_dict(value: str) -> dict:
3644
"""
3745
A helper function to decode incoming JSON data as python dicts. This is
3846
intended to be passed to the `type=` kwarg for ArgumentParaser.add_argument.
47+
48+
:param value: The json string to be parsed into dict.
49+
:type value: str
50+
51+
:returns: The dict value of the input.
52+
:rtype: dict
3953
"""
4054
if not isinstance(value, str):
4155
raise argparse.ArgumentTypeError("Expected a JSON string")
@@ -68,10 +82,16 @@ class ExplicitEmptyListValue:
6882
"""
6983

7084

71-
def wrap_parse_nullable_value(arg_type):
85+
def wrap_parse_nullable_value(arg_type: str) -> TYPES:
7286
"""
7387
A helper function to parse `null` as None for nullable CLI args.
7488
This is intended to be called and passed to the `type=` kwarg for ArgumentParser.add_argument.
89+
90+
:param arg_type: The arg type.
91+
:type arg_type: str
92+
93+
:returns: The nullable value of the type.
94+
:rtype: TYPES
7595
"""
7696

7797
def type_func(value):
@@ -93,7 +113,13 @@ class ArrayAction(argparse.Action):
93113
empty lists using a singular "[]" argument value.
94114
"""
95115

96-
def __call__(self, parser, namespace, values, option_string=None):
116+
def __call__(
117+
self,
118+
parser: argparse.ArgumentParser,
119+
namespace: argparse.Namespace,
120+
values: List,
121+
option_string: str = None,
122+
):
97123
if getattr(namespace, self.dest) is None:
98124
setattr(namespace, self.dest, [])
99125

@@ -121,7 +147,13 @@ class ListArgumentAction(argparse.Action):
121147
lists in the output namespace.
122148
"""
123149

124-
def __call__(self, parser, namespace, values, option_string=None):
150+
def __call__(
151+
self,
152+
parser: argparse.ArgumentParser,
153+
namespace: argparse.Namespace,
154+
values: List,
155+
option_string: str = None,
156+
):
125157
if getattr(namespace, self.dest) is None:
126158
setattr(namespace, self.dest, [])
127159

@@ -149,7 +181,7 @@ def __call__(self, parser, namespace, values, option_string=None):
149181

150182
adjacent_items = {k: getattr(namespace, k) for k in adjacent_keys}
151183

152-
# Find the deepest field so we can know if
184+
# Find the deepest field, so we can know if
153185
# we're starting a new object.
154186
deepest_length = max(len(x) for x in adjacent_items.values())
155187

@@ -175,7 +207,13 @@ class PasswordPromptAction(argparse.Action):
175207
def __init__(self, *args, **kwargs):
176208
super().__init__(*args, **kwargs)
177209

178-
def __call__(self, parser, namespace, values, option_string=None):
210+
def __call__(
211+
self,
212+
parser: argparse.ArgumentParser,
213+
namespace: argparse.Namespace,
214+
values: str,
215+
option_string: str = None,
216+
):
179217
# if not provided on the command line, pull from the environment if it
180218
# exists at this key
181219
environ_key = f"LINODE_CLI_{self.dest.upper()}"
@@ -202,7 +240,13 @@ class OptionalFromFileAction(argparse.Action):
202240
the file exists, otherwise it will fall back to using the provided value.
203241
"""
204242

205-
def __call__(self, parser, namespace, values, option_string=None):
243+
def __call__(
244+
self,
245+
parser: argparse.ArgumentParser,
246+
namespace: argparse.Namespace,
247+
values: str,
248+
option_string: str = None,
249+
):
206250
if isinstance(values, str):
207251
input_path = path.expanduser(values)
208252

@@ -232,7 +276,7 @@ class OpenAPIOperationParameter:
232276
A parameter is a variable element of the URL path, generally an ID or slug
233277
"""
234278

235-
def __init__(self, parameter):
279+
def __init__(self, parameter: openapi3.paths.Parameter):
236280
"""
237281
:param parameter: The Parameter object this is parsing values from
238282
:type parameter: openapi3.Parameter
@@ -254,7 +298,7 @@ def __init__(self, command, operation: Operation, method, params):
254298
"""
255299
Wraps an openapi3.Operation object and handles pulling out values relevant
256300
to the Linode CLI.
257-
.. note::
301+
note::
258302
This function runs _before pickling! As such, this is the only place
259303
where the OpenAPI3 objects can be accessed safely (as they are not
260304
usable when unpickled!)
@@ -341,16 +385,32 @@ def args(self):
341385
return self.request.attrs if self.request else []
342386

343387
@staticmethod
344-
def _flatten_url_path(tag):
388+
def _flatten_url_path(tag: str) -> str:
389+
"""
390+
Returns the lowercase of the tag to build up url path. Replace space with hyphen.
391+
392+
:param tag: The tag value to be flattened.
393+
:type tag: str
394+
395+
:returns: The flattened tag.
396+
:rtype: str
397+
"""
398+
345399
new_tag = tag.lower()
346400
new_tag = re.sub(r"[^a-z ]", "", new_tag).replace(" ", "-")
347401
return new_tag
348402

349403
def process_response_json(
350-
self, json, handler
404+
self, json: Dict[str, Any], handler: OutputHandler
351405
): # pylint: disable=redefined-outer-name
352406
"""
353-
Processes the response as JSON and prints
407+
Processes the response as JSON and prints.
408+
409+
:param json: The json response.
410+
:type json: Dict[str, Any]
411+
412+
:param handler: The CLI output handler.
413+
:type handler: OutputHandler
354414
"""
355415
if self.response_model is None:
356416
return
@@ -366,7 +426,14 @@ def process_response_json(
366426
json = self.response_model.fix_json(json)
367427
handler.print_response(self.response_model, json)
368428

369-
def _add_args_filter(self, parser):
429+
def _add_args_filter(self, parser: argparse.ArgumentParser):
430+
"""
431+
Builds up filter args for GET operation.
432+
433+
:param parser: The parser to use.
434+
:type parser: ArgumentParser
435+
"""
436+
370437
# build args for filtering
371438
filterable_args = []
372439
for attr in self.response_model.attrs:
@@ -404,7 +471,19 @@ def _add_args_filter(self, parser):
404471
help="Either “asc” or “desc”. Defaults to “asc”. Requires +order_by",
405472
)
406473

407-
def _add_args_post_put(self, parser) -> List[Tuple[str, str]]:
474+
def _add_args_post_put(
475+
self, parser: argparse.ArgumentParser
476+
) -> List[Tuple[str, str]]:
477+
"""
478+
Builds up args for POST and PUT operations.
479+
480+
:param parser: The parser to use.
481+
:type parser: ArgumentParser
482+
483+
:returns: A list of arguments.
484+
:rtype: List[Tuple[str, str]]
485+
"""
486+
408487
list_items = []
409488

410489
# build args for body JSON
@@ -468,6 +547,9 @@ def _validate_parent_child_conflicts(self, parsed: argparse.Namespace):
468547
"""
469548
This method validates that no child arguments (e.g. --interfaces.purpose) are
470549
specified alongside their parent (e.g. --interfaces).
550+
551+
:param parsed: The parsed arguments.
552+
:type parsed: Namespace
471553
"""
472554
conflicts = defaultdict(list)
473555

@@ -508,8 +590,23 @@ def _validate_parent_child_conflicts(self, parsed: argparse.Namespace):
508590

509591
@staticmethod
510592
def _handle_list_items(
511-
list_items: List[Tuple[str, str]], parsed: Any
593+
list_items: List[Tuple[str, str]], parsed: argparse.Namespace
594+
) -> (
595+
argparse.Namespace
512596
): # pylint: disable=too-many-locals,too-many-branches,too-many-statements
597+
"""
598+
Groups list items and parses nested list.
599+
600+
:param list_items: The list items to be handled.
601+
:type list_items: List[Tuple[str, str]]
602+
603+
:param parsed: The parsed arguments.
604+
:type parsed: argparse.Namespace
605+
606+
:returns: The parsed arguments updated with the list items.
607+
:rtype: argparse.Namespace
608+
"""
609+
513610
lists = {}
514611

515612
# group list items as expected
@@ -582,10 +679,16 @@ def _handle_list_items(
582679

583680
return parsed
584681

585-
def parse_args(self, args):
682+
def parse_args(self, args: Any) -> argparse.Namespace:
586683
"""
587684
Given sys.argv after the operation name, parse args based on the params
588685
and args of this operation
686+
687+
:param args: The arguments to be parsed.
688+
:type args: Any
689+
690+
:returns: The parsed arguments.
691+
:rtype: Namespace
589692
"""
590693

591694
# build an argparse

0 commit comments

Comments
 (0)