{"id":13937255,"url":"https://github.com/digidotcom/epoxy","last_synced_at":"2026-01-22T11:42:50.516Z","repository":{"id":17261425,"uuid":"20031013","full_name":"digidotcom/epoxy","owner":"digidotcom","description":"A  Dependency Injection framework for Python applications","archived":false,"fork":false,"pushed_at":"2015-10-09T04:52:53.000Z","size":340,"stargazers_count":29,"open_issues_count":0,"forks_count":6,"subscribers_count":39,"default_branch":"master","last_synced_at":"2025-09-22T14:44:16.938Z","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":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/digidotcom.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2014-05-21T17:47:37.000Z","updated_at":"2022-04-16T20:05:54.000Z","dependencies_parsed_at":"2022-09-12T22:40:24.759Z","dependency_job_id":null,"html_url":"https://github.com/digidotcom/epoxy","commit_stats":null,"previous_names":["etherios/epoxy"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/digidotcom/epoxy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digidotcom%2Fepoxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digidotcom%2Fepoxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digidotcom%2Fepoxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digidotcom%2Fepoxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/digidotcom","download_url":"https://codeload.github.com/digidotcom/epoxy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digidotcom%2Fepoxy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28662306,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"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-08-07T23:03:26.172Z","updated_at":"2026-01-22T11:42:50.500Z","avatar_url":"https://github.com/digidotcom.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"Epoxy\n=====\n\n[![Build Status](https://img.shields.io/travis/digidotcom/epoxy.svg)](https://travis-ci.org/digidotcom/epoxy)\n[![Coverage Status](https://img.shields.io/coveralls/digidotcom/epoxy.svg)](https://coveralls.io/r/digidotcom/epoxy)\n[![Code Climate](https://img.shields.io/codeclimate/github/digidotcom/epoxy.svg)](https://codeclimate.com/github/digidotcom/epoxy)\n[![Latest Version](https://img.shields.io/pypi/v/epoxy.svg)](https://pypi.python.org/pypi/epoxy/)\n[![License](https://img.shields.io/badge/license-MPL%202.0-blue.svg)](https://github.com/digidotcom/epoxy/blob/master/LICENSE)\n\nIntroduction\n------------\n\nEpoxy is an dependency injection framework for Python applications\npackaged with a set of adapters that can be used with a number of\nexisting technologies.  Epoxy allows you to clearly separate out the\nconcern of mapping dependencies to components from defining those\ncomponents.\n\nEpoxy is probably overkill for small apps (like the example below) but\nshows its true value on larger projects where a higher degree of\nflexibility and lower degree of coupling is desirable.\n\nLicense\n-------\n\nThis library is available under the terms of the MPL.  Please see the\nLICENSE file for details.\n\nAn Example\n----------\n\nHere's an example of an epoxy component:\n\n```python\nfrom epoxy.component import Component, Dependency\n\nclass PrinterComponent(Component):\n\n    prefix = StringSetting(required=False, default=\"PRINTING\")\n\n    def write(self, stuff):\n        print (\"[%s] %%s\" % self.prefix) % stuff\n\n    def start(self):\n        print self.write(\"Warming up printer\")\n\n\nclass ScreenRenderer(Component):\n\n    printer = Dependency()\n\n    def render_screen(self):\n        self.printer.write(\"My Stuff\")\n\n    def start(self):\n        self.printer.write(\"Screen Renderer Initialized\")\n```\n\nIn this example, ScreenRenderer does not need to know the precise\nprinter which will be used as a dependency at runtime, it just needs\nto declare the dependency and use it (there is an assumed interface,\nas with much in python we just use duck typing).\n\nTo wire these components up at runtime, we would write a yaml file\nthat would have something like this:\n\n```yaml\ncomponents:\n  printer:\n    class: my.module:PrinterComponent\n    settings:\n      prefix: PREFIX\n\n  screen_renderer:\n    class: my.module:ScreenRenderer\n    dependencies:\n      printer: printer\n\nentry-point:\n  screen_renderer:render_screen\n```\n\nFinally, to load in our configuration and run the application, we\nwould write something like the following:\n\n```python\nfrom epoxy.configuration import YamlConfigurationLoader\nfrom epoxy.core import ComponentManager\n\nloader = YamlConfigurationLoader(\"myapp.yml\")\nconfig = loader.load_configuration()\ncomponent_mgr = ComponentManager()\ncomponent_mgr.launch_configuration(config)\n```\n\nThis would run our entry point and print the following to the screen:\n\n    [PREFIX] Warming up printer\n    [PREFIX] Screen Renderer Initialized\n    [PREFIX] my stuff\n\nWriting a Component\n-------------------\n\nAny Component that is written should follow these basic rules in order\nto play nicely:\n\n1.  No-args constructor: Components should have a no-args constructor\n    in order to be instantiated by the framework.  To initialize a\n    Component in your own code (maybe from a unit test) you can use\n    the \"from_dependencies\" classmethod available on any component and\n    pass in any relevant dependencies/settings as keyword arguments.\n    \n    For instance, instantiating our previous object graph would look\n    like the following:\n\n    ```python\n    printer = PrinterComponent.from_dependencies(prefix=\"FROM_DEPS\")\n    renderer = ScreenRenderer.from_dependencies(printer=printer)\n    ```\n\n    When ``__init__`` is executed it is guaranteed that all dependencies\n    will be present and initialized (but not started).\n\n2.  Implement ``start()`` method: After all objects in the graph are\n    instantiated, they will be started.  Like with ``__init__``,\n    dependencies will be present and will have had ``start()`` called.\n    Calls to ``start()`` should not block.  For long-running tasks, using\n    an entry-point is more appropriate.\n\n3.  Avoid Dependency Cycles: If the object graph has dependencies, you\n    will get errors when trying to build the dependency graph and you\n    will not be able to run your application.  There are many\n    different strategies for breaking these cycles.  If you run into\n    this issue and are ticked off, just know that fixing this issue is\n    making your application better.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigidotcom%2Fepoxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdigidotcom%2Fepoxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigidotcom%2Fepoxy/lists"}