Trainspotting - Python Dependency Injector based on interface binding

Overview

trainspotting

Choose dependency injection

  • Friendly with MyPy
  • Supports lazy injections
  • Supports fabrics with environment variables
  • Can connect/disconnect clients in correct order

Install

pip install trainspotting

Contact

Feel free to ask questions in telegram t.me/PulitzerKenny

Examples

from typing import Protocol
from dataclasses import dataclass
from trainspotting import DependencyInjector
from trainspotting.factory import factory, EnvField


class TransportProtocol(Protocol):
    def go(self): ...

class EngineProtocol(Protocol):
    def start(self): ...

class HeadlightsProtocol(Protocol):
    def light(self): ...

@dataclass
class Driver:
    transport: TransportProtocol
    
    def drive(self):
        self.transport.go()

@dataclass
class V8Engine:
    sound: str

    def start(self):
        print(self.sound)

@dataclass
class XenonHeadlights:
    brightness: int

    def light(self):
        print(f'LIGHT! {self.brightness}')

@dataclass
class Car:
    engine: EngineProtocol
    headlights: HeadlightsProtocol

    def go(self):
        self.engine.start()
        self.headlights.light()

def get_config():
    return {
        EngineProtocol: factory(V8Engine, sound=EnvField('ENGINE_SOUND')),
        HeadlightsProtocol: factory(
            XenonHeadlights, 
            brightness=EnvField('HEADLIGHTS_BRIGHTNESS', int)
        ),
        TransportProtocol: Car,
    }

injector = DependencyInjector(get_config())
injected_driver = injector.inject(Driver)
injected_driver().drive()

Clients connect/disconnect

Connect can be used for async class initialization

import aioredis

from typing import Protocol
from trainspotting import DependencyInjector

class ClientProtocol(Protocol):
    async def do(self):
        ...

class RedisClient:
    def __init__(self):
        self.pool = None
        
    async def do(self):
        if not self.pool:
            raise ValueError
        print('did something')
    
    async def connect(self):
        self.pool = await aioredis.create_redis_pool(('127.0.0.1', 6379))
        print('connected')
        
    async def disconnect(self):
        self.pool.close()
        await self.pool.wait_closed()
        print('disconnected')


async def main(client: ClientProtocol):
    await client.do()


injector = DependencyInjector({ClientProtocol: RedisClient})
injected = injector.inject(main)

async with injector.deps:  # connected
    await injected() # did something
# disconnected

Types Injection

class EntityProtocol(Protocol):
    def do(self): ...

class Entity:
    def do(self):
        print('do something')

@dataclass
class SomeUsefulClass:
    entity: Type[EntityProtocol]

injector.add_config({EntityProtocol: Entity})
injector.inject(SomeUsefulClass)

Lazy injections

@injector.lazy_inject
async def some_func(client: ClientProtocol):
    await client.do_something()


some_func()  # raise TypeError, missing argument client
injector.do_lazy_injections()
some_func()  # ok

Extend or change config

injector.add_config({ClientProtocol: Client})

EnvField

import os
from typing import Protocol
from dataclasses import dataclass
from trainspotting import DependencyInjector
from trainspotting.factory import factory, EnvField


class ClientProtocol(Protocol):
    def do(self):
        ...


@dataclass
class Client(ClientProtocol):
    url: str
    log_prefix: str
    timeout: int = 5

    def do(self):
        print(f'{self.log_prefix}: sent request to {self.url} with timeout {self.timeout}')


injector = DependencyInjector({
    ClientProtocol: factory(
        Client,
        url=EnvField('SERVICE_URL'),
        log_prefix=EnvField('LOG_PREFIX', default='CLIENT'),
        timeout=EnvField('SERVICE_TIMEOUT', int, optional=True),
    )
})


def main(client: ClientProtocol):
    client.do()
    
    
os.environ.update({'SERVICE_URL': 'some_url'})
injected = injector.inject(main)
injected()  # CLIENT: sent request to some_url with timeout 5

Supports type validation

from typing import Protocol, runtime_checkable
from trainspotting import DependencyInjector


@runtime_checkable
class ClientProtocol(Protocol):
    def do(self):
        ...


class Client:
    def do(self):
        print('did something')


class BadClient:
    def wrong_do(self):
        ...
    

def main(client: ClientProtocol):
    client.do()

injector = DependencyInjector({
    ClientProtocol: BadClient,
})

injector.inject(main)()  # raise InjectionError: 
   
     does not realize 
    
      interface
    
   

injector = DependencyInjector({
    ClientProtocol: Client,
})

injector.inject(main)()  # prints: did something
You might also like...
Python-based proof-of-concept tool for generating payloads that utilize unsafe Java object deserialization.

Python-based proof-of-concept tool for generating payloads that utilize unsafe Java object deserialization.

A Python r2pipe script to automatically create a Frida hook to intercept TLS traffic for Flutter based apps
A Python r2pipe script to automatically create a Frida hook to intercept TLS traffic for Flutter based apps

boring-flutter A Python r2pipe script to automatically create a Frida hook to intercept TLS traffic for Flutter based apps. Currently only supporting

Evil-stalker - A simple tool written in python, it is so simple that it is based on google dorks

evil-stalker How to run First of all, you must install the necessary libraries.

This is simple python FTP password craker. To crack FTP login using wordlist based brute force attack
This is simple python FTP password craker. To crack FTP login using wordlist based brute force attack

This is simple python FTP password craker. To crack FTP login using wordlist based brute force attack

A Radare2 based Python module for Binary Analysis and Reverse Engineering.
A Radare2 based Python module for Binary Analysis and Reverse Engineering.

Zepu1chr3 A Radare2 based Python module for Binary Analysis and Reverse Engineering. Installation You can simply run this command. pip3 install zepu1c

Windows Stack Based Auto Buffer Overflow Exploiter
Windows Stack Based Auto Buffer Overflow Exploiter

Autoflow - Windows Stack Based Auto Buffer Overflow Exploiter Autoflow is a tool that exploits windows stack based buffer overflow automatically.

Docker Compose based system for running remote browsers (including Flash and Java support) connected to web archives
Docker Compose based system for running remote browsers (including Flash and Java support) connected to web archives

pywb Remote Browsers This repository provides a simple configuration for deploying any pywb with remote browsers provided by OWT/Shepherd Remote Brows

Add a Web Server based on Rogue Mysql Server to allow remote user get
Add a Web Server based on Rogue Mysql Server to allow remote user get

介绍 对于需要使用 Rogue Mysql Server 的漏洞来说,若想批量检测这种漏洞的话需要自备一个服务器。并且我常用的Rogue Mysql Server 脚本 不支持动态更改读取文件名、不支持远程用户访问读取结果、不支持批量化检测网站。于是乎萌生了这个小脚本的想法 Rogue-MySql-

Owner
avito.tech
avito.ru engineering team open source projects
avito.tech
Dependency Combobulator is an Open-Source, modular and extensible framework to detect and prevent dependency confusion leakage and potential attacks.

Dependency Combobulator Dependency Combobulator is an Open-Source, modular and extensible framework to detect and prevent dependency confusion leakage

Apiiro 84 Dec 23, 2022
Midas ELF64 Injector is a tool that will help you inject a C program from source code into an ELF64 binary.

Midas ELF64 Injector Description Midas ELF64 Injector is a tool that will help you inject a C program from source code into an ELF64 binary. All you n

midas 20 Dec 24, 2022
Dependency injection in python with autoconfiguration

The base is a DynamicContainer to autoconfigure services using the decorators @services for regular services and @command_handler for using command pattern.

Sergio Gómez 2 Jan 17, 2022
DependConfusion-X Tool is written in Python3 that scans and monitors list of hosts for Dependency Confusion

DependConfusion-X Tool is written in Python3 which allows security researcher/bug bounty hunter to scan and monitor list of hosts for Dependency Confusion.

Ali Fathi Ali Sawehli 4 Dec 21, 2021
Reusable Lightweight Pythonic Dependency Injection Library

Vacuna Inject everything! Vacuna is a little library to provide dependency management for your python code. Install pip install vacuna Usage import va

Fernando Martínez González 16 Sep 15, 2021
labsecurity is a tool that brings together python scripts made for ethical hacking, in a single tool, through a console interface

labsecurity labsecurity is a tool that brings together python scripts made for ethical hacking, in a single tool, through a console interface. Warning

Dylan Meca 16 Dec 8, 2022
A simple Outline Server Access Key Copy and Paste Web Interface

Outline Keychain A simple Outline Server Access Key Copy and Paste Web Interface Developed for key and password export and copy & paste for other Shad

Zhe 1 Dec 28, 2021
DirBruter is a Python based CLI tool. It looks for hidden or existing directories/files using brute force method. It basically works by launching a dictionary based attack against a webserver and analyse its response.

DirBruter DirBruter is a Python based CLI tool. It looks for hidden or existing directories/files using brute force method. It basically works by laun

vijay sahu 12 Dec 17, 2022
A python based tool that executes various CVEs to gain root privileges as root on various MAC OS platforms.

MacPer A python based tool that executes various CVEs to gain root privileges as root on various MAC OS platforms. Not all of the exploits directly sp

null 20 Nov 30, 2022
It is a very simple XSS simulator based on flask, python.

It is a very simple XSS simulator based on flask, python. The purpose of making this is for teaching the concept of XSS.

Satin Wuker 3 May 10, 2022