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
Owner
avito.tech
avito.ru engineering team open source projects
avito.tech
wsvuls - website vulnerability scanner detect issues [ outdated server software and insecure HTTP headers.]

WSVuls Website vulnerability scanner detect issues [ outdated server software and insecure HTTP headers.] What's WSVuls? WSVuls is a simple and powerf

Anouar Ben Saad 47 Sep 22, 2022
Add a Web Server based on Rogue Mysql Server to allow remote user get

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

6 May 17, 2022
Fast python tool to test apache path traversal CVE-2021-41773 in a List of url

CVE-2021-41773 Fast python tool to test apache path traversal CVE-2021-41773 in a List of url Usage :- create a live urls file and use the flag "-l" p

Zahir Tariq 12 Nov 09, 2022
This exploit allows to connect to the remote RemoteMouse 3.008 service to virtually press arbitrary keys and execute code on the machine.

RemoteMouse-3.008-Exploit The RemoteMouse application is a program for remotely controlling a computer from a phone or tablet. This exploit allows to

Podalirius 25 Dec 04, 2022
Automatic SQL injection and database takeover tool

sqlmap sqlmap is an open source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws and taking over of

sqlmapproject 25.7k Jan 08, 2023
Tools to make working the Arch Linux Security Tracker easier

This is a collection of Python scripts to make working with the Arch Linux Security Tracker easier.

Jonas Witschel 6 Jul 13, 2022
ADExplorerSnapshot.py is an AD Explorer snapshot ingestor for BloodHound.

ADExplorerSnapshot.py ADExplorerSnapshot.py is an AD Explorer snapshot ingestor for BloodHound. AD Explorer allows you to connect to a DC and browse L

576 Dec 23, 2022
Um keylogger que se disfarça de um app que tira print da tela.

Keylogger_ Um keylogger que se disfarça de um app que tira print da tela. Este programa captura o print da tela e salva ,normalmente, na pasta Picture

Marcus Vinícius Ribeiro Andrade 1 Dec 03, 2021
CVE-2022-22536 - SAP memory pipes(MPI) desynchronization vulnerability CVE-2022-22536

CVE-2022-22536 SAP memory pipes desynchronization vulnerability(MPI) CVE-2022-22

antx 49 Nov 09, 2022
Using python 3 and Flask an MVC system where the AES 128 CBC and Trivium algorithms

This project was developed using python 3 and Flask, it is an MVC system where the AES 128 CBC and Trivium algorithms can be tested through a communication between the computer and a device such as a

Brandon Israel Camacho Reyes 1 Dec 26, 2021
Threat research and reporting from IronNet's Threat Research Teams

IronNet Threat Research 🕵️ Overview This repository contains IronNet's Threat Research. Research & Reporting 📝 Project Description Cobalt Strike Res

36 Dec 02, 2022
Abusing Microsoft 365 OAuth Authorization Flow for Phishing Attack

O365DevicePhish Microsoft365_devicePhish Abusing Microsoft 365 OAuth Authorization Flow for Phishing Attack This is a simple proof-of-concept script t

Trewis [work] Scotch 4 Sep 23, 2022
NoSecerets is a python script that is designed to crack hashes extremely fast. Faster even than Hashcat

NoSecerets NoSecerets is a python script that is designed to crack hashes extremely fast. Faster even than Hashcat How does it work? Instead of taking

DosentTrust GithubDatabase 9 Jul 04, 2022
The probability of having the password you want in the PassMaker is +90%!!

PasswordMaker Strong listing password Introduction The probability of having the password you want in the tool is +90%!! How to Install Open the termi

MasterBurnt 4 Sep 05, 2021
Exploit for GitLab CVE-2021-22205 Unauthenticated Remote Code Execution

Vuln Impact An issue has been discovered in GitLab CE/EE affecting all versions starting from 11.9. GitLab was not properly validating image files tha

Hendrik Agung 2 Dec 30, 2021
Exploiting CVE-2021-42278 and CVE-2021-42287 to impersonate DA from standard domain user

Exploiting CVE-2021-42278 and CVE-2021-42287 to impersonate DA from standard domain user Known issues it will not work outside kali , i will update it

Hossam 867 Dec 22, 2022
This little tool is to calculate a MurmurHash value of a favicon to hunt phishing websites on the Shodan platform.

MurMurHash This little tool is to calculate a MurmurHash value of a favicon to hunt phishing websites on the Shodan platform. What is MurMurHash? Murm

Viral Maniar 87 Dec 31, 2022
Source code for "A Two-Stream AMR-enhanced Model for Document-level Event Argument Extraction" @ NAACL 2022

TSAR Source code for NAACL 2022 paper: A Two-Stream AMR-enhanced Model for Document-level Event Argument Extraction. 🔥 Introduction We focus on extra

21 Sep 24, 2022
DNSpooq - dnsmasq cache poisoning (CVE-2020-25686, CVE-2020-25684, CVE-2020-25685)

dnspooq DNSpooq PoC - dnsmasq cache poisoning (CVE-2020-25686, CVE-2020-25684, CVE-2020-25685) For educational purposes only Requirements Docker compo

Teppei Fukuda 80 Nov 28, 2022
Microsoft Exchange Server SSRF漏洞(CVE-2021-26855)

Microsoft_Exchange_Server_SSRF_CVE-2021-26855 zoomeye dork:app:"Microsoft Exchange Server" 使用Seebug工具箱及pocsuite3编写的脚本Microsoft_Exchange_Server_SSRF_CV

conjojo 37 Nov 12, 2022