Catalog PyPI
PACKAGE EXPLORERView in registry

action0-service

PyPI

Lightweight service registry and dependency injection framework

dependency-injectioniocregistryservice-locatorsingletonyaml
Versions collected1
Direct dependencies1From release 0.1.1
Last observed20 Oct, 18:31 UTC

README

Version 0.1.1 documentation

Action0-Service

CI PyPI

A lightweight service registry and dependency injection framework: register classes, factories, or ready-made instances — by type or by name — and request them back with their constructor dependencies resolved automatically. Scopes (singleton, transient, thread-local, context-local), YAML service definitions, and a test-friendly override mechanism included. The core has zero dependencies.

Requires Python 3.11 or newer.

Full documentation including the API reference: https://laughinjar.github.io/action0-service/

Installation

pip install action0-service          # or: uv add action0-service
pip install "action0-service[yaml]"  # with YAML support (PyYAML)

Usage

Register services and let the registry wire them together:

from action0.service import Registry, Scope


class Database:
    def __init__(self, dsn: str = "sqlite://"):
        self.dsn = dsn


class UserRepository:
    def __init__(self, db: Database):  # injected from the registry
        self.db = db


registry = Registry()
registry.register(Database, params={"dsn": "postgres://db/app"})
registry.register(UserRepository)

repo = registry.get(UserRepository)
print(repo.db.dsn)
# postgres://db/app
print(registry.get(UserRepository) is repo)  # singletons by default
# True

Services can be named (several implementations of one type), scoped, and looked up by type — subclass-aware — or by name:

registry.register(Database, name="replica", params={"dsn": "postgres://replica/app"})
registry.get("replica")  # by name
registry.get(Database)  # the unnamed default
registry.get(Database, name="replica")  # typed + named
registry.register(UserRepository, name="fresh", scope=Scope.TRANSIENT, replace=True)

Or define whole registries in YAML (anchors and merges work as usual):

database:
  factory: myapp.db.Database
  dsn: !ENV ${DATABASE_DSN:-sqlite://}

user-repository:
  factory: myapp.repo.UserRepository
  db: !ref database
registry.load_yaml("conf/services.yaml")
registry.validate()  # catch config mistakes at boot, not at first use

For tests, swap any service temporarily:

with registry.override(Database, FakeDatabase()):
    ...

See the documentation for injection rules, scopes, custom scopes, the full YAML format, parent registries, lifecycle management (warmup() / close()), and the @registry.inject function decorator.

The action0 namespace is simply the one the author likes to use for personal projects.

AI disclosure

This library is developed with heavy use of AI coding tools: the code, tests, and documentation are largely written by Claude Code, working from the author's design brief and reviewed by the author. If that changes how much you want to rely on this package, that's a fair call — read the source, it's small.

License

MIT — see LICENSE.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.18 Aug 20261

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
laughinjar/action0-service

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 18:31 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:d3e0e2cd0b16fc3b2cedfb9bcbf4a6470090ab9d40e1305fb0340d510b2e712d