Modern Python Projects Transcripts
Chapter: Let's build a CLI
Lecture: First version of uptimer
0:00 So I start with an empty folder, and as you can see, I already have poetry install. So to start the project, using a poetry,
0:11 we would have to run poetry new and the name of the project. I'm going to call my up time monitoring to uptimer,
0:22 but before we do that, let's talk about where poetry stores the virtual environments.
0:28 By default. Poetry stores the virtual environments outside of the project folder. If we want poetry to store them inside the project,
0:35 we can modify the poetry configuration and said the virtualenvs.inproject option to true So let's do that. If you see that error message,
0:56 it means I used a wrong config option. It actually should be without the settings. Okay, now we are good. So now we can run poetry New.
1:05 and poetry will create a virtual environments in the current folder. So later, when we use VSCode,
1:11 VSCode will automatically detect this virtual environment so it will be more convenient to use it like that. Well,
1:17 let's create a project. And now let's add our dependencies.
1:39 I want to use the latest version of each of those tools. So I'm not providing
1:43 a specific version and we get a error because poetry is still using pytest py. So let's fix that. Let's go to the pyproject toml and remove pytest from
1:54 there. And let's rerun. Okay, we have all the dependencies installed and pinned. Now we can open VSCode and start writing some code.
2:14 The default convention with poetry is that inside of your project, you will have a folder called the Same as your projects and inside of that folder
2:22 this is the place where you should put all your Python files. Well, let's go inside the uptimer.
2:31 We have the underscore init file(__init__) that tells Python that this is a Python package. Inside, we only have the version number,
2:40 so it's not very important. Let's actually go one folder up and open this folder in the VSCode. Okay, so, inside our uptimer,
2:50 let's create a file called uptimer.py, And this is where we are going to store all the code
2:57 for our application. First, we need the function that will send ahead request and
3:02 return the status code. Let's write the standard Python snippet that will execute some code
3:19 When you call this file with Python, let's provide some random URL, I know at least one that should work,
3:36 and we get some errors because we have incorrect indentation, so you can run a command called format file, format Document. And now we are good.
3:48 To test if this code works, we have to actually print something. Let's run this code in the terminal to see if this actually works.
4:04 Perfect. So we got a status code 200 which means that my modernPythonProject website is still up and running.
4:11 Let's change it, so that it can accept URL as an argument. Well, let's write a new function that will check,
4:18 given URL. And now we have to mark this check command as a click command. so we can do this with the decorator.
4:39 And ofcourse, we have to import click. And we also have to tell Click that this URL parameter should be provided by a
4:49 user. So we do click arguments and that should work. Let's try, agin, if we don't provide an argument,
5:06 we got this error message. So let's specify the URL here. Let's other colorized output now. Since status is an integer,
5:27 we have to check if this integer starts with 100,200, 300, 400,or 500. One way to do this is to write a nested if statement,
5:41 so let's actually start checking from 200. So first we actually check if the state is divided by 100 then rounded down returns
5:50 true, this will be true for all the numbers from 200 to 299. So that's what we need. So if the status is 200 we want to return
6:00 green text. Let's make sure that still works.
6:22 Perfect. We got some colors, so let's take care of other statuses, in just in case we have a
6:44 different status. Let's also display it with a different color. We can either go and try to find the website of this broken,
6:55 or we can use this website called httpst.us, It contains examples of different websites that return different response codes.
7:07 So let's take one with the status code 301 Okay, that's not very useful. Copy link address.
7:24 I'm using 302, but it doesn't matter. Perfect. It's yellow. Let's try a broken page. Okay? And now 543 Cool.
7:37 So it's working. But what happens if we provide the URL that doesn't even exist I really hope no one will go and register this domain to break my code.
7:49 So please don't do that. Oh, now we have an exception. So we're not handling the case when the website doesn't even exist. So let's take care of that.
8:02 Let's simply catch this exception. And let's return an error message saying that this is not a proper URL. That should work.
8:26 No, it doesn't. Like that, Still wrong, Actually Let's do this here.
8:56 Okay, now it's fixed and the other website are still working. We have 301, because I forgot to add the US here before we move
9:15 on. Let's clean up our code a bit. I'm not a big fan of this huge if else statements, So, let's try to refactor it a bit.
9:52 So, now we have a dictionary where the colors are corresponding to a key that we
9:56 get from dividing status by 100 and then rounding it down. We also need to add the magenta color that we should get when none of the other colors feed.
10:08 So, let's add the default value of -1,
10:25 and that should work. We can remove all that and let's reformat. Okay, this dictionary is now kind of ruined but let's leave it like that.
10:38 Let's make sure it still works. Okay, Cool. One more thing that I don't like is that we have to call this poetry run Python and the name of the file.
10:52 And that doesn't really feel like a proper CLI application. I would prefer to call uptimer and the URL of the website.
11:01 Not all this long command. And we can actually actually that very easily, we can go to the poetry settings and define a script there.
11:12 While we are here, we can also move pytest and sphinx to the dev dependencies just to indicate that they are part of.
11:20 Dev dependency, is not part of the dependencies for our final package.
11:25 The difference here is that if you want to install this up time on the production server, you can call poetry, install --no-dev
11:34 and it will install everything from poetry dependencies, but not from poetry dev dependencies.
11:40 So let's add a new section with our script when you type, make sure you don't make any spelling errors.
11:52 For example, when I was first recording this part, I made a typo, and instead of writing Tool,
11:57 I wrote tools. I got no error from poetry saying that this config value is incorrect. And when I was trying to run my script,
12:04 I was getting some weird file, not found error. But I spent like, half on hour trying to fix this, so, make sure you don't make the same mistake.
12:13 Under the poetry scripts, we can define some scripts and map them to some functions in the code. So let's say I want to have a script called uptimer
12:23 and this should go inside my up timer package and call function check from my uptimer.py file. Once you have that,
12:37 go back to the terminal and run poetry install to make sure that poetry recognizes the script. And now we can do poetry.
12:47 Run uptimer. Great. We still have to add this poetry run because that's the way to run our command inside the virtual environment of poetry.
13:07 But if we are inside of the poetry virtual environment, which we can do by running poetry shell. from here, we can just call uptimer.
13:23 So here it really feels like a proper CLI command. And that's what we wanted to achieve.
13:29 So we have the first version of our uptimer ready. In the next video, we're going to add more features to it.