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
NS-LOOKUP - A python script for scanning website for getting ip address of a website

NS-LOOKUP A python script for scanning website for getting ip address of a websi

Spider Anongreyhat 5 Aug 02, 2022
Exploit for CVE-2017-17562 vulnerability, that allows RCE on GoAhead (< v3.6.5) if the CGI is enabled and a CGI program is dynamically linked.

GoAhead RCE Exploit Exploit for CVE-2017-17562 vulnerability, that allows RCE on GoAhead ( v3.6.5) if the CGI is enabled and a CGI program is dynamic

Francisco Spínola 2 Dec 12, 2021
nuclei scanner for proxyshell ( CVE-2021-34473 )

Proxyshell-Scanner nuclei scanner for Proxyshell RCE (CVE-2021-34423,CVE-2021-34473,CVE-2021-31207) discovered by orange tsai in Pwn2Own, which affect

PikaChu 29 Dec 16, 2022
Denial Attacks by Various Methods

Denial Service Attack Denial Attacks by Various Methods IIIIIIIIIIIIIIIIIIII PPPPPPPPPPPPPPPPP VVVVVVVV VVVVVVVV I::

Baris Dincer 9 Nov 26, 2022
A OSINT tool coded in python

Argus Welcome to Argus, a OSINT tool coded in python. Disclaimer I Am not responsible what you do with the information that is given to you by my tool

Aidan 2 Mar 20, 2022
DepFine Is a tool to find the unregistered dependency based on dependency confusion valunerablility and lead to RCE

DepFine DepFine Is a tool to find the unregistered dependency based on dependency confusion valunerablility and lead to RCE Installation: You Can inst

Hossam mesbah 14 Nov 11, 2022
Generates password lists/dictionaries based on keywords written in python3.

dicbyru Introduction Generates password lists/dictionaries based on keywords. It uses the keywords and adds capital letters, numbers and special chara

ru55o 2 Oct 31, 2022
Tool for finding PHP source code vulnerabilities.

vulnz Tool for finding php source code vulnerabilities. Scans PHP source code and prints out potentially dangerous lines. This tool is useful for secu

Mateo Hanžek 1 Jan 14, 2022
A tool to brute force a gmail account. Use this tool to crack multiple accounts

A tool to brute force a gmail account. Use this tool to crack multiple accounts. This tool is developed to crack multiple accounts

Saad 12 Dec 30, 2022
CVE 2020-14871 Solaris exploit

CVE 2020-14871 Solaris exploit This is a basic ROP based exploit for CVE 2020-14871. CVE 2020-14871 is a vulnerability in Sun Solaris systems. The act

Robin Massink 2 Oct 25, 2022
Send CVE information to the specified mailbox (from Github)

Send CVE information to the specified mailbox (from Github)

91 Nov 08, 2022
Complet and easy to run Port Scanner with Python

Port_Scanner Complet and easy to run Port Scanner with Python Installation 1- git clone https://github.com/s120000/Port_Scanner 2- cd Port_Scanner 3-

1 May 19, 2022
A tool combined with the advantages of masscan and nmap

A tool combined with the advantages of masscan and nmap

59 Dec 24, 2022
Tools ini digunakan untuk krekk pacebuk:v

E-Crack By Aang-XD Fitur Login • Login via token facebook • Login via cookie facebook Install On Termux $ pkg update && pkg upgrade $ pkg install pyth

Aang Ardiansyah-XD 2 Dec 24, 2021
Lazarus analysis tools and research report

Lazarus Research This repository publishes analysis reports and analysis tools for Operation Dream Job and Operation JTrack for Lazarus. Tools Python

JPCERT Coordination Center 50 Sep 13, 2022
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
"Video Moment Retrieval from Text Queries via Single Frame Annotation" in SIGIR 2022.

ViGA: Video moment retrieval via Glance Annotation This is the official repository of the paper "Video Moment Retrieval from Text Queries via Single F

Ran Cui 38 Dec 31, 2022
A web-app helping to create strong passwords that are easy to remember.

This is a simple Web-App that demonstrates a method of creating strong passwords that are still easy to remember. It also provides time estimates how long it would take an attacker to crack a passwor

2 Jun 04, 2021
Recon is a script to perform a full recon on a target with the main tools to search for vulnerabilities.

👑 Recon 👑 The step of recognizing a target in both Bug Bounties and Pentest can be very time-consuming. Thinking about it, I decided to create my ow

Dirso 171 Dec 31, 2022
log4j2 dos exploit,CVE-2021-45105 exploit,Denial of Service poc

说明 about author: 我超怕的 blog: https://www.cnblogs.com/iAmSoScArEd/ github: https://github.com/iAmSOScArEd/ date: 2021-12-20 log4j2 dos exploit log4j2 do

3 Aug 13, 2022