Skip to content

aiokitchen/aiomisc-dependency

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

aiomisc-dependency

Dependency injection plugin for aiomisc built with aiodine library and supports pytest fixture style dependency injection.

Installation

Installing from PyPI:

pip3 install aiomisc aiomisc-dependency

How to Use

Register Dependency

To register a dependency, you can use the aiomisc_dependency.dependency decorator.

from aiomisc_dependency import dependency

@dependency
async def pg_engine():
    pg_engine = await create_engine(dsn=pg_url)
    yield pg_engine
    pg_engine.close()
    await pg_engine.wait_closed()

As you can see, a dependency can be an async generator function. Code after yield will be executed on teardown to correctly close the dependency.

Coroutine functions, non-async functions, and generators are also supported.

Use Dependency

To use a dependency, you need to add its name to the __dependencies__ property for every service that depends on it. Specified dependencies will be injected as the service's attributes on entrypoint startup. If you need to map the dependency with a different name, use __dependencies_map__.

from contextlib import suppress
from types import MappingProxyType

import aiohttp
from aiomisc.service.aiohttp import AIOHTTPService

class HealthcheckService(AIOHTTPService):

    __dependencies__ = ('pg_engine',)

    async def create_application(self):
        app = aiohttp.web.Application()
        app.add_routes([aiohttp.web.get('/ping', self.healthcheck_handler)])
        return app

    async def healthcheck_handler(self, request):
        pg_status = False
        with suppress(Exception):
            async with self.pg_engine.acquire() as conn:
                await conn.execute('SELECT 1')
                pg_status = True

        return aiohttp.web.json_response(
            {'db': pg_status},
            status=(200 if pg_status else 500),
        )


class RESTService(AIOHTTPService):

    __dependencies__ = ('pg_engine',)

    ...

class AnotherRESTService(AIOHTTPService):

    __dependencies_map__ = MappingProxyType({'pg_engine': 'engine'})

    ...

If any required dependency is not found on entrypoint startup, a RuntimeError will be raised.

You can set a dependency manually by adding it to the keyword arguments on service creation. This can be convenient in tests.

from unittest import Mock

def test_rest_service():
    pg_engine_mock = Mock()
    service = RESTService(pg_engine=pg_engine_mock)
    ...

Dependencies for Dependencies

You can use dependencies as arguments for other dependencies. Arguments will be injected automatically.

@dependency
async def pg_connection(pg_engine):
    async with pg_engine.acquire() as conn:
        yield conn

loop Built-in Dependency

The built-in loop dependency can be used if your dependency requires an event loop instance.

import aioredis

@dependency
async def redis_pool(loop):
    pool = aioredis.create_pool(redis_url, loop=loop)
    yield pool
    pool.close()
    await pool.wait_closed()

License

MIT

About

pytest fixture's style dependency injection for aiomisc

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages