Skip to main content

A comprehensive async cancellation system for Python streams

Project description

Cancelable

PyPI version Python Versions License CI

A comprehensive, production-ready async cancellation system for Python 3.12+ using anyio.

Table of Contents

Features

  • Multiple Cancellation Sources: Timeout, manual tokens, OS signals, and custom conditions
  • Composable Design: Combine multiple cancellation sources easily
  • Stream Processing: Built-in support for cancelable async iterators
  • Operation Tracking: Full lifecycle tracking with status and progress reporting
  • Library Integrations: Ready-to-use integrations for httpx, FastAPI, and SQLAlchemy
  • Type Safe: Full type hints and runtime validation with Pydantic
  • Production Ready: Comprehensive error handling, logging, and performance optimized

Installation

Core Installation

The core library includes only essential dependencies (anyio and pydantic):

uv add hother-cancelable

Optional Extras

Cancelable provides optional extras for various integrations and use cases:

Integration Extras

Extra Dependencies Purpose
httpx httpx HTTP client integration for cancelable requests
sqlalchemy sqlalchemy, aiosqlite Database integration for cancelable queries
fastapi fastapi FastAPI middleware for request cancellation
aiofiles aiofiles Async file I/O operations
asyncer asyncer Additional async utilities

Development Extras

Extra Dependencies Purpose
examples google-genai, pynput, psutil Run example scripts and demonstrations

Installing with Extras

Single extra:

# HTTP client support
uv add "hother-cancelable[httpx]"

# Database support
uv add "hother-cancelable[sqlalchemy]"

# FastAPI integration
uv add "hother-cancelable[fastapi]"

Multiple extras:

# Install multiple integrations at once
uv add "hother-cancelable[httpx,sqlalchemy,fastapi]"

All extras:

# Install all optional extras (useful for development)
uv add "hother-cancelable[httpx,sqlalchemy,fastapi,aiofiles,asyncer,examples]"

Quick Start

Basic Usage

from hother.cancelable import Cancelable

# Timeout-based cancellation
async with Cancelable.with_timeout(30.0) as cancel:
    result = await long_running_operation()

# Manual cancellation with token
from hother.cancelable import CancellationToken

token = CancellationToken()

async with Cancelable.with_token(token) as cancel:
    # In another task/thread: await token.cancel()
    result = await interruptible_operation()

Stream Processing

# Cancelable stream processing
async with Cancelable.with_timeout(60.0) as cancel:
    async for item in cancel.stream(data_source(), report_interval=100):
        await process_item(item)

Function Decorators

from hother.cancelable import cancelable

@cancelable(timeout=30.0, register_globally=True)
async def process_data(data: list, cancelable: Cancelable = None):
    for i, item in enumerate(data):
        await cancelable.report_progress(f"Processing item {i+1}/{len(data)}")
        await process_item(item)

Integrations

Cancelable provides seamless integrations with popular async libraries. See the integrations documentation for detailed guides and examples.

  • HTTPX: Cancel HTTP requests with timeout and manual cancellation
  • FastAPI: Add cancellation middleware to FastAPI applications
  • SQLAlchemy: Cancel database operations and transactions

Documentation

To build and serve the documentation locally:

  1. Install the documentation dependencies:
uv sync --group doc
source .venv/bin/activate
  1. Serve the documentation:
mkdocs serve

Development

Dependency Groups

Cancelable uses dependency groups for development and documentation:

Group Purpose Key Dependencies
dev Development tools pytest, ruff, basedpyright, twine, git-cliff
doc Documentation building mkdocs, mkdocs-material, mike

Installation

Basic development setup:

uv sync --group dev
source .venv/bin/activate
lefthook install

This creates a virtual environment, installs all development dependencies, and installs the library in editable mode. It also sets up Lefthook git hooks.

Full development setup with integrations:

Some tests require optional integration extras. To run the full test suite:

# Install dev tools + all integration extras
uv sync --group dev --all-extras

Selective installation:

# Install only specific integrations
uv sync --group dev --extra httpx --extra sqlalchemy

# Install documentation tools
uv sync --group doc

Quick Reference

Available extras:

  • httpx - HTTP client integration
  • sqlalchemy - Database integration
  • fastapi - FastAPI middleware
  • aiofiles - Async file I/O
  • asyncer - Async utilities
  • examples - Example scripts

Available groups:

  • dev - Development tools (pytest, ruff, basedpyright, etc.)
  • doc - Documentation tools (mkdocs, mkdocs-material, etc.)

Git Hooks with Lefthook

This project uses Lefthook for managing git hooks. Hooks are automatically installed when you run make install-dev.

To run hooks manually:

# Run all pre-commit hooks
lefthook run pre-commit

Tests

Run core tests (without integration extras):

uv run pytest

Integration tests that require optional dependencies (httpx, sqlalchemy, fastapi) will be automatically skipped if the extras are not installed.

Run all tests including integrations:

# First install all extras
uv sync --all-extras

# Then run tests
uv run pytest

Run specific test categories:

# Run only unit tests
uv run pytest tests/unit

# Run only integration tests (requires extras)
uv run pytest tests/integration

Coverage

uv run pytest --cov=hother.cancelable

Building the package

uv build

Release process

This project uses Git tags for versioning with automatic semantic versioning based on conventional commits. Version numbers are automatically derived from Git tags using hatch-vcs.

Quick Release Commands

# Check current version
hatch version

# Create development release (v1.0.0 → v1.0.1-dev1)
hatch release dev

# Create release candidate (v1.0.1-dev1 → v1.0.1rc1)
hatch release rc

# Create final release (v1.0.1rc1 → v1.0.1)
hatch release final

Release from Specific Commit

You can optionally specify a commit SHA to create a release from:

# Release from a specific commit
hatch release dev abc123
hatch release rc def456
hatch release final 789xyz

The SHA must be:

  • Reachable from HEAD (on current branch history)
  • Not already included in a previous release

How it Works

  • Development releases (dev): Increments patch version and adds -dev suffix
  • Release candidates (rc): Removes -dev and adds rc suffix
  • Final releases (final): Uses git-cliff to analyze commits and automatically bumps major/minor/patch based on conventional commits

The release process:

  1. Analyzes commit history (for final releases)
  2. Calculates the next version number
  3. Creates and pushes the git tag
  4. GitHub Actions automatically builds and publishes the release

Manual Tagging (Advanced)

If needed, you can still create tags manually:

# Manual tag creation
git tag -a v1.2.3 -m "Release v1.2.3"
git push origin v1.2.3

Changelog Management

This project uses git-cliff to automatically generate changelogs from conventional commits.

# Generate/update CHANGELOG.md
make changelog

# Preview unreleased changes
make changelog-unreleased

# Get changelog for latest tag (used in releases)
make changelog-tag

The changelog is automatically updated and included in GitHub releases when you push a version tag.

Generate the licenses:

uv run pip-licenses --from=mixed --order count -f md --output-file licenses.md
uv run pip-licenses --from=mixed --order count -f csv --output-file licenses.csv

Build the new documentation:

uv run mike deploy --push --update-aliases <version> latest
uv run mike set-default latest
uv run mike list

Checking the documentation locally

uv run mike serve

Development practices

Branching & Pull-Requests

Each git branch should have the format <tag>/item_<id> with eventually a descriptive suffix.

We us a Squash & Merge approach.

Conventional Commits

We use Conventional Commits.

Format: <type>(<scope>): <subject>

<scope> is optional

Example

feat: add hat wobble
^--^  ^------------^
|     |
|     +-> Summary in present tense.
|
+-------> Type: chore, docs, feat, fix, refactor, style, or test.

More Examples:

  • feat: (new feature for the user, not a new feature for build script)
  • fix: (bug fix for the user, not a fix to a build script)
  • docs: (changes to the documentation)
  • style: (formatting, missing semi colons, etc; no production code change)
  • refactor: (refactoring production code, eg. renaming a variable)
  • test: (adding missing tests, refactoring tests; no production code change)
  • chore: (updating grunt tasks etc; no production code change)
  • build: (changes in the build system)
  • ci: (changes in the CI/CD and deployment pipelines)
  • perf: (significant performance improvement)
  • revert: (revert a previous change)

Contributing

We welcome contributions! Please see our Contributing Guide for details on how to get started.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hother_cancelable-0.4.0.tar.gz (122.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hother_cancelable-0.4.0-py3-none-any.whl (60.4 kB view details)

Uploaded Python 3

File details

Details for the file hother_cancelable-0.4.0.tar.gz.

File metadata

  • Download URL: hother_cancelable-0.4.0.tar.gz
  • Upload date:
  • Size: 122.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for hother_cancelable-0.4.0.tar.gz
Algorithm Hash digest
SHA256 5bf4259bd88497f14dd3adadc7085e49681486c7a969261f31d83395e8a3fa86
MD5 37b19233c389053ebf6f5f216604a04e
BLAKE2b-256 93f47540a787cbae816868543349966d047b451afd6165959d1288333edd9253

See more details on using hashes here.

File details

Details for the file hother_cancelable-0.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for hother_cancelable-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 33c03726ec2e198658aaf5372ce5f155162534e150ed585b9cf2437db36b65ca
MD5 b0f659d2d4899fb9f16f4c4af4d33f9c
BLAKE2b-256 8d04fb4e6683cd53c99a39b7ad7e6ebe1ec46534676a9bfe69ccedafabc7f255

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page