{ "info": { "author": "Mirko Rossini", "author_email": "mirko.rossini@ymail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 2 - Pre-Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Natural Language :: English", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5" ], "description": "=====\nzanna\n=====\n\n\n.. image:: https://img.shields.io/pypi/v/zanna.svg\n :target: https://pypi.python.org/pypi/zanna\n\n.. image:: https://img.shields.io/travis/MirkoRossini/zanna.svg\n :target: https://travis-ci.org/MirkoRossini/zanna\n\n.. image:: https://readthedocs.org/projects/zanna/badge/?version=latest\n :target: https://zanna.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n\n.. image:: https://pyup.io/repos/github/mirkorossini/zanna/shield.svg\n :target: https://pyup.io/repos/github/mirkorossini/zanna/\n :alt: Updates\n\n.. image:: https://pyup.io/repos/github/mirkorossini/zanna/python-3-shield.svg\n :target: https://pyup.io/repos/github/mirkorossini/zanna/\n :alt: Python 3\n\nSimple Dependency Injection library.\nSupports python 3.5+ and makes full use of the typing annotations.\nThe design is pythonic but inspired by Guice in many aspects.\n\n* Free software: BSD license\n* Documentation: https://zanna.readthedocs.io.\n\nMotivation\n==========\n\nZanna is meant to be a modern (3.5+), well maintained injection library for Python.\n\n\nFeatures\n========\n\n* Support for typing annotations\n* Decorators are not mandatory: all the injection logic can be outside your modules\n* Supports injection by name\n* Instances can be bound directly, useful when testing (i.e. by override bindings with mocks)\n* No autodiscover for performance reasons and to avoid running into annoying bugs\n\nUsage\n=====\n\nInjecting by variable name\n--------------------------\n\nThe basic form of injection is performed by variable name.\nThe injector expects a list of modules (any callable that takes a Binder as argument).\nYou can get the bound instance by calling get_instance\n\n.. code-block:: python\n\n from zanna import Injector, Binder\n\n def mymodule(binder: Binder) -> None:\n binder.bind_to(\"value\", 3)\n\n injector = Injector(mymodule)\n assert injector.get_instance(\"value\") == 3\n\nZanna will automatically inject the value into arguments with the same name:\n\n.. code-block:: python\n\n from zanna import Injector, Binder\n\n def mymodule(binder: Binder) -> None:\n binder.bind_to(\"value\", 3)\n\n class ValueConsumer:\n def __init__(self, value):\n self.value = value\n\n injector = Injector(mymodule)\n assert injector.get_instance(ValueConsumer).value == 3\n\n\nInjecting by type annotation\n----------------------------\n\nZanna also makes use of python typing annotations to find the right instance to inject.\n\n.. code-block:: python\n\n from zanna import Injector, Binder\n\n class ValueClass:\n def __init__(self, the_value: int):\n self.the_value = the_value\n\n class ValueConsumer:\n def __init__(self, value_class_instance: ValueClass):\n self.value_class_instance = value_class_instance\n\n def mymodule(binder: Binder) -> None:\n binder.bind_to(\"the_value\", 3)\n binder.bind(ValueClass)\n\n injector = Injector(mymodule)\n assert injector.get_instance(ValueConsumer).value_class_instance.the_value == 3\n\n\nSingleton or not singleton?\n---------------------------\n\nInstances provided by the injector are always singletons, meaning that the __init__ method of\nthe class will be called only the first time, and every subsequent call of get_instance will\nreturn the same instance:\n\n.. code-block:: python\n\n from zanna import Injector\n\n class MyClass:\n pass\n injector = Injector(lambda binder: binder.bind(MyClass))\n assert injector.get_instance(MyClass) == injector.get_instance(MyClass)\n\n\n\nUse providers for more complex use cases\n----------------------------------------\n\nBinder instances can be used to bind providers. A provider is any callable that takes\nany number of arguments and returns any type. The injector will try to inject all the necessary\narguments. Providers can be bound explicitely or implicitely (in which case zanna will use the\nreturn annotation to bind by type).\n\n.. code-block:: python\n\n from zanna import Injector, Binder\n\n class AValueConsumer:\n def __init__(self, value: int):\n self.value = value\n\n def explicit_provider(a_value: int) -> int:\n return a_value + 100\n\n def implicit_provider(value_plus_100: int) -> AValueConsumer:\n return AValueConsumer(value_plus_100)\n\n def mymodule(binder: Binder) -> None:\n binder.bind_to(\"a_value\", 3)\n binder.bind_provider(\"value_plus_100\", explicit_provider)\n binder.bind_provider(implicit_provider)\n\n injector = Injector(mymodule)\n assert injector.get_instance(AValueConsumer).value == 103\n\n\nOverride existing bindings\n--------------------------\n\nBindings can be overridden. Overriding a non-existent binding will result in a ValueError being raised.\n\nOverride bindings is extremely useful when testing, as any part of your stack can be replaced with a mock.\n\n\n.. code-block:: python\n\n from zanna import Injector, Binder\n from unittest.mock import MagicMock\n\n class ValueClass:\n def __init__(self):\n pass\n def retrieve_something(self):\n return ['some', 'thing']\n\n class ValueConsumer:\n def __init__(self, value: ValueClass):\n self.value = value\n\n\n def mymodule(binder: Binder) -> None:\n binder.bind(ValueClass)\n\n injector = Injector(mymodule)\n assert injector.get_instance(ValueConsumer).value.retrieve_something() == ['some', 'thing']\n\n def module_overriding_value_class(binder: Binder) -> None:\n mock_value_class = MagicMock(ValueClass)\n mock_value_class.retrieve_something.return_value = ['mock']\n binder.override_binding(ValueClass, mock_value_class)\n\n injector = Injector(mymodule, module_overriding_value_class)\n assert injector.get_instance(ValueConsumer).value.retrieve_something() == ['mock']\n\n\nUsing the decorators\n--------------------\n\nOne of the advantages of using Zanna over other solutions is that it doesn't force you\nto pollute your code by mixing in the injection logic.\n\nIf you are working on a small project and would like to handle part (or all) of the\ninjection logic using decorators instead of modules, Zanna supports that as well.\n\nInternally, Zanna creates a module that sets up the bindings as indicated by the decorators\n(in a random order).\n\nAll Injectors initialized with use_decorators=True will run that module first on their Binder.\n\nZanna supports the following decorators:\n\n* decorators.provider, which takes a provided annotated with an appropriate return type\n* decorators.provider_for, which can be given the name or the class of the instance provided\n* decorators.inject, to annotate class to be bound/injected\n\nHere's an example:\n\n.. code-block:: python\n\n from zanna import Injector\n from zanna import decorators\n class Thing:\n pass\n\n @decorators.provider_for(\"value\")\n def provide_value():\n return 3\n\n @decorators.provider\n def provide_thing() -> Thing:\n return Thing()\n\n\n @decorators.inject\n class OtherThing:\n def __init__(self, value, thing:Thing):\n self.value = value\n self.thing = thing\n\n inj = Injector(use_decorators=True)\n otherthing = inj.get_instance(OtherThing)\n assert otherthing.value == 3\n assert isinstance(otherthing.thing, Thing)\n assert isinstance(otherthing, OtherThing)\n\n\nCredits\n-------\n\nThis package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.\n\n.. _Cookiecutter: https://github.com/audreyr/cookiecutter\n.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage\n\n\n\n=======\nHistory\n=======\n\n* 0.1.0 (2016-10-13)\n* 0.3.1 (2017-01-21)", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/MirkoRossini/zanna", "keywords": "zanna", "license": "BSD license", "maintainer": "", "maintainer_email": "", "name": "zanna", "package_url": "https://pypi.org/project/zanna/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/zanna/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/MirkoRossini/zanna" }, "release_url": "https://pypi.org/project/zanna/0.3.1/", "requires_dist": null, "requires_python": "", "summary": "Simple Dependency Injection library", "version": "0.3.1" }, "last_serial": 2589470, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "95e63ef7449a4e80a107c757285a13e6", "sha256": "83f65c2da525fb5ca48f7efd60d9496dae98a5314e98c2d2b92247bd32abb333" }, "downloads": -1, "filename": "zanna-0.1.0.tar.gz", "has_sig": false, "md5_digest": "95e63ef7449a4e80a107c757285a13e6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14139, "upload_time": "2017-01-21T15:06:30", "url": "https://files.pythonhosted.org/packages/df/08/33b8386ed1f39a41b83719cf5a189c69f2582c204726cf728427496b053b/zanna-0.1.0.tar.gz" } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "55ae31f2e51235cebc8b5226415b8892", "sha256": "64fc9e826c76280865060aa2094fa77f01a5395ad8f258cbab73cd4007118a6f" }, "downloads": -1, "filename": "zanna-0.3.1.tar.gz", "has_sig": false, "md5_digest": "55ae31f2e51235cebc8b5226415b8892", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14153, "upload_time": "2017-01-21T15:35:04", "url": "https://files.pythonhosted.org/packages/ef/91/8fd80fd2b73c7ddf66b27c6d68316037dfe805cafab712631a2dcf31d469/zanna-0.3.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "55ae31f2e51235cebc8b5226415b8892", "sha256": "64fc9e826c76280865060aa2094fa77f01a5395ad8f258cbab73cd4007118a6f" }, "downloads": -1, "filename": "zanna-0.3.1.tar.gz", "has_sig": false, "md5_digest": "55ae31f2e51235cebc8b5226415b8892", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14153, "upload_time": "2017-01-21T15:35:04", "url": "https://files.pythonhosted.org/packages/ef/91/8fd80fd2b73c7ddf66b27c6d68316037dfe805cafab712631a2dcf31d469/zanna-0.3.1.tar.gz" } ] }