Transcription
Have you ever started writing a project and then noticed that you are executing many similar commands? This takes a lot of time, creates new problems, including bugs, errors, and so on. Because one of the stages might be missed. But what about this project? It solves all of this, and why does it allow you to write code much simpler, also reducing development time?
So, initially, we have these files: Project, where the main project is located. Then come the tests. This is already the config file for Nox itself. Next, the config for uv, which is a very powerful dependency manager, about which you can watch this video. So, all these three files are from uv. Let's go into Project, and here we have one main file. Let's open it.
Initially, this is a function for reversing, then a palindrome check, and the entry point. If you run it directly, it can be used as a regular file for execution. You will understand why I did this later when I assemble everything. So, with this function, everything is clear. Let's look at the tests.
So, we open the tests folder. Here, an init is definitely needed because there might be an error if this file is not here. Next is the test file with tests. I am testing those same two functions. First, I import them, then I check the string. I just write them in advance. If there is an error in the process of changing the previous function, this test will show it. The palindrome is also tested. This is all just an introduction. Let's see how Nox can greatly improve all of this.
So, the Nox file itself is created in the root of the project. It's this little file. Project and other files I generated. Nox needs to be installed. You can use pipx or just pip. I will use uv for this. Install uv, Nox, and press Enter. As a result, pip and Nox are installed.
Next, you need to open the Nox file. We open the Nox file. Here, first, we do an import, and then we divide everything into sessions. Here I use Python 3.13. Next, a function with tests. We install pytest and run it. You can even write it like this, that is, minus wm and specify the tests folder. As a result, let's run it. We enter `python -m tox run Nox` or just `nox` if it's pip. As a result, the tests run, and all two tests passed.
But do you really need to constantly enter such a command? Actually, no, because you can install Nox using `pip install --user nox` and then install all of this globally, and then just enter `nox`. As a result, the tests also passed. But is it really possible to just set up the execution of tests? We don't have more functions, but it's not that simple.
Firstly, it allows working with different environments. Simply put, we set this command. It allows installing one backend. It goes from left to right, initially uv, and then Virtualenv. As a result, why is this cool? Because if I enter `python --version`, it also works from the virtual environment. So, I will get these Python versions. As a result, you can go back and install version 3.12 here as well, and also below. As a result, we run Nox 5. It tests all of this on different versions and returns the result.
But why is this cool? Suppose we have our own project, and it uses different code. As a result, let's say the request on the latest Python version allows using the `GET` method. However, on version 3.10, it's already, let's say, `get_url`. I'm making all this up on the fly to make it understandable. As a result, due to different functions, classes, and so on, your tests will not pass. This command will give an error. You understand in just one command whether the project works on this version or not. You don't need to do all this manually.
But this is far from all. What if we need, say, to ignore documentation? Let's do this. I use this code. I put `idoc`. Then I call `run`. This is a regular command from the terminal. That is, I take the project where the code itself is located, and then I put the ready-made documentation folder, Docs. So, we call Nox again. As a result, the last session also passed. There is a Docs folder. Here is such a project. Let's run `index.html`. We get the project. Then the main file is `string_utils`. Then those same two functions. We can click "View Source" and get the code. If we click above, we get the whole project in general. In essence, this is minimal documentation. There is a function signature, the content itself from which it returns the documentation string. We can also add a function that itself opens that very file with documentation. Let's remove the version because it's not needed here. And as a result, this command takes it from the arguments.
So, how to do this? I access `session.notify`, then the name of the function, or rather, the session itself. Then the argument. Let's add it above. First, we get the path to `index.html`. Then we put the file at the beginning so that it can be opened through Firefox. As a result, this session depends on the session above. You can specify `requires` and the name of the session itself. As a result, this session always runs after the session it depends on, that is, from the session above. If we just need to ignore documentation, I will enter `nox -c check_docs`. Then the name of the session with the documentation itself. Press Enter, and everything worked. We get this documentation. Here, this session is executed initially, and then `check_docs`. Let's swap them. Let's run this session, which depends on the session above, that is, let's run it first. It has no arguments, so it shouldn't work.
But is it so? Let's run it. And as a result, we get an error. If we run `nox` without the `-s` flag and with my session, then although all our tests pass, the `check_docs` itself does not work because a direct call is needed. But you can go back to the file. As a result, we can set default sessions. Let's say we need to run only the tests. We specify "tests" here and run `nox`. As a result, only the tests ran, without documentation.
But can we add tags? Let's take such a situation. There is a session for Black, isort, and flake8. And as a result, there are tags for `style` and for `fix`. Let's say I need to fix errors. I enter `nox -t fix`. Because these are tags, and I enter `fix`. I get Black and isort. If I need style, I just enter the tag `style`. As a result, I can divide sessions into tags as well. In the case of style, I get the execution of all commands.
Next, I will show a very cool thing. This is already a whole convenient system for building. In the private channel, I published several videos on this topic. There were separate videos about hooks, about installers, about embedding resources, already executable files, and in general, other videos on building. I also publish separate videos in the private channel besides YouTube. I post different mini-courses, tools, and development approaches there. For example, protecting Python programs, different Python tricks, including generics, parsing insights, Linux setup, and many interesting things. The private channel also includes a private chat, which is given as a gift. The course on OOP is not the course where only the basics go, because here there is a very deep study of OOP. Here is the entire OOP, including SOLID, metaclasses, single state, different optimization methods, and then design patterns, even antipatterns. I have completely removed all the water and provide only valuable material. This is what is written in the course reviews: the material is maximally unique, there is support, there are homework assignments that I personally check, and also, since lifetime access is given, you can take the course at any time, ask me questions in DMs, and I will answer at a convenient time for you. Moreover, since it is lifetime access, I add new courses, new material, new chapters, different research, tools, and so on. As a result, all this content, all these updates that you see now, course participants have already received for free. I plan to add more and more content. Therefore, after your registration, all further content is already provided for free. I am currently accepting only 20 people, so follow the first link in the description. If the application form is still open, you can sign up right now.
So, the course on OOP is indeed cool. However, the question remains: how to use Nox for building projects? So, let's add such code. I will build on two versions, then ignore the name, then put `pyinstaller`. I will assemble all this into one file and run the desired one without a console. I set the name and assemble the main file. Then, after building, I check for the existence of the directory and delete it, because only `dist` is needed.
So, let's import `shutil` and also add a function for generating a name. Here, too, we need either random. As a result, we set eight characters. We can run it. Just enter `nox` and press Enter. As a result, we add the `ring` module and run it again. We enter `nox` again and build the project. As a result, initially, such a version, then the next one, and as a result, we have an error. This is even good, because we understand that the build stage did not pass, it does not work anywhere, and the problem is that there is no `import os`. Again, we add the import and run the build. As a result, the build stage passed. Let's write `ls`. Here `dist` appears, and in `dist` are the files. Let's run the first project, then the second.
Moreover, the build stage itself can be supplemented with tests, adding formatting, documentation, and so on. As a result, by entering just `nox`, we launch a whole combine that tests, builds the project, generates documentation, and even fries us a shawarma. But some will say, "We already have a regular tox." Many people use it. However, for tox, you need to write such files. We are tied to the TOML format and the INI format. And this is also convenient. It's just a tool. Sometimes TOML is more convenient, and sometimes Nox. Although Nox is used by very large projects, including this project, including Hydra, and also Jupyter. If we scroll down, here is that very Nox file. Let's open it and find the code for tests.
But why exactly Nox? This is because we have the ability to use regular code, and directly from the config, we can call the necessary functions and then, let's say, do cleanup, optimization, sending reports to Telegram, and generally anything. And what if we need to add, say, a linter to Nox? Can it do it? Let's check. Initially, we install the files that need to be checked. Then I set the `ruff` of this version, and then I call `ruff` for these files. Let's run all this. As a result, we have an error because in the file `next_file.py`, `sys` is imported but not used. Also, in Python 3.12 versions, there can be different standards, so `ruff` checks all this.
So, let's remove `sys` and run again. As a result, the tests have already passed. But it also happens that for testing, we also use different versions, or for example, `django` of different versions. We set the required version and run the test. As a result, it checks version 1.9 and also version 2.0. It checks if the tests have passed or not. The test is taken from our folder. Again, I showed all this on uv. However, if it is not there, then Virtualenv will be used.
Moreover, if we have a `requirements.txt` file in the folder, we can use it for Nox to install everything, instead of writing them one by one, like this. Sometimes we only need the build, or only the tests, or the `fix` function. If I call just `nox`, everything runs. However, I can use only `fix`, or only `test`, or only `build`, and as a result, everything works.
In conclusion, I have shown you essentially all the possibilities except `configuration.app`. You can go here and look at these attributes. In essence, you can reuse the virtual environment, use `list` to display sessions, set the same name, you can even use pip directly from the box. But put all this in `venv` or `virtualenv`. I've already covered this in the video, again in the description. You can also not use Python at all and write similar scripts.
Let's get 1000 likes for motivation. If you watched until the end, write how you like Nox. Do you use Nox specifically, or is it more convenient for you to use tox?