A lightweight Python framework for managing the lifecycle and dependencies of stateful components
Project description
Python Components
A lightweight Python framework for managing the lifecycle and dependencies of stateful components.
Inspired by Alexandra Sierra's Component library for Clojure.
Overview
Component is a small framework for managing the lifecycle of software components that have runtime state. It provides:
- Dependency injection using explicit dependency declarations
- Lifecycle management with
startandshutdownmethods - Automatic dependency resolution using topological sorting
- Clean separation between component definition and composition
Installation
uv add python-components
Or with pip:
pip install python-components
Quick Start
1. Define Your Components
from python_components import Component
class Database(Component):
def __init__(self, host: str, port: int):
super().__init__()
self.host = host
self.port = port
self.connection = None
def start(self):
"""Connect to the database."""
self.connection = connect_to_db(self.host, self.port)
print(f"Database connected to {self.host}:{self.port}")
def shutdown(self):
"""Close the database connection."""
if self.connection:
self.connection.close()
print("Database connection closed")
class WebServer(Component):
def __init__(self, port: int):
super().__init__()
self.port = port
self.server = None
def start(self):
"""Start the web server."""
self.server = start_server(self.port)
print(f"Web server started on port {self.port}")
def shutdown(self):
"""Stop the web server."""
if self.server:
self.server.stop()
print("Web server stopped")
2. Compose Your System
from python_components import System
# Build the system
system_map = {
"database": Database(host="localhost", port=5432),
"cache": Cache().using(["database"]),
"web_server": WebServer(port=8080).using(["database", "cache"]),
}
system = System(system_map)
3. Start and Stop the System
# Start all components in dependency order
system.start()
# Your application runs...
# Shutdown all components in reverse dependency order
system.shutdown()
Key Concepts
Components
A component is any object that:
- Extends the
Componentabstract base class - Implements
start()andshutdown()methods - May depend on other components
Dependencies
Declare dependencies using the using() method:
component = MyComponent().using(["dependency1", "dependency2"])
Dependencies are automatically resolved and components are started in the correct order.
System
A system is a collection of components with declared dependencies. The System class:
- Builds a dependency graph from component declarations
- Performs topological sorting to determine initialization order
- Starts components in dependency order
- Shuts down components in reverse dependency order
- Detects circular dependencies and raises an error
Example: Complete Application
from python_components import Component, System
class Database(Component):
def __init__(self, connection_string: str):
super().__init__()
self.connection_string = connection_string
self.connection = None
def start(self):
self.connection = create_connection(self.connection_string)
print("✓ Database connected")
def shutdown(self):
self.connection.close()
print("✓ Database disconnected")
class Cache(Component):
def __init__(self):
super().__init__()
self.data = {}
def start(self):
print("✓ Cache initialized")
def shutdown(self):
self.data.clear()
print("✓ Cache cleared")
class ApiService(Component):
def __init__(self):
super().__init__()
self.server = None
def start(self):
self.server = start_api_server()
print("✓ API service started")
def shutdown(self):
self.server.stop()
print("✓ API service stopped")
# Compose the system
system = System({
"database": Database("postgresql://localhost/mydb"),
"cache": Cache().using(["database"]),
"api": ApiService().using(["database", "cache"]),
})
# Lifecycle management
try:
system.start()
# Application logic here
finally:
system.shutdown()
Features
- ✨ Simple API: Just implement
start()andshutdown() - 🔗 Explicit Dependencies: Clear, declarative dependency management
- 📊 Automatic Ordering: Topological sorting ensures correct initialization order
- 🔄 Lifecycle Management: Consistent start/shutdown across all components
- 🚨 Cycle Detection: Catches circular dependencies at runtime
- 🐍 Pythonic: Uses type hints and follows Python best practices
Why Use Components?
Problem: Global State and Initialization Order
Without a component system, applications often struggle with:
- Global mutable state scattered throughout the codebase
- Unclear initialization order leading to subtle bugs
- Difficulty testing components in isolation
- Complex shutdown logic that's easy to forget
Solution: Managed Components
The Component pattern provides:
- Explicit lifecycle: Every stateful resource has clear start/shutdown methods
- Dependency injection: Components receive their dependencies explicitly
- Testability: Easy to create test doubles and inject them
- Reliability: Guaranteed correct initialization and cleanup order
Development
Running Tests
This project uses pytest for testing. To run the tests:
uv run pytest
To run tests with coverage:
uv run pytest --cov=python_components --cov-report=term-missing
Installing Development Dependencies
uv add pytest ruff --group=dev
Requirements
- Python >= 3.13
- networkx >= 3.5
License
MIT License - see LICENSE file for details
Acknowledgments
This library is inspired by Alexandra Sierra's Component library for Clojure, which pioneered the pattern of explicit lifecycle management and dependency injection using immutable data structures.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file python_components-0.2.0.tar.gz.
File metadata
- Download URL: python_components-0.2.0.tar.gz
- Upload date:
- Size: 7.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1dbdd5b51db6e2880a906c5f9f41753777826630307a9c74d4636583141cebc
|
|
| MD5 |
079e6ba2f6431349d42defe7c8576280
|
|
| BLAKE2b-256 |
cdc5f5759b80b5fec0e6739e27bcf6870f47f64ea083054d8903af745c37c6af
|
Provenance
The following attestation bundles were made for python_components-0.2.0.tar.gz:
Publisher:
publish-pypi.yml on lucassant95/python-components
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
python_components-0.2.0.tar.gz -
Subject digest:
e1dbdd5b51db6e2880a906c5f9f41753777826630307a9c74d4636583141cebc - Sigstore transparency entry: 642056627
- Sigstore integration time:
-
Permalink:
lucassant95/python-components@00e33e60e8ff72ec71ffebd7cd7ac3c7a6782766 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/lucassant95
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@00e33e60e8ff72ec71ffebd7cd7ac3c7a6782766 -
Trigger Event:
release
-
Statement type:
File details
Details for the file python_components-0.2.0-py3-none-any.whl.
File metadata
- Download URL: python_components-0.2.0-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
90bf62f713be6c06836df3136c9e00ccd475b884a7dce2de854586d5bb897112
|
|
| MD5 |
186a5ef4dc59ab5e89f195ff9a5bf0f9
|
|
| BLAKE2b-256 |
27b20e77d1757a29adbf7f63c3fc4bdeb05c08530384beb4bbb5e8638a82a7d2
|
Provenance
The following attestation bundles were made for python_components-0.2.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on lucassant95/python-components
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
python_components-0.2.0-py3-none-any.whl -
Subject digest:
90bf62f713be6c06836df3136c9e00ccd475b884a7dce2de854586d5bb897112 - Sigstore transparency entry: 642056632
- Sigstore integration time:
-
Permalink:
lucassant95/python-components@00e33e60e8ff72ec71ffebd7cd7ac3c7a6782766 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/lucassant95
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@00e33e60e8ff72ec71ffebd7cd7ac3c7a6782766 -
Trigger Event:
release
-
Statement type: