11# ruff: noqa: N802
22import logging
33
4+ from abc import ABC , abstractmethod
45from collections .abc import AsyncIterable , Awaitable , Callable
56from typing import TypeVar
67
4041
4142logger = logging .getLogger (__name__ )
4243
43- GrpcContextBuilder = Callable [[grpc .aio .ServicerContext ], User ]
4444
45+ class GrpcContextBuilder (ABC ):
46+ """Interface for building ServerCallContext from gRPC context."""
4547
46- def default_grpc_user_builder (context : grpc .aio .ServicerContext ) -> User :
47- """Default strategy for creating a User from a gRPC context."""
48- return UnauthenticatedUser ()
48+ @abstractmethod
49+ def build (self , context : grpc .aio .ServicerContext ) -> ServerCallContext :
50+ """Builds a ServerCallContext from a gRPC ServicerContext."""
51+
52+ @abstractmethod
53+ def build_user (self , context : grpc .aio .ServicerContext ) -> User :
54+ """Builds a User from a gRPC ServicerContext."""
55+
56+
57+ class DefaultGrpcContextBuilder (GrpcContextBuilder ):
58+ """Default implementation of GrpcContextBuilder."""
59+
60+ def build (self , context : grpc .aio .ServicerContext ) -> ServerCallContext :
61+ """Builds a ServerCallContext from a gRPC ServicerContext."""
62+ user = self .build_user (context )
63+ state = {'grpc_context' : context }
64+ return ServerCallContext (
65+ user = user ,
66+ state = state ,
67+ requested_extensions = get_requested_extensions (
68+ _get_metadata_value (context , HTTP_EXTENSION_HEADER )
69+ ),
70+ )
71+
72+ def build_user (self , context : grpc .aio .ServicerContext ) -> User :
73+ """Builds a User from a gRPC ServicerContext."""
74+ return UnauthenticatedUser ()
4975
5076
5177def _get_metadata_value (
@@ -62,22 +88,6 @@ def _get_metadata_value(
6288 if k .lower () == lower_key
6389 ]
6490
65-
66- def build_grpc_server_call_context (
67- context : grpc .aio .ServicerContext ,context_builder : GrpcContextBuilder
68- ) -> ServerCallContext :
69- """Builds a ServerCallContext from a gRPC ServicerContext."""
70- user = context_builder (context )
71- state = {'grpc_context' : context }
72- return ServerCallContext (
73- user = user ,
74- state = state ,
75- requested_extensions = get_requested_extensions (
76- _get_metadata_value (context , HTTP_EXTENSION_HEADER )
77- ),
78- )
79-
80-
8191_ERROR_CODE_MAP = {
8292 types .InvalidRequestError : grpc .StatusCode .INVALID_ARGUMENT ,
8393 types .MethodNotFoundError : grpc .StatusCode .NOT_FOUND ,
@@ -105,7 +115,7 @@ def __init__(
105115 self ,
106116 agent_card : AgentCard ,
107117 request_handler : RequestHandler ,
108- context_builder : GrpcContextBuilder | None = None ,
118+ context_builder : GrpcContextBuilder | None = None ,
109119 card_modifier : Callable [[AgentCard ], Awaitable [AgentCard ] | AgentCard ]
110120 | None = None ,
111121 ):
@@ -115,14 +125,14 @@ def __init__(
115125 agent_card: The AgentCard describing the agent's capabilities.
116126 request_handler: The underlying `RequestHandler` instance to
117127 delegate requests to.
118- context_builder: Optional custom user builder to extract user from the
128+ context_builder: Optional custom user builder to extract user from the
119129 gRPC context.
120130 card_modifier: An optional callback to dynamically modify the public
121131 agent card before it is served.
122132 """
123133 self .agent_card = agent_card
124134 self .request_handler = request_handler
125- self .user_builder = context_builder or default_grpc_user_builder
135+ self ._context_builder = context_builder or DefaultGrpcContextBuilder ()
126136 self .card_modifier = card_modifier
127137
128138 async def _handle_unary (
@@ -446,8 +456,6 @@ def _build_call_context(
446456 context : grpc .aio .ServicerContext ,
447457 request : message .Message ,
448458 ) -> ServerCallContext :
449- server_context = build_grpc_server_call_context (
450- context , self .user_builder
451- )
459+ server_context = self ._context_builder .build (context )
452460 server_context .tenant = getattr (request , 'tenant' , '' )
453461 return server_context
0 commit comments