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


Talk Python's Mastodon Michael Kennedy's Mastodon