{"id":20901433,"url":"https://github.com/38elements/dependency","last_synced_at":"2026-05-27T18:31:43.850Z","repository":{"id":149125754,"uuid":"98267989","full_name":"38elements/dependency","owner":"38elements","description":"A dependency injection framework for Python.","archived":false,"fork":false,"pushed_at":"2017-07-25T11:48:49.000Z","size":46,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-05-13T12:48:53.720Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/38elements.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-07-25T05:34:35.000Z","updated_at":"2026-01-05T02:34:45.000Z","dependencies_parsed_at":null,"dependency_job_id":"5f75820c-0749-4ce7-8f09-0679df0706b3","html_url":"https://github.com/38elements/dependency","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/38elements/dependency","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/38elements%2Fdependency","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/38elements%2Fdependency/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/38elements%2Fdependency/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/38elements%2Fdependency/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/38elements","download_url":"https://codeload.github.com/38elements/dependency/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/38elements%2Fdependency/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33579665,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-27T02:00:06.184Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-18T11:30:46.240Z","updated_at":"2026-05-27T18:31:43.829Z","avatar_url":"https://github.com/38elements.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dependency\n\n*A dependency injection library, using Python type annotations.*\n\n[![Build Status](https://travis-ci.org/encode/dependency.svg?branch=master)](https://travis-ci.org/encode/dependency)\n[![codecov](https://codecov.io/gh/encode/dependency/branch/master/graph/badge.svg)](https://codecov.io/gh/encode/dependency)\n[![Package version](https://badge.fury.io/py/dependency.svg)](https://pypi.python.org/pypi/dependency)\n\n**Requirements**: Python 3.5+\n\n---\n\nDependency Injection is a pattern that can help with managing complexity\nand testability in large codebases.\n\nThe `dependency` package provides the building blocks required to\nimplement type-annotation based dependency injection.\n\n## Examples\n\nRather than starting with the API of the package itself, let's instead take\na look at the sort of code the `dependency` package allows you to write.\n\n### Web framework\n\nIn this case we've built a web framework that supports dependency injected components\nto provide the information that each view uses:\n\n```python\nfrom web_framework import Method, Path, Headers, App, Response\nimport json\n\n\ndef echo_request_info(method: Method, path: Path, headers: Headers):\n    content = json.dumps({\n        'method': method,\n        'path': path,\n        'headers': dict(headers)\n    }, indent=4).encode('utf-8')\n    return Response(content)\n\n\ndef echo_user_agent(user_agent: Header):\n    content = json.dumps({\n        'User-Agent': user_agent\n    }, indent=4).encode('utf-8')\n    return Response(content)\n\n\napp = App({\n    '/request/': echo_request_info,\n    '/user-agent/': echo_user_agent\n})\n\n\nif __name__ == '__main__':\n    app.run()\n```\n\nYou can see that the views have more expressive interfaces and are more easily\ntestable than they would be if every function accepted a single `request` argument.\n\nThe framework source code is available here: [/examples/web_framework.py](/examples/web_framework.py)\n\n### Test framework\n\nHere's another example, of using `dependency` to create a testing framework\nthat supports dependency-injection of reusable components into test cases...\n\n```python\nfrom tempfile import TemporaryDirectory\nfrom examples.test_framework import run_tests\nimport dependency\nimport os\n\n\n@dependency.add_provider\ndef get_temp_dir() -\u003e TemporaryDirectory:\n    \"\"\"\n    A temporary directory component that may be injected into test cases.\n    Each directory will only exist for the lifetime of a single test.\n    \"\"\"\n    return TemporaryDirectory()\n\n\ndef test_list_empty_directory(tmp_dir: TemporaryDirectory):\n    assert len(os.listdir(tmp_dir.name)) == 0\n\n\ndef test_list_nonempty_directory(tmp_dir: TemporaryDirectory):\n    path = os.path.join(tmp_dir.name, 'example.txt')\n    open(path, 'w').close()\n    assert len(os.listdir(tmp_dir.name)) == 1\n\n\nif __name__ == \"__main__\":\n    run_tests()\n```\n\nThe framework source code is available here: [/examples/test_framework.py](/examples/test_framework.py)\n\n---\n\n## Library usage\n\nThe core functionality is provided as two functions:\n\n* `dependency.add_provider(func: Callable)` - Add a provider function.\n* `dependency.inject(func: Callable)` - Create a dependency injected function.\n\nYou can use these either as plain function calls, or as decorators...\n\n```python\nimport datetime\nimport dependency\nimport typing\n\nNow = typing.NewType('Now', datetime.datetime)\n\n@dependency.add_provider\ndef get_now() -\u003e Now:\n    datetime.datetime.now()\n\n@dependency.inject\ndef do_something(now: Now):\n    ...\n\ndo_something()\n```\n\nThe functions passed to `dependency.add_provider()` must be fully type annotated.\nThe parameters of a provider function may include class dependencies themselves.\n\n### Working with initial state\n\nOften you'll want your provider functions to depend on some initial state.\nThis might be something that's setup when your application is initialised,\nor state that exists in the context of a single HTTP request/response cycle.\n\n* `dependency.set_required_state(required_state: Dict[str, type])`\n\nYou can include required state classes in provider functions...\n\n```python\nimport dependency\n\n# Add some provider functions\n@dependency.add_provider\ndef get_database_session(engine: Engine) -\u003e Session:\n    \"\"\"\n    Return a database session, given the database engine.\n    \"\"\"\n\n@dependency.add_provider\ndef create_database_engine(settings: settings) -\u003e Engine:\n    \"\"\"\n    Return a database engine instance, given the application settings.\n    \"\"\"\n\n@dependency.add_provider\ndef get_request(environ: Environ) -\u003e Request:\n    \"\"\"\n    Return a request instance, given a WSGI environ.\n    \"\"\"\n\n# Indicate classes that will be provided as initial state\ndependency.set_required_state({'settings': Settings, 'environ': Environ})\n\n# Wrap a function in a dependency injection\n@dependency.inject\ndef list_users(request: Request, session: Session):\n    ...\n```\n\nIn order to run a dependency that has some required initial state, you'll\nneed to include the state as a keyword argument.\n\n```python\nlist_users(state={'settings': ..., 'environ': ...})\n```\n\n### Namespaced dependencies\n\nThe function calls we've looked at so far all operate against a single\nglobal dependency namespace, but you can also create individual instances\ngiving you more explicit control over the dependency injection.\n\n```python\ninjector = dependency.Injector()\n\n@injector.add_provider\ndef get_now() -\u003e Now:\n    datetime.datetime.now()\n\n@injector.inject\ndef do_something(now: Now):\n    ...\n```\n\nThe constructor takes two arguments, both of which are optional:\n\n* `providers: Dict[type, Callable]` - A map of dependency types onto their provider functions.\n* `required_state: Dict[str, type]` - A map of any dependency types which will be provided as initial state.\n\nThese are also both available directly on the instance...\n\n```python\ninjector = dependency.Injector()\ninjector.providers[Now] = get_now\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F38elements%2Fdependency","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F38elements%2Fdependency","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F38elements%2Fdependency/lists"}