From 93f5020cccb711829c9765e30b5331a904c54eb9 Mon Sep 17 00:00:00 2001 From: robcxyz Date: Mon, 12 Dec 2022 08:28:00 +0530 Subject: [PATCH] chore: add better excpetion for prompts run in automation where no input can be given --- tackle/exceptions.py | 21 +++++++++++++++++++-- tackle/providers/prompts/hooks/checkbox.py | 5 ++++- tackle/providers/prompts/hooks/confirm.py | 5 ++++- tackle/providers/prompts/hooks/editor.py | 5 ++++- tackle/providers/prompts/hooks/expand.py | 5 ++++- tackle/providers/prompts/hooks/input.py | 5 ++++- tackle/providers/prompts/hooks/password.py | 5 ++++- tackle/providers/prompts/hooks/rawlist.py | 5 ++++- tackle/providers/prompts/hooks/select.py | 5 ++++- 9 files changed, 51 insertions(+), 10 deletions(-) diff --git a/tackle/exceptions.py b/tackle/exceptions.py index b4c6864f3..4387036c7 100644 --- a/tackle/exceptions.py +++ b/tackle/exceptions.py @@ -147,10 +147,27 @@ def __init__(self, extra_message: str, context: 'Union[Context, BaseContext]'): class HookCallException(TackleParserException): """ - Exception for an unknown field in a hook. + Exception when calling a hook. - Raised when field has been provided not declared in the hook type. + Raised within a python hook. + """ + + +class PromptHookCallException(TackleParserException): """ + Exception when calling a prompt hook typically in automation. + + Raised within a python hook. + """ + + def __init__(self, context: 'Union[Context, BaseContext]'): + super().__init__( + extra_message="Error calling hook most likely due to hook being called in " + "automation where no input was given for key. Try setting " + "the key with an `override` if that is the case. Check: " + "https://sudoblockio.github.io/tackle/testing-providers/#testing-tackle-scripts", # noqa + context=context, + ) class HookParseException(TackleParserException): diff --git a/tackle/providers/prompts/hooks/checkbox.py b/tackle/providers/prompts/hooks/checkbox.py index 06a6190bc..5e4e20435 100644 --- a/tackle/providers/prompts/hooks/checkbox.py +++ b/tackle/providers/prompts/hooks/checkbox.py @@ -6,6 +6,7 @@ from tackle.models import BaseHook, Field from tackle.utils.dicts import get_readable_key_path +from tackle import exceptions class InquirerCheckboxHook(BaseHook): @@ -13,7 +14,7 @@ class InquirerCheckboxHook(BaseHook): Hook for PyInquirer `checkbox` type prompts. Allows the user to multi-select from a list of choices and outputs a list. Takes in three forms of `choices` inputs. A list of string, a list of maps with all keys having a `name` field per the original - [spec](https://github.com/CITGuru/PyInquirer/blob/master/examples/checkbox.py), or + [spec](https://github.com/kazhala/InquirerPy/blob/master/examples/checkbox.py), or list of maps with the key as the question, the value as the output. """ @@ -145,4 +146,6 @@ def _run_prompt(self): except KeyboardInterrupt: print("Exiting...") sys.exit(0) + except EOFError: + raise exceptions.PromptHookCallException(context=self) return response['tmp'] diff --git a/tackle/providers/prompts/hooks/confirm.py b/tackle/providers/prompts/hooks/confirm.py index c883ddf63..2ca5aedc6 100644 --- a/tackle/providers/prompts/hooks/confirm.py +++ b/tackle/providers/prompts/hooks/confirm.py @@ -3,12 +3,13 @@ from tackle.models import BaseHook, Field from tackle.utils.dicts import get_readable_key_path +from tackle import exceptions class InquirerConfirmHook(BaseHook): """ Hook to confirm with a message and return a boolean. - [Source example](https://github.com/CITGuru/PyInquirer/blob/master/examples/confirm.py) + [Source example](https://github.com/kazhala/InquirerPy/blob/master/examples/confirm.py) """ hook_type: str = 'confirm' @@ -37,6 +38,8 @@ def exec(self) -> bool: except KeyboardInterrupt: print("Exiting...") sys.exit(0) + except EOFError: + raise exceptions.PromptHookCallException(context=self) return response['tmp'] elif self.default: diff --git a/tackle/providers/prompts/hooks/editor.py b/tackle/providers/prompts/hooks/editor.py index fd28f25d2..27edd6d09 100644 --- a/tackle/providers/prompts/hooks/editor.py +++ b/tackle/providers/prompts/hooks/editor.py @@ -5,12 +5,13 @@ from tackle.models import BaseHook, Field from tackle.utils.dicts import get_readable_key_path +from tackle import exceptions class InquirerEditorHook(BaseHook): """ Hook for PyInquirer `editor` type prompts. Opens an editor like nano to fill in a - field. [Source example](https://github.com/CITGuru/PyInquirer/blob/master/examples/editor.py) + field. [Source example](https://github.com/kazhala/InquirerPy/blob/master/examples/editor.py) """ hook_type: str = 'editor' @@ -37,6 +38,8 @@ def exec(self) -> bool: except KeyboardInterrupt: print("Exiting...") sys.exit(0) + except EOFError: + raise exceptions.PromptHookCallException(context=self) return response['tmp'] elif self.default: diff --git a/tackle/providers/prompts/hooks/expand.py b/tackle/providers/prompts/hooks/expand.py index 73eb52592..695b9a5b3 100644 --- a/tackle/providers/prompts/hooks/expand.py +++ b/tackle/providers/prompts/hooks/expand.py @@ -4,12 +4,13 @@ from typing import Any from tackle.models import BaseHook, Field from tackle.utils.dicts import get_readable_key_path +from tackle import exceptions class InquirerExpandHook(BaseHook): """ Hook for PyInquirer `expand` type prompt. - [Source example](https://github.com/CITGuru/PyInquirer/blob/master/examples/expand.py) + [Source example](https://github.com/kazhala/InquirerPy/blob/master/examples/expand.py) """ hook_type: str = 'expand' @@ -38,6 +39,8 @@ def exec(self) -> list: except KeyboardInterrupt: print("Exiting...") sys.exit(0) + except EOFError: + raise exceptions.PromptHookCallException(context=self) return response['tmp'] elif self.default: diff --git a/tackle/providers/prompts/hooks/input.py b/tackle/providers/prompts/hooks/input.py index 13473d89d..5bd9bb436 100644 --- a/tackle/providers/prompts/hooks/input.py +++ b/tackle/providers/prompts/hooks/input.py @@ -4,12 +4,13 @@ from typing import Any from tackle.models import BaseHook, Field from tackle.utils.dicts import get_readable_key_path +from tackle import exceptions class InquirerInputHook(BaseHook): """ Hook for PyInquirer 'input' type prompts. Allows the user to input a string input. - [Source example](https://github.com/CITGuru/PyInquirer/blob/master/examples/input.py) + [Source example](https://github.com/kazhala/InquirerPy/blob/master/examples/input.py) """ hook_type: str = 'input' @@ -42,6 +43,8 @@ def exec(self) -> str: except KeyboardInterrupt: print("Exiting...") sys.exit(0) + except EOFError: + raise exceptions.PromptHookCallException(context=self) return response['tmp'] elif self.default: diff --git a/tackle/providers/prompts/hooks/password.py b/tackle/providers/prompts/hooks/password.py index 83094ef76..e64054597 100644 --- a/tackle/providers/prompts/hooks/password.py +++ b/tackle/providers/prompts/hooks/password.py @@ -6,12 +6,13 @@ from tackle.models import BaseHook, Field from tackle.utils.dicts import get_readable_key_path +from tackle import exceptions class InquirerPasswordHook(BaseHook): """ Hook for PyInquirer `password` type prompts. Masks the input as the user types it - in. [Source example](https://github.com/CITGuru/PyInquirer/blob/master/examples/password.py) + in. [Source example](https://github.com/kazhala/InquirerPy/blob/master/examples/password.py) """ hook_type: str = 'password' @@ -39,6 +40,8 @@ def exec(self) -> str: except KeyboardInterrupt: print("Exiting...") sys.exit(0) + except EOFError: + raise exceptions.PromptHookCallException(context=self) return response['tmp'] elif self.default: diff --git a/tackle/providers/prompts/hooks/rawlist.py b/tackle/providers/prompts/hooks/rawlist.py index 93c889502..37a5f51bf 100644 --- a/tackle/providers/prompts/hooks/rawlist.py +++ b/tackle/providers/prompts/hooks/rawlist.py @@ -4,12 +4,13 @@ from typing import Any from tackle.models import BaseHook, Field from tackle.utils.dicts import get_readable_key_path +from tackle import exceptions class InquirerRawListHook(BaseHook): """ Hook for PyInquirer 'rawlist' type prompts. Similar to `select` hook with less - flexibility. [Source example](https://github.com/CITGuru/PyInquirer/blob/master/examples/rawlist.py) + flexibility. [Source example](https://github.com/kazhala/InquirerPy/blob/master/examples/rawlist.py) """ hook_type: str = 'rawlist' @@ -40,6 +41,8 @@ def exec(self) -> list: except KeyboardInterrupt: print("Exiting...") sys.exit(0) + except EOFError: + raise exceptions.PromptHookCallException(context=self) return response['tmp'] elif self.default: diff --git a/tackle/providers/prompts/hooks/select.py b/tackle/providers/prompts/hooks/select.py index 8b16e99da..ff6f6224a 100644 --- a/tackle/providers/prompts/hooks/select.py +++ b/tackle/providers/prompts/hooks/select.py @@ -5,6 +5,7 @@ from tackle.models import BaseHook, Field from tackle.utils.dicts import get_readable_key_path +from tackle import exceptions class InquirerListHook(BaseHook, smart_union=True): @@ -12,7 +13,7 @@ class InquirerListHook(BaseHook, smart_union=True): Hook for PyInquirer 'list' type prompts, a single selector that returns a string. Takes in two forms of `choices` inputs, list of string or list of maps with the key as the question and the value as the output. - [Source example](https://github.com/CITGuru/PyInquirer/blob/master/examples/list.py) + [Source example](https://github.com/kazhala/InquirerPy/blob/master/examples/list.py) """ hook_type: str = 'select' @@ -81,6 +82,8 @@ def _run_prompt(self): except KeyboardInterrupt: print("Exiting...") sys.exit(0) + except EOFError: + raise exceptions.PromptHookCallException(context=self) return response['tmp'] elif isinstance(self.choices[0], str):