{"id":16641247,"url":"https://github.com/cmstead/py-auto-di","last_synced_at":"2025-10-10T08:09:27.214Z","repository":{"id":62578792,"uuid":"346183139","full_name":"cmstead/py-auto-di","owner":"cmstead","description":"A dead simple dependency injection container for Python application development","archived":false,"fork":false,"pushed_at":"2021-03-11T18:45:29.000Z","size":17,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-24T20:37:40.080Z","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":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cmstead.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}},"created_at":"2021-03-10T00:26:14.000Z","updated_at":"2021-03-11T18:45:31.000Z","dependencies_parsed_at":"2022-11-03T21:02:04.244Z","dependency_job_id":null,"html_url":"https://github.com/cmstead/py-auto-di","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cmstead/py-auto-di","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmstead%2Fpy-auto-di","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmstead%2Fpy-auto-di/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmstead%2Fpy-auto-di/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmstead%2Fpy-auto-di/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cmstead","download_url":"https://codeload.github.com/cmstead/py-auto-di/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmstead%2Fpy-auto-di/sbom","scorecard":{"id":294408,"data":{"date":"2025-08-11","repo":{"name":"github.com/cmstead/py-auto-di","commit":"eee4ae07263ed845415a0931027ea2b6bfe74005"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.5,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":0,"reason":"Found 0/13 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2022-42969"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-17T19:07:17.951Z","repository_id":62578792,"created_at":"2025-08-17T19:07:17.951Z","updated_at":"2025-08-17T19:07:17.951Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279003294,"owners_count":26083555,"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","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"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-10-12T07:45:58.019Z","updated_at":"2025-10-10T08:09:27.195Z","avatar_url":"https://github.com/cmstead.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PyAutoDI #\n\n## What Is It? ##\n\nPyAutoDI is a simple dependency injection library which simplifies the process of creating and managing application dependency trees. The goal of PyAutoDI is to be lightweight and powerful with a shallow learning curve.\n\nThe core tenets of PyAutoDI are:\n\n- Make it easy to use dependency injection\n- Limit stuff humans have to remember\n- Be project structure agnostic\n- Break application filesystem coupling\n\nIf you aren't clear about what dependency injection is, [have a look at this primer](https://www.freecodecamp.org/news/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f/).\n\n## Setup ##\n\n### Installing PyAutoDi ###\n\nIn your project, run:\n\n```\npip install py-auto-di\n```\n\nFor more information about pip, please visit the [Real Python page](https://realpython.com/what-is-pip/).\n\n### Setting Up a Container ###\n\nThe easiest way to set up your DI container is to let it find and set up your dependencies for you:\n\n```\nfrom PyAutoDI import PyAutoDI\n\ndef get_new_container():\n    container = PyAutoDI.get_new_container()\n\n    return PyAutoDI.load_and_register_modules(\"./dependencies/**/*.py\", container)\n\napp_container = get_new_container()\n```\n\nNow you have a container with all of your dependencies loaded and ready to go!\n\n(We'll take a look at how to write your dependencies in a moment)\n\nIf you want to register your dependencies by hand, you can do that too. Here's how you'd do it:\n\n```\nfrom PyAutoDI import PyAutoDI\n\nfrom .dependencies.MyFirstDependency import MyFirstDependency\nfrom .dependencies.MySecondDependency import MySecondDependency\n\ndef get_new_container():\n    container = PyAutoDI.get_new_container()\n\n    container.register(MyFirstDependency)\n    container.register(MySecondDependency)\n\n    return container\n\napp_container = get_new_container()\n```\n\nEasy peasy.\n\n## Building Injected Dependencies ##\n\nBuilding any injected dependency is a one-liner:\n\n```\nnew_instance = container.build(\"my_dependency\")\n```\n\nThough this behavior could be used as a service locator, resist the temptation.\n\nIt is recommended that you only build dependencies this way at the entrypoint of your application. PyAutoDI will manage the dependency tree for you, so you don't need to worry about managing dependencies at each level.\n\n## Writing Injectible Dependencies ##\n\n### Auto-registering Dependencies ###\nIf you are planning on having PyAutoDI discover and register your dependencies, they need to follow a simple convention:\n\n```\nclass MyDependency:\n    def __init__(self, logger):\n        self.logger = logger\n\n    def do_stuff(self, message):\n        self.logger.log(message)\n\ndef register(container):\n    container.register(MyDependency)\n```\n\nPyAutoDI will look for a register function to call. If it finds one, it will automatically call it, and register your dependency however you see fit. This is the easiest way to keep all of the information about your module together.\n\nIf you have an interface defined, you can register it along with your dependency. This helps when you want to define how your module works in case you need to create a hot-swappable version, or a test double. This can be especially useful for modules which have side effects you want to mitigate during testing.\n\n```\nfrom ..interfaces.MyDependencyInterface import MyDependencyInterface\n\nclass MyDependency(MyDependencyInterface):\n    def __init__(self, logger):\n        self.logger = logger\n\n    def do_stuff(self, message):\n        self.logger.log(message)\n\ndef register(container):\n    container.register(MyDependency, interface=MyDependencyInterface)\n```\n\n### Hand-registered Dependencies ###\n\nFor hand-registered dependencies, you can either build your dependencies as you would for auto-registering, and call the register function yourself:\n\n```\nfrom PyAutoDI import PyAutoDI\n\nfrom .dependencies.MyFirstDependency import MyFirstDependency\n\ndef get_new_container():\n    container = PyAutoDI.get_new_container()\n\n    MyFirstDependency.register(container)\n\n    return container\n\napp_container = get_new_container()\n```\n\nOr you can skip the register function, and hand-register like the following:\n\nDependency:\n\n```\nfrom ..interfaces.MyDependencyInterface import MyDependencyInterface\n\nclass MyDependency(MyDependencyInterface):\n    def __init__(self, logger):\n        self.logger = logger\n\n    def do_stuff(self, message):\n        self.logger.log(message)\n```\n\nHand-registration:\n\n```\nfrom PyAutoDI import PyAutoDI\n\nfrom .dependencies.MyDependency import MyDependency\nfrom .interfaces.MyDependencyInterface import MyDependencyInterface\n\ndef get_new_container():\n    container = PyAutoDI.get_new_container()\n\n    container.register(MyDependency, MyDependencyInterface)\n\n    return container\n\napp_container = get_new_container()\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmstead%2Fpy-auto-di","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcmstead%2Fpy-auto-di","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmstead%2Fpy-auto-di/lists"}