"""This module handle interactive user changes to the runcard."""
import os
import six
import signal
from typing import Callable
from logging import Logger
from pathlib import Path
import subprocess as sp
MAX_ITERATIONS = 10 # maximmum number of allowed failing attempts
[docs]class TimeOutError(Exception):
"""Exception class for time-out error."""
[docs]def question_instance(logger: Logger, question: str) -> str:
"""Asks for user input and checks if the answer is valid
Parameters
----------
logger: Logger
The logger instance.
question: str
The question to ask.
Returns
-------
str
The user answer to the question.
"""
valid_results = ["0", "auto", "done", "1"]
logger.info(question)
counter = 0
while True:
result = input().lower()
if result in valid_results:
break
try:
result = Path(result)
if result.is_file():
break
except:
logger.info("Valid inputs: [0, done, 1, runcard, enter path], try again.")
if counter >= MAX_ITERATIONS:
break
counter += 1
return result
[docs]def ask_question(
logger: Logger, question: str, default: str, timeout: float = 10
) -> str:
"""Asks question to user.
The user has only ``timeout`` seconds to answer, then the ``default`` is
returned.
Parameters
----------
logger: Logger
The logger instance.
question: str
The question to ask.
default: str
The default answer.
timeout: float
Time limit to answer in seconds.
Returns
-------
str
The user answer to the question.
"""
value = timed_input(
logger, question, default, timeout=timeout, fct=question_instance
)
return value
[docs]def ask_edit_card(logger: Logger, output: Path):
"""Asks interactively to edit the runcard.
Receives the input from the user and opens an editor in the terminal as a
subprocess. Default editor is nano, otherwise the `QUAKE_EDITOR` environment
variable allows for custom choice.
Parameters
----------
logger: logger
The logger instance.
output: Path
The output folder.
"""
default_quake_editor = "nano"
editor = os.environ.get("QUAKE_EDITOR", default_quake_editor)
question = """Do you want to edit a card (press enter to bypass editing)?
Type '0', 'auto', 'done' or just press enter when you are done
[0, done, 1, runcard, enter path]"""
answer = ask_question(logger, question, "0", timeout=60)
if answer not in ["0", "auto", "done"]:
if answer == "1":
fname = output / "cards/runcard.yaml"
else:
fname = answer
sp.call([editor, fname])
logger.info(f"Updated runcard at {fname}")