Skip to main content

type_dep

type_dep is a dependency injection framework that uses type hints to inject dependencies (much like Angular, Dotnet and the like)

Quick Start

  • Install the package
pip install type_dep
  • Inherit from the package's Dependency class to create an injectable dependency class.
  • Use the dependencyinjected decorator to tag functions or methods that require dependency injection through their parameter type annotations.
import os
from type_dep import Dependency, dependencyinjected, Context

counter = 0


class A(Dependency):
    def __init__(self, name: str):
        self.name = name

    @classmethod
    def instantiate(cls):
        global counter
        counter += 1
        return A(f"{counter}")


class B(Dependency):

    def __init__(self, sex: str):
        self.sex = sex

    @classmethod
    def instantiate(cls):
        return B(os.environ.get("SEX", "female"))

    @dependencyinjected
    def get_detail(self, a: A):
        """
        A method which uses dependency injection
        `a` will be instantiated and injected into this method at runtime.
        By default, these dependencies are stored in a global context.
        Subsequent method calls will use the instances of the dependencies that were
        instantiated on the first run.

        NOTE: The type hints on the parameters are a must
        """
        return {"name": a.name, "sex": self.sex}

    @dependencyinjected
    def scoped_get_detail(self, a: A, context: Context):
        """
        When a `Context` argument is passed,
        the dependencies are stored in a context that gets destroyed after every method call.
        NOTE: The type hints on the parameters are a must
        """
        return {"name": a.name, "sex": self.sex}


@dependencyinjected
def run(males: int, females: int, a: A, greeting: str, b: B):
    """
    Just some function that is dependency injected.
    `a` and `b` will be instantiated and injected into the function at runtime

    By default, these dependencies are stored in a global context.
    Subsequent method calls will use the instances of the dependencies that were
    instantiated on the first run.

    NOTE: The type hints on the parameters are a must
    """
    print(f"males: {males}, females: {females}, greeting: {greeting}, a.name: {a.name}, b.sex: {b.sex}")
    print(f'{b.get_detail()}\n')


@dependencyinjected
def scoped_run(males: int, females: int, a: A, greeting: str, b: B, context: Context):
    """
    Just some function that is dependency injected.
    `a` and `b` will be instantiated and injected into the function at runtime

    When a `Context` argument is passed,
    the dependencies are stored in a context that gets destroyed after every function call.

    NOTE: The type hints on the parameters are a must
    """
    print(f"scoped: males: {males}, females: {females}, greeting: {greeting}, a.name: {a.name}, b.sex: {b.sex}")
    print(f'scoped: {b.scoped_get_detail()}\n')


if __name__ == '__main__':
    counter = 0

    for _ in range(3):
        run(6, 56, greeting="hey")

    # males: 6, females: 56, greeting: hey, a.name: 1, b.sex: female
    # {'name': '2', 'sex': 'female'}
    # 
    # males: 6, females: 56, greeting: hey, a.name: 1, b.sex: female
    # {'name': '2', 'sex': 'female'}
    # 
    # males: 6, females: 56, greeting: hey, a.name: 1, b.sex: female
    # {'name': '2', 'sex': 'female'}

    for _ in range(3):
        scoped_run(6, 56, greeting="hey")

        # scoped: males: 6, females: 56, greeting: hey, a.name: 3, b.sex: female
    # scoped: {'name': '4', 'sex': 'female'}
    # 
    # scoped: males: 6, females: 56, greeting: hey, a.name: 5, b.sex: female
    # scoped: {'name': '6', 'sex': 'female'}
    # 
    # scoped: males: 6, females: 56, greeting: hey, a.name: 7, b.sex: female
    # scoped: {'name': '8', 'sex': 'female'}

Why use type hints

Python type hints have matured alot. It is high time we used them to the maximum. Apart from helping us avoid some logical errors, wouldn't be nice if type hints helped inject dependencies.

  • Very little extra code is needed if you are already using types
  • It is intuitive

How to test

  • Clone the repository
git clone git@github.com:sopherapps/type_dep.git
cd type_dep
  • Create and activate the virtual environment
python3 -m venv env
source env/bin/activate
  • Run the test command
python -m unittest

License

Copyright (c) 2022 Martin Ahindura Licensed under the MIT License

Metadata

Release files for type-dep 0.0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for type-dep 0.0.2
File Size Uploaded Provenance
type_dep-0.0.2.tar.gz 5.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for type-dep 0.0.2
File Interpreter ABI Platform
type_dep-0.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 10.9 kB

Release files / type_dep-0.0.2.tar.gz

Download URL type_dep-0.0.2.tar.gz
Size 5.7 kB
Tags Source
SHA-256 checksum
How to use checksums
dc05b01db7268bd90395c99b6b427b80efd6a86e8817000ac98a9f05b83787e1
BLAKE2b-256 checksum
How to use checksums
078fa8fa6e8e62e1dac7ce841be296d97c84c401518ff510c5339e2eae80888d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.0 CPython/3.9.17

Release files / type_dep-0.0.2-py3-none-any.whl

Download URL type_dep-0.0.2-py3-none-any.whl
Size 5.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b0bf9b4cd77bad882e94c374957b5c626c8f4e76d38d2220540f9ee8ab45c826
BLAKE2b-256 checksum
How to use checksums
7933d975301c4a4385b8c5a86569b12ba9fff24d45d272406a8903b044903c43
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.0 CPython/3.9.17

Security for type-dep 0.0.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.0.2 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page