1- #
2- # Licensed to the Apache Software Foundation (ASF) under one or more
3- # contributor license agreements. See the NOTICE file distributed with
4- # this work for additional information regarding copyright ownership.
5- # The ASF licenses this file to You under the Apache License, Version 2.0
6- # (the "License"); you may not use this file except in compliance with
7- # the License. You may obtain a copy of the License at
8- #
9- # http://www.apache.org/licenses/LICENSE-2.0
10- #
11- # Unless required by applicable law or agreed to in writing, software
12- # distributed under the License is distributed on an "AS IS" BASIS,
13- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14- # See the License for the specific language governing permissions and
15- # limitations under the License.
16-
171import inspect
182from typing import Callable , Optional , List , Type , Any , get_type_hints
193from dubbo .classes import MethodDescriptor
2711__all__ = ["RpcMethodHandler" , "RpcServiceHandler" ]
2812
2913
14+ class RpcMethodConfigurationError (Exception ):
15+ """
16+ Raised when RPC method is configured incorrectly.
17+ """
18+ pass
19+
20+
3021class RpcMethodHandler :
22+ """
23+ Rpc method handler that wraps metadata and serialization logic for a callable.
24+ """
25+
3126 __slots__ = ["_method_descriptor" ]
3227
3328 def __init__ (self , method_descriptor : MethodDescriptor ):
29+ """
30+ Initialize the RpcMethodHandler
31+ :param method_descriptor: the method descriptor.
32+ :type method_descriptor: MethodDescriptor
33+ """
3434 self ._method_descriptor = method_descriptor
3535
3636 @property
3737 def method_descriptor (self ) -> MethodDescriptor :
38+ """
39+ Get the method descriptor
40+ :return: the method descriptor
41+ :rtype: MethodDescriptor
42+ """
3843 return self ._method_descriptor
3944
4045 @staticmethod
4146 def get_codec (** kwargs ) -> tuple :
47+ """
48+ Get the serialization and deserialization functions based on codec
49+ :param kwargs: codec settings like transport_type, parameter_types, return_type
50+ :return: serializer and deserializer functions
51+ :rtype: Tuple[SerializingFunction, DeserializingFunction]
52+ """
4253 return DubboTransportService .create_serialization_functions (** kwargs )
4354
4455 @classmethod
4556 def _infer_types_from_method (cls , method : Callable ) -> tuple :
57+ """
58+ Infer method name, parameter types, and return type from a callable
59+ :param method: the method to analyze
60+ :type method: Callable
61+ :return: tuple of method name, parameter types, return type
62+ :rtype: Tuple[str, List[Type], Type]
63+ """
4664 try :
4765 type_hints = get_type_hints (method )
4866 sig = inspect .signature (method )
4967 method_name = method .__name__
5068 params = list (sig .parameters .values ())
69+
5170 if params and params [0 ].name == "self" :
52- params = params [1 :]
71+ raise RpcMethodConfigurationError (
72+ f"Method '{ method_name } ' appears to be an unbound method with 'self' parameter. "
73+ "RPC methods should be bound methods (e.g., instance.method) or standalone functions. "
74+ "If you're registering a class method, ensure you pass a bound method: "
75+ "RpcMethodHandler.unary(instance.method) not RpcMethodHandler.unary(Class.method)"
76+ )
5377
5478 params_types = [type_hints .get (p .name , Any ) for p in params ]
5579 return_type = type_hints .get ("return" , Any )
5680 return method_name , params_types , return_type
81+ except RpcMethodConfigurationError :
82+ raise
5783 except Exception :
5884 return method .__name__ , [Any ], Any
5985
@@ -70,6 +96,20 @@ def _create_method_descriptor(
7096 return_decoder : Optional [SerializingFunction ] = None ,
7197 ** kwargs ,
7298 ) -> MethodDescriptor :
99+ """
100+ Create a MethodDescriptor with serialization configuration
101+ :param method: the actual function/method
102+ :param method_name: RPC method name
103+ :param params_types: parameter type hints
104+ :param return_type: return type hint
105+ :param rpc_type: type of RPC (unary, stream, etc.)
106+ :param codec: serialization codec (json, pb, etc.)
107+ :param param_encoder: deserialization function
108+ :param return_decoder: serialization function
109+ :param kwargs: additional codec args
110+ :return: MethodDescriptor instance
111+ :rtype: MethodDescriptor
112+ """
73113 if param_encoder is None or return_decoder is None :
74114 codec_kwargs = {
75115 "transport_type" : codec or "json" ,
@@ -101,6 +141,18 @@ def unary(
101141 response_serializer : Optional [SerializingFunction ] = None ,
102142 ** kwargs ,
103143 ) -> "RpcMethodHandler" :
144+ """
145+ Register a unary RPC method handler
146+ :param method: the callable function
147+ :param method_name: RPC method name
148+ :param params_types: input types
149+ :param return_type: output type
150+ :param codec: serialization codec
151+ :param request_deserializer: custom deserializer
152+ :param response_serializer: custom serializer
153+ :return: RpcMethodHandler instance
154+ :rtype: RpcMethodHandler
155+ """
104156 inferred_name , inferred_param_types , inferred_return_type = cls ._infer_types_from_method (method )
105157 resolved_method_name = method_name or inferred_name
106158 resolved_param_types = params_types or inferred_param_types
@@ -133,6 +185,18 @@ def client_stream(
133185 response_serializer : Optional [SerializingFunction ] = None ,
134186 ** kwargs ,
135187 ) -> "RpcMethodHandler" :
188+ """
189+ Register a client-streaming RPC method handler
190+ :param method: the callable function
191+ :param method_name: RPC method name
192+ :param params_types: input types
193+ :param return_type: output type
194+ :param codec: serialization codec
195+ :param request_deserializer: custom deserializer
196+ :param response_serializer: custom serializer
197+ :return: RpcMethodHandler instance
198+ :rtype: RpcMethodHandler
199+ """
136200 inferred_name , inferred_param_types , inferred_return_type = cls ._infer_types_from_method (method )
137201 resolved_method_name = method_name or inferred_name
138202 resolved_param_types = params_types or inferred_param_types
@@ -165,6 +229,18 @@ def server_stream(
165229 response_serializer : Optional [SerializingFunction ] = None ,
166230 ** kwargs ,
167231 ) -> "RpcMethodHandler" :
232+ """
233+ Register a server-streaming RPC method handler
234+ :param method: the callable function
235+ :param method_name: RPC method name
236+ :param params_types: input types
237+ :param return_type: output type
238+ :param codec: serialization codec
239+ :param request_deserializer: custom deserializer
240+ :param response_serializer: custom serializer
241+ :return: RpcMethodHandler instance
242+ :rtype: RpcMethodHandler
243+ """
168244 inferred_name , inferred_param_types , inferred_return_type = cls ._infer_types_from_method (method )
169245 resolved_method_name = method_name or inferred_name
170246 resolved_param_types = params_types or inferred_param_types
@@ -197,6 +273,18 @@ def bi_stream(
197273 response_serializer : Optional [SerializingFunction ] = None ,
198274 ** kwargs ,
199275 ) -> "RpcMethodHandler" :
276+ """
277+ Register a bidirectional streaming RPC method handler
278+ :param method: the callable function
279+ :param method_name: RPC method name
280+ :param params_types: input types
281+ :param return_type: output type
282+ :param codec: serialization codec
283+ :param request_deserializer: custom deserializer
284+ :param response_serializer: custom serializer
285+ :return: RpcMethodHandler instance
286+ :rtype: RpcMethodHandler
287+ """
200288 inferred_name , inferred_param_types , inferred_return_type = cls ._infer_types_from_method (method )
201289 resolved_method_name = method_name or inferred_name
202290 resolved_param_types = params_types or inferred_param_types
@@ -219,9 +307,20 @@ def bi_stream(
219307
220308
221309class RpcServiceHandler :
310+ """
311+ Rpc service handler that maps method names to their corresponding RpcMethodHandler.
312+ """
313+
222314 __slots__ = ["_service_name" , "_method_handlers" ]
223315
224- def __init__ (self , service_name : str , method_handlers : list [RpcMethodHandler ]):
316+ def __init__ (self , service_name : str , method_handlers : List [RpcMethodHandler ]):
317+ """
318+ Initialize the RpcServiceHandler
319+ :param service_name: the name of the service.
320+ :type service_name: str
321+ :param method_handlers: list of RpcMethodHandler instances
322+ :type method_handlers: List[RpcMethodHandler]
323+ """
225324 self ._service_name = service_name
226325 self ._method_handlers : dict [str , RpcMethodHandler ] = {}
227326
@@ -231,8 +330,18 @@ def __init__(self, service_name: str, method_handlers: list[RpcMethodHandler]):
231330
232331 @property
233332 def service_name (self ) -> str :
333+ """
334+ Get the service name
335+ :return: the service name
336+ :rtype: str
337+ """
234338 return self ._service_name
235339
236340 @property
237341 def method_handlers (self ) -> dict [str , RpcMethodHandler ]:
238- return self ._method_handlers
342+ """
343+ Get the registered RPC method handlers
344+ :return: mapping of method names to handlers
345+ :rtype: Dict[str, RpcMethodHandler]
346+ """
347+ return self ._method_handlers
0 commit comments