Reputation: 375
I am not sure if I am using Pydantic incorrectly but I want users to type in a terminal and if they get it wrong, I want them to keep trying until entering a valid range.
class Input(BaseModel):
number_range:str
name:str
@validator("number_range")
def all_numbers_are_valid(cls, value:str) -> str:
string_list:list = value.split(",")
string_list = list(map(cls.remove_spaces, string_list))
string_bool = list(map(lambda x: x.isnumeric(), string_list))
if False in string_bool:
flag = True
while flag:
print("Invalid characters, please try again.")
value = input("Range of floors:")
string_list:list = value.split(",")
string_list = list(map(cls.remove_spaces, string_list))
string_bool = list(map(lambda x: x.isnumeric(), string_list))
flag = True if False in string_bool else False
return ", ".join(map(str,string_list))
@validator("name")
def no_space_name(cls, value:str) -> str:
return cls.remove_spaces(value)
Input(number_range=input("Enter a range of numbers:"), name=input("Enter name:"))
Example of input:
Enter a range of numbers: 0,1,a
Enter name: he llo
I want user to be prompted with entering the a valid range of numbers BEFORE moving onto next field. Is that possible?
Upvotes: 1
Views: 796
Reputation: 793
You probably overcomplicate your model. The better way is to move the input process out of the class.
Firstly, if you want the number_range
to be the list of integers it is better to declare it in the class
class Input(BaseModel):
number_range: List[int]
name: str
Secondly, if you want a name
without spaces between words, you should handle this by a validator.
@validator("name", pre=True)
def no_space_name(cls, v):
# your logic or...
return v.replace(" ", "")
Then we move the whole input process outside of the class. This way you are still able to simply create a class instance in other places in your code without this whole input process.
whole code:
from typing import List
from pydantic import BaseModel, validator
class Input(BaseModel):
number_range: List[int]
name: str
@validator("name", pre=True)
def no_space_name(cls, v):
# your logic or...
return v.replace(" ", "")
if __name__ == '__main__':
input_kwargs = {}
while not input_kwargs.get("number_range"):
range_data = input("Enter a range of numbers (coma separated): ").split(",")
if all([item.isnumeric() for item in range_data]):
input_kwargs["number_range"] = range_data
else:
print("All values must be coma separated integers")
while not input_kwargs.get("name"):
input_kwargs["name"] = input("Enter name: ").strip()
my_instance = Input(**input_kwargs)
print(my_instance.json())
Example:
>>> Enter a range of numbers (coma separated):
1, 3, 4, a
All values must be coma separated integers
>>> Enter a range of numbers (coma separated):
1,3,4,5
>>> Enter name:
Two Words
{"number_range": [1, 3, 4, 5], "name": "TwoWords"}
And if you need, you can still declare your class like this:
>>> other_instance = Input(name="TheName", number_range=[1,3,4])
>>> other_instance.json()
'{"number_range": [1, 3, 4], "name": "TheName"}'
Upvotes: 3
Reputation: 1
I guess it's not possible since the class Input
has to wait for all the values from the accomplished input("Enter a range of numbers:")
and input("Enter name:")
, then it is able to run the validator decorator and your customized checking scripts.
How about using questionary
? I think it will satisfy your needs. You could refer to it here.
Upvotes: 0