Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

tidi

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tidi

A small dependency injection Python library

  • 0.3.0
  • PyPI
  • Socket score

Maintainers
1

Tidi

Test Package version Documentation Supported Python versions

A small dependency injection Python library.

Inspired by Kent Tong's disl and FastAPI's Depends.

Motivation

I found myself wanting to learn more about how dependency injection can be done in a pythonic way, with type-hinting, so had the itch to develop (yet another) library for it and share it as open source 🧑‍💻✌️

Read more about the motivation in this Medium article.

Primary API

The top level import of tidi provides everything needed it's primary intended use.

  • @tidi.inject - a decorator that will replace certain keyword arguments with dependencies, based on their type & if they haven't been passed in
  • tidi.Injected[DependencyClass] - a type alias, wrapping typing.Annotated, that indicates that a keyword argument should be injected
  • tidi.register(dependency_instance) - a function that registers an object to be available for injection as a dependency
  • tidi.Provider(get_dependency_function) - a wrapper class around a function that will be called to provide a dependency
  • tidi.UNSET - a sentinel object to indicate that a dependency should be loaded from the registry
  • tidi.field_factory(DependencyClass) - a helper function for injecting dependencies into dataclass fields

Example of use

Consider a micro-sized interactive CLI that lets a user choose a handbag then search through it,

# search-handbag.py

import tidi

from handbags import Handbag, HandbagItem, load_handbag


@tidi.inject
def dig_through_handbag(
    item_type: str,
    handbag: tidi.Injected[Handbag] = tidi.UNSET,
) -> HandbagItem | None:
    return handbag.get_items_by_type(item_type).first(default=None)


def init_handbag():
    selected_handbag = input("Select a handbag: ")
    tidi.register(load_handbag(selected_handbag))


def run_search():
    item_type = input("What are you looking for? ")
    # ⬇️ registered `Handbag` instance gets injected ✨
    item = dig_through_handbag(item_type)
    if item is None:
        print("Uh oh, can't find it 🤷‍♀️, try again")
        run_search()
    else:
        print(f"We're in luck! Here's your {item.name} 😎")


if __name__ == "__main__":
    init_handbag()
    run_search()

Running it looks something like this,

$ python search-handbag
Select a handbag: BCBGMAXAZRIA
What are you looking for? Nail file
Uh oh, can't find it 🤷‍♀️, try again
What are you looking for? Lip balm
We're in luck! Here's your Blistex 😎

We can see Dependency Injection happening hear to achieve Inversion of Control and obey the Law of Demeter.

  • dig_through_handbag isn't responsible for creating a Handbag and doesn't require its caller to know about it, rather a Handbag is injected ✨
  • init_handbag creates the Handbag, but doesn't need to return it. An example of separating the app initialisation from the main logic.
  • run_search doesn't need to know about anything that it doesn't use (in this case the Handbag), obeying the Law of Demeter.

When testing,

  • a mock Handbag could be passed in as a keyword argument to test dig_through_handbag, and
  • patching dig_through_handbag with a stub could be done to test run_search with no requirement for a mock Handbag.

More examples

You can find some executable examples in the demo/ directory of the repo.

Also see the Usage documentation for more examples.

Interested in contributing?

Feel free to create an issue or author a PR 😊

For the latter, check out the CONTRIBUTING guide for a quick start on development.

FAQs


Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc