{"id":24297134,"url":"https://github.com/gh0st-work/blacksheep_decorators","last_synced_at":"2026-06-10T07:31:15.258Z","repository":{"id":130143513,"uuid":"571850030","full_name":"gh0st-work/blacksheep_decorators","owner":"gh0st-work","description":"Example implementation of decorators DI (Dependency injection) in blacksheep at a non-framework level.","archived":false,"fork":false,"pushed_at":"2023-01-07T10:35:16.000Z","size":19,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-24T18:45:50.819Z","etag":null,"topics":["blacksheep","decorators","python","python-decorators","python3","web-framework"],"latest_commit_sha":null,"homepage":"","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/gh0st-work.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":"2022-11-29T02:31:39.000Z","updated_at":"2023-11-22T09:32:57.000Z","dependencies_parsed_at":"2023-07-15T13:00:32.327Z","dependency_job_id":null,"html_url":"https://github.com/gh0st-work/blacksheep_decorators","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gh0st-work/blacksheep_decorators","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gh0st-work%2Fblacksheep_decorators","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gh0st-work%2Fblacksheep_decorators/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gh0st-work%2Fblacksheep_decorators/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gh0st-work%2Fblacksheep_decorators/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gh0st-work","download_url":"https://codeload.github.com/gh0st-work/blacksheep_decorators/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gh0st-work%2Fblacksheep_decorators/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34142637,"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-06-10T02:00:07.152Z","response_time":89,"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":["blacksheep","decorators","python","python-decorators","python3","web-framework"],"created_at":"2025-01-16T19:51:24.049Z","updated_at":"2026-06-10T07:31:15.245Z","avatar_url":"https://github.com/gh0st-work.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# blacksheep_decorators\nExample implementation of decorators DI (Dependency injection) in [blacksheep](https://github.com/Neoteroi/BlackSheep) at a non-framework level.\n\n### Install\n- clone\n- configure venv\n- `pip install -r requirements.txt`\n\n\n### Run tests\n- `python main.py`\n\n\n### Usage\n- create your decorator\n- without `functools.wraps` (!)\n- required to extract `request: Request` and `services: Services`\n- calculate your data\n- `return await with_deps_injection(...)` with params\n- - **original_handler** - original request function\n- - **request**\n- - **services**\n- - **your new classes** with any key\n- wrap your handler with your decorator, after decorator @app.router.\u003cmethod\u003e(...)\n\n\n### Example\n```python\n...\n\n\nclass Rights(Enum):\n\t...\n\n\ndef check_auth(minimal_rights: Optional[Rights] = None):\n\tdef real_decorator(original_function):\n\t\t\n\t\tasync def wrapper(\n\t\t\trequest: Request,\n\t\t\tservices: Services,\n\t\t) -\u003e Response:\n\t\t\trights, allowed = check_rights_from_headers(  # your logic\n\t\t\t\theaders=request.headers,\n\t\t\t\tminimal_rights=minimal_rights,\n\t\t\t)\n\n\t\t\tif not allowed:\n\t\t\t\treturn failure_response(  # if failure, your logic\n\t\t\t\t\tyour_rights=rights.value,\n\t\t\t\t\trights_required=minimal_rights,\n\t\t\t\t)\n\n\t\t\treturn await with_deps_injection( # if ok\n\t\t\t\torig_handler=original_function,\n\t\t\t\trequest=request,\n\t\t\t\tservices=services,\n\t\t\t\trights=rights\n\t\t\t\t# your classes, with any key, in example only one class 'Rights' (variable 'rights') with key 'rights'\n\t\t\t)\n\n\t\treturn wrapper\n\n\treturn real_decorator\n\n\n@app.router.get('/{home_id}/')\n@check_auth(Rights.admin)\nasync def home(\n\thome_id: int,  # from Route\n\trights: Rights,\n):\n\treturn success_response(\n\t\trights=rights.value,\n\t\thome_id=home_id,\n\t)\n\n\n```\n\n\n### Source\nJust for easy paste in your code:\n\n\n`injections.py`\n```python\nfrom blacksheep import Route, Request\nfrom blacksheep.server.normalization import normalize_handler, ensure_response\nfrom rodi import Services, class_name\n\n\nclass TempInject:\n\n\tdef __init__(self, services: Services, *args, **kwargs):\n\t\tself.services = services\n\n\t\tself.injections = [*args, *kwargs.values()]\n\t\tself.injections_types = []\n\t\tself.injections_class_names = []\n\t\tfor injection in self.injections:\n\t\t\tinjection_type = injection.__class__\n\t\t\tself.injections_types.append(injection_type)\n\n\t\t\traw_injection_class_name = class_name(injection_type)\n\t\t\tself.injections_class_names.append(raw_injection_class_name)\n\n\t\t\tself.services.set(injection_type, injection)\n\n\tdef __enter__(self) -\u003e Services:\n\t\treturn self.services\n\n\tdef __exit__(self, exc_type, exc_val, exc_tb):\n\t\tfor injection_class_name in self.injections_class_names:\n\t\t\tdel self.services._map[injection_class_name]\n\t\tfor injection_type in self.injections_types:\n\t\t\tdel self.services._map[injection_type]\n\n\nasync def with_deps_injection(\n\torig_handler,\n\trequest: Request,\n\tservices: Services,\n\t*args,\n\t**kwargs\n):\n\troute_like = Route('', orig_handler)  # For this (normal typing \u0026 beauty) are needed extra changes in core\n\tif request.route_values is not None:\n\t\troute_like.param_names = list(request.route_values.keys())\n\n\twith TempInject(services, *args, **kwargs) as temp_services:\n\t\tnorm_handler = normalize_handler(\n\t\t\troute=route_like,\n\t\t\tservices=temp_services\n\t\t)\n\t\tresponse = ensure_response(await norm_handler(request))\n\n\treturn response\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgh0st-work%2Fblacksheep_decorators","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgh0st-work%2Fblacksheep_decorators","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgh0st-work%2Fblacksheep_decorators/lists"}