DEV Community

Wilfredinni
Wilfredinni

Posted on • Originally published at pythoncheatsheet.org

Python projects with Poetry and VSCode. Part 3

In the First Part we:

  • Started a new project.
  • Created a Virtual Environment.
  • Managed dependencies.

In the Second Part:

  • Added our virtual Environment to VSCode.
  • Integrated our dev dependencies with the editor:
    • Flake8
    • Black
    • Pytest

And finally, in this third and last part we'll:

  • Write a sample library.
  • Build our project with Poetry.
  • Publish it on PyPI.

Poetry Commands

Here is a table with the commands used in this series as well as their descriptions. For a full list read the Poetry Documentation.

Command Description
poetry new [package-name] Start a new Python Project.
poetry init Create a pyproject.toml file interactively.
poetry install Install the packages inside the pyproject.toml file.
poetry add [package-name] Add a package to a Virtual Environment.
poetry add -D [package-name] Add a dev package to a Virtual Environment.
poetry remove [package-name] Remove a package from a Virtual Environment.
poetry remove -D [package-name] Remove a dev package from a Virtual Environment.
poetry update Get the latest versions of the dependencies
poetry shell Spawns a shell within the virtual environment.
poetry build builds the source and wheels archives.
poetry publish Publish the package to PyPi.
poetry publish --build Build and publish a package.
poetry self:update Update poetry to the latest stable version.

The Project

You can download the source code from GitHub if you want, but as mentioned earlier, this will be a very simple decorator that the only thing it will do is print to the console how long it takes for a function to run:

from how_long import timer

@timer
def test_function():
    [i for i in range(10000)]

test_function()
# Execution Time: 955 ms.
Enter fullscreen mode Exit fullscreen mode

In the end, the project directory will look, more or less, like this:

how-long
├── how_long
│   ├── how_long.py
│   └── __init__.py
├── how_long.egg-info
│   ├── dependency_links.txt
│   ├── PKG-INFO
│   ├── requires.txt
│   ├── SOURCES.txt
│   └── top_level.txt
├── LICENSE
├── poetry.lock
├── pyproject.toml
├── README.rst
└── tests
    ├── __init__.py
    └── test_how_long.py
Enter fullscreen mode Exit fullscreen mode

Before we start, check for package updates with the poetry update command:

poetry update

Ok, now add a short description of the project in the README.rst:

how_long
========

Simple Decorator to measure a function execution time.

Example
_______

.. code-block:: python

    from how_long import timer


    @timer
    def some_function():
        return [x for x in range(10_000_000)]
Enter fullscreen mode Exit fullscreen mode

Navigate to how_long/how_long.py:

# how_long.py
from functools import wraps

import pendulum


def timer(function):
    """
    Simple Decorator to measure a function execution time.
    """

    @wraps(function)
    def function_wrapper():
        start = pendulum.now()
        function()
        ellapsed_time = pendulum.now() - start
        print(f"Execution Time: {ellapsed_time.microseconds} ms.")

    return function_wrapper
Enter fullscreen mode Exit fullscreen mode

In how_long/__init__.py:

from .how_long import timer

__version__ = "0.1.1"
Enter fullscreen mode Exit fullscreen mode

And finally, the tests/test_how_long.py file:

from how_long import __version__
from how_long import timer


def test_version():
    assert __version__ == "0.1.1"


def test_wrap():
    @timer
    def wrapped_function():
        return

    assert wrapped_function.__name__ == "wrapped_function"
Enter fullscreen mode Exit fullscreen mode

You can now use poetry install on your terminal to install and prove your package locally. Activate your virtual environment if you haven't and in the Python interactive shell:

>>> from how_long import timer
>>>
>>> @timer
... def test_function():
...     [i for i in range(10000)]
...
>>> test_function()
Execution Time: 705 ms.
Enter fullscreen mode Exit fullscreen mode

Run the tests and if everything is fine, move on.

Building and Publishing

Finally, the time to make this project available to the world has come! First, make sure you have an account on Pypi, and if not, register one. Remember that the package name must be unique, if unsure go and use the search to check it out.

Build

The poetry build command builds the source and wheels archives that will letter be uploaded as the source of the project:

poetry build

The how_long.egg-info directory will be created.

Publish

This command publishes the package to Pypi and automatically register it before uploading if this is the first time it is submitted:

poetry publish

You can also build and publish your project with $ poetry publish --build.

Enter your credentials and if everything is ok, browse your project and you'll see something like this:

pipy how-long

We can now let others know that they can pip install how-long from any machine, anywhere!

Conclusion

I remember the first time I tried to publish a package, and it was a nightmare. I was just starting in Python and I have to spend a "few hours" trying to understand what the setup.py file was and how to use it. In the end, I ended up with several different files: a Makefile, a MANIFEST.in, a requirements.txt and a test_requirements.txt. That's why the words of Sébastien Eustace, the creator of Poetry, made a lot of sense to me:

Packaging and dependency management in Python are rather convoluted and hard to understand for newcomers. Even for seasoned developers it might be cumbersome at times to create all files needed in a Python project: setup.py, requirements.txt, setup.cfg, MANIFEST.in and the newly added Pipfile.

So I wanted a tool that would limit everything to a single configuration file to do: dependency management, packaging and publishing.

It takes inspiration in tools that exist in other languages, like composer (PHP) or cargo (Rust).

And, finally, there is no reliable tool to properly resolve dependencies in Python, so I started poetry to bring an exhaustive dependency resolver to the Python community.

Poetry is by no means perfect but, unlike other tools, it really does what promises.

Top comments (0)