Source code for ReFreSH.MobileSuit.Core.SuitMethodShell

from typing import Callable, Any, List
import inspect

from . import SuitBuildUtils

from .SuitMethodParameterInfo import TailParameterType

from ..Decorators.DecoratorUtils import get_info
from ..RequestStatus import RequestStatus
from .SuitContext import SuitContext
from .SuitShell import SuitShell, MemberType


[docs] class SuitMethodShell(SuitShell): """ Object's Member which may be a method. """ def __init__(self, method: Callable, factory: Callable[[SuitContext], Any], absoluteName=None): super().__init__(method, factory, absoluteName) self.Method = method sig = inspect.signature(method) parameters = [param for (_, param) in filter(lambda x: x[0] != 'self', sig.parameters.items())] if 'self' not in sig.parameters: # For static methods self._instanceFactory = lambda _: None else: self._instanceFactory=factory self.Parameters = parameters self._suitMethodParameterInfo = SuitBuildUtils.GetMethodParameterInfo( self.Method) info = get_info(method) if info is None: # TODO: Auto Info self.Type = MemberType.MethodWithoutInfo infoSb = '' if self._suitMethodParameterInfo.MaxParameterCount > 0: for parameter in self.Parameters: infoSb += parameter.name if parameter.annotation == list or parameter.annotation == tuple: infoSb += "[]" elif getattr(parameters[-1].annotation, "IDynamicParameter", None) is not None: infoSb += "{}" elif parameter.default != inspect.Parameter.empty: infoSb += f"={parameter.default}" else: infoSb += "" infoSb += ',' self._info = infoSb[:-1] else: self.Type = MemberType.MethodWithInfo self._info = info @property def MemberCount(self): return len(self.Parameters)
[docs] @classmethod def FromDelegate(cls, methodName, delegate: Callable): return cls(delegate, lambda _: None, methodName)
[docs] @classmethod def FromInstance(cls, method: Callable, factory: Callable[[SuitContext], Any]): return cls(method, factory)
[docs] def MayExecute(self, request: List[str]) -> bool: return len(request) > 0 and request[0].lower() in self.FriendlyNames and self.CanFitTo(len(request) - 1)
async def _Execute(self, context: SuitContext, args): try: obj = self.GetInstance(context) if obj is not None: if args: returnValue=self.Method(obj, *args) else: returnValue=self.Method(obj) else: if args: returnValue=self.Method(*args) else: returnValue=self.Method() if inspect.isawaitable(returnValue): returnValue = await returnValue if isinstance(returnValue, RequestStatus): context.RequestStatus = returnValue context.Response = None else: context.RequestStatus = RequestStatus.Handled context.Response = str( returnValue) if returnValue is not None else None except Exception as ex: context.RequestStatus = RequestStatus.Faulted raise ex
[docs] def CanFitTo(self, argumentCount: int) -> bool: return self._suitMethodParameterInfo.MinParameterCount <= argumentCount <= self._suitMethodParameterInfo.MaxParameterCount
[docs] async def Execute(self, context: SuitContext): if self._suitMethodParameterInfo.TailParameterType == TailParameterType.NoParameter: await self._Execute(context, None) return args = context.Request[1:] try: pass_ = SuitBuildUtils.GetArgsInternal( self.Method, self._suitMethodParameterInfo, args, context) if pass_ is None: return await self._Execute(context, pass_) except ValueError: pass