I am trying to make a login script check for a verified email the check script is
#check for verification
while True:
if "'emailVerified': True" in accountinfo:
break
else:
print("Your email has not been verified! Please verify it with the new link we have sent.")
auth.send_email_verification(user['idToken'])
menu()
The value in the table I am trying to find is
'emailVerified': True
It keeps saying it can not find it though the value is there. How do I make it look for that? Am I doing it wrong?
It looks like you are trying to use the string "'emailVerified': True" as a key to the accountinfo dictionary object (representing an account's info I think).
The think the best way to do it would be to do this:
while True:
if accountinfo['users'][0]['emailVerified']:
break
else:
print("Your email has not been verified! Please verify it with the new link we have sent.")
auth.send_email_verification(user['idToken'])
menu()
Although this is quite bad and the structure of your accountinfo object is convoluted. I think you should either split it up into two objects or just unpack the lists into key value pairs for the entire accountinfo object. I would avoid having to use [0] (or having to use [i]) to index the List within the dictionary object, which has ANOTHER dictionary in it! That is very confusing hierarchy of python objects.
You should try to change the accountinfo object to allow this:
while True:
if accountinfo['emailVerified']:
break
else:
print("Your email has not been verified! Please verify it with the new link we have sent.")
auth.send_email_verification(user['idToken'])
menu()
Your user validation logic is not very clear. But if you simply ask why emailVerified: True is in accountinfo, but if "'emailVerified': True" in accountinfo always gets False. The answer is they are different types. The left is a string, the right is a dictionary(or json).
Can you try this function:
def is_any_user_email_verified(accountinfo):
return any(u for u in accountinfo['users'] if u['emailVerified'])
# usage:
if is_any_user_email_verified(accountinfo):
break
Related
I am working my way through Python Crash Course, and in Chapter 8 the author gives the following code as an example for filling a dictionary with user input. I am confused in the step where he stores the responses into the dictionary, as to my eye it looks as though he is only saving one piece of , "response" which is immutable data to the "responses" dictionary under the key "name". I am missing how both the name input and response input are put into the dictionary.
It seems to make no sense to me, but that is what I have loved about this journey so far, finding sense in seeming nonsense. Thank you for helping demystify this world for me.
responses = {}
# Set a flag to indicate that polling is active.
polling_active = True
while polling_active:
#Prompt for the person's name and response.
name = input("\nWhat is your name? ")
response = input("Which mountain would you like to climb someday? ")
#Store the response in the dictionary:
responses[name] = response
#Find out if anyone else is going to take the poll.
repeat = input("Would you like to let another person respond? (yes/no) ")
if repeat == 'no':
polling_active = False
#Polling is complete. Show the results.
print("\n--- Poll Results ---")
for name, response in responses.items():
print(name + " would like to climb " + response + ".")
The thing with dictionaries is that you can change the value of the key like this: dictionary[key] = value. If the key doesn't exist it will simply create a new key. You don't need any function like append which is used for lists. The line where you wrote responses[name] = response works because it stays in a while loop. After the loop runs again it asks another input and replaces the old name with a new name and old response with a new response. In conclusion, name and response is added every time the loop runs if the name is not already in the dictionary. If the name is there then it will simply change its value response if that is different from the old one.
Does this answer your question?
name and response are variables names that are filled with the inputted data, let's say 'John' and 'Kalimanjaro'.
Now, 'John' and 'Kalimanjaro' are indeed immutable, but that doesn't mean you can't replace the values stored in name and response in the next loop. You can assign a new value, maybe also immutable, to name if you want.
One possible source of confusion could be that you started learning dictionaries using statements like responses['John'] = 'Kalimanjaro', where both key and value were strings. Now you are doing responses[name] = response (no quotes around name and response). So you create a key called whatever was stored in name and a value with whatever was stored in response.
If in the next iteration the value of name is replaced by, let's say 'Maria' and response becomes 'Andes', the new responses[name] = response will be equivalent to responses['Maria'] = 'Andes'.
In the most basic explanation, dictionaries associates an arbitrary value at an arbitrary key. So, what the author is actually doing is associating the user's response with their name. The author does this by using the name as a key and the response as a value. Using dictionaries like this is fairly common.
If you want to retrieve a value in the array, you must know it key. However, you can retrieve all key and value pairs with dictionary.items(). This way, the author can get those two associated pieces of data (the name and the response).
all. Python newbie here.
Simply-put here is my basic idea:
I want to create a "Login" feature where people must input a valid username from a preset tuple.
Next, once a valid name is entered, they will be asked to enter the corresponding code name, which is saved to a dictionary. (I have a feeling that I am over-complicating this, or maybe the dictionary is the wrong idea entirely, so any advice on how to simplify would be great).
real_names = ("JD", "JM" "JC")
player_ids = {"JD":"Arrow","JM":"Bullet","JC":"Blade"}
while True:
# user must input a name from the real_names tuple
name = input("User unidentified. Please input your name: ")
# if username is not in tuple, rerun script
if not name in real_names:
print("Invalid username detected")
continue
print(f"Positive ID! Welcome, {name}")
break
The above code works just fine. But next, I want to make a new input that requires the player ID to match the previously input name. In Pseudo-code, something like this:
# While True Loop:
id = input("Please confirm user Code Name: ")
#ID must correspond to keyword in dictionary
if ID value does not match username Keyword:
print("Invalid ID")
continue
print("Identity confirmed!")
break
Am I on the right path? If so, how would I syntax the second part? If the dictionary is the wrong idea entirely, please provide a good alternative. Many thanks!
player_ids[name] is the value you're looking for. So, you want something like this:
if id != player_ids[name]:
print("invalid ID")
Also, the dictionary already keeps track of player names, so you don't need the real_names tuple.
This previous answer works perfect, because you are looking up the value based on the key from a dictionary. Finally, one little tip, it's always good practice to avoid naming variables after reserved variables and keywords, that is to say, use another variable name just in case you are going to use to use the id() function again in the program.
I'm trying to create a personnal password vault. Basically I want to create a program that asks me what I want to do and depending on my input (New, or Access "title of website here") the program either lets me add a website title with it's corresponding username and password. Then in I type "Access..." i should get the username and password returned relative to the website's tite I input after the Access input. OFC all of this data is to be stored in a text file.
PROBLEM:
The problem is that when I check the text file, it stays blank. I tried changing the access mode (a, r, etc) and it doesn't work. Not only that, but the program returns only the last data entered, and not whichever data in select.
Keep in mind I'm a beginner.
Below is the code used:
vault = open("Passvault.txt", "a")
total = True
while total == True:
creation = True
action = input("What do you want to do? ")
if action == "New" or action == "new":
title = input("Add website: ")
username = input("Create username: ")
password = input("Create password: ")
vault.write("Title:" + username)
vault.write("\n")
vault.write("Username:" + username)
vault.write("\n")
vault.write("Password:" + password)
elif action == "Access " + title:
print(title)
print("Username: " + username)
print("Password: " + password)
creation = False
elif action == "Close":
creation = False
total = False
vault.close()
First of all, you are not reading the file. Reading AND writing in 'append' ('a') mode is a bad idea (see potential cursor issues).
I tested the code on Google Colab and it works. Note that the writing occurs only if you close the file.
Suggestions:
It is a good time to learn about databases. Even a simple Excel file would fit your goal better (check package csv).
Use 'a+' as the mode of opening the file: if the file does not exist, create it.
Try to open and close the file a bit more frequently, say, each time when you want to write something. Also with clause may be useful (https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files)
First of all, where do you define the variable title used in the elif condition. Another that how you are reading the file for title. Third and most important that your problem clearly mentions is that you are not seeing results being saved and that is because you don't close the file instantly and close method actually writes all data and saves the file in the end. Another way to save data before closing the file is by using the flush method.
Try this code:
vault = open("Passvault.txt", "a")
total = True
while total == True:
creation = True
action = input("What do you want to do? ")
if action.lower() == "new":
title = input("Add website: ")
username = input("Create username: ")
password = input("Create password: ")
vault.write("Title:" + username)
vault.write("\n")
vault.write("Username:" + username)
vault.write("\n")
vault.write("Password:" + password)
elif action == "Access " + title:
print(title)
print("Username: " + username)
print("Password: " + password)
creation = False
elif action == "Close":
creation = False
total = False
vault.close()
You didn't close the file at the end.
First of all you seem to be a bit confused how everything is working here so lets me clarify and then I will point out all the problems.
You first create a variable vault and assign it to file opened via append(a) mode.
Now append mode is used generally to append data, here you want to both read and write
data so you need to use read and write permission(r+).
Second , you are trying to create a vault and don't encrypt it any way. the problem is
that anyone can see it as a plain text by opening that file.
Now you set total to True and then use it for infinite while loop.
The problem here is that you can directly do while True so that loop continues
forever and you don't need to assign total a value of True because it doesn't need to
be changed as you can use break keyword to break out of loop. You just wasted memory
by assigning variable to True
Now inside the while loop, you create creation variable but never use it for a purpose, so it is I think not needed or you might have another plan and might use it in the future so I won't say about it.
Now you get input from the user and set it's value to action variable. This step is OK but I wan't to clarify that there are several security problems here but since they are very complex so I won't tell them here but this should be OK.
Now's the time of conditions:
Now in first if condition, you check is action == 'New or action == 'new', here you don't need to includeor` , although that's okay and there is no problem with it, you can do better. .lower() is a string method and it lower cases all the letters of the alphabet.
Either you can do if action.lower() in ['new' , 'create' , 'n' ....all inputs you want ] , note here you dont have to include '.....all inputs you want' , Its just to tell you that you need to put there all inputs on which you want the condition to be true.
Or you can simply do if action.lower() == 'new'
Now only if the condition is true this code runs
You create title variable and set it to user input, now here's too security problem but due to complexity I won't go into much deep. Always remember , wherever you have user interaction with application , there's a chance of security problem there.
Then you get the password and same problem. But also notice that you don't encrypt anything here. That's a big issue.
Now you write everything to the file but be aware that .write() doesn't write directly. You either have to call .flush() or close the file via .close() . But notice the problem , you called .close() but in the very end and out of the infinite while loop. You can tell that that close command is out of while loop by telling that both while loop and close are at the same level. If you have to put it inside while loop, you need to indent it a bit just like other code which is inside while loop. But that is also not gonna work because you close the file and you can't reuse it withot reopening it so either you put both open and close parts inside while loop or you use the .flush() method. This is the biggest bug due to which you are facing such a problem.
Now's the time of elif conditon
Here you see that in the condition you do if action == 'Access ' + title: and there are several problems here.
First you see that you directly compare action to access and you can do it better by using that list trich used in above if condition and can use .lower() method
Second that you use the title variable which notice only get defined when the above if condition runs. What if the above if condition doesn't run and what is the user directly said 'Access Google" or anything accept the above if condition such as "#^%&GJ" . Then elif condition will run and your variable title will not be found by python and then your program will crash. So it is better that you first search that if the input contains Access and the break it into Access And The keyword after it. There are several functions you can use like .strip() or others. Visit this link fore more methods.
Third, you are using the file cursor without being aware of it. Just like cursor in any text editor, the file handler also has a cursor which move foreward as you read the file and in the end it will reach the end of the file and once again you read , it wont return anything since there's nothing ahead of it. To know more about it, visit this link.
And these were the main problems due to which your code is not working correctly
There are also many more problems such as
Your way of reading from file
Your way of writing to the file
No error handling
Your way of closing the file
Your way of handling file
No encryptions
Security problems
Etc.
But for now, that's gonna help you in your task.
Good Luck And Smart Work!
I have a list of tuples, holding information about people (one for each tuple, with things like (name, age, etc.)). I want to check the list to see whether any names match a user input. My problem is if I use a for loop I then get multiple lines returning false, rather than just one. I also cannot then ask the user to try again, until success. My current code is:
last_name = input("Please input person's last name")
for person in personList:
if person[0] == last_name.capitalize():
print("success")
else:
print("fail")
This will print out "fail" for each player, rather than just once, and will not prompt a user to try again. I know a while loop would enable multiple attempts but I can't see how to link the while with the for, and still output a "fail" only once.
As I'm trying to learn more about tuples, please don't suggest using objects. I know it would make a lot more sense but it doesn't help me understand tuples.
You need two modifications: a way to stop the loop if you find a match, and a way to print 'fail' only if you found no matches in the entire list.
You can get the first modification by adding a break in the if statement, and you can get the second one by adding an else clause to the for loop, which means "run this code if the loop ran to its full completion".
for person in personList:
if person[0] == last_name.capitalize():
print("success")
break
else:
print("fail")
You could simplify checking if user input value is in personList to one line like so and then check whether input matched at least once and if it did print 'success' and break loop, else print 'fail' and ask user again.
personList = [('Abc', 'Cba'), ('Xyz', 'Zyx')]
while True:
last_name = input("Please input person's last name: ").capitalize()
if any(last_name == i[0] for i in personList):
print("success")
break
else:
print("fail")
Output:
Please input person's last name: random
fail
Please input person's last name: xyz
success
So first of all lets understand whats happening.
For each person in the tuple you ask if his name is X.
So accordingly each person will answer you: "No", until you get to the right person, and only that person will say: "Yes", and even further, unless he is the last one it will go on until the very end.
In conclusion, you're asking every single tuple to say whether it matches the user input, or not.
But there is also an easy way of fixing this. So what can we do instead?
We will just collect every answer, and then check whether our input exists in the collection.
Lets write down in code:
total_collection = []
for person in personList:
if person[0] == last_name.capitalize():
total_collection.append("1")
else:
total_collection.append("0")
if "1" in total_collection:
print("Success!")
else:
print("Fail...")
In this code, the string "1" represents a match, and the string "0" represents no-match.
Also, this way you can say at which index the match/es was/were located.
pnew to python and I am playing around with lists within tuples. I want to delete just the password not the Username, and update the password after the password has been deleted, however i tested the code to find out that it deletes the whole tuple and list within the tuple, then it gives me IndexError: list index out of range....any help would be appreciated.
Users=[("Jim","password1"),("Bob","password2"),("Helen","password3"),("Beverly","blue")]
def changePassword():
a=raw_input("Enter old password to continue:\n")
for i in range(len(Users)):
c,d=Users[i]
if a==d:
Users.remove(Users[i])
print "Password deleted"
print Users
if a!=d:
print"Incorrect"
changePassword()
a=raw_input("Enter new password:\n")
for i in range(len(Users)):
c,d=Users[i]
if a==d:
Users.append(Users[i])
changePassword()
There are several problems with your function, unless I completely misunderstand its purpose, but let’s start with the IndexError you get.
This is the code where it happens:
for i in range(len(Users)):
c,d=Users[i]
if a==d:
Users.remove(Users[i])
print "Password deleted"
print Users
So what happens here? You loop over the length of your list and if you matched the password then you remove the current user from the list. After that you continue iterating over the previously calculated length of the list. So, if you delete one item from the list, its length is reduced by one, but the for loop will still iterate over the old length (because range(len(Users)) is immediately evaluated). So if you just deleted one user from the list, the last value for i will try to access an item that no longer exists in the list.
There is a related problem which would occur directly as a follow-up, and that is that you would skip elements in the loop. You are removing an item from the list but you are also advancing i just as you would if no item was removed. So when you remove, say, item 1, then the new item 1 is the one that was previously 2. So when you advance to 2, you will have skipped that item.
So what can you do to fix this? Well, there are different methods. You could make a while loop instead and handle that indexing in a “classic” way (incrementing yourself and always checking the length in the while condition). You could also keep a second list to remember the items you are going to delete later (after the loop). However in your case, I think it might be a good idea to do something completely different.
From how I understood your function, you want to write something that allows you to change the password for a single user. So you enter the current password, then the new password and it will update the entry for the user in the list. This is not what is happening in your version as of now. What your function does is the following:
Ask for current password
Remove all users which have a matching password
Print "Incorrect" if the last user in the list did not have the entered password (it will only see the last value of d, so it will only check the very last user)
Ask for new password
Loop through the user list again and save only the last user (again, c and d will contain the last value after the loop)
If the last user had the same password as you have entered (why would you want to check that, you want to enter a new password), then append the very same user (because i again points at the last index in the list) to the list.
As you can see, there are some weird things going on, probably not intended. What you probably want to do instead is something like this:
Ask for the current password
Find the user for that password
Ask for the new password
Remove the old user from the list
Append a modified user to the list
So maybe something like this:
oldPassword = raw_input('Enter your old password to continue:\n') # 1
found = False
for name, password in Users:
if password == oldPassword: # 2
found = True
break
if found:
newPassword = raw_input('Enter new password:\n') # 3
Users.remove((name, password)) # 4
Users.append((name, newPassword)) # 5
else:
print 'Incorrect password'
I am not sure that a list of tuples is the best way to store user ids and passwords.
Maybe you could use a dictionary instead, that would look like this:
Passwords = {"Jim": "password1", "Bob": "password2", "Helen":"password3", "Beverly": "blue"}
This way you are sure that two different users will not have the same id.
Also, retrieving a user by its password is not a good idea, as several users may have the same
password. You should prompt for the user id first, or pass it as a parameter of your change password function. Something like this :
def changePassword(userId):
input=raw_input("Enter old password to continue:\n")
if input == Passwords[userId]:
new_password = raw_input("Enter new password:\n")
Passwords[userId] = new_password
else:
print "Wrong password"
changePassword(userId)