ExceptionFactory

Producing content that a reasonable developer might want to read

Getting Started with Hatch for Python Projects

Dependencies Hatch Python

2024-05-15 • 5 minute read • David Handermann

Introduction

Beyond the code itself, straightforward tooling is one of the most important elements of the software development lifecycle. Dynamically typed languages such as Python make it easy to write code first and ask structural questions later, but when building for sustainability or designing for distribution, project management capabilities are essential. The Python ecosystem includes numerous options for linting, testing, and packaging, which can be combined using various strategies. Hatch is a relatively recent addition to the landscape of Python project tooling, but it combines an intuitive command-line interface with standardized declarative configuration, providing a solid framework for building libraries and applications.

Getting Started

The Hatch installation instructions outline the steps required to get started on popular operating systems.

In addition to platform-specific packages, pipx supports installing Hatch regardless of operating system.

pipx install hatch

Installing with pipx makes the hatch command available for project creation and subsequent lifecycle operations.

Project Management with Hatch

Hatch provides a common set of commands for creating, building, testing, and publishing Python projects. Each command has a distinct set of options that apply to the invoked operation.

New Project Creation

With sensible defaults and configurable templates, Hatch can create a new project with a single command.

hatch new hello-world

The hatch new command creates a directory corresponding to the project name specified, and prints the structure of the new project.

hello-world
├── src
│   └── hello_world
│       ├── __about__.py
│       └── __init__.py
├── tests
│   └── __init__.py
├── LICENSE.txt
├── README.md
└── pyproject.toml

The default configuration creates the project using the src layout strategy, which places the project package name under the base src directory.

Hatch project templates create a package directory based on the project name, including __about__.py containing the project version and __init__.py as the project module initializer.

The tests directory contains a module initializer, but no additional files.

The project license defaults to MIT, following the license of Hatch itself.

Project Configuration

The generated pyproject.toml contains important default settings for project lifecycle operations. The TOML structure of the project configuration enables both readability and programmatic parsing using an intuitive structure consisting of hierarchical sections with specific properties.

The default configuration includes several properties that should be changed to reflect correct ownership and reference information. The [project] section includes an authors property that should be adjusted to indicate the name and email address of one or more developers.

[project]
authors = [
    { name = "U.N. Owen", email = "void@some.where" }
]

Setting a value for the description property under the [project] section provides a helpful summary beyond the project name itself.

The [project.urls] section includes several links that default to GitHub, which should be changed or removed based on the actual location of the project repository.

Additional settings provide reasonable defaults, but should be evaluated and adjusted depending on Python version requirements.

Building

Building project artifacts is a core capability. The default build command creates both a source distribution and a packaged binary distribution, according to the Python wheel format.

hatch build

The build command generates distribution archives in the dist directory for subsequent review or publishing.

The --target option supports selective building of one or more formats, including sdist and wheel as well as other formats provided through a Hatch plugin. The default Hatch build command is equivalent to running with the following targets:

hatch build -t sdist -t wheel

Testing

Automated testing is essential to building maintainable software. Hatch supports testing using the test command.

hatch test

The standard Hatch configuration includes pytest for assertions and test invocation. Test files should be created in the tests directory.

The Coverage.py project provides code coverage measurement, which Hatch also includes in the default configuration. Running the test command with --cover enables coverage reporting as part of the testing process.

hatch test --cover

Linting

Static analysis, also known as linting, is a first-class feature of Hatch using the fmt command. The default behavior includes both error checking and reformatting.

hatch fmt

Adding the --check option runs error checking without automated fixes. Running the format command with checking enabled supports configuration with continuous integration workflows that enforce standard coding conventions.

hatch fmt --check

Hatch uses Ruff for linting with reasonable default settings, providing high performance support for hundreds of configurable rules.

Hinting

Although Python is a dynamically typed language at the core, it also supports optional static typing using hinting as described in PEP 484.

The mypy project is a common implementation of Python type hinting, which Hatch supports in the default configuration. The Hatch run command supports invoking tools defined in the project configuration, such as checking for correct type hinting.

hatch run types:check

The run command takes an environment and argument, corresponding to a tool section in pyproject.toml with the same environment and argument properties.

[tool.hatch.envs.types.scripts]
check = "mypy --install-types --non-interactive {args:src/hello_world tests}"

Versioning

Versioning numbering is an important part of the software development lifecycle, particularly as a means to communicate the relative significance of changes from one version to another. The Semantic Versioning specification is one common strategy. The Python PEP 440 specification defines specific rules for public version identifiers to provide a consistent vocabulary for different types of releases.

The Hatch version command enables semantic changes to version information stored in __about__.py under the project package directory. Running the version command without any arguments prints the current version number.

hatch version

Running the version command with a specific number updates the version to the value provided.

hatch version 1.0.0

Running the version command with one or more supported version segments performs an incremental update to the segment specified.

hatch version minor

With a current version of 1.0.0, running the command with the minor argument sets the version to 1.1.0.

Conclusion

Incorporating a number of best practices, Hatch provides the essential features for building robust projects in Python. Hatch has a growing community of users across major industries, highlighting significant adoption since the release of version 1.0.0 in 2022. With support for migrating existing projects, Hatch presents a compelling solution for both old and new Python projects.