{ "info": { "author": "Jens Blawatt", "author_email": "jblawatt@googlemail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Topic :: Utilities" ], "description": "Python Simple DI\n================\n\n.. image:: https://travis-ci.org/jblawatt/python-simple-di.svg?branch=master\n.. image:: https://img.shields.io/pypi/v/python-simple-di.svg\n\n\n*python-simple-di* is a simple dependency injection container implementation. With its help you can create instances and its dependencies on runtime.\n\n\n.. contents::\n\n\nChanges\n-------\n\n1.7.0\n_____\n- Loosely coupled `inject` and `inject_many` decorator. (WARNING: `inject_many` uses `resolve_many` that makes use of the unsorted `items` dict-method. So there is no garanty that the first instance is the first registered instance.)\n- `resolve` also accepts a type as parameter `name` and will return the first instance subclassing that type (first result of `resolve_many`). (WARNING: `resolve_many` that makes use of the unsorted `items` dict-method. So there is no garanty that the first instance is the first registered instance.)\n\n1.6.0\n_____\n- **resolve many**: the new methods `resolve_many` and `resolve_many_lazy` gives you the possibility to resolve multiple objects depending on their class.\n- **alias names**: you can provide a list of alias names within the object configuration.\n- **constructor/factory (kw)argument overridies**: resolve methods noch accepts args and kwargs that will can be used instead of args configurations.\n- **register decorator**: :code:`register` can be used as decorator now.\n- **use as contextmanager**: the container can be used as context manager to temporarily override settings in :code:`with` block.\n- **mixin support**: new options :code:`mixins` can container a list or a type of types that will be used to create the new type.\n\n1.5.2\n_____\n- copy settings in DIContainer.__init__.\n\n\nInstall\n-------\n\nYou can install it via pip: ::\n\n\tpip install python-simple-di\n\nor via easy_install: ::\n\n\teasy_install -U python-simple-di\n\n\nConfiguration\n-------------\n\nTo configure the ``di.DIContainer`` you need to pass a dict with the needed configuration in it. Alternativly you can use an instance of ``di.DIConfig`` which is used internal anyway.\nDefine the objects name as *key* to access it at runtime. The *value* needs to be the configuration to create the instance.\n\n- **type** *(required)*: This option defines the type with its complete python dotted path or the python type instance. You can add a path that will dynamicly become added to the ``sys.path`` if the instance is requested. *Examples:*\n\n.. code-block:: python\n\n\t'type': 'path.to.my.Type'\n\t'type': path.to.my.Type\n\t# or\n\t'type': '/add/to/sys/path:add.to.sys.path.Type'\n\n- **args** *(optional)*: The args can either be a ``list`` of values to pass as Arguments or a ``dict`` to pass as Keyword Arguments. To mix both, you can define a dictionary with an empty string or None as key and a list as value. *Examples:*\n\n.. code:: python\n\n\t'args': ['first', 3, 'third']\n\t# or\n\t'args': {'one': '1', 'two':'two'}\n\t# or\n\t'args': {'': [1, 'two'], 'three': 3}\n\n- **lazy** *(optional)*: This option defines whether the instance will be created on runtime or on container initialization. *Example:*\n\n.. code:: python\n\n\t'lazy': False # default: True\n\n- **singleton** *(optional, default: True)*: If this option is set to ``True``, the created instance will be saved inside the container. Next time the same instance will be returned. If this value is set to ``False`` a new instance will be created every time.\n\n- **properties** *(optional)*: This option is similar to the ``args`` option. After an instance was created a buildup is called. This buildup fills the given properties with the given values in this dictionary. *Examples:*\n\n.. code-block:: python\n\n\t{\n\t\t'type': 'some.Person',\n\t\t'propeties': {\n\t\t\t'first_name': 'John',\n\t\t\t'last_name': 'Doe'\n\t\t}\n\t}\n\n- **assert_type** *(optional)*: Checks weather the created type has the given base_type.\n\n.. code:: python\n\n\t'type': 'path.to.implementet.Type',\n\t'assert_type': 'path.to.parent.Type'\n\n- **factory_method** *(optional)*: This options can be used to create an instance by a classmethod which creates the wanted instance. For example this can be used to create a class based views in django at runtime. *Example:*\n\n.. code:: python\n\n\t'type': 'myapp.views.ClassBasedView',\n\t'factory_method': 'as_view'\n\n- **mixins** *(optional)*: This options allows you to mix the given types into the configured type to create complete new type.\n\n\nArgument Resolvers\n__________________\n\nWith the help of the resolver the magic comes into play. Thanks to this small classes it is possible to trigger the dependencies of a type at runtime.\n\nThe following resolver be brought by the default package. Individual resolver can be implemented by extending the base class ``di.Resolver``.\n\nReferenceResolver\n.................\nThe ReferenceResolver offers the possibility to an attribute within the python path to refer. This must be the path and the object, as a Python dotted path.\n\n*Example:*\n\n.. code:: python\n\n\t{\n\t\t'args': {\n\t\t\t'output_stream': ReferenceResolver('sys.stdout')\n\t\t}\n\t}\n\n`di` also provides some shortcuts for this name:\n\n- ``di.ref('sys.stdout')`` as shortcut for type.\n- ``di.reference('sys.stdout')`` as shortcut for the type.\n- ``'ref:sys.stdout'`` as prefix of the configured type to lazy use the resolver.\n\nRelationResolver\n................\nThe RelationResolver allows the resolution of an object of this container at runtime.\n\n*Example:*\n\n.. code:: python\n\n\t{\n\t\t'object_a': {\n\t\t\t'type': 'some.ClassName'\n\t\t},\n\t\t'object_b': {\n\t\t\t'type': 'some.other.ClassName',\n\t\t\t'args': [\n\t\t\t\tRelationResolver('object_a')\n\t\t\t]\n\t\t},\n\t}\n\n\n`di` also provides some shortcuts for this name:\n\n- ``di.rel('object_a')`` as shortcut for type.\n- ``di.relation('object_a')`` as shortcut for the type.\n- ``'rel:object_a'`` as prefix of the configured type to lazy use the resolver.\n\nModuleResover\n.............\n\nSometimes it may be necessary to pass an entire module as a parameter. For this purpose the ModuleResolver available.\n\n*Example:*\n\n.. code:: python\n\n\t{\n\t\t'type': 'some.ClassName',\n\t\t'args': {\n\t\t\t'serializer': ModuleResolver('json')\n\t\t}\n\t}\n\n\nDi also provides some shortcuts for this name.\n\n- ``di.mod('json')`` as shortcut for type.\n- ``di.module('json')`` as shortcut for the type.\n- ``'mod:json'`` as prefix of the configured type to lazy use the resolver.\n\n\nFactoryResolver\n...............\n\nWith the help of FactoryResolver the return value of a function as an argument can be passed to the specified type.\n\n*Example.*\n\n.. code:: python\n\n\t{\n\t\t'type': 'some.ClassName',\n\t\t'args': [\n\t\t\tFactoryResolver('path.to.the.factory_method')\n\t\t]\n\t}\n\nDi also provides some shortcuts for this name.\n\n- ``di.fac('path.to.the.factory_method')`` as shortcut for type.\n- ``di.factory('path.to.the.factory_method')`` as shortcut for the type.\n- ``'factory:path.to.the.factory_method'`` as prefix of the configured type to lazy use the resolver.\n\n\nAttributeResolver\n.................\n\nWith the Resolver an attribute of an instance can be passed as an argument. This can be very useful if you are using the django web framework and want to pass a settings value as an argument fo an instance.\n\n*Example:*\n\n.. code:: python\n\n\t{\n\t\t'type': 'some.ClassName':\n\t\t'args': {\n\t\t\t'debug': AttributeResolver('django.conf.settings.DEBUG')\n\t\t}\n\t}\n\n\nDi also provides some shortcuts for this name.\n\n- ``di.attr('django.conf.settings.DEBUG')`` as shortcut for type.\n- ``di.attribute('django.conf.settings.DEBUG')`` as shortcut for the type.\n- ``'attr:django.conf.settings.DEBUG'`` as prefix of the configured type to lazy use the resolver.\n\n\nEvents\n______\n\nYou can pass an EventDispatcher into the DiContainer. This Dispatcher will be called if anything interesting happens inside the Container. BaseType is ``di.DIEventDispatcher``.\n\n\nUsage\n.....\n\nSimply create a dictionary with your type configuration and pass it as settings argument to the ``DIContainer``. The Dictionarys key is the type key to resolve the instance.\n\n.. code:: python\n\n\t# create the container\n\tcontainer = DIContainer(config)\n\n\t# resolve the instance\n\tinstance = container.resolve('instance_key')\n\n\t# resolve the instance type only\n\ttype_of_instance_key = container.resolve_type('instance_key')\n\n\nResolve Lazy\n____________\n\nSometimes it may be necessary to create an instance at its first useage. So there are the following two messages, that returns a ``di.Proxy`` instance at first.\n\nTo use this Feature you need to provide a ``proxy_type_name`` and install the specific package for this. I recommend ``lazy-object-proxy`` with its type ``Proxy``. Which is the default value for this argument. It is not shipped with this package because of the many different other implementations and thier different licence.\nIf you use this in combination with django you can use ``django.utils.functional.SimpleLazyObject``. **But at this moment the ``resolve_type_lazy`` is not working properly with ``SimpleLazyObject``**.\n\n.. code:: python\n\n\t# create the container\n\tcontainer = DIContainer(config, proxy_type_name='lazy_object_proxy.Proxy')\n\n\t# lazy resolves the instance\n\tinstance = container.resolve_lazy('instance_key')\n\n\t# lazy resolves the instance type only\n\ttype_of_instance_key = container.resolve_type_lazy('instance_key')\n\n\nChild Container\n_______________\n\nIf you need the same container but override some settings you can create a child container and pass the deviant settings into it.\n\nThis is the unittest that explains this function at its best.\n\n.. code:: python\n\n\tcontainer = DIContainer({\n\t\t'one': {\n\t\t\t'type': 'mock.Mock',\n\t\t\t'properties': {\n\t\t\t\t'source': 'parent'\n\t\t\t}\n\t\t},\n\t\t'two': {\n\t\t\t'type': 'mock.Mock',\n\t\t\t'properties': {\n\t\t\t\t'source': 'parent'\n\t\t\t}\n\t\t}\n\t})\n\n\tself.assertEqual(container.one.source, 'parent')\n\tself.assertEqual(container.two.source, 'parent')\n\n\tchild_container = container.create_child_container({\n\t\t'two': {\n\t\t\t'type': 'mock.Mock',\n\t\t\t'properties': {\n\t\t\t\t'source': 'child'\n\t\t\t}\n\t\t}\n\t})\n\n\tself.assertEqual(child_container.one.source, 'parent')\n\tself.assertEqual(child_container.two.source, 'child')\n\tself.assertEqual(container.one.source, 'parent')\n\tself.assertEqual(container.two.source, 'parent')\n\n\nDecorators\n__________\nSome method of the ``di.DIContainer`` can be used as decorator zu register or inject instances within your code.\n\nRegister by decorator\n......................\nThe method `register` can be used as decorator for classes or factory methods. With this\nyou do not need to provide the instances configuration at container creation.\n\nPassing the settings is optional.\n\n.. code:: python\n\n\t@container.register(\"my_service\", dict(args={'init_arg': 'test'}))\n\tclass MyService(object):\n\n\t\tdef __init__(self, init_arg):\n\t\t\tself.init_arg = init_arg\n\n\t\tdef get_data(self, args):\n\t\t\tpass\n\n\nInject with decorator\n......................\nThe method :code:`inject` gives you the possibility to inject instances into a\nmethod if a keyword argument was not provided. that makes the loosely coupeling\nand testing very easy:\n\n.. code:: python\n\n\t@container.inject(service='some_service')\n\tdef some_method(value, service):\n\t\tservice.do_work(value)\n\n\tsome_method(\"hello world\")\n\tsome_method(\"hello world\", ExplicitService())\n\n\nInject many with decorator\n..........................\nThe method :code:`inject_many` gives you the possibility to inject multiple instances depending on\ntheir type.\n\n.. code-block:: python\n\n @container.inject_many(hooks=SomeHookClass)\n def method(data, hook_instances):\n for hook in hook_instance:\n hook.hook(data)\n # ...\n\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://bitbucket.org/jblawatt/python-simple-di/", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "python-simple-di", "package_url": "https://pypi.org/project/python-simple-di/", "platform": "", "project_url": "https://pypi.org/project/python-simple-di/", "project_urls": { "Homepage": "http://bitbucket.org/jblawatt/python-simple-di/" }, "release_url": "https://pypi.org/project/python-simple-di/1.7.0/", "requires_dist": null, "requires_python": "", "summary": "A simple dependency injection container.", "version": "1.7.0" }, "last_serial": 3051075, "releases": { "1.3.0": [ { "comment_text": "", "digests": { "md5": "f8b3c889d7462c7f9c9759b5ac4195b2", "sha256": "81a544208af4f2e4ce111ff82ae031cf00a7a7ee9e1c08577ef30904ad4f2f06" }, "downloads": -1, "filename": "python-simple-di-1.3.0.tar.gz", "has_sig": false, "md5_digest": "f8b3c889d7462c7f9c9759b5ac4195b2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4498, "upload_time": "2014-05-13T13:31:44", "url": "https://files.pythonhosted.org/packages/99/37/e98804c83e6b3816e08cc5f40a0017e81ec17d107014538384ffd6b5d5b0/python-simple-di-1.3.0.tar.gz" } ], "1.3.1": [ { "comment_text": "", "digests": { "md5": "2c07527fb2ef146b8a03e4fc04028b66", "sha256": "3d1837404f4c38299a4b33118ea45517f91796eb7c3884fdfc5c9eb3dd7d0749" }, "downloads": -1, "filename": "python-simple-di-1.3.1.tar.gz", "has_sig": false, "md5_digest": "2c07527fb2ef146b8a03e4fc04028b66", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4522, "upload_time": "2014-05-14T08:09:31", "url": "https://files.pythonhosted.org/packages/cb/d6/7d510e6644dba809fdb6f1c4553d600f188789607dec34165040d61c3200/python-simple-di-1.3.1.tar.gz" } ], "1.3.2": [ { "comment_text": "", "digests": { "md5": "50a66249a5e84b8b61737f4c4abbb071", "sha256": "7fb0d59c21736d53456250ff3f28693a48483d81822285a0104e9f927f6ea659" }, "downloads": -1, "filename": "python-simple-di-1.3.2.tar.gz", "has_sig": false, "md5_digest": "50a66249a5e84b8b61737f4c4abbb071", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4568, "upload_time": "2014-05-15T13:50:45", "url": "https://files.pythonhosted.org/packages/76/cd/c2ec74c0882f1859de14ba4c53a6484f212b461f9ce4f2593d8d2426548b/python-simple-di-1.3.2.tar.gz" } ], "1.3.3": [ { "comment_text": "", "digests": { "md5": "24f4aa116e47f6918f80051275656fc7", "sha256": "63862c2ab504a94450e0b7268e1e12874fc02e8a8df551e7a8aa7ec699b80300" }, "downloads": -1, "filename": "python-simple-di-1.3.3.tar.gz", "has_sig": false, "md5_digest": "24f4aa116e47f6918f80051275656fc7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4593, "upload_time": "2014-05-16T07:52:56", "url": "https://files.pythonhosted.org/packages/ee/7a/ef189eab4ff499761bfa0e28b370a11e4b71759ae69ba00d898e4d6212e2/python-simple-di-1.3.3.tar.gz" } ], "1.4.0": [ { "comment_text": "", "digests": { "md5": "51dce28c263e4639105729457a1f9292", "sha256": "424e9f7bf930cfd0eae47f02b3740bafc44f1f3040a84a4d1fe78e75f8f23b1e" }, "downloads": -1, "filename": "python-simple-di-1.4.0.tar.gz", "has_sig": false, "md5_digest": "51dce28c263e4639105729457a1f9292", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6028, "upload_time": "2014-08-07T07:28:16", "url": "https://files.pythonhosted.org/packages/f8/e8/45fbd4e7a8f0b5b290aebbd913ce1e6c60699553a4d0b09b5a4c724a8524/python-simple-di-1.4.0.tar.gz" } ], "1.5.1": [ { "comment_text": "", "digests": { "md5": "109b9a5906428fd40a415ca2930aaedb", "sha256": "d5462149b0f8ba782a9a560fdaffb27c7d57c791b2c92b06c74c93c4ad6866a9" }, "downloads": -1, "filename": "python-simple-di-1.5.1.tar.gz", "has_sig": false, "md5_digest": "109b9a5906428fd40a415ca2930aaedb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12585, "upload_time": "2015-06-25T20:31:50", "url": "https://files.pythonhosted.org/packages/86/a4/f02caff317409b13974872193be59073c1bde80d11d695a3e9ce1336ca2c/python-simple-di-1.5.1.tar.gz" } ], "1.5.2": [ { "comment_text": "", "digests": { "md5": "398e74070b1b06b64d7e61fc811edbe0", "sha256": "0e6b391daa7c36fe4fbdade7ff166d716212bff2b53ebd937611773824921eaa" }, "downloads": -1, "filename": "python-simple-di-1.5.2.tar.gz", "has_sig": false, "md5_digest": "398e74070b1b06b64d7e61fc811edbe0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12675, "upload_time": "2015-07-19T13:13:26", "url": "https://files.pythonhosted.org/packages/c4/60/abee9aade292f4a406a8a7234275712eeca39ed8cf4d5d5e107511ebf1d4/python-simple-di-1.5.2.tar.gz" } ], "1.5.3": [ { "comment_text": "", "digests": { "md5": "0a98be4e3062b40e827a7a4129cbca0f", "sha256": "299e999e2d6a32711da5f47afb059bbeca886e43d00894d0bae48119a764b952" }, "downloads": -1, "filename": "python-simple-di-1.5.3.tar.gz", "has_sig": false, "md5_digest": "0a98be4e3062b40e827a7a4129cbca0f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12864, "upload_time": "2015-07-22T14:46:34", "url": "https://files.pythonhosted.org/packages/78/93/01ce387c8bd104a37207fc823035446279b185e6dbf25999bc3e7c324c93/python-simple-di-1.5.3.tar.gz" } ], "1.6.0": [ { "comment_text": "", "digests": { "md5": "403ebf3548d602f82bdc9dd6eda3cafe", "sha256": "42ccc3f50600da00bd9f86871c3b02df3b066e5f9c1937d49ad7e9cb0b15b42a" }, "downloads": -1, "filename": "python-simple-di-1.6.0.zip", "has_sig": false, "md5_digest": "403ebf3548d602f82bdc9dd6eda3cafe", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20952, "upload_time": "2016-09-22T18:30:21", "url": "https://files.pythonhosted.org/packages/98/8f/c6ee324ef3a95e906e5524fccff350596800e138828a6e775a69ff45b12a/python-simple-di-1.6.0.zip" } ], "1.7.0": [ { "comment_text": "", "digests": { "md5": "8e6c61fda4994e6b0cb0290c1c9f9e2c", "sha256": "232c7b7b277e3fee645144150ebb08e85b6b40fa8f3879e6414ea59549c71fb6" }, "downloads": -1, "filename": "python-simple-di-1.7.0.zip", "has_sig": false, "md5_digest": "8e6c61fda4994e6b0cb0290c1c9f9e2c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22010, "upload_time": "2017-07-26T20:34:34", "url": "https://files.pythonhosted.org/packages/a9/f1/277c23b75802cf328a9dc095edb3fb26f3fa49999da4808dd5247467256c/python-simple-di-1.7.0.zip" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "8e6c61fda4994e6b0cb0290c1c9f9e2c", "sha256": "232c7b7b277e3fee645144150ebb08e85b6b40fa8f3879e6414ea59549c71fb6" }, "downloads": -1, "filename": "python-simple-di-1.7.0.zip", "has_sig": false, "md5_digest": "8e6c61fda4994e6b0cb0290c1c9f9e2c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22010, "upload_time": "2017-07-26T20:34:34", "url": "https://files.pythonhosted.org/packages/a9/f1/277c23b75802cf328a9dc095edb3fb26f3fa49999da4808dd5247467256c/python-simple-di-1.7.0.zip" } ] }