Anvil: Web apps with nothing but Python Transcripts
Chapter: Consuming the API with Fitnessd Local app
Lecture: A GUI version of Fitnessd Local

Login or purchase this course to watch this video and the rest of the course contents.
0:00 We're the grand finale for application.
0:02 We're going to convert this command line app
0:04 into a GUI app that will run on Mac, Windows and Linux.
0:08 How cool is that?
0:09 We're going to use a library called Gooey.
0:12 Not this, this.
0:15 But we can just have PyCharm install it.
0:17 You'll see it'll spin down here at the bottom for a sec.
0:19 Again, just hit install dashboard requirements.
0:22 You're not doing it through PyCharm.
0:24 All right, well that worked well.
0:25 Let's go over here and we're going to do some more imports.
0:28 We're going to import this thing called Gooey and GooeyParser.
0:31 And the way this Gooey thing works is
0:33 we go over here and we say this is a Gooey application.
0:37 We say program name is going to be Fitnessd Local.
0:44 That's what we're going to call it.
0:45 And we'll say show
0:47 this doesn't have auto complete for some reason.
0:48 It's kind of annoying.
0:49 Anyway, show_success_modal=False.
0:54 So when things succeed, don't show me a dialog that says
0:56 Hey this worked. Like you know what, I know it worked.
0:59 Tell PyCharm that's not misspelled.
1:00 Okay so this is going to trigger an interesting UI.
1:05 The next thing we need to do is come down here
1:07 and say parser = GooeyParser.
1:11 Want to give it a description of the app.
1:13 Let's just put it in like this, Fitnessd Local.
1:16 Local edition, record your health on the go.
1:22 Now, what we're going to do is the way Gooey works
1:25 is we go to the parser and we add an argument.
1:28 These arguments show up as UI form elements.
1:32 But we first want to check this part here.
1:34 And if it's not authorized
1:36 what we're going to do is we're going to add an argument
1:41 for the email and we're going to set
1:43 the default equals auth.email
1:47 if for some reason that happened to exist.
1:52 We'll say widget though equals password field.
1:58 And that will put the little dots
2:00 instead of showing the password.
2:02 Now let's go ahead and just configure.
2:03 That's going to take care of a whole bunch of stuff here.
2:06 Let's go ahead and configure some more arguments.
2:08 And I'm just going to drop them in there.
2:11 So regardless of whether they're logged in
2:13 we want these things to be added.
2:16 So we're always going to ask for a rate
2:18 a weight, and a date.
2:19 Here's some description, the types are integers
2:21 and we even have a calendar picker type thing.
2:24 So that's all good.
2:25 And then the next thing that we want to do
2:27 is we want to show the UIs.
2:29 The way we do that is parse args, like that.
2:33 This is where it gets interesting.
2:34 So we should be able to come down here
2:37 not do a whole bunch of this stuff.
2:39 Before we were getting user data
2:41 and that's kind of gone now
2:42 because the Gooey itself is actually doing that.
2:46 But something like this
2:48 we could actually drop this whole thing here
2:50 or we could move maybe this into it.
2:54 And the way this works, whoops I need to store this here.
2:58 This data that comes back from parser
3:00 it's basically like a dynamic object.
3:03 It has the values, rate, weight, and date, in it.
3:06 So super easy.
3:09 data.Weight and I'm using capitals
3:12 because this is the title in the UI.
3:15 We have data.Date but the way this comes back
3:18 is kind of crummy.
3:19 So I'm going to bring in one more library for parsing it.
3:22 Python dateutil.
3:25 Just refer it to this code.
3:27 Here you have to put the Python in front
3:29 and that's not misspelled
3:31 which is what I was actually trying to do.
3:33 So that got installed.
3:34 Up here, we can import dateutil
3:38 and say dateutil.parser.parse.
3:43 A lot of parsing going on here, isn't there?
3:45 Okay, super.
3:46 Now, we kind of have to ask the same question again.
3:49 Did they already log in and get authorized?
3:51 So if they're not authorized, is authorize again
3:56 we want to get email over here.
3:59 data.Email, password equals data.Password
4:04 and we want to save it.
4:05 But we need the API key.
4:07 Let's put API key.
4:09 So over here, we're just going to go
4:11 to the service.authenticate email and password once again.
4:17 So we're going to save that.
4:19 And then finally, we should be okay.
4:22 We'll say for some reason they couldn't log in.
4:25 We'll print their authenticating and return.
4:33 Otherwise, we'll put login successful.
4:36 And we're down to this.
4:37 Now the final thing we need to do
4:39 is just save the measurement.
4:41 And here, this is going to be auth.apikey and auth.email.
4:47 And then we have our data
4:49 and I guess it probably is a little bit nicer
4:52 to pass those as values.
4:54 Let's go ahead and change these.
4:57 Rate int, weight int, recorded is a str
5:02 and let's just change this
5:03 to data, weight is weight, and so on.
5:09 Whoo, all right.
5:10 Final thing, we have to pass different values here
5:12 so we can pass the, let's see where are we.
5:15 We're at rate, weight, and recorded.
5:18 Get those in the right order.
5:20 All right, well this reworks is to use this parser idea.
5:26 What does this parser even look like?
5:28 Let's go ahead and run it and see
5:29 well first if I got it working
5:31 and didn't make any stupid mistakes
5:32 while talking and coding.
5:34 And second, what it looks like.
5:35 If it works, you'll be impressed.
5:38 Here goes. Oh check that out!
5:41 How awesome is that?
5:42 So we have our rate in pounds.
5:44 Look, we built a GUI!
5:45 This is so amazing!
5:47 So let's go over here and put this as 77 and 177.
5:52 Just so we recognize it.
5:53 We even have a cool little date picker thing
5:55 and that's not incredible
5:57 but whatever, it still works.
5:58 Actually, I do want to pick today.
6:01 I guess we should probably default it to today.
6:03 Wouldn't that make sense?
6:05 Put that as 25 or something in the future.
6:08 So this is going to gather the data
6:10 and then we're going to run it
6:11 and it'll call save that into the API.
6:14 Let's see how that works.
6:15 Oh, oh there's a problem.
6:18 I need to import this, sorry.
6:24 Parser, date util doesn't seem to import it's sub packages.
6:28 That's fine.
6:31 Oh here we go.
6:32 For some reason, that's so weird
6:34 that that didn't work before.
6:35 Anyway, we were setting the default but whatever.
6:39 All right, let's go 77, 199
6:42 again, just to get it a unique value there.
6:46 Boom.
6:48 datetime is not serializable.
6:49 I forgot to call isoformat.
6:52 Where are we doing that down here?
6:55 Put isoformat.
6:57 Remember I told you this is a datetime.date.
7:05 There we go.
7:06 JSON doesn't deal with dates, annoying.
7:08 All right, last time.
7:11 77, 199, go.
7:15 Could not save the measurement.
7:17 What did I pass in wrong this time.
7:19 Oh we're so close!
7:20 But nope, it didn't work.
7:22 Let's see what our app log says.
7:26 Oh it passed in the wrong date time format there.
7:31 So let's go back to our code.
7:33 Dates are always super annoying here.
7:36 Let's print this out real quick, just see what this is.
7:42 Didn't really matter what I put there
7:43 because it's not going to work.
7:46 Yeah, I think it might be getting a time zone
7:48 or something funky in there.
7:49 So let's split on T and just get the last one.
7:52 So that's sort of annoying but this should work.
7:55 77, 198, and that date.
7:59 Off it goes. Yes! Success!
8:03 This is probably not the message we want to show to them
8:05 but let's go check it out and make sure our Gooey app worked.
8:09 That 198, there it is. It just went in.
8:13 So super, super cool.
8:15 We were able to go and build these cool APIs.
8:18 We authorized our users.
8:19 And most importantly, we can now add our measurement.
8:22 Once we have the API, we're able to call it externally
8:25 from pretty much any client, as we saw with Postman here.
8:29 And then we said
8:30 Let's build something super nice like a Python app.
8:33 Started out as a just throw it together command line app
8:37 and then we actually converted it
8:39 using the GUI library over here.
8:42 GUI library and the GUI parser
8:45 to be a full fledged GUI application.
8:47 The grand finale, I guess, which we're not going to do
8:51 would be to use PyInstaller or PyOxidizer
8:54 to bundle this up as an EXE or a .app
8:56 You could just ship to your user
8:58 they double click it, they run it, they see that UI.
9:01 Everybody's happy.
9:03 All right well, there it is.
9:04 There's consuming our Anvil API with our Python app.