 Good afternoon, everyone. Next talk is Publishing Well-Found Python Packages by Zillin S. Zillin, the stage is yours. Thank you, everyone. OK, hi, everyone. I'm Zillin. I come to my talk. So my talk is about publishing Well-Found Python packages. So what is the Well-Found package? It's a package which has some sort of a structure in place by following certain guidelines and adopting some practices which makes it easier to develop and maintain. It is done by because it is possible because of a sufficient documentation, a well-written test with a proper test coverage, which facilitates both collaboration between the developers and the community involved into your project and your patent package. So how can we make our package well-formed? So these are some of the points that I had in mind, which I will go through in this talk, right from the styling aspect of your code through testing till packaging. So let's have a look at each of them one by one. So a good first step towards making your package better-formed is by adopting a style guide and sticking with it. It makes your code better, more readable, with the consistent formatting. And if you use a linting and styling tool along with it, it can greatly help in detecting stuff through bugs. So that would often go unnoticed if it wasn't for the usage of such tools. As for the style guide part of your project, Pep 8 is, of course, a good starting point. But as Pep 8 itself stays, it's better to take this as guidelines instead of steadfast rules. In short, you shouldn't be following them blindly, just because it says so, it has to be so. No, but it's better if you don't do it like that. Pep 8 itself advises against that. For example, consider a long link, link to an external site or something that you wish to include in the documentation part of your code as a comment or something. And say that your style guide, I mean, mantains your number of characters in per line to be some, let's say 89 is a common number. And your link is too long. It's 100 characters or something. If you're following your style guide just like that, you may be tempted to slice up the link or something into two lines. But that would mess up things a little bit, right? I mean, if you want to follow that link, you have to either copy paste or join them together and click on it. No, that doesn't sound that good, right? So it is better to leave it like that probably so that your editor, whichever editor that you're using, can recognize instantly it as a link that you and that you can follow to that link just by clicking on it instead of just copy pasting or anything like that. So what tools can be used for styling and lending? Pilot and Flake 8 are arguably the most prominent lending and styling tools that are widely in use by the community state. They are there for configurable options. So you need not stick with the defaults, although the default options are kind of used as a good starting point. And you can configure them as to fit the needs of your project as you go on. For instance, you can change the number of characters per line limit if you wish. And then there is Black. Black is an automatic copy format tool that is quite popular and getting more popular by the day. So suppose that you spend too much time fixing the styling and formatting of your code all the time, especially if a lot of projects are contributing to your project. And if you're willing to let an external tool take control of our styling and formatting part, you can use Black. It automatically does the work. I mean, no matter what style that your code is written in, if it is valid Python code, Black will automatically reformat it so that all the files, all the source files, will look in a uniform style to follow a uniform style. So Black does in big projects with a lot of people contributing to it, Black can produce, I mean, considerably save your time fixing, I mean, spend on fixing the styling and formatting part. Of course, it means that you have to give up some of the fine control over your code formatting part. But it is usually worth it. Another aspect that can be used to make your package better formed is by using type annotations and doing some static type checking on it on your code. Python had been supporting static type annotations for quite some time now. And you're making, taking advantage of it by actually using it in your code and not only improves the readability of your code, but also allows us the developers to use static type checking tools to run type checks on. So in a way, using static type checking, you can combine the ease of use offered by the dynamic typing of Python along with the static type system in some way using a static type checking tool. So some of the popular type checking tools that we have is include MyPy, PyType and PyRay. So let's see how static type checking and type annotations can help improve our code. So I have a function here add if which takes two arguments x and y. If x boolean value turns out to be true or whatever that value is, if it's boolean value like bool of x turns out to be true, the function will then add 10 to the value of y and return it. Otherwise, the value of y is returned unchanged. So just by looking at it, it's not exactly easy to figure out what exactly this add if function expects as arguments and what exactly it returns. Okay, look at x. x could be a number, an integer, a float, a boolean, a list, a string, it could be anything. Anything that can produce a boolean value if you apply a bool on it, it would work. But that may not be what you actually expect. So let us use type annotations and see how it looks like afterwards. As you can see just by adding type annotations, the readability part alone has been considerably improved. Now we know that add if expects x and y as with bool and integer values and returns an int. So obviously the add if function as it is used in the line seven, in the second part, which should be an error. I mean, but in Python by itself cannot consider it as an error. So, but if you run a type, static type checking tool like mypy on it, you will get the following error like this. It adds if expected a bool as the first argument, but instead it got an integer, which is two. We fix that and return a true, I mean pass true as the value and the error disappears. It may look simple in this example, but in bigger code bases, such errors are very difficult to spot. Another concern is dead code. It is quite natural for a project to have some dead code accumulated. I mean, it's not always possible to manually find the dead code. The project will have some dead code over as it evolves. So these dead codes sometimes can interfere with the other, I mean the real code and produce very puzzling errors. So this is where a dead code elimination and detection and eliminated function. If you're going for a static dead code identification tool, you can use Vulture. Vulture is quite fast because it is the static analysis using abstraction.x3 of Python and doesn't actually run the code. It can identify the dead code with an appropriate confidence level like that. Of course, just for writing your code, you have okay, your code is fine or you think it is fine, but it's always a good idea to test, right? So you can do unit testing to be sure that your code works as you expect it to work and doesn't do something anything crazy by mistake or by chance or some features of the language or something like that. It's good to do testing. In the case of unit testing, it is to be helpful to design your code so that your different functionalities are different in the separate functions, separate testable functions. You can use the built-in unit test module of Python and it's present in standard library to do the testing or you could use an other test to find those like Python. Between the two, I would advise you to use Python unless you don't have to use unit test because Python test is usually easier to write and easier to understand. So let's consider an example of the advantage of using unit testing. In this case, using Python. I have here a function name check which accepts it to a two argument, the first name and last name, which are strings and returns the ratio of the, which is supposed to return the ratio of the first name to the last name. So the result should be length of first name divided by the last name. I guess you will have already spotted it in this slide. I have the function that does it the other way around. It instead of dividing the first name by the last name, it divides the last name by the first name. But suppose I missed it while writing it. So I write, but instead of leaving it untested I had written the test for it. And I check if it works as I expected it to be. But no, it's not as I expected it to be. So I will be prompted to pay close attention to this. And I see it, I fix it and it works out all right. Next, now comes test coverage. Having the test alone is not always useful, right? It should test the part of the code that should be tested. It should have adequate test coverage. It should cover the code base of your project well enough so that you test parts of your development parts of your code that needs to be tested. If you use a test coverage tool, you should be able to see that part of the part of your code which the test helped missed. And you should also get a test coverage percentage, tools like coverage.py, and which is a standalone third-party module, and pytest.go which is a pytest plugin that can help you with this. Let's consider another example to illustrate the coverage, the test coverage. I have in the left, I have the function and the right I have the test for it. This function is very simple. It returns true if the value is an even number, otherwise it returns an odd. I mean, otherwise it returns false. Notice that in the test that I have written, it considers only the behavior of the function when it is a pass and even number. So I run coverage on it, and it shows me that one line has been missed. Then the coverage is not as it should be, it's not coverage is not less. I fix that by adding another case, I mean another to cover that part of the function as well. And I get 100% coverage. So now we have got a lot of tests to be run on your project, right? From PyLint, MyPy, Vulture, you named. So it's definitely useful to have some sort of a test automation mechanism in place which can run all the tests for you just like that instead of you having to run all these tests manually one by one. You can use this test automation tool to run them all at once or as per your wishes. And you should also be able to run these tests in all the supporter environments. So right now you probably have tested in your own machine, it works well good enough, but it should also work in the systems of other people who will be using your Python package, Python module. So these other people may be using a different versions of Python language or maybe even different implementation of Python language. So you need to be sure that your project, I mean your module works as expected on all these environments. You can use test automation tools like docs and docs for that. These projects, docs and docs can run the test locally or with the use of some continuous integration, CICV tool and the elements as well. So now let's look at the package layouts which has some role to play in the testing part, some prominent load, if I may add. Flat layout is the way flat layout have the package which is in here is named package name. The package name packages source code under the package name directory and the tests that are used to test that package name package are present in the same directory level. See package name and test are present in the same directory and without any nesting in it. And then there is SRC layout where the packages source code in the under the package name directory is isolated into an SRC for another directory by adding another directory level to further separate it from the test directory. This has some part to play. See running your talks test, I mean, what talks really does tools like talks, what they really do is that they create a temporary a separate isolated virtual environment and install your project, your module into that virtual environment and test it there so that the testing would happen as it would as if the package is installed in a different environment and a different fresh environment. So if it works there, it should work on other machines as well. That is the idea behind running a talks test in an isolated virtual environment. But if you run these tests in a flat layout package using package with flat layout, what really could happen is that if your test which would import your package source code from packages source code would import from the package itself because they are in the same directory level within the same package. It would import the source code programs from the package directory itself instead of actually importing from the installed package which is available in the site packages directory in your virtual environment of talks. So there's a problem of accidental import happens. It is not importing what it was expected to import. This is a problem with flat layouts. But in a surgery layout, this problem does not happen because of the way Python imports work and because of this further isolation into a deeper and nested directory and a problem of accidental import in the test from the package name directory itself is avoided. It is not possible usually. And it would install from the site package as directory itself and the test would work as expected. So this is a reason why, one of the reasons why a lot of projects moved away from flat layout to a surgery layout. But that said, there is no officially recommended layout. It's important to say that in the Python community has not reached a consensus about which layout is better or which layout is bad. You should decide that for yourself. Check out these links to see some interesting takes on this matter. So once your package is ready, well-tested, good, cool, everything is ready, you need to be able to share your package. For that, share a model. For that, you have to package your source code into a file or format which can be used to install that module into other systems, like VL or Sdisk. To do this packaging part, you can use setup tools from the PyPA, Python Packaging Authority, or newer tools like Flit and Poetry. So once you have the packaged files ready, you need to be able to publish it into a server of your choice, usually commonly PyPI.org server. If you're using setup tools, you need another package like a twine to do the publishing part, to push your source code in your package to the server. And Flit, tools like Flit and Poetry can do this publishing part by themselves. These are some other tools. There are a lot of other tools available which can help in managing a project better. These are some of them, there are a lot of others. Use read up on them. I would recommend you to read up on them and to use those tools which you think you can help your project better. It may not be a good idea to use all of them at once. I mean, all the tools that you find, maybe, it's not a good idea, maybe, but use your development and use what you will need. So the way forward is that PyProject.toml file of your project, of your package, has become already the center point around which your project package revolves. And it's been expanded upon. And a lot of the tools that I mentioned like the PlayGate talks and all, they used to have separate configuration files because there was no unified way earlier, argue sometimes. We can use a configure instead of, instead, into the PyProject.toml files without needing for another file. So this toml format and the toml file has become more important in the future. And we can probably expect a toml module in the standard library. Many like are already have become popular because of this toml files. So that's it. I'll come to the end of the talk. So let me summarize what we saw so far. We use so a style linting and styling, type checking using mypy and other tools, that code elimination and identification, testing, test coverage, test automation, and finally packaging. So that's it. Thank you for listening. If you have any talk, I'll be happy to take them. Hey, so we don't really have any questions as far as I have been noticing the talk, but we do have one wish. Where can we get to your slides? That's the thing that was asked the most. I will share the link on the chat. Soon enough, yeah. Sure, so folks, I guess if you want the slide, you'll have to go to Zulin Bangal stream and that's where Zulin will be sharing it. Yeah, sure. All right. Thanks a lot, Zulin. It was a great talk. And we really appreciate it. Have a good day. Thanks everyone. Thanks.