PyInquirer
PyInquirer copied to clipboard
Can't use "message" as a function(answers: dict) -> str
The documentation says that the "message" attribute of a question can be a string or a function that takes the current answers and returns a string. That doesn't appear to be accurate documentation as any function, or lambda, I use as a questions "message" gets evaluated as a string in the prompt.
e.g. This question definition;
def my_message(answers):
return "Hello {x}".format(x=len(answers))
questions = [
dict(
type="list",
name="answer",
message=my_message,
choices=[dict(name=x) for x in "foo bar baz".split()],
]
... renders like so;
? <function get_questions.<locals>.my_message at 0x7ff19399d158> (Use arrow keys)
❯ foo
bar
baz
Originally posted by @AndrewOwenMartin in https://github.com/CITGuru/PyInquirer/issues/39#issuecomment-487012662
I have a workaround for this, you need to do a few things.
Firstly, you need to make an answers
variable, to which you keep a reference and pass to prompt
.
Secondly, you need to make a class that has a __str__
function, you will pass this as your message so when PyInquirer casts it to a string, that function gets called.
Thirdly you must be very careful with the answers
variable, if you initialise it as an empty dictionary then PyInquirer will assume you passed nothing and make its own variable, so you need to also do one of two things
- Initialise
answers
as anything not empty e.g. `answers = {"ignore this":"ignore this"} - Define a new class, derived from
dict
which evaluates to True when empty (and hence always evaluates as True)
Here's a minimum working example...
from PyInquirer import prompt
class Message:
def __init__(self, msg):
self.msg = msg
def __str__(self):
return "{msg} Your previous answers were {a}".format(msg=self.msg, a=answers)
questions = [
dict(
type="input",
message="Type anything",
default="foo",
name="first answer",
),
dict(
type="input",
message=Message("Type anything again."),
name="second answer",
),
]
answers = {'ignore me':'ignore me'}
prompt(questions, answers)
print(answers)
class TruthyDict(dict):
def __bool__(self):
return True
answers = TruthyDict()
prompt(questions, answers)
print(answers)
Produces this output...
? Type anything first example
? Type anything again. Your previous answers were {'first answer': 'first example', 'ignore me': 'ignore me'} notice the extra "ignore me"
{'first answer': 'first example', 'second answer': 'notice the extra "ignore me"', 'ignore me': 'ignore me'}
? Type anything second example
? Type anything again. Your previous answers were {'first answer': 'second example'} much nicer :)
{'first answer': 'second example', 'second answer': 'much nicer :)'}
@AndrewOwenMartin Sorry for my late response. I am currently working on this. I will get back to you
Any updates?