Metadata-Version: 2.1
Name: punq
Version: 0.5
Summary: Unintrusive dependency injection for Python 3.6 +
Home-page: http://github.com/bobthemighty/punq
Author: Bob Gregory
Author-email: bob@codefiend.co.uk
License: MIT
Platform: any
Classifier: Programming Language :: Python
Classifier: Development Status :: 3 - Alpha
Classifier: Natural Language :: English
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
License-File: LICENSE

Punq
====

.. image:: https://travis-ci.org/bobthemighty/punq.svg?branch=master
      :target: https://travis-ci.org/bobthemighty/punq

.. image:: https://img.shields.io/codecov/c/github/bobthemighty/punq.svg?style=flat
      :target: https://codecov.io/gh/bobthemighty/punq

.. image:: https://readthedocs.org/projects/punq/badge/?version=latest
      :target: https://punq.readthedocs.io/en/latest/?badge=latest
      :alt: Documentation Status

An unintrusive library for dependency injection in modern Python.
Inspired by `Funq`_, Punq is a dependency injection library you can understand.

- No global state
- No decorators
- No weird syntax applied to arguments
- Small and simple code base with 100% test coverage and developer-friendly comments.

Installation
------------

Punq is available on the `cheese shop`_.

.. code:: bash

    pip install punq

Documentation is available on `Read the docs`_.

Quick Start
-----------

Punq avoids global state, so you must explicitly create a container in the entrypoint of your application:

.. code:: python

   import punq
    
   container = punq.Container()

Once you have a container, you can register your application's dependencies. In the simplest case, we can register any arbitrary object with some key:

.. code:: python

   container.register("connection_string", "postgresql://...")

We can then request that object back from the container:

.. code:: python

   conn_str = container.resolve("connection_string")

Usually, though, we want to register some object that implements a useful service.:

.. code:: python

   class ConfigReader:
      def get_config(self):
         pass
 
   class EnvironmentConfigReader(ConfigReader):
      def get_config(self):
         return {
            "logging": {
               "level": os.env.get("LOGGING_LEVEL", "debug")
            }
            "greeting": os.env.get("GREETING", "Hello world")
         }

   container.register(ConfigReader, EnvironmentConfigReader)

Now we can `resolve` the `ConfigReader` service, and receive a concrete implementation:

.. code:: python

   config = container.resolve(ConfigReader).get_config()

If our application's dependencies have their *own* dependencies, Punq will inject those, too:

.. code:: python

   class Greeter:
      def greet(self):
         pass


   class ConsoleGreeter:
      def __init__(self, config_reader: ConfigReader):
         self.config = config_reader.get_config()

      def greet(self):
         print(self.config['greeting'])


   container.register(Greeter)
   container.resolve(Greeter).greet()
         
If you just want to resolve an object without having any base class, that's okay:

.. code:: python

   class Greeter:
      def __init__(self, config_reader: ConfigReader):
         self.config = config_reader.get_config()

      def greet(self):
         print(self.config['greeting'])

   container.register(Greeter)
   container.resolve(Greeter).greet()
         
And if you need to have a singleton object for some reason, we can tell punq to register a specific instance of an object:

.. code:: python

   class FileWritingGreeter:
      def __init__(self, path, greeting):
         self.path = path
         self.message = greeting
         self.file = open(self.path, 'w')

      def greet(self):
         self.file.write(self.message)


   one_true_greeter = FileWritingGreeter("/tmp/greetings", "Hello world")
   container.register(Greeter, instance=one_true_greeter)


You might not know all of your arguments at registration time, but you can provide them later:

.. code:: python

   container.register(Greeter, FileWritingGreeter)
   greeter = container.resolve(Greeter, path="/tmp/foo", greeting="Hello world")

Conversely, you might want to provide arguments at registration time, without adding them to the container:

.. code:: python

   container.register(Greeter, FileWritingGreeter, path="/tmp/foo", greeting="Hello world")
   
Fuller documentation is available on `Read the docs`_.

.. _cheese shop: https://pypi.org/project/punq/
.. _Read the docs: http://punq.readthedocs.io/en/latest/ 
.. _Funq: https://github.com/jlyonsmith/Funq

Changelog
=========

`0.4.1`_ 2020-02-01
-------------------
    The container now includes itself as a dependency. This makes some funky
    use-cases simple to implement, eg. dynamic dispatch to multiple
    implementations.

`0.4.0`_ 2020-02-01
-------------------
    Punq now supports registering implementations as singleton. Singleton
    instances are cached per-container, and instantiation is lazy, ie. we defer
    creation until we first resolve the service.
    Hat tip to `jbcpollak`_

`0.3.0`_ 2019-07-13
-------------------
Fixes
    Punq only passes required arguments to nested dependencies. Previously, we would pass
    all the arguments in our context as kwargs, which caused unintuitive failures if constructors
    weren't expecting them.
    Fixed by `Thielen B`_

`0.2.1`_ 2019-05-22
-------------------
Fixes
    Punq will now prefer to use a provided resolution argument instead of creating it anew.

`0.2.0`_ 2019-02-12
-------------------
Fixes
    Added handling for typing.ForwardRef

Breaking Changes
    Added explicit `instance` kwarg to `register` which replaces the previous behaviour where
    `container.register(Service, someInstance)` would register a concrete instance.
    This fixes https://github.com/bobthemighty/punq/issues/6

0.1.2-alpha 2019-02-11
----------------------
Feature
    First automatic Travis deploy

0.0.1
-----
    Basic resolution and registration works
    Punq is almost certainly slow as a dog, non thread-safe, and prone to weird behaviour in the edge cases.

.. _0.2.0: https://github.com/bobthemighty/punq/compare/v0.1.2-alpha...v0.2
.. _0.2.1: https://github.com/bobthemighty/punq/compare/v0.2...v0.2.1
.. _0.3.0: https://github.com/bobthemighty/punq/compare/v0.2.1...v0.3.0
.. _0.4.0: https://github.com/bobthemighty/punq/compare/v0.3.0...v0.4.0
.. _0.4.1: https://github.com/bobthemighty/punq/compare/v0.4.0...v0.4.1
.. _Thielen B: https://github.com/FourSpotProject
.. _jbcpollak: https://github.com/jbcpollak


