{ "info": { "author": "Ivan Korobkov", "author_email": "ivan.korobkov@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "# python-inject [![Build Status](https://travis-ci.org/ivankorobkov/python-inject.svg?branch=master)](https://travis-ci.org/ivankorobkov/python-inject)\nDependency injection the python way, the good way. Not a port of Guice or Spring.\n\n## Key features\n* Fast.\n* Thread-safe.\n* Simple to use.\n* Does not steal class constructors.\n* Does not try to manage your application object graph.\n* Transparently integrates into tests.\n* Supports Python 2.7 and Python 3.3+.\n* Supports type hinting in Python 3.5+.\n* Autoparams leveraging type annotations.\n\n\n## Installation\nUse pip to install the lastest version:\n\n```bash\npip install inject\n```\n\n## Autoparams example\n`@inject.autoparams` returns a decorator which automatically injects arguments into a function \nthat uses type annotations. This is supported only in Python >= 3.5.\n\n```python\n@inject.autoparams()\ndef refresh_cache(cache: RedisCache, db: DbInterface):\n pass\n```\n\nThere is an option to specify which arguments we want to inject without attempts of \ninjecting everything:\n\n```python\n@inject.autoparams('cache', 'db')\ndef sign_up(name, email, cache, db):\n pass\n```\n\n## Step-by-step example\n```python\n# Import the inject module.\nimport inject\n\n\n# `inject.instance` requests dependencies from the injector.\ndef foo(bar):\n cache = inject.instance(Cache)\n cache.save('bar', bar)\n\n\n# `inject.params` injects dependencies as keyword arguments or positional argument. \n# Also you can use @inject.autoparams in Python 3.5, see the example above.\n@inject.params(cache=Cache, user=CurrentUser)\ndef baz(foo, cache=None, user=None):\n cache.save('foo', foo, user)\n\n# this can be called in different ways:\n# with injected arguments\nbaz('foo')\n\n# with positional arguments\nbaz('foo', my_cache)\n\n# with keyword arguments\nbaz('foo', my_cache, user=current_user)\n\n\n# `inject.param` is deprecated, use `inject.params` instead.\n@inject.param('cache', Cache)\ndef bar(foo, cache=None):\n cache.save('foo', foo)\n\n\n# `inject.attr` creates properties (descriptors) which request dependencies on access.\nclass User(object):\n cache = inject.attr(Cache)\n \n def __init__(self, id):\n self.id = id\n\n def save(self):\n self.cache.save('users', self)\n \n @classmethod\n def load(cls, id):\n return cls.cache.load('users', id)\n\n\n# Create an optional configuration.\ndef my_config(binder):\n binder.install(my_config2) # Add bindings from another config.\n binder.bind(Cache, RedisCache('localhost:1234'))\n\n# Configure a shared injector.\ninject.configure(my_config)\n\n\n# Instantiate User as a normal class. Its `cache` dependency is injected when accessed.\nuser = User(10)\nuser.save()\n\n# Call the functions, the dependencies are automatically injected.\nfoo('Hello')\nbar('world')\n```\n\n\n## Usage with Django\nDjango can load some modules multiple times which can lead to \n`InjectorException: Injector is already configured`. You can use `configure_once` which\nis guaranteed to run only once when the injector is absent:\n```python\nimport inject\ninject.configure_once(my_config)\n```\n\n## Testing\nIn tests use `inject.clear_and_configure(callable)` to create a new injector on setup,\nand optionally `inject.clear()` to clean up on tear down:\n```python\nclass MyTest(unittest.TestCase):\n def setUp(self):\n inject.clear_and_configure(lambda binder: binder\n .bind(Cache, Mock() \\\n .bind(Validator, TestValidator())\n \n def tearDown(self):\n inject.clear()\n```\n\n## Thread-safety\nAfter configuration the injector is thread-safe and can be safely reused by multiple threads.\n\n## Binding types\n**Instance** bindings always return the same instance:\n\n```python\nredis = RedisCache(address='localhost:1234')\ndef config(binder):\n binder.bind(Cache, redis)\n```\n \n**Constructor** bindings create a singleton on injection:\n\n```python\ndef config(binder):\n # Creates a redis cache singleton on first injection.\n binder.bind_to_constructor(Cache, lambda: RedisCache(address='localhost:1234'))\n```\n\n**Provider** bindings call the provider on injection:\n\n```python\ndef get_my_thread_local_cache():\n pass\n\ndef config(binder):\n # Executes the provider on each injection.\n binder.bind_to_provider(Cache, get_my_thread_local_cache) \n```\n\n**Runtime** bindings automatically create singletons on injection, require no configuration.\nFor example, only the `Config` class binding is present, other bindings are runtime:\n\n```python\nclass Config(object):\n pass\n\nclass Cache(object):\n config = inject.attr(Config)\n\nclass Db(object):\n config = inject.attr(Config)\n\nclass User(object):\n cache = inject.attr(Cache)\n db = inject.attr(Db)\n \n @classmethod\n def load(cls, user_id):\n return cls.cache.load('users', user_id) or cls.db.load('users', user_id)\n \ninject.configure(lambda binder: binder.bind(Config, load_config_file()))\nuser = User.load(10)\n```\n## Disabling runtime binding\nSometimes runtime binding leads to unexpected behaviour. Say if you forget\nto bind an instance to a class, `inject` will try to implicitly instantiate it.\n\nIf an instance is unintentionally created with default arguments it may lead to\nhard-to-debug bugs. To disable runtime binding and make sure that only \nexplicitly bound instances are injected, pass `bind_in_runtime=False` \nto `inject.configure`, `inject.configure_once` or `inject.clear_and_configure`.\n\nIn this case `inject` immediately raises `InjectorException` when the code\ntries to get an unbound instance.\n\n## Keys\nIt is possible to use any hashable object as a binding key. For example:\n\n```python\nimport inject\n\ninject.configure(lambda binder: \\\n binder.bind('host', 'localhost') \\\n binder.bind('port', 1234))\n```\n\n## Why no scopes?\nI've used Guice and Spring in Java for a lot of years, and I don't like their scopes.\n`python-inject` by default creates objects as singletons. It does not need a prototype scope\nas in Spring or NO_SCOPE as in Guice because `python-inject` does not steal your class \nconstructors. Create instances the way you like and then inject dependencies into them.\n\nOther scopes such as a request scope or a session scope are fragile, introduce high coupling,\nand are difficult to test. In `python-inject` write custom providers which can be thread-local, \nrequest-local, etc.\n\nFor example, a thread-local current user provider:\n\n```python\nimport inject\nimport threading\n\n# Given a user class.\nclass User(object):\n pass\n\n# Create a thread-local current user storage.\n_LOCAL = threading.local()\n\ndef get_current_user():\n return getattr(_LOCAL, 'user', None)\n\ndef set_current_user(user):\n _LOCAL.user = user\n\n# Bind User to a custom provider.\ninject.configure(lambda binder: binder.bind_to_provider(User, get_current_user))\n\n# Inject the current user.\n@inject.params(user=User)\ndef foo(user):\n pass\n```\n\n## Links\n* Project: https://github.com/ivankorobkov/python-inject\n\n## License\nApache License 2.0\n\n## Contributers\n* Ivan Korobkov [@ivankorobkov](https://github.com/ivankorobkov)\n* Jaime Wyant [@jaimewyant](https://github.com/jaimewyant)\n* Sebastian Buczy\u0144ski [@Enforcer](https://github.com/Enforcer)\n* Oleksandr Fedorov [@Fedorof](https://github.com/Fedorof)\n* cselvaraj [@cselvaraj](https://github.com/cselvaraj)\n* \u9646\u96e8\u6674 [@SixExtreme](https://github.com/SixExtreme)\n* Andrew William Borba [@andrewborba10](https://github.com/andrewborba10)\n* jdmeyer3 [@jdmeyer3](https://github.com/jdmeyer3)\n* Alex Grover [@ajgrover](https://github.com/ajgrover)", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/ivankorobkov/python-inject", "keywords": "", "license": "Apache License 2.0", "maintainer": "", "maintainer_email": "", "name": "Inject", "package_url": "https://pypi.org/project/Inject/", "platform": "", "project_url": "https://pypi.org/project/Inject/", "project_urls": { "Homepage": "https://github.com/ivankorobkov/python-inject" }, "release_url": "https://pypi.org/project/Inject/3.5.4/", "requires_dist": null, "requires_python": "", "summary": "Python dependency injection framework", "version": "3.5.4" }, "last_serial": 5606448, "releases": { "1.0": [ { "comment_text": "", "digests": { "md5": "b027a495845a7ee94051a39fbbbfbd6c", "sha256": "1e56ea7b46f57933975be322ce547376bfc72357d2cc6401328da29322308cd1" }, "downloads": -1, "filename": "Inject-1.0.tar.gz", "has_sig": false, "md5_digest": "b027a495845a7ee94051a39fbbbfbd6c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 38539, "upload_time": "2010-02-12T09:52:16", "url": "https://files.pythonhosted.org/packages/47/fd/79b38e78e54681c9e7c831a34b79c5deba9c648187cce6557eefd0907b47/Inject-1.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "c1d8cc4b0a8992e54cac20213d5f76a0", "sha256": "fcbecd3cfbcfa2ef9947400148b966deea85776562d0cbcbbe86b45579a46b72" }, "downloads": -1, "filename": "Inject-1.0.1.tar.gz", "has_sig": false, "md5_digest": "c1d8cc4b0a8992e54cac20213d5f76a0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 39902, "upload_time": "2010-06-18T08:33:21", "url": "https://files.pythonhosted.org/packages/f4/e4/81cc9c8f90d81158c1ec95bb431ab5b77e246939ca1135a00ca4291d762e/Inject-1.0.1.tar.gz" } ], "2.0.0": [ { "comment_text": "", "digests": { "md5": "f4968ddd8dd756c261e24d3422a585d4", "sha256": "7baf710aa38034eebf990c2011c551505e29e8f747d475e31b16431f3749754b" }, "downloads": -1, "filename": "Inject-2.0.0.tar.gz", "has_sig": false, "md5_digest": "f4968ddd8dd756c261e24d3422a585d4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30550, "upload_time": "2014-02-10T10:57:44", "url": "https://files.pythonhosted.org/packages/e9/10/80b167fa39fb56da4e6465fec8515f108cc79ff33deca5d3f72a1ae40958/Inject-2.0.0.tar.gz" } ], "3.0.0": [ { "comment_text": "", "digests": { "md5": "aa98e7b28eaa84b4cf39a55a779418dd", "sha256": "2d325874c9bcbca6514dd663ceeafdd6c982e7e1234274941c3a67bc0d1a5595" }, "downloads": -1, "filename": "Inject-3.0.0.tar.gz", "has_sig": false, "md5_digest": "aa98e7b28eaa84b4cf39a55a779418dd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7902, "upload_time": "2014-02-10T11:07:50", "url": "https://files.pythonhosted.org/packages/db/31/da5fc602c622558bedc76e3546baec1e8a95f5c3ecd56c4c3d4e783168a8/Inject-3.0.0.tar.gz" } ], "3.1.0": [ { "comment_text": "", "digests": { "md5": "092bed111137caebd202ae889337e55a", "sha256": "e326fa7934353c4e21fc85be4bf717266a24b7aa2ab3494755155fbebfd88e8b" }, "downloads": -1, "filename": "Inject-3.1.0.tar.gz", "has_sig": false, "md5_digest": "092bed111137caebd202ae889337e55a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8759, "upload_time": "2014-03-06T21:34:06", "url": "https://files.pythonhosted.org/packages/f9/1c/a6b292c21f9cfbe49006d16197ba09515f6bd193038be4d0a18d8601a05f/Inject-3.1.0.tar.gz" } ], "3.1.1": [ { "comment_text": "", "digests": { "md5": "6ad47a0d48449f03f951ad16541a8035", "sha256": "cd873982656892a539df0c6e60f3378ce35dbf603358e3fb9107a9b52933a230" }, "downloads": -1, "filename": "Inject-3.1.1.tar.gz", "has_sig": false, "md5_digest": "6ad47a0d48449f03f951ad16541a8035", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8961, "upload_time": "2014-03-14T15:48:21", "url": "https://files.pythonhosted.org/packages/4c/13/c4ee31c9a954d464996b75fecc28d8fd6bee30f0467365c7f86b661b2f95/Inject-3.1.1.tar.gz" } ], "3.2.0": [ { "comment_text": "", "digests": { "md5": "8a66b17f6ee38e5838fe4e7a05da9928", "sha256": "032f49874c4e4f2db19612002e66eb6b137150e565df6f947fb02fe36eb5ca65" }, "downloads": -1, "filename": "Inject-3.2.0.tar.gz", "has_sig": false, "md5_digest": "8a66b17f6ee38e5838fe4e7a05da9928", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9354, "upload_time": "2014-08-04T11:02:28", "url": "https://files.pythonhosted.org/packages/5a/9d/42d398e8daef197a4672a5dd9e3f8e8317272682219a6a48b996e09a9ae9/Inject-3.2.0.tar.gz" } ], "3.3.0": [ { "comment_text": "", "digests": { "md5": "36f36c87d04f8a579558c975fbd487b9", "sha256": "aec5f6b7199b05183125a9e20fb7d082e649b93836c687e764d1f65e8395fe14" }, "downloads": -1, "filename": "Inject-3.3.0.tar.gz", "has_sig": false, "md5_digest": "36f36c87d04f8a579558c975fbd487b9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9973, "upload_time": "2014-08-22T07:44:51", "url": "https://files.pythonhosted.org/packages/22/89/e74144610522279aa394fd38e165d00fc4e90a16fceb3d1dd2fdbce209fc/Inject-3.3.0.tar.gz" } ], "3.3.1": [ { "comment_text": "", "digests": { "md5": "050982b15735bb9045e309ad9fa1077e", "sha256": "274234dd18e9dd525998077f59c9c59d1e49ae5226f095f4364fc98009a1da6c" }, "downloads": -1, "filename": "Inject-3.3.1.tar.gz", "has_sig": false, "md5_digest": "050982b15735bb9045e309ad9fa1077e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10024, "upload_time": "2015-03-26T13:31:17", "url": "https://files.pythonhosted.org/packages/10/78/bdbd65cb1115652254c93adb3238a5c857de9bb07897939e468e734d5f67/Inject-3.3.1.tar.gz" } ], "3.3.2": [ { "comment_text": "", "digests": { "md5": "280da064c9b22bda8cd7bb6639f133b8", "sha256": "1977d07ad617cee5c99e447f8a78cd90722c0cab7e129a9fa6b1d263fe81773f" }, "downloads": -1, "filename": "Inject-3.3.2.tar.gz", "has_sig": false, "md5_digest": "280da064c9b22bda8cd7bb6639f133b8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10106, "upload_time": "2017-09-14T16:07:36", "url": "https://files.pythonhosted.org/packages/07/43/c51c1acfbdeda9f871e23ed53c5caedc50f00d0ae582a06d230d3bf8cdcf/Inject-3.3.2.tar.gz" } ], "3.4.0": [ { "comment_text": "", "digests": { "md5": "f90b65e0b5bce8395ffe1d4c85f20bca", "sha256": "b6fe50ba8a06f078c07900319c057273edfd48090e40de5f97f0c14bcac5ce08" }, "downloads": -1, "filename": "Inject-3.4.0.tar.gz", "has_sig": false, "md5_digest": "f90b65e0b5bce8395ffe1d4c85f20bca", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10977, "upload_time": "2018-08-01T08:01:31", "url": "https://files.pythonhosted.org/packages/57/64/f04bcdd00c8c955a19fb84c53d880f78ed7c17112e319f4ed5cdc36c3c33/Inject-3.4.0.tar.gz" } ], "3.5.0": [ { "comment_text": "", "digests": { "md5": "c1a8f7cf244907f2cbead05039fe005c", "sha256": "557f5e4d62cb7ddd29a6f97f4fa6b2e5d892c4f908be573157c7841fc1021634" }, "downloads": -1, "filename": "Inject-3.5.0.tar.gz", "has_sig": false, "md5_digest": "c1a8f7cf244907f2cbead05039fe005c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11379, "upload_time": "2019-03-11T07:43:53", "url": "https://files.pythonhosted.org/packages/95/f5/d1a3fcc84b5b35b90edc85e045b94049d6b29157b9a8b13950c1bdb63642/Inject-3.5.0.tar.gz" } ], "3.5.1": [ { "comment_text": "", "digests": { "md5": "1d5937c9d85e5409d6d179f85a0e4e1f", "sha256": "370759a8b15f1131f82a953ed67fbf57760dea2f3651d4c949d8da098e8dc69e" }, "downloads": -1, "filename": "Inject-3.5.1.tar.gz", "has_sig": false, "md5_digest": "1d5937c9d85e5409d6d179f85a0e4e1f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11450, "upload_time": "2019-04-16T09:27:14", "url": "https://files.pythonhosted.org/packages/db/80/f6490401babadca3fcba3c7cc538d1e1ad6995485ad661496be9caacd2a1/Inject-3.5.1.tar.gz" } ], "3.5.2": [ { "comment_text": "", "digests": { "md5": "6c7d55a7c9a5e4792f5ae9947bfd25ef", "sha256": "6bc0844542384326794ce8dd992d4c930f06a3c382009a6e4a6d91d877766f2b" }, "downloads": -1, "filename": "Inject-3.5.2.tar.gz", "has_sig": false, "md5_digest": "6c7d55a7c9a5e4792f5ae9947bfd25ef", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11916, "upload_time": "2019-07-10T08:22:49", "url": "https://files.pythonhosted.org/packages/2b/80/7affa02949cb00048a3406d5dcda585c34fbbf2c383606a387fa4096cfb8/Inject-3.5.2.tar.gz" } ], "3.5.3": [ { "comment_text": "", "digests": { "md5": "26e53a7530dd296aef025abd08758b2c", "sha256": "867d43caefa9d92ed9d541d27c5f2a94f154b265121a2d8f038a85ca37695f7b" }, "downloads": -1, "filename": "Inject-3.5.3.tar.gz", "has_sig": false, "md5_digest": "26e53a7530dd296aef025abd08758b2c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12018, "upload_time": "2019-07-23T21:11:59", "url": "https://files.pythonhosted.org/packages/72/b4/24e603398e0b9148e72ecb1f3e41be6ddf90bfe51f170d0d21e4be23d67a/Inject-3.5.3.tar.gz" } ], "3.5.4": [ { "comment_text": "", "digests": { "md5": "0a2e260d9826c1d607a214481f555db0", "sha256": "de218eca8400f0fdd10ff0b779880a77ecab8bd52e0455dce94803964f360e96" }, "downloads": -1, "filename": "Inject-3.5.4.tar.gz", "has_sig": false, "md5_digest": "0a2e260d9826c1d607a214481f555db0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9548, "upload_time": "2019-07-30T08:32:44", "url": "https://files.pythonhosted.org/packages/3b/f0/23703cbb81f878308ec23426fd9a94a98e4302fefcb021c625343e2512ce/Inject-3.5.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "0a2e260d9826c1d607a214481f555db0", "sha256": "de218eca8400f0fdd10ff0b779880a77ecab8bd52e0455dce94803964f360e96" }, "downloads": -1, "filename": "Inject-3.5.4.tar.gz", "has_sig": false, "md5_digest": "0a2e260d9826c1d607a214481f555db0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9548, "upload_time": "2019-07-30T08:32:44", "url": "https://files.pythonhosted.org/packages/3b/f0/23703cbb81f878308ec23426fd9a94a98e4302fefcb021c625343e2512ce/Inject-3.5.4.tar.gz" } ] }