summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine A <>2024-02-24 19:05:20 +0100
committerAntoine A <>2024-02-24 19:05:20 +0100
commitb88b78e626083d1495b90441d0cdf7dd4c2afc32 (patch)
tree05915bd3e46c44c91d0c19c67216d19621e622a0
parent31a7de33b12e5e941a9025de86a66d67a7e27f61 (diff)
downloaddeployment-b88b78e626083d1495b90441d0cdf7dd4c2afc32.tar.gz
deployment-b88b78e626083d1495b90441d0cdf7dd4c2afc32.tar.bz2
deployment-b88b78e626083d1495b90441d0cdf7dd4c2afc32.zip
Simplify and document python code
-rwxr-xr-xregional-currency/ask_questions.py92
1 files changed, 60 insertions, 32 deletions
diff --git a/regional-currency/ask_questions.py b/regional-currency/ask_questions.py
index 8c36311..c8da3b1 100755
--- a/regional-currency/ask_questions.py
+++ b/regional-currency/ask_questions.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python3
+"""Python script to ask questions using an interactive prompt"""
import base64
import os
@@ -11,6 +12,7 @@ CONFIG_FILE = "config/user.conf"
def load_conf() -> Dict[str, str]:
+ """Load user configuration file"""
conf = {}
with open(CONFIG_FILE, "r") as f:
for kv in f.read().splitlines():
@@ -24,6 +26,7 @@ conf = load_conf()
def add_conf(name: str, value: str):
+ """Update a user configuration value and update the configuration file"""
conf[name] = value
content = ""
for key, value in conf.items():
@@ -36,6 +39,7 @@ def add_conf(name: str, value: str):
def run_cmd(
cmd: list[str], input: str | None = None, env: Dict[str, str] | None = None
) -> int:
+ """Run a command in a child process and return its exit code"""
result = subprocess.run(
cmd,
stdout=subprocess.PIPE,
@@ -53,6 +57,7 @@ def run_cmd(
def try_cmd(
cmd: list[str], input: str | None = None, env: Dict[str, str] | None = None
) -> bool:
+ """Run a command in a child process and return if successful"""
return run_cmd(cmd, input, env) == 0
@@ -60,35 +65,44 @@ A = TypeVar("A")
T = TypeVar("T")
-def custom(
+def conf_value(
name: str | None,
action: Callable[[], str | None],
default: T | None = None,
check: Callable[[str], T | None] = lambda it: it,
fmt: Callable[[T], str] = lambda it: str(it),
-):
+) -> T:
+ """
+ Logic to configure a value
+
+ :param name: if present will try to fetch the current value and will store the new value
+ :param action: how a value will be obtained
+ :param default: default value to use if no value is given
+ :param check: check and normalize the value
+ :param fmt: format value for storage
+ :return: the configuration value
+ """
+ value = None
+
+ # Fetch current value
if name is not None:
- prev = conf.get(name, None)
- if prev is not None: # If got previous value
- checked = check(prev)
- if checked is not None: # And previous value is valid
- add_conf(name, fmt(checked)) # Add again in case normalization changed
- return checked
-
- while True:
- raw = action()
- if raw is None:
- if default is not None:
- if name is not None:
- add_conf(name, fmt(default))
- return default
- continue
- else:
- checked = check(raw)
- if checked is not None:
- if name is not None:
- add_conf(name, fmt(checked))
- return checked
+ curr = conf.get(name, None)
+ if curr is not None:
+ # Check the current value and ask again if invalid
+ value = check(curr)
+
+ # Ask for a new value until we get a valid one
+ while value is None:
+ new = action()
+ # Use default if no value was provided else check the new value
+ value = check(new) if new is not None else default
+
+
+ # Store the new value
+ if name is not None:
+ add_conf(name, fmt(value))
+
+ return value
def ask(
@@ -98,9 +112,19 @@ def ask(
check: Callable[[str], T | None] = lambda it: it,
fmt: Callable[[T], str] = lambda it: str(it),
) -> T:
- def do_ask():
- log.write(msg.encode())
- log.write("\n".encode())
+ """
+ Prompt the user to configurea value
+ :param name: if present will try to fetch the current value and will store the new value
+ :param msg: the message to prompt the user with
+ :param default: default value to use if no value is obtained
+ :param check: check and normalize the value
+ :param fmt: format value for storage
+ :return: the configuration value
+ """
+ def do_ask() -> str | None:
+ # Log the prompt
+ log.write(msg.encode() + "\n".encode())
+ # Actual prompt
raw = input(msg).strip()
if raw == "":
if default is None:
@@ -108,14 +132,16 @@ def ask(
return None
return raw
- return custom(name, do_ask, default, check, fmt)
+ return conf_value(name, do_ask, default, check, fmt)
def ask_str(name: str | None, msg: str, default: str | None = None) -> str:
+ "Prompt the user to configure a string"
return ask(name, msg, default)
def ask_currency(name: str, msg: str, default: str | None = None) -> str:
+ "Prompt the user to configure a currency name"
def check_currency(currency: str) -> str | None:
currency = currency.upper()
if not currency.isascii() or not currency.isalpha():
@@ -130,6 +156,7 @@ def ask_currency(name: str, msg: str, default: str | None = None) -> str:
def ask_host(name: str, msg: str, default: str | None = None) -> str:
+ "Prompt the user to configure the installation hostname"
def check_host(host: str) -> str | None:
success = True
for subdomain in ["backend", "bank", "exchange"]:
@@ -143,6 +170,7 @@ def ask_host(name: str, msg: str, default: str | None = None) -> str:
def ask_yes_no(name: str | None, msg: str, default: bool | None = None) -> bool:
+ "Prompt the user to configure a boolean"
def check_yes_no(raw: str) -> bool | None:
raw = raw.lower()
if raw == "y" or raw == "yes":
@@ -187,7 +215,7 @@ if ask_yes_no("ENABLE_TLS", "5. Setup TLS using Let's Encrypt? (Y/n): ", True):
else:
return "y"
- custom("TLS_TOS", ask_tos)
+ conf_value("TLS_TOS", ask_tos)
add_conf("PROTO", "https")
else:
add_conf("PROTO", "http")
@@ -201,7 +229,7 @@ if not ask_yes_no(
if ask_yes_no(
"DO_TELESIGN",
- "7. Setup sms two-factor authentication using Telesign https://www.telesign.com? (Y/n): ",
+ "7. Setup SMS two-factor authentication using Telesign https://www.telesign.com? (Y/n): ",
True,
):
@@ -215,11 +243,11 @@ if ask_yes_no(
auth_token = base64.b64encode(f"{customer_id}:{api_key}".encode()).decode()
if not try_cmd(
["libeufin-tan-sms.sh", phone_number],
- "12345",
+ "12345 is your verification code for GNU Taler setup",
{**os.environ, "AUTH_TOKEN": auth_token},
):
print(
- "Failed to send an sms using Telesign API, check your credentials and phone number"
+ "Failed to send an SMS using Telesign API, check your credentials and phone number"
)
return None
code = ask_str(None, f"7.4. Enter the code received by {phone_number} : ")
@@ -230,7 +258,7 @@ if ask_yes_no(
return None
return auth_token
- custom("TELESIGN_AUTH_TOKEN", ask_telesign)
+ conf_value("TELESIGN_AUTH_TOKEN", ask_telesign)
ask_str(
"BANK_ADMIN_PASSWORD",
"8. Enter the admin password for the bank (or press enter to autogenerate password): ",