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
Proof on Concept Exploit for CVE-2021-38647 (OMIGOD)

OMIGOD Proof on Concept Exploit for CVE-2021-38647 (OMIGOD) For background information and context, read the our blog post detailing this vulnerabilit

Horizon 3 AI Inc 231 Nov 12, 2022
Cloud One Container Security Runtime Events Forwarder

Example on how to query events by a RESTful API, compose CEF event format and send the events to an UDP receiver.

Markus Winkler 3 Feb 10, 2022
open detection and scanning tool for discovering and fuzzing for Log4J RCE CVE-2021-44228 vulnerability

CVE-2021-44228-log4jVulnScanner-metasploit open detection and scanning tool for discovering and fuzzing for Log4J RCE CVE-2021-44228 vulnerability pre

Taroballz 7 Nov 09, 2022
A python module for retrieving and parsing WHOIS data

pythonwhois A WHOIS retrieval and parsing library for Python. Dependencies None! All you need is the Python standard library. Instructions The manual

Sven Slootweg 384 Dec 23, 2022
Password list generator for password spraying - prebaked with goodies

Generates permutations of Months, Seasons, Years, Sports Teams (NFL, NBA, MLB, NHL), Sports Scores, "Password", and even Iterable Keyspaces of a specified size.

Casey Erdmann 65 Dec 22, 2022
This respository contains the source code of the printjack and phonejack attacks.

Printjack-Phonejack This repository contains the source code of the printjack and phonejack attacks. The Printjack directory contains the script to ca

pietrobiondi 2 Feb 12, 2022
A malware to encrypt all the .txt and .jpg files in target computer using RSA algorithms

A malware to encrypt all the .txt and .jpg files in target computer using RSA algorithms. Change the Blackgound image of targets' computer. and decrypt the targets' encrypted files in our own compute

Li Ka Lok 2 Dec 02, 2022
Sudo Baron Samedit Exploit

CVE-2021-3156 (Sudo Baron Samedit) This repository is CVE-2021-3156 exploit targeting Linux x64. For writeup, please visit https://datafarm-cybersecur

Worawit Wang 559 Jan 03, 2023
Tool to decrypt iOS apps using r2frida

r2flutch Yet another tool to decrypt iOS apps using r2frida. Requirements It requires to install Frida on the Jailbroken iOS device: Jailbroken device

Murphy 146 Jan 03, 2023
Web-eyes - OSINT tools for website research

WEB-EYES V1.0 web-eyes: OSINT tools for website research, 14 research methods ar

8 Nov 10, 2022
Visibility and Mitigation for Log4J vulnerabilities

Visibility and Mitigation for Log4J vulnerabilities Several scripts for the visibility and mitigation of Log4J vulnerabilities. Static Scanner - Linux

SentinelLabs 15 May 21, 2022
Script checks provided domains for log4j vulnerability

log4j Script checks provided domains for log4j vulnerability. A token is created with canarytokens.org and passed as header at request for a single do

Matthias Nehls 2 Dec 12, 2021
Password Manager is a simple Python project which helps users in managing their passwords in a easier way

Password Manager is a simple Python project which helps users in managing their passwords in a easier way

Manish Jalui 4 Sep 29, 2021
Proof of concept for CVE-2021-31166, a remote HTTP.sys use-after-free triggered remotely.

CVE-2021-31166: HTTP Protocol Stack Remote Code Execution Vulnerability This is a proof of concept for CVE-2021-31166 ("HTTP Protocol Stack Remote Cod

Axel Souchet 820 Dec 18, 2022
Repo for The Crown: Exploratory Analysis of Nim Malware DEF CON 615 talk

Repo for "The Crown: Exploratory Analysis of Nim Malware" DEF CON 615 talk

HuskyHacks 43 Dec 03, 2022
Local File Inclusion Scanner and Exploiter

LFI-Paradise Local File Inclusion Scanner and Exploiter Features 1- Scanner 2- E

11 Sep 04, 2022
Scarecrow is a tool written in Python3 allowing you to protect your Python3 scripts.

🕷️ Scarecrow 🕷️ Scarecrow is a tool written in Python3 allowing you to protect your Python3 scripts. It looks for processes with specific names to v

Billy 33 Sep 28, 2022
阿里云accesskey利用工具

aliyun-accesskey-Tools 此工具用于查询ALIYUN_ACCESSKEY的主机,并且远程执行命令。 对于ALIYUN_ACCESSKEY利用方式可参考文章:记一次阿里云主机泄露Access Key到Getshell 工具截图 安装模块 pip install -r require

一灯老和尚 826 Jan 01, 2023
A fully automated, accurate, and extensive scanner for finding vulnerable log4j hosts

log4j-scan A fully automated, accurate, and extensive scanner for finding vulnerable log4j hosts Features Support for lists of URLs. Fuzzing for more

Duc Linh Nguyen 4 Aug 08, 2022
A python script to decrypt media files encrypted using the Android application 'Decrypting 'LOCKED Secret Calculator Vault''. Will identify PIN / pattern.

A python script to decrypt media files encrypted using the Android application 'Decrypting 'LOCKED Secret Calculator Vault''. Will identify PIN / pattern.

3 Sep 26, 2022