# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['inseminator', 'inseminator.integrations']

package_data = \
{'': ['*']}

install_requires = \
['pydantic>=1.8.2,<2.0.0']

setup_kwargs = {
    'name': 'inseminator',
    'version': '0.4.7',
    'description': 'Python dependency injection library based on type hints',
    'long_description': "# Inseminator\n\n[![codecov](https://codecov.io/gh/sukovanej/container/branch/master/graph/badge.svg)](https://codecov.io/gh/sukovanej/container)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n\n*(definition from dictionary.com)*\n\n> a technician who introduces prepared ~semen~ **dependencies** into the ~genital tract \n> of breeding animals~ python classes, especially ~cows and mares~ pure classes with \n> proper IoC, for ~artificial insemination~ well coupled components and clear classes \n> signatures.\n\nPython library for type-based dependency injection. Write code without global state\nand noisy boilerplate. Inseminator is meant to be used in an entry-point layer of your\napplication and the only thing it requires is properly type-hinted classes \ndependencies.\n\n## Installation\n\nInstall using the pip tool.\n\n```\npip install inseminator\n```\n\n## Usage\n\nYou start by defining the *container* of your dependencies. Whenever you want the container\nto resolve a dependency, it uses the container to search for existing objects and a \nresolver automatically creates desired dependencies.\n\n```Python\nfrom inseminator import Container\n\n\nclass DomainModel:\n    def __init__(self):\n        self.__logic_constant = 1\n\n    def domain_logic(self, input_value: int) -> int:\n        return input_value + self.__logic_constant\n\n\nclass Controller:\n    def __init__(self, domain_model: DomainModel):\n        self.__domain_model = domain_model\n\n    def handler(self, input_value: int) -> int:\n        return self.__domain_model.domain_logic(input_value)\n\n\n# entry-point of your application\n\ncontainer = Container()\n\n# view layer handling\n\ncontroller = container.resolve(Controller)\nresult = controller.handler(1)\nprint(result)\n```\n\nThe strategy for resolving `Controller` is its constructor signature. The resolver works as follows.\n\n  1) We ask the `container` to resolve a dependency `Controller` -> `container.resolve(Controller)`.\n  2) Resolver inside the `container` checks the `Controller`'s constructor signature, i.e. **type hints**\n     of `__init__` method and sees `domain_models: DomainModel`.\n  3) If an instance of `DomainModel` class is already known by the `container` it uses that instance.\n     In the opposite case, the container starts the same resolving machinery for `DomainModel` - which\n     is the exact case we are facing now.\n  4) Because `DomainModel` doesn't have any dependencies it can construct it directly.\n  5) Now the resolver has all the dependencies for `Controller` constructor and can instantiate it.\n\nIf we programmed against an interface instead of implementation the example is modified like this.\n\n```Python\nfrom inseminator import Container\n\nfrom typing import Protocol\n\nclass DomainModel(Protocol):\n    def domain_logic(self, input_value: int) -> int:\n        ...\n\nclass Controller:\n    def __init__(self, domain_model: DomainModel):\n        self.__domain_model = domain_model\n\n    def handler(self, input_value: int) -> int:\n        return self.__domain_model.domain_logic(input_value)\n\n\n# domain model implementation\n\n\nclass ConcreteDomainModel:\n    def __init__(self):\n        self.__logic_constant = 1\n\n    def domain_logic(self, input_value: int) -> int:\n        return input_value + self.__logic_constant\n\n\n# entry point of your application\n\ncontainer = Container()\ncontainer.register(DomainModel, value=ConcreateDomainModel())\n\n# view layer handling\n\ncontroller = container.resolve(Controller)\nresult = controller.handler(1)\nprint(result)\n```\n\nIn this situation, protocol `DomainModel` doesn't hold implementation details, only interface.\nUsing \n\n```\ncontainer.register(DomainModel, value=ConcreateDomainModel())\n```\n\nwe're guiding the resolver to use instance of `ConcreateDomainModel` in case someone asks\nfor `DomainModel`.\n\n### Enforced parameters\n\nIf it is not desired to provide a single concrete implementation for abstract or protocol dependency\none can enforce the resolver to use concrete types for specified parameters. Simply call `container.resolve`\nalso with keywords and tell the resolve how it should resolve some particular parameters.\n\n```Python\ncontainer = Container()\ncontroller = container.resolve(Controller, domain_model=ConcreteDomainModel())\n```\n\nMoreover, using this approach `ConcreteDomainModel` is not evaluated and saved in the container but\nrather in a sub-container which exists only during the resolving. Therefore, if we want to create\nanother instance that depends on `DomainModel` we must either use `register` or again specify\nthe parameter during resolving.\n\n\n### Injecting functions\n\n\nIt might be convinient to specify funcion's dependencies in-place. The great example is Flask\nhandler function. It should live in the same layer the DI container lives because it provides\nonly infrastructure functionality and desirably the only thing it does it calling domain layer's\nfunctions. For this purpose, there is `injector` decorator on the `Container` object. You just\ntell which dependency to provide using `Depends` type constructor.\n\n\n```Python\nfrom inseminator import Container, Depends\n\n\nclass Dependency:\n    def __init__(self):\n        self.x = 1\n\n\ncontainer = Container()\n\n\n@container.inject\ndef my_handler(input_value: int, dependency: Dependency = Depends(Dependency)):\n    return input_value + dependency.x\n```\n\nUsed like that, `my_handler` takes a single argument and thanks to closure it has `dependency` \nprepared with the right instance of `Dependency`.\n\n\n```\n>>> my_handler(1)\n2\n```\n\n### Default parameter values\n\n\nWhen default parameters are specified the resolver uses them unless we override that value\nby enforced parameter.\n\n```python\ndef MyDependency:\n    def __init__(self, parameter: int = 1) -> None:\n        self.parameter = parameter\n\nmy_dependency = container.resolve(MyDependency)\nassert my_dependency.parameter == 1\n```\n\n\n## Docs\n\n - [Clean architecture introduction (draft version)](docs/introduction.md)\n",
    'author': 'Milan Suk',
    'author_email': 'Milansuk@email.cz',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://www.github.com/sukovanej/inseminator/',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.8,<4.0',
}


setup(**setup_kwargs)
