WEBVTT

0
00:00.360 --> 00:02.100
In the previous lessons today,

1
00:02.250 --> 00:07.250
we looked at how we can use the JSON format to store and load data into our

2
00:08.880 --> 00:09.713
program.

3
00:10.050 --> 00:15.050
We also looked at how we can use the try, except, else, and finally keywords to

4
00:15.750 --> 00:20.750
handle exceptions in our program to make sure that it doesn't fail and end up

5
00:21.540 --> 00:26.010
crashing our program so the user ends up with a bad user experience.

6
00:26.430 --> 00:30.810
Instead, we can anticipate the things that might happen. For example,

7
00:30.810 --> 00:32.640
the first time when we run our program,

8
00:32.850 --> 00:37.740
we might not have a data.json file and we deal with it accordingly.

9
00:38.520 --> 00:42.720
Now, all that's left to do is to put in the last bit of functionality,

10
00:42.840 --> 00:45.960
which is the search functionality, because after all,

11
00:45.960 --> 00:49.680
we don't want to be digging through a JSON file to find out all email and

12
00:49.680 --> 00:52.800
password combinations for the websites that we've stored.

13
00:53.460 --> 00:57.300
So what we want to be able to do is to add a search button

14
00:57.540 --> 01:02.160
and it's going to look very similar in size to the generate password button

15
01:02.520 --> 01:06.210
and it's going to be in the same grid column. Now,

16
01:06.240 --> 01:09.660
when we type in a website and we hit search,

17
01:09.870 --> 01:13.110
it's going to look through our JSON, find that data,

18
01:13.650 --> 01:18.650
load that data up and look through it for a key that matches the one the user

19
01:19.680 --> 01:21.750
typed in. If they find it,

20
01:21.900 --> 01:26.900
then we get a pop up showing up and it tells us the email and the password

21
01:27.030 --> 01:29.040
that's associated with that account.

22
01:30.060 --> 01:35.040
So you've actually done all of this before. Creating tkinter widgets,

23
01:35.310 --> 01:37.350
laying out tkinter widgets,

24
01:37.650 --> 01:42.650
creating message boxes or these popups and giving it a title,

25
01:42.840 --> 01:44.160
giving it a message.

26
01:44.520 --> 01:49.520
You've also seen how you can load JSON data and get the data in the format of a

27
01:52.260 --> 01:55.920
Python dictionary. Now, once you have the Python dictionary,

28
01:55.980 --> 02:00.660
then you can use your usual dictionary methods to try and get hold of the data

29
02:00.660 --> 02:02.880
that's inside. And finally,

30
02:02.910 --> 02:06.030
you also know how to deal with exceptions.

31
02:06.330 --> 02:10.020
So remember, there might also be an exception in this case,

32
02:10.410 --> 02:15.120
because if this was the first time that we were running this password manager,

33
02:15.480 --> 02:16.110
and in fact,

34
02:16.110 --> 02:21.110
we hadn't stored any websites or any emails or passwords in our database,

35
02:21.450 --> 02:25.230
then if you hit search, it might actually just give you a file

36
02:25.230 --> 02:29.820
not found error as well. So there's quite a few components involved,

37
02:29.910 --> 02:33.060
but I'm pretty sure that you can actually get this to work.

38
02:33.690 --> 02:38.040
So the end outcome you're looking for looks something like this in terms of

39
02:38.040 --> 02:38.873
layout,

40
02:39.120 --> 02:44.120
and you should be able to test this so that when you start out without a data

41
02:45.150 --> 02:49.290
.json file and you hit search, it should tell you error,

42
02:49.530 --> 02:50.970
No data file found.

43
02:51.450 --> 02:56.310
But, if you had saved a password under that name and you added it to the

44
02:56.310 --> 02:58.770
database, then you try to find it,

45
02:59.080 --> 03:02.200
then it should find you the email and the password that you saved.

46
03:02.590 --> 03:04.180
So this is what you're aiming for

47
03:04.330 --> 03:07.900
and I'm pretty sure that you can do it with just a little bit of thought and 

48
03:07.900 --> 03:11.590
a little bit of time spent problem-solving. Once you're ready,

49
03:11.710 --> 03:15.910
pause the video and give this final challenge a go to complete the password

50
03:15.910 --> 03:16.380
manager

51
03:16.380 --> 03:18.030
<v 1>project. Good luck.</v>

52
03:22.440 --> 03:23.440
Alright, so I hope

53
03:23.880 --> 03:27.750
<v 0>you gave that a good go. And as I always say, if there's no struggle,</v>

54
03:27.750 --> 03:28.620
there's no learning.

55
03:28.920 --> 03:33.900
So make sure that you've allocated at least 20 minutes to trying things out and

56
03:33.900 --> 03:38.790
figuring things out and debugging and just messing with the code yourself before

57
03:38.790 --> 03:41.280
you're coming to the solution. But all right,

58
03:41.340 --> 03:43.530
I'm going to walk through the solution with you together.

59
03:44.130 --> 03:49.050
And the first thing we're going to do is we're going to add a button next to our

60
03:49.050 --> 03:50.280
website entry.

61
03:51.360 --> 03:56.360
So right here. Now notice how we've got our three columns in our grid system.

62
03:57.450 --> 04:02.450
So our search button is going to go in pretty much in the same column as our

63
04:02.490 --> 04:07.350
generate password button. So let's go ahead and create our

64
04:07.530 --> 04:09.120
<v 1>search button.</v>

65
04:10.470 --> 04:14.850
<v 0>This is going to be a button with the text that says</v>

66
04:15.300 --> 04:16.133
<v 1>Search.</v>

67
04:17.520 --> 04:21.630
<v 0>Now, once we've created that, let's go ahead and lay it out</v>

68
04:21.630 --> 04:23.250
uusing the grid system.

69
04:23.970 --> 04:28.970
Now the search button is going to go onto the grid in the same row as the

70
04:29.550 --> 04:34.290
website label and the website entry. So that is row 1.

71
04:34.560 --> 04:38.940
So let's go ahead and add row equals 1 and column-wise,

72
04:38.970 --> 04:42.600
it's going to go in the same column as the generate password.

73
04:42.990 --> 04:47.730
So that is a column 2. Now, if we run our code, as it is

74
04:47.730 --> 04:48.450
however,

75
04:48.450 --> 04:53.280
you'll see that the search button seems to be sitting inside the entry.

76
04:53.790 --> 04:57.210
And the reason is because initially when we created this entry,

77
04:57.240 --> 04:59.520
we gave it a column span of 2

78
04:59.880 --> 05:03.690
so that it spans this second and third column.

79
05:04.260 --> 05:05.670
So we have to change that.

80
05:06.150 --> 05:11.150
Let's go and find our website entry and delete this column span equals 2.

81
05:12.150 --> 05:16.260
So now you can see that this has a column span of 1,

82
05:16.260 --> 05:18.300
so it's only in this middle column,

83
05:18.660 --> 05:23.010
but it's so large that it's pushing the rest of our layout out of the way.

84
05:23.580 --> 05:26.520
So what we need to do is we need to make this entry

85
05:26.700 --> 05:29.220
the same width as the password entry

86
05:29.490 --> 05:31.860
so that it'll actually fit into our layout.

87
05:32.490 --> 05:35.550
So our password entry has a width of 21.

88
05:35.850 --> 05:40.850
So our website entry is also going to need to change down to a smaller size.

89
05:42.750 --> 05:47.750
Now you can see the entry is now the same size and its looking a lot better. If

90
05:47.970 --> 05:51.540
you want, and this is really not strictly necessary

91
05:51.570 --> 05:56.520
but I think it's quite neat, is you can tweak and adjust the width of this search

92
05:56.520 --> 06:00.440
button so that it's roughly the same as the generate password button.

93
06:01.130 --> 06:05.540
Now this button is this width because it's what is needed to accommodate all of

94
06:05.540 --> 06:09.710
the words in that button, but we can manually change the search button

95
06:09.950 --> 06:11.990
so that it's about the same width.

96
06:13.790 --> 06:18.770
And in this case, I'm literally just using trial and error to figure it out. Width as

97
06:18.770 --> 06:23.210
10 looks maybe a little bit small, let's try width of 13

98
06:23.750 --> 06:28.280
and it looks just about right. Now that I'm done with my layout,

99
06:28.490 --> 06:32.420
it's onto the next part which is adding functionality.

100
06:33.110 --> 06:36.890
Now the functionality is going to come when the search button is pressed.

101
06:37.250 --> 06:39.620
So I'm going to add a command to this

102
06:40.280 --> 06:45.280
and the command is going to call a method which I'll call find_password. We've

103
06:46.370 --> 06:49.970
got generate_password and we'll now have find_password.

104
06:50.690 --> 06:54.680
Now I'm going to go and create my find_password.

105
06:56.090 --> 06:59.450
And just because we've got all these sections set up, I'm going to add 

106
06:59.450 --> 07:04.450
another section which I'll call find_password. Inside

107
07:05.270 --> 07:08.270
the section is where we're going to be creating our

108
07:08.300 --> 07:12.980
find_ password function. And this find_password,

109
07:13.040 --> 07:15.380
let's just check to make sure there were no errors here

110
07:15.380 --> 07:16.910
and we've spelled at the same way.

111
07:17.720 --> 07:22.720
And this find_password function is going to need to get hold of the entry

112
07:23.360 --> 07:25.550
that's inside the website entry.

113
07:26.480 --> 07:31.480
So the website that we're looking for comes from the website_entry.get,

114
07:32.000 --> 07:36.440
and then we'll be able to get the value of whatever the user typed inside this

115
07:36.440 --> 07:37.273
entry.

116
07:37.640 --> 07:42.050
And then we're going to use that to search through our data.json.

117
07:42.890 --> 07:47.890
Now the easiest way for this to work is actually to first add a website.

118
07:48.020 --> 07:53.020
So I'm just going to generate a website with my email and password and add it so

119
07:53.660 --> 07:56.510
that it gets saved inside my data.json.

120
07:56.960 --> 08:00.320
This way I'll be able to print things and I'll be able to work with the data a

121
08:00.320 --> 08:01.160
little bit easier.

122
08:01.730 --> 08:04.490
And then we'll address the exception catching a little bit later on.

123
08:05.120 --> 08:07.400
What exactly are we looking for? Well,

124
08:07.430 --> 08:11.960
we're looking to load up the data inside this JSON file.

125
08:12.470 --> 08:14.780
So we're going to be opening up that file.

126
08:14.780 --> 08:19.250
So with open and then the filename is data.json,

127
08:19.610 --> 08:22.520
and then we'll save this as the data_file.

128
08:24.350 --> 08:26.660
Now, once we've got our data file,

129
08:26.660 --> 08:30.830
then we can use our JSON module to load up that file

130
08:31.340 --> 08:34.970
and we're going to be getting hold of the data that's inside.

131
08:35.240 --> 08:38.720
So we can save this to a variable called data.

132
08:39.350 --> 08:42.560
Now this data, if I go ahead and print it,

133
08:43.370 --> 08:47.570
you should remember is basically just a dictionary.

134
08:48.020 --> 08:51.770
So as soon as I hit search, that should trigger this find_password

135
08:52.100 --> 08:54.800
and now I've got my dictionary printed in here.

136
08:55.500 --> 08:58.740
So what do we want to do with this dictionary? Well,

137
08:58.740 --> 09:03.740
we want to look through it and check to see if this website that we're searching

138
09:04.020 --> 09:07.320
for actually exists inside that dictionary.

139
09:07.950 --> 09:12.950
The way we do that is we say if website in data,

140
09:15.030 --> 09:18.300
well, in that case, it's actually success, right?

141
09:18.300 --> 09:21.030
We've managed to find it inside the data

142
09:21.300 --> 09:25.170
and we now just need to get hold of the email and password values.

143
09:26.580 --> 09:31.580
So let's create a variable called email and we want to pick out this particular

144
09:31.860 --> 09:34.050
value from this dictionary.

145
09:34.740 --> 09:36.930
If this is the entire dictionary,

146
09:37.230 --> 09:42.230
then we want to get hold of the dictionary and pick out the item with the key

147
09:42.900 --> 09:47.280
that matches the website that we're searching for, like this.

148
09:47.880 --> 09:50.490
Now, once we've gotten hold of this,

149
09:50.550 --> 09:53.220
this is going to be a nested dictionary.

150
09:53.250 --> 09:57.690
So it's equivalent to basically this part of the dictionary.

151
09:58.290 --> 10:00.210
So this in itself is the dictionary,

152
10:00.240 --> 10:02.190
which you could save to a separate variable,

153
10:02.490 --> 10:07.380
but I think it's actually easy enough to understand that we can tag on another

154
10:07.380 --> 10:08.213
key here

155
10:08.310 --> 10:13.310
which is the word email in order to get hold of the value that's associated with

156
10:13.830 --> 10:15.480
that key. So that way,

157
10:15.480 --> 10:18.840
this email variable now saves this value here.

158
10:19.590 --> 10:23.880
And in the same way, we can get the password from data

159
10:24.060 --> 10:29.060
getting hold of the data under the website key and then passing in the password

160
10:29.850 --> 10:33.780
key. Now that we've got the email and password,

161
10:33.840 --> 10:38.840
we can go ahead and create our message box using show info. And we'll set the

162
10:39.210 --> 10:43.020
title to be the website that the user is searching for

163
10:43.470 --> 10:46.320
and the message is going to be a f-string,

164
10:46.710 --> 10:49.950
which has the email listed.

165
10:50.640 --> 10:52.710
And then on a new line,

166
10:52.740 --> 10:57.000
it's also got the password that's going to be listed as well.

167
10:58.400 --> 10:59.233
<v 2>Like that.</v>

168
11:01.160 --> 11:04.460
<v 0>Let's go ahead and run this code and make sure that it works.</v>

169
11:05.690 --> 11:10.310
Let's say that we have a couple more passwords that we save in here.

170
11:11.900 --> 11:15.590
Now I should have three entries, Amazon, eBay, and Twitter,

171
11:15.980 --> 11:19.460
and I want to go and search for my password for eBay.

172
11:19.940 --> 11:24.770
Once I hit the search button, it goes into that find_password function

173
11:25.130 --> 11:28.880
and if it finds that one of these has the key eBay,

174
11:29.210 --> 11:34.130
then it's going to fetch all of these relevant pieces of data that I wanted from

175
11:34.160 --> 11:35.540
that JSON file.

176
11:37.010 --> 11:42.010
So now what we have to do is to make sure that we catch any exceptions that

177
11:42.740 --> 11:47.740
might occur and you might already have realized that this works really well

178
11:48.110 --> 11:50.240
right now because we have data

179
11:50.630 --> 11:53.260
and because we have this data.json file.

180
11:53.860 --> 11:57.250
But the first time that I run my program,

181
11:57.490 --> 11:59.140
this is not going to exist.

182
11:59.650 --> 12:04.600
So this is a more realistic version of what the program will look like

183
12:04.660 --> 12:09.340
the first time we run it. And the first time that we go ahead and run this

184
12:09.430 --> 12:13.870
and I search for something that is going to look for a file that doesn't exist

185
12:14.110 --> 12:18.340
immediately, our program crashes, and we get the file not found error.

186
12:18.970 --> 12:23.740
So what we need to do is we need to be aware enough that these things like

187
12:23.770 --> 12:26.020
opening files can fail.

188
12:26.440 --> 12:31.420
So what we have to do is we have to catch the exceptions and handle them.

189
12:32.080 --> 12:37.000
Let's go ahead and indent this entire block and put it inside the try.

190
12:37.570 --> 12:40.300
Now, the part that's most likely to fail in fact,

191
12:40.330 --> 12:44.050
the first time the program starts, this is definitely going to fail.

192
12:44.710 --> 12:48.640
But what we want to do is we want to catch the exception

193
12:48.670 --> 12:53.020
that is file not found error. And in the situation,

194
12:53.050 --> 12:57.820
what we want to do is we want to create a message box that tells the user

195
12:58.120 --> 13:00.430
this data file doesn't exist.

196
13:01.060 --> 13:03.340
This is just a simple showinfo

197
13:03.700 --> 13:08.700
and we'll give it a title of error and we'll give it a message of no data file

198
13:12.730 --> 13:13.563
found,

199
13:15.220 --> 13:19.420
or you can put any other message you can think of. However,

200
13:19.420 --> 13:22.060
if we were successful in opening this file,

201
13:22.420 --> 13:25.720
then this is the part of the code that we want to implement.

202
13:26.140 --> 13:29.230
So let's go ahead and bring it up to the right indentation.

203
13:29.680 --> 13:31.360
And we searched through our data,

204
13:31.690 --> 13:36.690
look for this website and then give the user a popup if it exists.

205
13:37.620 --> 13:41.910
Now, if we run our code again and we search for something

206
13:42.060 --> 13:45.720
even though we don't have a data file, we haven't saved anything yet,

207
13:46.050 --> 13:49.830
then we get this error popup and it tells us no data files found.

208
13:50.160 --> 13:51.930
And hopefully the user would realize, well,

209
13:51.930 --> 13:54.060
actually I haven't actually saved any passwords.

210
13:54.900 --> 13:58.620
So there's one other situation that we haven't yet addressed however.

211
13:59.280 --> 14:02.820
If I had, um, let's say Amazon, um,

212
14:02.970 --> 14:07.970
eBay and Twitter saved in my JSON file,

213
14:10.680 --> 14:13.680
but I decided to search for something that I never saved.

214
14:13.830 --> 14:18.780
Let's say my details for Facebook. Well in this situation, actually

215
14:18.810 --> 14:23.220
nothing really happens. And it's a little bit confusing because for the user,

216
14:23.220 --> 14:27.300
it seems like our program just doesn't work. But in fact, we

217
14:27.300 --> 14:31.350
as the programmers know what the problem is. It's basically this

218
14:31.560 --> 14:36.510
if statement is coming out as false. The website doesn't exist in the data.

219
14:36.960 --> 14:40.920
So none of this gets carried out and the function ends.

220
14:41.460 --> 14:45.030
That's probably not the best user experience. Instead,

221
14:45.060 --> 14:49.560
we probably want to catch it with an else statement and we want to use a message

222
14:49.560 --> 14:52.430
box to tell the that again,

223
14:52.670 --> 14:55.010
there is a error in this situation

224
14:55.850 --> 14:59.090
but the reason for this error is because

225
15:01.940 --> 15:06.380
there are no details that currently exist for the website that they're searching

226
15:06.380 --> 15:08.030
for. That way

227
15:08.060 --> 15:13.060
they're not sitting there confused as to why searching for some sort of website

228
15:13.910 --> 15:15.410
doesn't actually come up with anything.

229
15:15.680 --> 15:19.070
It tells them that there are no details and they would have to add it

230
15:19.280 --> 15:21.410
if they wanna find it in the database.

231
15:22.400 --> 15:24.770
A lot of students might be wondering at this point, well,

232
15:24.950 --> 15:27.680
why don't we catch this with some sort of exception?

233
15:29.240 --> 15:32.570
And in fact, we could create an exception.

234
15:32.570 --> 15:36.890
We could raise an exception here and then we could catch it somewhere else and

235
15:36.920 --> 15:38.390
show this message box.

236
15:38.780 --> 15:43.780
But the thing you want to keep in mind is that if you can do something with if

237
15:44.000 --> 15:47.690
and else very easily, then you should stick to if and else.

238
15:48.170 --> 15:52.460
If you can't do it with if and else very easily, and it's actually an error

239
15:52.460 --> 15:55.910
that's going to be thrown that you don't have any other way of dealing with,

240
15:56.210 --> 16:00.950
then you should be using the try, except, else, finally, keywords.

241
16:01.670 --> 16:03.500
And in fact, if you think about this,

242
16:03.920 --> 16:08.920
I don't have an easy way of checking to see if this data file ends up being not

243
16:10.490 --> 16:14.660
found. But I do have this file not found error

244
16:14.660 --> 16:18.230
which is going to be thrown every time that I try to open a file and that

245
16:18.230 --> 16:19.010
doesn't exist.

246
16:19.010 --> 16:24.010
The other way to think about it is that an exception is something that is

247
16:24.020 --> 16:27.560
meant to be exceptional. It's something that happens very rarely.

248
16:28.100 --> 16:32.120
Whereas if and else catches things that happen frequently.

249
16:32.420 --> 16:36.290
It's pretty often that your user might search through the website

250
16:36.530 --> 16:40.550
thinking that they saved some sort of details for a website. But in fact,

251
16:40.580 --> 16:43.970
they didn't. Think about this when you're writing your code

252
16:44.090 --> 16:49.090
and remember that only use exception handling when you don't have an easy

253
16:49.520 --> 16:52.100
alternative. There you have it.

254
16:52.430 --> 16:56.990
That's the completed code for our upgraded password manager.

255
16:57.500 --> 16:59.750
If you want to take a look at any of this code,

256
16:59.810 --> 17:02.570
then, as always, head over to the course resources

257
17:02.870 --> 17:06.320
and you'll see a link to the completed code that you can review.

258
17:06.860 --> 17:08.150
But in today's lessons,

259
17:08.390 --> 17:13.370
we added a lot more knowledge regarding things like error handling and saving

260
17:13.370 --> 17:18.370
data in JSON formats and handling and loading and updating and dealing with

261
17:18.530 --> 17:23.530
all of that data in order to create this fully-fledged password manager project.

262
17:24.830 --> 17:27.920
Now, I'm sure there's a lot more improvements you can add to this,

263
17:28.160 --> 17:31.880
but it's going to go beyond the allocated time for today's lessons.

264
17:32.330 --> 17:33.163
So if you want,

265
17:33.170 --> 17:37.550
please continue messing around with the code and improving it and make your own

266
17:37.550 --> 17:39.590
customizations and modifications.

267
17:39.920 --> 17:41.810
If you create something that you thought was cool,

268
17:41.840 --> 17:46.340
then be sure to share it with us in the Q/A below the lesson so that we can

269
17:46.340 --> 17:50.810
all admire your hard work and maybe improve our own code as a result.

270
17:51.380 --> 17:55.880
So have fun playing around with this program and I'll see you tomorrow.