questions.py 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. """Functions to collect user input.
  2. """
  3. from milc import cli, format_ansi
  4. def yesno(prompt, *args, default=None, **kwargs):
  5. """Displays prompt to the user and gets a yes or no response.
  6. Returns True for a yes and False for a no.
  7. If you add `--yes` and `--no` arguments to your program the user can answer questions by passing command line flags.
  8. @add_argument('-y', '--yes', action='store_true', arg_only=True, help='Answer yes to all questions.')
  9. @add_argument('-n', '--no', action='store_true', arg_only=True, help='Answer no to all questions.')
  10. Arguments:
  11. prompt
  12. The prompt to present to the user. Can include ANSI and format strings like milc's `cli.print()`.
  13. default
  14. Whether to default to a Yes or No when the user presses enter.
  15. None- force the user to enter Y or N
  16. True- Default to yes
  17. False- Default to no
  18. """
  19. if not args and kwargs:
  20. args = kwargs
  21. if 'no' in cli.args and cli.args.no:
  22. return False
  23. if 'yes' in cli.args and cli.args.yes:
  24. return True
  25. if default is not None:
  26. if default:
  27. prompt = prompt + ' [Y/n] '
  28. else:
  29. prompt = prompt + ' [y/N] '
  30. while True:
  31. print()
  32. answer = input(format_ansi(prompt % args))
  33. print()
  34. if not answer and prompt is not None:
  35. return default
  36. elif answer.lower() in ['y', 'yes']:
  37. return True
  38. elif answer.lower() in ['n', 'no']:
  39. return False
  40. def question(prompt, *args, default=None, confirm=False, answer_type=str, **kwargs):
  41. """Prompt the user to answer a question with a free-form input.
  42. prompt
  43. The prompt to present to the user. Can include ANSI and format strings like milc's `cli.print()`.
  44. default
  45. The value to return when the user doesn't enter any value. Use None to prompt until they enter a value.
  46. answer_type
  47. Specify a type function for the answer. Will re-prompt the user if the function raises any errors. Common choices here include int, float, and decimal.Decimal.
  48. """
  49. if not args and kwargs:
  50. args = kwargs
  51. if default is not None:
  52. prompt = '%s [%s] ' % (prompt, default)
  53. while True:
  54. print()
  55. answer = input(format_ansi(prompt % args))
  56. print()
  57. if answer:
  58. if confirm:
  59. if yesno('Is the answer "%s" correct?', answer, default=True):
  60. try:
  61. return answer_type(answer)
  62. except Exception as e:
  63. cli.log.error('Could not convert answer (%s) to type %s: %s', answer, answer_type.__name__, str(e))
  64. else:
  65. try:
  66. return answer_type(answer)
  67. except Exception as e:
  68. cli.log.error('Could not convert answer (%s) to type %s: %s', answer, answer_type.__name__, str(e))
  69. elif default is not None:
  70. return default