 Hello, so I'm Stefanos. I'm a software engineer at Piper. We are building a a web app for managers. And as a software engineer, at some point in my career, I decided that I have something that I want to share to the world. So I tried to make a library and publish it to PyPy. I tried to do it with a few libraries I have published about 10 of them. None of them have become viral or anything, but I have tried to do it many times. I've made many mistakes in the process. I hope that every subsequent one that after the first one was better than evolving. And one of the biggest problems that I had when I was publishing my first library was there's nothing, there's no manual, no documentation, no how to do it. I mean, yeah, you can find how to get something from your computer up to PyPy, but it's not exactly the same as writing code for you or for a company. So most of these the examples and the ideas will come from this library jam that I have written. I'm the author. And this will be the main example. It's not the library that has the most downloads from the ones that they have written, not the first and not the last, but I think it's the one that I, the most well thought out. So that's why I will draw examples from this one. So in order to start, this is just a very incomplete, very inaccurate categorization of Python projects, but it's project that you make has different problems and you kind of want to treat it differently. So you can write a library, you can write a server like a Django server, a Flask server, or you can write a click. We will focus mainly on the first thing because that's what mainly gets published to PyPy. So what's different from writing like coding for your company and writing a web server in Django. The first one is that your audience is much bigger and it's, you don't know your audience. Like if you have a Django server for your company and something goes wrong, you know everyone, you can say, oops, I made a mistake in deployment, let's roll back. But this is not exactly an option when you publish a library. It's there and it's kind of there forever. And the other thing that's different is that because you don't know your audience, you don't really know how the people will work and use your library. So you may write a bug and people may start treating it as functionality and may start depending on your bug. So it's not just fixing a bug. You fix a bug and you might get an email, hey, I was relying on that. What can I do? So this is another big difference. So let's, so this brings me to my first point on what you should think of and this has, this is about building the API. So when you publish a library, the first thing that has to be well thought is the API. So you will expose some functions, some classes that you intend people to use and you will have some code that is kind of code that you expect people that they will not use. So marking it as private with a leading underscore is a good practice to show your intent. You don't know that people will actually respect that, but I mean, there's only so much you can do when you provide something. Also, a very good idea is in the init.py of every module to have the done their own list that says what's your API that you intend people to use. And a good idea also is to limit the init.py to expose the interface only. You can hide everything somewhere else and just expose it with the all or imports in the init.py. This will also help in my opinion with testing as well. So the second thing is supporting stuff. So ideally any published library should aim to support all the pythons that are officially supported. So to do that, you should also test for all the libraries that you do that. Tox is a good idea. My libraries are in github, so I use github axioms. I support these python versions. Sometimes it's hard. You have a dependency and famously numpy kind of doesn't support the oldest one. It's a bit unaligned, so you might not be able to do that, but you should try to aim to support the latest version, the latest supported versions. So another good idea which doesn't have to do with pypy, exactly is most developers will use your app from pip. They will do a pip install, this thing, but that's not always the case. If it has a key element, it stands to reason that people will install it in their operating system. Like if you have something like poetry or black or something, people will want to use it as a standalone thing. So providing packets for the major operating systems is a good idea and it's easier if you do it as the author, because if it has a strange thing in setup, you can control it. You know the dependency is better than everyone, so it's kind of easy to test on your machine, installing, installing and changing. So I think that this is a good advice in general. So the other thing that I think it's a good idea when you start building a library is the first version number to be 010. Like 0, 0, 1, it doesn't really matter, but start with Semper. If you want to move to calendar versioning, you can. It's easy to go from 010 to 2211, but it's very hard if you see that, oh, I don't need calendar versioning. I need Semper to move back because it will be like going a version back. So I think this is from another library that I have that if you don't want to use Semant versioning, it's good to explain why. So this is from a library that I have that has isocodes for currencies and country names and all these things, which are things that, well, my API is very stable, but when the countries change names, it's not like a software decision. It's a political decision. So people know that in 2023, country A renamed themselves to that. So people will want to know which year, which month this has to do. So if you want to use maybe commit houses as a version, that's fine, but explain why so people know, so people can decide what to do and how to treat it. So the other thing that I, this was a big mistake that I made initially. So the first thing that I published, I pinned all the dependencies. So actually people couldn't use it because they had to have the specific version for everything that I had. And because when people will use a library, you don't know the other things that they have. They can use it in a lot of settings. Being as permissive as possible is good because you have a bigger audience. If, let's say, I say this needs DJ settings 2.2, 0.1, only people who have this specific one will be able to use it. And separating if you use a tool like poetry to match your dependencies, which is a good idea, you can separate the dev ones with the non-dev ones. So people who want to not to download the source code and run the tests and everything will not get all the dependencies that you have for linting, testing, and all these things. My personal thinking about log files because poetry is creating log files is if you're building a library, keep them out. I know that famously NPM disagrees with that. I can see the advantages on having them or not having them, but I think for a library it's better to let poetry do what they need to do. So one other thing is the project structure. So when I first started building my first library, I was, okay, I'll copy the way I do it in my company, in the Django apps that we have, and it wasn't working because the way that things get installed by PIP, it's not exactly the same as what you run if you have the directory here. So this is from Yam. I want to be able to do from Yam import something, but this is in a directory somewhere in the virtual environment. So specifying all these things is very easy with poetry, and I believe that this is a very good separation to keep your documentation, the source code, and the tests separate. People who install the library don't care at all about the tests. They don't even have to install them. They don't care about the docs. They just want the source. So this can say, this is the source. And documentation, well, one good thing is to have documentation because people will need to understand how your code works, and it's kind of cleaner to have it separate, totally separate in another directory. And this also makes it easier for PyTest to find the tests and run them without any issues. Also things that it's good to consider to include is readme, which is not exactly the same as documentation. Readme is what people will see when they visit your GitHub page. So it should be, in my opinion, something like, this is an easy example that you can copy paste. Here are some links for, let's say, the full docs, some small information like a TLDR version of your documentation. Good thing is the change log, because when versions change, it's good to have just a file that people know that I can go take a look, and they know if they can upgrade or not, or if they have to do something. And the license is very important, especially if you want this to be used in a more corporate environment. A good candidate for me is LGPL, MIT is a good license. It's good to be permissive. If you are open sourcing something, you probably don't need to have one of the very strict license to protect your copyright. You're setting something with everyone in the world, so permissive licenses are better. So another thing that I have found very strange when I started, when I wanted to code, is that the first, before writing my own library, I said, okay, let's contribute to another library. And because you have to start somewhere, it's good for someone to try it where people who know what they are doing are. So one good thing is be very welcoming to newcomers. If you have a famous, if your library becomes viral, you will attract newcomers. Just make clear what is the goal, what's not the goal of the library, because you just don't want to implement everything. You have a specific thing, but be clear, explain, and, you know, let, and be supportive to people that want to join the open source community. It's one of the strengths of, the biggest strengths of Python, our community. So being welcoming is good. And there are some general parting thoughts, some mistakes that I made. So don't delete published versions. So one of my first libraries that I published, I realized that, you know, I thought, okay, this is a patch version. So why would anyone want to download 0.1.1 now that I have 0.1.2? And I went to PyPy and deleted the previous patch version, which then I got an email from someone that was complaining. And, you know, I cannot install something that I was able to install. And then I tried to re-upload it. It's, you can't. So if you want to delete something, if there is a very, very good reason to do like something that, like a password door, I don't know, it's better to change the password. Think very, very hard before deleting a published version. The second thing is test on PyPy, test on, test PyPy. So apart from PyPy, there's test PyPy that you can upload something. And if it breaks, no one cares. But it's a good thing to see, does my upload script work? Have I forgotten anything? Is there something that I should do differently? So test PyPy is a very nice sandbox. The second thing is being as permissive as possible with everything, with how the library will be used, with which dependencies are there, and everything should be open for use from every possible user. Because there's no way that you can guess how people will use what you are supplying. And the other thing is it's good to update fast. So in October, Python 3.11 will be out. It's good if you have a library not to wait for months and months. Because like in my company, we will want to update to Python 3.11 because it's faster. So if a library doesn't support it, we will consider dropping it. And that's not just in my workplace. It will be in many workplaces. So if you wait too much to support the next version, well, you will lose. And another thing about updating is about keeping up with the latest versions of your dependencies as well. Because it's most of the times, it's not just your... You are not using just a standard library. You are using other libraries as well. So that's all that I wanted to say. And if anyone has any questions, please. First, let's have a generous round of applause. And since we have some time left, let's see if the microphone works. Since we have some time left, we should do a Q&A. If somebody has a question, please come to the microphone. Thank you for your talk. I have a question in regards to the log files of poetry. When you publish a library, like this, okay. So when you publish a library and you have a log file, does that influence the required packages of library? Or is it just for local installation? I was talking about GitHub. I think that it shouldn't even be in the inversion control. The reason is, and why I think this should happen, is that when someone tries your library or you have your desktop and you want to go to your laptop, you'll have the latest dependencies. So you get it's easier for things to fail fast. So if there is a breaking change, it will fast as soon as possible and you will have time to change it. So I don't know if I had the same approach, if I had something like requests that's used, like has a billion downloads or something. But in the libraries that I have seen, they have some users, like Yamis used in our production daily without problems. And it has like 10k, 100k downloads or something. I think it's better to fail fast, to see issues as soon as possible. So that's why I say, leave them out. Yeah, okay. So that's when you install directly from a checkout directory. Thanks. Okay. I'll quickly have a look at the back if we have remote questions. Since I don't see any, we'll continue with the next local question. Thank you very much for the talk. I have a question regarding not locking dependencies. How would you test and make sure that your library works with many versions of the dependencies that you have for your library? So if you use something like docs, you can specify that I want this to be, like if one of your dependencies is Django and you want to support Django 2.0 to 4.1, you can just say this is the matrix and test for all these Django versions. And it will automatically, I'm not a tox expert, but I've seen the tox in me and I know that when you say test for these Django versions, it does the right thing. So. Okay. Thank you very much. Thank you very much for the question. Do we have any further questions from the audience? And there's a final question coming now. Are you running away from the question? Please. No, I'm going to ask a question. Thanks. Do you find that there's certain contributors that want to get all the fancy new features from Python and say, hey, I'm just doing only 3.10 and above, or is for the most part people trying to support as much Python versions as possible? So mainly, I think that there are some sign versions, like when f strings came out, I saw that most people said, okay, I'm not going to support anything without f strings because I don't want to write that format. But I have generally the feeling that people are okay because most of us work in an environment that like most companies have the oldest supported version. So most people also want to be able to use what they contribute to. It's natural. So I have the feeling that people are okay with supporting all these versions of Python. Okay. Thank you. Thank you for your talk. Okay. So that concludes the Q&A. So what's left is to thank Stefanos again for his presentation. So let's have a round of applause. Thank you.