Applications¶
HARP applications are Python packages that integrate with the system through a standard protocol. Both core features and third-party extensions use the same protocol.
An application is a Python package with an __app__.py file that defines how it hooks into the system.
Basic Structure¶
To create a HARP application, add an __app__.py file to your Python package:
from harp.config import Application
application = Application()
Applications usually also need settings.
Configuring Settings¶
Define your settings in a settings.py file:
from harp.config import ApplicationSettingsMixin, Configurable
class AcmeSettings(ApplicationSettingsMixin, Configurable):
owner: str = "Joe"
Added in version 0.10: All application settings must inherit from ApplicationSettingsMixin.
Then reference them in __app__.py:
from harp.config import Application
from .settings import AcmeSettings
application = Application(
settings_type=AcmeSettings,
)
Test your settings:
from harp.config.asdict import asdict
from ..settings import AcmeSettings
def test_default_settings():
settings = AcmeSettings()
assert asdict(settings) == {}
assert asdict(settings, verbose=True) == {"enabled": True, "owner": "Joe"}
def test_custom_settings():
settings = AcmeSettings(owner="Alice")
assert asdict(settings) == {"owner": "Alice"}
assert asdict(settings, verbose=True) == {"enabled": True, "owner": "Alice"}
Important
ApplicationSettingsMixin must be the first base class in the inheritance chain.
Declaring Dependencies¶
Added in version 0.10: Applications can declare dependencies to ensure correct initialization order.
Applications declare dependencies as a list. At startup, the system validates all dependencies exist, detects cycles, and initializes applications in topological order.
from harp.config import Application
from .settings import ProxySettings
application = Application(
settings_type=ProxySettings,
dependencies=["http_client"], # Simple list of app names
)
Best practices:
Declare only direct dependencies (transitive dependencies are resolved automatically)
Use simple names (
storage, notharp_apps.storage)Applications without dependencies work unchanged
Error examples:
# Missing dependency
MissingDependencyError: Application 'dashboard' requires 'storage' but it is not enabled
# Circular dependency
CircularDependencyError: Circular dependency detected: a → b → c → a
Testing with partial systems:
Tests building incomplete systems can bypass validation with validate_dependencies=False:
system = await ConfigurationBuilder(
{"applications": ["http_client", "storage"]},
use_default_applications=False,
).abuild_system(validate_dependencies=False) # Skip validation for tests
Warning
Only use validate_dependencies=False in tests. Production code should always validate (default behavior).
Application Lifecycle¶
Applications interact with the system through lifecycle hooks. All hooks are async functions that receive an event object.
On Bind¶
Called during system setup. Register services and dependencies here.
from harp.config import Application, OnBindEvent
async def on_bind(event: OnBindEvent):
...
application = Application(
...,
on_bind=on_bind,
)
Reference: harp.config.OnBindEvent
On Bound¶
Called after services are registered. Access and configure service instances here.
from harp.config import Application, OnBoundEvent
async def on_bound(event: OnBoundEvent):
...
application = Application(
...,
on_bound=on_bound,
)
Reference: harp.config.OnBoundEvent
On Ready¶
Called when the system starts. All services are ready.
from harp.config import Application, OnReadyEvent
async def on_ready(event: OnReadyEvent):
...
application = Application(
...,
on_ready=on_ready,
)
Reference: harp.config.OnReadyEvent
On Shutdown¶
Called during system shutdown. Clean up resources here.
Shutdown events are dispatched in reverse order - the first application initialized is the last to shut down.
from harp.config import Application, OnShutdownEvent
async def on_shutdown(event: OnShutdownEvent):
...
application = Application(
...,
on_shutdown=on_shutdown,
)
Reference: harp.config.OnShutdownEvent