1- import functools as ft
21import inspect
32from typing import Any , Dict , Iterable , List , Optional , Tuple
43
@@ -15,7 +14,7 @@ class ValidationError(Exception):
1514
1615class BaseValidator :
1716 """
18- Base method parameters validator. Uses :py:func:`inspect.signature` for validation.
17+ Base method parameters validator factory . Uses :py:func:`inspect.signature` for validation.
1918
2019 :param exclude_param: a function that decides if the parameters must be excluded
2120 from validation (useful for dependency injection)
@@ -29,7 +28,7 @@ def validate(self, maybe_method: Optional[MethodType] = None, **kwargs: Any) ->
2928 Decorator marks a method the parameters of which to be validated when calling it using JSON-RPC protocol.
3029
3130 :param maybe_method: method the parameters of which to be validated or ``None`` if called as @validate(...)
32- :param kwargs: validator arguments
31+ :param kwargs: method validator arguments
3332 """
3433
3534 def decorator (method : MethodType ) -> MethodType :
@@ -43,28 +42,39 @@ def decorator(method: MethodType) -> MethodType:
4342 else :
4443 return decorator (maybe_method )
4544
46- def validate_method (
47- self , method : MethodType , params : Optional ['JsonRpcParams' ], exclude : Iterable [str ] = (), ** kwargs : Any ,
48- ) -> Dict [str , Any ]:
45+ def build_method_validator (
46+ self ,
47+ method : MethodType ,
48+ exclude : Iterable [str ] = (),
49+ ** kwargs : Any ,
50+ ) -> 'BaseMethodValidator' :
51+ return BaseMethodValidator (method , self ._exclude_param , exclude )
52+
53+
54+ class BaseMethodValidator :
55+ """
56+ Base method parameters validator.
57+ """
58+
59+ def __init__ (self , method : MethodType , exclude_func : ExcludeFunc , exclude : Iterable [str ] = ()):
60+ self ._method = method
61+ self ._signature = self ._build_signature (method , exclude_func , tuple (exclude ))
62+
63+ def validate_params (self , params : Optional ['JsonRpcParams' ]) -> Dict [str , Any ]:
4964 """
5065 Validates params against method signature.
5166
52- :param method: method to validate parameters against
5367 :param params: parameters to be validated
54- :param exclude: parameter names to be excluded from validation
55- :param kwargs: additional validator arguments
5668
5769 :raises: :py:class:`pjrpc.server.validators.ValidationError`
5870 :returns: bound method parameters
5971 """
6072
61- signature = self .signature (method , tuple (exclude ))
62- return self .bind (signature , params ).arguments
73+ return self ._bind (params ).arguments
6374
64- def bind (self , signature : inspect . Signature , params : Optional ['JsonRpcParams' ]) -> inspect .BoundArguments :
75+ def _bind (self , params : Optional ['JsonRpcParams' ]) -> inspect .BoundArguments :
6576 """
6677 Binds parameters to method.
67- :param signature: method to bind parameters to
6878 :param params: parameters to be bound
6979
7080 :raises: ValidationError is parameters binding failed
@@ -75,12 +85,16 @@ def bind(self, signature: inspect.Signature, params: Optional['JsonRpcParams'])
7585 method_kwargs = params if isinstance (params , dict ) else {}
7686
7787 try :
78- return signature .bind (* method_args , ** method_kwargs )
88+ return self . _signature .bind (* method_args , ** method_kwargs )
7989 except TypeError as e :
8090 raise ValidationError (str (e )) from e
8191
82- @ft .lru_cache (None )
83- def signature (self , method : MethodType , exclude : Tuple [str , ...]) -> inspect .Signature :
92+ def _build_signature (
93+ self ,
94+ method : MethodType ,
95+ exclude_func : ExcludeFunc ,
96+ exclude : Tuple [str , ...] = (),
97+ ) -> inspect .Signature :
8498 """
8599 Returns method signature.
86100
@@ -93,7 +107,7 @@ def signature(self, method: MethodType, exclude: Tuple[str, ...]) -> inspect.Sig
93107
94108 method_parameters : List [inspect .Parameter ] = []
95109 for param in signature .parameters .values ():
96- if param .name not in exclude and not self . _exclude_param (param .name , param .annotation , param .default ):
110+ if param .name not in exclude and not exclude_func (param .name , param .annotation , param .default ):
97111 method_parameters .append (param )
98112
99113 return signature .replace (parameters = method_parameters )
0 commit comments