{"id":13458904,"url":"https://github.com/bobthemighty/punq","last_synced_at":"2025-03-24T16:31:11.344Z","repository":{"id":38325444,"uuid":"102712859","full_name":"bobthemighty/punq","owner":"bobthemighty","description":"An IoC container for Python 3.8+","archived":false,"fork":false,"pushed_at":"2025-01-14T15:34:35.000Z","size":833,"stargazers_count":345,"open_issues_count":17,"forks_count":15,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-16T13:17:49.842Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/bobthemighty.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.rst","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","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-09-07T08:38:38.000Z","updated_at":"2025-03-09T22:28:56.000Z","dependencies_parsed_at":"2024-06-18T18:43:48.741Z","dependency_job_id":"348f9653-5f1c-40e5-b349-7e93bfd63c8c","html_url":"https://github.com/bobthemighty/punq","commit_stats":{"total_commits":80,"total_committers":12,"mean_commits":6.666666666666667,"dds":0.6125,"last_synced_commit":"ec3cbbe11e4cf41fa672f178073c29951e656fc9"},"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bobthemighty%2Fpunq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bobthemighty%2Fpunq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bobthemighty%2Fpunq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bobthemighty%2Fpunq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bobthemighty","download_url":"https://codeload.github.com/bobthemighty/punq/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245308521,"owners_count":20594261,"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-07-31T09:00:59.534Z","updated_at":"2025-03-24T16:31:11.337Z","avatar_url":"https://github.com/bobthemighty.png","language":"Python","funding_links":[],"categories":["Software"],"sub_categories":["DI Frameworks / Containers"],"readme":"# Punq\n\n[![Release](https://img.shields.io/github/v/release/bobthemighty/punq)](https://img.shields.io/github/v/release/bobthemighty/punq)\n[![Build status](https://img.shields.io/github/actions/workflow/status/bobthemighty/punq/main.yml?branch=main)](https://github.com/bobthemighty/punq/actions/workflows/main.yml?query=branch%3Amain)\n[![Tests](https://codecov.io/github/bobthemighty/punq/graph/badge.svg?token=52hQhaggnk)](https://codecov.io/github/bobthemighty/punq)\n[![Commit activity](https://img.shields.io/github/commit-activity/m/bobthemighty/punq)](https://img.shields.io/github/commit-activity/m/bobthemighty/punq)\n[![License](https://img.shields.io/github/license/bobthemighty/punq)](https://img.shields.io/github/license/bobthemighty/punq)\n\n\u003c!-- quick_start --\u003e\n\nAn unintrusive library for dependency injection in modern Python.\nInspired by [Funq][1], Punq is a dependency injection library you can understand.\n\n- No global state\n- No decorators\n- No weird syntax applied to arguments\n- Small and simple code base with 100% test coverage and developer-friendly comments.\n\n## Installation\n\nPunq is available on the [cheese shop][2]\n\n```shell\npip install punq\n```\n\nDocumentation is available on [Github pages][3].\n\n## Quick Start\n\nPunq avoids global state, so you must explicitly create a container in the entrypoint of your application:\n\n```python\nimport punq\n\ncontainer = punq.Container()\n```\n\nOnce you have a container, you can register your application's dependencies. In the simplest case, we can register any arbitrary object with some key:\n\n```python\ncontainer.register(\"connection_string\", instance=\"postgresql://...\")\n```\n\nWe can then request that object back from the container:\n\n```python\nconn_str = container.resolve(\"connection_string\")\n```\n\nUsually, though, we want to register some object that implements a useful service.:\n\n```python\nclass ConfigReader:\n    def get_config(self):\n        pass\n\nclass EnvironmentConfigReader(ConfigReader):\n    def get_config(self):\n        return {\n        \"logging\": {\n            \"level\": os.env.get(\"LOGGING_LEVEL\", \"debug\")\n        },\n        \"greeting\": os.env.get(\"GREETING\", \"Hello world\")\n        }\n\ncontainer.register(ConfigReader, EnvironmentConfigReader)\n```\n\nNow we can `resolve` the `ConfigReader` service, and receive a concrete implementation:\n\n```python\nconfig = container.resolve(ConfigReader).get_config()\n```\n\nIf our application's dependencies have their _own_ dependencies, Punq will inject those, too:\n\n```python\nclass Greeter:\n    def greet(self):\n        pass\n\n\nclass ConsoleGreeter(Greeter):\n    def __init__(self, config_reader: ConfigReader):\n        self.config = config_reader.get_config()\n\n    def greet(self):\n        print(self.config['greeting'])\n\n\ncontainer.register(Greeter, ConsoleGreeter)\ncontainer.resolve(Greeter).greet()\n\n```\n\nIf you just want to resolve an object without having any base class, that's okay:\n\n```python\nclass Greeter:\n    def __init__(self, config_reader: ConfigReader):\n        self.config = config_reader.get_config()\n\n    def greet(self):\n        print(self.config['greeting'])\n\ncontainer.register(Greeter)\ncontainer.resolve(Greeter).greet()\n```\n\nAnd if you need to have a singleton object for some reason, we can tell punq to register a specific instance of an object:\n\n```python\nclass FileWritingGreeter:\n    def __init__(self, path, greeting):\n        self.path = path\n        self.message = greeting\n        self.file = open(self.path, 'w')\n\n    def greet(self):\n        self.file.write(self.message)\n\n\none_true_greeter = FileWritingGreeter(\"/tmp/greetings\", \"Hello world\")\ncontainer.register(Greeter, instance=one_true_greeter)\n```\n\nYou might not know all of your arguments at registration time, but you can provide them later:\n\n```python\ncontainer.register(Greeter, FileWritingGreeter)\ngreeter = container.resolve(Greeter, path=\"/tmp/foo\", greeting=\"Hello world\")\n\n```\n\nConversely, you might want to provide arguments at registration time, without adding them to the container:\n\n```python\ncontainer.register(Greeter, FileWritingGreeter, path=\"/tmp/foo\", greeting=\"Hello world\")\n```\n\n[1]: https://github.com/jlyonsmith/Funq\n[2]: https://pypi.org/project/punq/\n[3]: https://bobthemighty.github.io/punq/\n[4]: https://github.com/fpgmaas/cookiecutter-uv\n\n\u003c!-- end_quick_start --\u003e\n\nFuller documentation is available on [Github pages][3]\n\nGithub workflows, nox configuration, and linting gratefully stolen from [CookieCutter UV][4]\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbobthemighty%2Fpunq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbobthemighty%2Fpunq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbobthemighty%2Fpunq/lists"}