11import typing as t
22from abc import ABC , abstractmethod
3- from contextlib import asynccontextmanager
43
54from ellar .common .constants import (
6- CONTROLLER_CLASS_KEY ,
5+ NOT_SET ,
76 SCOPE_API_VERSIONING_RESOLVER ,
87 VERSIONING_KEY ,
98)
1514)
1615from ellar .common .logging import request_logger
1716from ellar .common .types import TReceive , TScope , TSend
18- from ellar .core .context import current_injector
17+ from ellar .core .execution_context import current_injector
18+ from ellar .di import register_request_scope_context
1919from ellar .reflect import reflect
2020from starlette .routing import Match
2121
@@ -33,13 +33,11 @@ class RouteOperationBase:
3333 methods : t .Set [str ]
3434 _controller_type : t .Optional [t .Union [t .Type , t .Type ["ControllerBase" ]]] = None
3535
36- def __init__ (self , endpoint : t .Callable ) -> None :
36+ def __init__ (
37+ self , endpoint : t .Callable , controller_class : t .Optional [t .Type ] = None
38+ ) -> None :
3739 self .endpoint = endpoint
38- _controller_type : t .Type = self .get_controller_type ()
39-
40- self ._controller_type : t .Union [t .Type , t .Type ["ControllerBase" ]] = t .cast (
41- t .Union [t .Type , t .Type ["ControllerBase" ]], _controller_type
42- )
40+ self ._controller_type = controller_class or NOT_SET
4341
4442 # @t.no_type_check
4543 # def __call__(
@@ -51,23 +49,6 @@ def __init__(self, endpoint: t.Callable) -> None:
5149 def _load_model (self ) -> None :
5250 """compute route models"""
5351
54- @asynccontextmanager
55- async def _ensure_dependency_availability (
56- self , context : IExecutionContext
57- ) -> t .AsyncGenerator :
58- controller_type = context .get_class ()
59- module_scope_owner = next (
60- context .get_app ().injector .tree_manager .find_module (
61- lambda data : controller_type in data .providers
62- or controller_type in data .exports
63- )
64- )
65- if module_scope_owner and module_scope_owner .is_ready :
66- async with module_scope_owner .value .context ():
67- yield
68- else :
69- yield
70-
7152 async def app (self , scope : TScope , receive : TReceive , send : TSend ) -> None :
7253 request_logger .debug (
7354 f"Started Computing Execution Context - '{ self .__class__ .__name__ } '"
@@ -77,19 +58,19 @@ async def app(self, scope: TScope, receive: TReceive, send: TSend) -> None:
7758 context = execution_context_factory .create_context (
7859 operation = self , scope = scope , receive = receive , send = send
7960 )
80- current_injector . update_scoped_context (IExecutionContext , context )
61+ register_request_scope_context (IExecutionContext , context )
8162
8263 interceptor_consumer = current_injector .get (IInterceptorsConsumer )
8364 guard_consumer = current_injector .get (IGuardsConsumer )
8465
8566 request_logger .debug (
8667 f"Running Guards and Interceptors - '{ self .__class__ .__name__ } '"
8768 )
88- async with self ._ensure_dependency_availability (context ):
89- await guard_consumer .execute (context , self )
90- await interceptor_consumer .execute (context , self )
9169
92- def get_controller_type (self ) -> t .Type :
70+ await guard_consumer .execute (context , self )
71+ await interceptor_consumer .execute (context , self )
72+
73+ def get_controller_type (self ) -> t .Any :
9374 """
9475 For operation under a controller, `get_control_type` and `get_class` will return the same result
9576 For operation under ModuleRouter, this will return a unique type created for the router for tracking some properties
@@ -98,11 +79,6 @@ def get_controller_type(self) -> t.Type:
9879 request_logger .debug (
9980 f"Resolving Endpoint Handler Controller Type - '{ self .__class__ .__name__ } '"
10081 )
101- if not self ._controller_type :
102- _controller_type = reflect .get_metadata (CONTROLLER_CLASS_KEY , self .endpoint )
103- if _controller_type is None or not isinstance (_controller_type , type ):
104- raise Exception ("Operation must have a single control type." )
105- return t .cast (t .Type , _controller_type )
10682
10783 return self ._controller_type
10884
0 commit comments