{"id":18830261,"url":"https://github.com/sopherapps/type_dep","last_synced_at":"2025-04-14T03:42:19.308Z","repository":{"id":57678842,"uuid":"491534650","full_name":"sopherapps/type_dep","owner":"sopherapps","description":"type_dep is a dependency injection framework that uses type hints to inject dependencies (much like Angular, Dotnet and the like)","archived":false,"fork":false,"pushed_at":"2023-07-05T15:16:06.000Z","size":15,"stargazers_count":8,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-09T21:43:41.405Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sopherapps.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-05-12T13:53:18.000Z","updated_at":"2024-09-04T12:18:07.000Z","dependencies_parsed_at":"2022-09-26T21:31:31.113Z","dependency_job_id":null,"html_url":"https://github.com/sopherapps/type_dep","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sopherapps%2Ftype_dep","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sopherapps%2Ftype_dep/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sopherapps%2Ftype_dep/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sopherapps%2Ftype_dep/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sopherapps","download_url":"https://codeload.github.com/sopherapps/type_dep/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248818765,"owners_count":21166468,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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-08T01:48:18.875Z","updated_at":"2025-04-14T03:42:19.284Z","avatar_url":"https://github.com/sopherapps.png","language":"Python","readme":"# type_dep\n\ntype_dep is a dependency injection framework that uses type hints to inject dependencies (much like Angular, Dotnet and the like)\n\n## Quick Start\n\n- Install the package\n\n```shell\npip install type_dep\n```\n\n- Inherit from the package's `Dependency` class to create an injectable dependency class.\n- Use the `dependencyinjected` decorator to tag functions or methods that require dependency injection through their parameter type annotations.\n\n```python\nimport os\nfrom type_dep import Dependency, dependencyinjected, Context\n\ncounter = 0\n\nclass A(Dependency):\n    def __init__(self, name: str):\n        self.name = name\n\n    @classmethod\n    def instantiate(cls):\n        global counter\n        counter += 1\n        return A(f\"{counter}\")\n\nclass B(Dependency):\n\n    def __init__(self, sex: str):\n        self.sex = sex\n\n    @classmethod\n    def instantiate(cls):\n        return B(os.environ.get(\"SEX\", \"female\"))\n\n    @dependencyinjected\n    def get_detail(self, a: A):\n        \"\"\"\n        A method which uses dependency injection\n        `a` will be instantiated and injected into this method at runtime.\n        By default, these dependencies are stored in a global context.\n        Subsequent method calls will use the instances of the dependencies that were\n        instantiated on the first run.\n\n        NOTE: The type hints on the parameters are a must\n        \"\"\"\n        return {\"name\": a.name, \"sex\": self.sex}\n\n    @dependencyinjected\n    def scoped_get_detail(self, a: A, context: Context):\n        \"\"\"\n        When a `Context` argument is passed,\n        the dependencies are stored in a context that gets destroyed after every method call, unless\n        an externally instantiated `Context` is passed to this function. For the later\n        case, the `Context` object will be destroyed when it gets out of scope, as in normal python.\n\n        NOTE: The type hints on the parameters are a must\n        \"\"\"\n        return {\"name\": a.name, \"sex\": self.sex}\n\n@dependencyinjected\ndef run(males: int, females: int, a: A, greeting: str, b: B):\n    \"\"\"\n    Just some function that is dependency injected.\n    `a` and `b` will be instantiated and injected into the function at runtime\n\n    By default, these dependencies are stored in a global context.\n    Subsequent method calls will use the instances of the dependencies that were\n    instantiated on the first run.\n\n    NOTE: The type hints on the parameters are a must\n    \"\"\"\n    print(f\"males: {males}, females: {females}, greeting: {greeting}, a.name: {a.name}, b.sex: {b.sex}\")\n    print(f'{b.get_detail()}\\n')\n\n@dependencyinjected\ndef scoped_run(males: int, females: int, a: A, greeting: str, b: B, context: Context):\n    \"\"\"\n    Just some function that is dependency injected.\n    `a` and `b` will be instantiated and injected into the function at runtime\n\n    When a `Context` argument is passed,\n    the dependencies are stored in a context that gets destroyed after every function call, unless\n    an externally instantiated `Context` is passed to this function. For the later\n    case, the `Context` object will be destroyed when it gets out of scope, as in normal python.\n\n    NOTE: The type hints on the parameters are a must\n    \"\"\"\n    print(f\"scoped: males: {males}, females: {females}, greeting: {greeting}, a.name: {a.name}, b.sex: {b.sex}\")\n    print(f'scoped: {b.scoped_get_detail()}\\n')\n\nif __name__ == '__main__':\n    counter = 0\n\n    for _ in range(3):\n        run(6, 56, greeting=\"hey\")\n\n    # males: 6, females: 56, greeting: hey, a.name: 1, b.sex: female\n    # {'name': '2', 'sex': 'female'}\n    # \n    # males: 6, females: 56, greeting: hey, a.name: 1, b.sex: female\n    # {'name': '2', 'sex': 'female'}\n    # \n    # males: 6, females: 56, greeting: hey, a.name: 1, b.sex: female\n    # {'name': '2', 'sex': 'female'}\n\n    for _ in range(3):\n        scoped_run(6, 56, greeting=\"hey\")\n\n    # scoped: males: 6, females: 56, greeting: hey, a.name: 3, b.sex: female\n    # scoped: {'name': '4', 'sex': 'female'}\n    # \n    # scoped: males: 6, females: 56, greeting: hey, a.name: 5, b.sex: female\n    # scoped: {'name': '6', 'sex': 'female'}\n    # \n    # scoped: males: 6, females: 56, greeting: hey, a.name: 7, b.sex: female\n    # scoped: {'name': '8', 'sex': 'female'}\n```\n\n## Why use type hints\n\nPython type hints have matured alot. It is high time we used them to the maximum. \nApart from helping us avoid some logical errors, wouldn't be nice if type hints helped inject dependencies.\n\n- Very little extra code is needed if you are already using types\n- It is intuitive\n\n## How to test\n\n- Clone the repository\n\n```shell\ngit clone git@github.com:sopherapps/type_dep.git\ncd type_dep\n```\n\n- Create and activate the virtual environment\n\n```shell\npython3 -m venv env\nsource env/bin/activate\n```\n\n- Run the test command\n\n```shell\npython -m unittest\n```\n\n## License\n\nCopyright (c) 2022 [Martin Ahindura](https://github.com/Tinitto) Licensed under the [MIT License](./LICENSE)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsopherapps%2Ftype_dep","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsopherapps%2Ftype_dep","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsopherapps%2Ftype_dep/lists"}