Python projects with Poetry and VSCode Part 1

meta: layout: article title: 'Python projects with Poetry and VSCode Part 1' description: We'll use Poetry to start a simple project, manage dependencies and publish it on PyPI. We'll also integrate Pytest, Black, and Flake8 into VSCode directly from a Virtual Environment. date: April 12, 2019 updated: July 3, 2022

<blog-title-header :frontmatter=”frontmatter” title=”Python projects with Poetry and VSCode Part 1” />

A Virtual Environment is an isolated Python installation designed to avoid filling our base one with libraries we might use for only one project. It also allows us to manage multiple versions of the same package in different projects. We could, for example, need Django 4.1 for one and 1.9 for the other.

Python Poetry Poetry is a tool to handle dependency installation as well as building and packaging of Python packages. It only needs one file to do all of that: the new, standardized pyproject.toml`. In other words, poetry uses pyproject.toml to replace setup.py, requirements.txt, setup.cfg, MANIFEST.in and the newly added Pipfile.

In this series of articles, we’ll use Poetry to manage our dependencies, build a simple project and, with a single command, publish it on PyPI.

In this first part, we will:

  • Start a new project.
  • Create a Virtual Environment.
  • Manage dependencies.

In the second article, we’ll:

  • Add our virtual Environment to VSCode.
  • Integrate our dev dependencies:
    • Flake8
    • Black
    • Pytest

And finally, in a third article we’ll:

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

Installing Poetry

The easiest way is to use pip:

$ pip install poetry

But we will use Poetry own installer to isolate it from the rest of the system by vendorizing its dependencies. This is the recommended way of installing poetry:

$ curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -

This way, we will later be able to update poetry to the latest stable version with the poetry self update command.

Starting a new project

We can now start a new Python project by using the poetry new [project_name] command. I will call it how-long and will be a simple library to measure the execution time of a function:

$ poetry new how-long

Note: For existing projects, you can use the poetry init command and interactively create a pyproject.toml.

The directory how-long is created and inside is a basic project structure:

how-long
├── README.rst
├── how_long
│   └── __init__.py
├── pyproject.toml
└── tests
    ├── __init__.py
    └── test_how_long.py

Note: To be able to publish your project, you need an available name. Use the PyPI search for this.

The pyproject.toml file

The pyproject.toml file will manage the details and dependencies of the project:

[tool.poetry]
name = "how-long"
version = "0.1.0"
description = "A simple decorator to measure a function execution time."
authors = ["wilfredinni <carlos.w.montecinos@gmail.com>"]

[tool.poetry.dependencies]
python = "^3.7"

[tool.poetry.dev-dependencies]
pytest = "^3.0"

[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

[tool.poetry]

The details. Adding a license and a README might be a good idea:

[tool.poetry]
...
license = "MIT"
readme = "README.rst"

[tool.poetry.dependencies]

First is the Python version. Basically, this project will be compatible with Python 3.7 and up. Furthermore, from now on, every package we install that is meant to be used in production will be listed here.

[tool.poetry.dev-dependencies]

These packages are only for development and will not be included when we publish our project. By default, Poetry includes Pytest, so we will use it to test our project later on.

Creating a Virtual Environment

To create a Virtual Environment and install Pytest, we will use the poetry install command:

$ poetry install

poetry-install-command

After is done, a new file, poetry.lock will be created.

When Poetry has finished installing, it writes all the packages and the exact versions of them that it downloaded to the poetry.lock file, locking the project to those specific versions. You should commit the poetry.lock file to your project repo so that all people working on the project are locked to the same versions of dependencies.

Dependency management

One way to add or remove dependencies is to directly edit pyproject.toml and then run poetry install to apply the changes. We will instead use the add and remove commands to avoid manual modifications.

Adding dependencies

Let’s add two packages to the project, pendulum, and coo:

$ poetry add pendulum coo

poetry-add-command

Open pyproject.toml and poetry.lock and see how they have updated.

Adding Dev dependencies

These dependencies will be available only during development, Poetry will not include them when building and publishing the project.

We already installed Pytest, but we will also use flake8 for linting and mypy for static typing:

$ poetry add -D flake8 mypy

Now that I think about it, I forgot to add a formatter. We’ll go with black:

$ poetry add -D black
[ValueError]
Could not find a matching version of package black

add [-D|--dev] [--git GIT] [--path PATH] [-E|--extras EXTRAS] [--optional] [--python PYTHON] [--platform PLATFORM] [--allow-prereleases] [--dry-run] [--] <name> (<name>)...

This error happens because black is in a pre-release state, so Poetry cannot find any stable version for us. But I really want it, so let’s install it anyway with the --allow-prereleases flag:

$ poetry add -D black --allow-prereleases

poetry-add-dev-command

Removing dependencies

You know what, I changed my mind, this project will use nor coo nor mypy. Start by removing coo, a normal dependency of our project:

$ poetry remove coo

Now mypy which is a dev dependency:

$ poetry remove -D mypy

Conclusion

In this first part, we have started a new project, created a Virtual Environment and added and removed dependencies by using the following commands:

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 self:update Update poetry to the latest stable version.

In a second article, we will see more Poetry commands, add our Virtual Environment to VSCode and use the dev packages we installed to lint (Flake8), format (Black) and test (Pytest) our code inside the editor. Finally, in a third one, we will write and publish a sample library to PyPI.

Any doubt or suggestion? Please leave a comment.


Python abs() built-in function Python aiter() built-in function Python all() built-in function Python any() built-in function Python ascii() built-in function Python bin() built-in function Python bool() built-in function Python breakpoint() built-in function Python bytearray() built-in function Python bytes() built-in function Python callable() built-in function Python chr() built-in function Python classmethod() built-in function Python compile() built-in function Python complex() built-in function Python delattr() built-in function Python dict() built-in function Python dir() built-in function Python divmod() built-in function Python enumerate() built-in function Python eval() built-in function Python exec() built-in function Python filter() built-in function Python float() built-in function Python format() built-in function Python frozenset() built-in function Python getattr() built-in function Python globals() built-in function Python hasattr() built-in function Python hash() built-in function Python help() built-in function Python hex() built-in function Python id() built-in function Python __import__() built-in function Python input() built-in function Python int() built-in function Python isinstance() built-in function Python issubclass() built-in function Python iter() built-in function Python len() built-in function Python list() built-in function Python locals() built-in function Python map() built-in function Python max() built-in function Python memoryview() built-in function Python min() built-in function Python next() built-in function Python object() built-in function Python oct() built-in function Python open() built-in function Python ord() built-in function Python pow() built-in function Python print() built-in function Python property() built-in function Python range() built-in function Python repr() built-in function Python reversed() built-in function Python round() built-in function Python set() built-in function Python setattr() built-in function Python slice() built-in function Python sorted() built-in function Python staticmethod() built-in function Python str() built-in function Python sum() built-in function Python super() built-in function Python tuple() built-in function Python type() built-in function Python vars() built-in function Python zip() built-in function