55import argparse
66import os
77import sys
8- from typing import Any , Dict , List , Optional
8+ from typing import Any , Dict , List , Optional , Type , TypeVar , cast
99
1010from linodecli .exit_codes import ExitCodes
1111
2727
2828ENV_TOKEN_NAME = "LINODE_CLI_TOKEN"
2929
30+ T = TypeVar ("T" )
31+
3032
3133class CLIConfig :
3234 """
@@ -216,15 +218,12 @@ def plugin_set_value(self, key: str, value: Any):
216218 :param value: The value to set for this key
217219 :type value: any
218220 """
219- if self .running_plugin is None :
220- raise RuntimeError (
221- "No running plugin to retrieve configuration for!"
222- )
223-
224221 username = self .username or self .default_username ()
225- self .config .set (username , f"plugin- { self .running_plugin } - { key } " , value )
222+ self .config .set (username , self ._get_plugin_key ( key ) , value )
226223
227- def plugin_get_value (self , key : str ) -> Optional [Any ]:
224+ def plugin_get_value (
225+ self , key : str , default : Optional [T ] = None , value_type : Type [T ] = str
226+ ) -> Optional [T ]:
228227 """
229228 Retrieves and returns a config value previously set for a plugin. Your
230229 plugin should have set this value in the past. If this value does not
@@ -235,18 +234,54 @@ def plugin_get_value(self, key: str) -> Optional[Any]:
235234 :param key: The key of the value to return
236235 :type key: str
237236
237+ :param default: The default value to return if the key is not set
238+ :type default: T
239+
240+ :param value_type: The type to which the value should be cast
241+ :type value_type: Type[T]
242+
238243 :returns: The value for this plugin for this key, or None if not set
239244 :rtype: any
240245 """
246+ username = self .username or self .default_username () or "DEFAULT"
247+ value = self .config .get (
248+ username , self ._get_plugin_key (key ), fallback = None
249+ )
250+ if value is None :
251+ return default
252+
253+ if value_type == str :
254+ return value
255+
256+ if value_type == bool :
257+ bool_value = self .parse_boolean (value )
258+ return bool_value if bool_value is not None else default
259+
260+ try :
261+ return cast (T , value_type (value ))
262+ except (ValueError , TypeError ):
263+ print (
264+ f"Could not cast config value { value } to { value_type } ." ,
265+ file = sys .stderr ,
266+ )
267+ return default
268+
269+ def plugin_remove_option (self , key : str ):
270+ """
271+ Removes a plugin configuration option.
272+
273+ :param key: The key of the option to remove
274+ """
275+ username = self .username or self .default_username ()
276+ self .config .remove_option (username , self ._get_plugin_key (key ))
277+
278+ def _get_plugin_key (self , key : str ) -> str :
241279 if self .running_plugin is None :
242280 raise RuntimeError (
243281 "No running plugin to retrieve configuration for!"
244282 )
245283
246- username = self .username or self .default_username () or "DEFAULT"
247- full_key = f"plugin-{ self .running_plugin } -{ key } "
248-
249- return self .config .get (username , full_key , fallback = None )
284+ return f"plugin-{ self .running_plugin } -{ key } "
250285
251286 # TODO: this is more of an argparsing function than it is a config function
252287 # might be better to move this to argparsing during refactor and just have
@@ -654,3 +689,13 @@ def get_custom_aliases(self) -> Dict[str, str]:
654689 if (self .config .has_section ("custom_aliases" ))
655690 else {}
656691 )
692+
693+ def parse_boolean (self , value : str ) -> Optional [bool ]:
694+ """
695+ Parses a string config value into a boolean. Returns None if the value
696+ cannot be parsed as a boolean.
697+
698+ :param value: The string value to parse.
699+ :return: The parsed boolean value.
700+ """
701+ return self .config .BOOLEAN_STATES .get (value .lower (), None )
0 commit comments