Skip to main content

DI framework

Project description

thinking-injection

CI PyPI version codecov

Part of thinking family.

Pythonic DI for AI, as funny as it sounds.

Requires python 3.12. Is properly typed.

Better docs pending. For now, see "long story short" and an example

Long story short

  • put your code in a root package (let's call it root) with any number and depth of subpackages
  • mark the types that should be picked up by framework with @discover
    • from thinking_injection.discovery import discover
  • mark your protocols and ABCs with @interface
    • from thinking_injection.interfaces import interface
  • make the classes that should be managed extend Injectable
    • in Java you'd call these "beans", but I wanted to avoid that kind of copycating
    • from thinking_injection.injectable import Injectable
  • implement inject_requirements(self, ...) and make sure to annotate the arguments
    • class X(Injectable): def inject_requirements(self, a: A, b: list[B], c: C | None: ...
    • in that case, instance of X will be created for you, and that method will be called with auto-created instances of A, list of all known instances of B and instance of C if there is one
    • A is a SIMPLE dependency, B - a COLLECTIVE one, C - an optional one
    • there is a notion of primary implementation, which works as you'd expect it (the type itself for non-interface types, the subclass if there is only one subclass, but you can also force one, e.g. with decorator)
      • see 'Implementations.build(...)'
      • from thinking_injection.discovery import PrimaryImplementation - use @PrimaryImplementation(Supertype) on the subtype
    • simple dependencies will use the primary implementation
    • optional dependencies can be phrased any way you like: C | None, Optional[C] or Union[C, None], etc
      • if there is no primary implementation, None will be injected, even if there are multiple implementations
    • collective dependencies can only be phrased as lists of supertype (interface or not)
    • framework will only call that method for you with proper args, you should store them in self on your own - or act on them in any way you'd like
  • make a ContextScope using of factory method:
    • from thinking_injection.scope import ContextScope
    • ContextScope.of(*from_package("root"))
    • more readable factory methods pending
    • generally, it's ContextScope.of(Type1, Type2, ...)
    • you can also define which implementations should be primary with defaults and forced kw-only args
      • todo document this

    • there is also from_module("root.some.submodule") function, as well as types(Type1, Type2, ...)
    • see thinking_injection.typeset

The entrypoint to your program should boil down to:

if __name__=="__main__":
    scope = ContextScope.of(...)
    ctx = BasicContext.build(scope)
    with ctx.lifecycle():
        instance = ctx.instance(SomeType)
        instance.foo(...)

An example

There is an example app in this repo. It's short, but showcases most of the basic features.

See the ./calculator directory.

Local development

There are 2 useful scripts in this repo. They both work based on ./thinking-dependencies.txt file, which lists other thinking projects used by this one.

  • install_develop.sh
    • will install all the thinking dependencies from their develop branches
  • ./install_local_thinking.sh
    • aligned to my personal layout of home directory
    • assumes you clone repositories to ~/repos
    • expects all the thinking dependencies to be cloned there
    • will create venv for you if missing or use an existing one
    • will remove currently installed thinking dependencies
    • and will install them again from the cloned repos
    • useful when you're making complimentary changes across repos

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

thinking_injection-0.0.1.tar.gz (16.7 kB view details)

Uploaded Source

Built Distribution

thinking_injection-0.0.1-py3-none-any.whl (19.6 kB view details)

Uploaded Python 3

File details

Details for the file thinking_injection-0.0.1.tar.gz.

File metadata

  • Download URL: thinking_injection-0.0.1.tar.gz
  • Upload date:
  • Size: 16.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.5

File hashes

Hashes for thinking_injection-0.0.1.tar.gz
Algorithm Hash digest
SHA256 b54864f6e155c9541c8ca3085dfa4ab9587dd0880fc6e685896c11b1e58519de
MD5 8493f38d21fc665caf3f3eb5ecffbf4f
BLAKE2b-256 e24a245bb1a49d96afcde5f10ffdb45df7558e9b19d25cb0da7bc40f2f40533a

See more details on using hashes here.

File details

Details for the file thinking_injection-0.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for thinking_injection-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0de444a031ec1d399b766da9f863244275633394397c0df299c57cb3aeb23cc2
MD5 5b970817079329500fa9001b52f11d6d
BLAKE2b-256 68fef82fef969e7d7ab3cacc6ae0ca7a43f2ad0bec77fdcf5b7f4fdc352029d1

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page