Python Package Development practice with Poetry
Published: 2023-11-25 21:24:44

Poetry is a tool for dependency management and packaging in Python. In this blog, I would like to share my experience of publishing my tool, [txt2html](https://github.com/mingming-ma/txt2html), using Poetry.

## Create configuration file
The `pyproject.toml` is used to store build system requirements for Python projects, we can get by running the command
```bash
$ poetry init


Package name [txt2html]:  
Version [0.1.0]:  0.9.0
Description []:  a command-line tool process input .txt files into generated .html files
...
```  
It allows you to enter the basic information and requirements of the project.

```bash
Would you like to define your main dependencies interactively? (yes/no) [yes] 
You can specify a package in the following forms:
  - A single name (requests): this will search for matches on PyPI
  - A name and a constraint (requests@^2.23.0)
  - A git url (git+https://github.com/python-poetry/poetry.git)
  - A git url with a revision (git+https://github.com/python-poetry/poetry.git#develop)
  - A file path (../my-package/my-package.whl)
  - A directory (../my-package/)
  - A url (https://example.com/packages/my-package-0.1.0.tar.gz)

Package to add or search for (leave blank to skip): tomli
Found 20 packages matching tomli
Showing the first 10 matches

Enter package # to add, or the complete package name if it is not listed []:
 [ 0] tomli
 [ 1] tomli-w
 [ 2] tom-the-bomb
 [ 3] ecspylibs
 [ 4] toml-tools
 [ 5] tom-hermes
 [ 6] AsyncGear
 [ 7] tomtoolkit
 [ 8] tom-gemini-community
 [ 9] toms
 [ 10] 
 > 0
```
Here `yes` means you will type the project's dependencies at this time, mine is `tomli`. You can also manually add them later in the generated `pyproject.toml` file

## Configure Poetry for TestPyPI
TestPy is a separate instance of the Python Package Index that allows you to try distribution tools and processes without affecting the real index. It is ideal for practice the whole publish process.

First, configure Poetry to use TestPyPI instead of the real PyPI:
```bash
poetry config repositories.testpypi https://test.pypi.org/legacy/
```
And then configure your credentials:
```bash
poetry config pypi-token.testpypi <your-token>
```
You can generate the TestPy API token from `Account settings`.
![token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0a6vns3d8pp2ozl8qr36.png)

Then we can build our package
```bash
poetry build
```

With everything set up, publish your package to TestPyPI:
```bash
poetry publish -r testpypi
```

## Install from TestPyPI
Now move to our TestPyPI page, we can see our package link at [`Your projects`](https://test.pypi.org/manage/projects/)

![packagelink](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xcpjta8smiy27zddouc8.png)

click the view we can see install commands of that package

![packageHome](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e47n1xs2uwjb0m8o1gg7.png)

Now we can install it by 
```bash
pip install -i https://test.pypi.org/simple/ txt2html
```

## Command-line Accessibility
If your tool runs as command-line, we need to define entry points for your package, here’s how you can define an entry point in Poetry:
```bash
[tool.poetry.scripts]
txt2html = 'txt2html:main'
```
If your main function is in a different module, adjust the path accordingly. For example, if it's in a file called cli.py inside a package txt2html, you would write:
```bash
[tool.poetry.scripts]
txt2html = 'txt2html.cli:main'
```
This configuration will give the tool command-line accessibility:
```bash
txt2html examples/test-folder/test1.txt 
HTML file '/Users/mingmingma/txt2html/txt2html/test1.html' generated successfully.
```

## Use Poetry to Update the Version
The versioning pattern is MAJOR.MINOR.PATCH. Poetry has built-in version command to update the version number. 
This is useful as it will automatically adhere to semantic versioning rules:
```bash
poetry version patch  # increments the patch version
poetry version minor  # increments the minor version
poetry version major  # increments the major version
```
Note that it updates the `pyproject.toml` file and not deal with `git tag`. 

That's it, hope it helps!