Source code for argclz.dispatch.builder

import inspect
import sys
from typing import Callable, TypeVar, Generic

from .core import ARGCLZ_DISPATCH_COMMAND, DispatchCommand
from ..validator import Validator

__all__ = ['DispatchCommandBuilder']

T = TypeVar('T')
P = inspect.Parameter


[docs] class DispatchCommandBuilder: """ (internal) Do not use class directly. """
[docs] def __init__(self, func): self.func = func self.signature = inspect.signature(func, eval_str=True) self.validators = {}
[docs] @classmethod def of(cls, f): ret = getattr(f, ARGCLZ_DISPATCH_COMMAND, None) if ret is None: ret = DispatchCommandBuilder(f) setattr(f, ARGCLZ_DISPATCH_COMMAND, ret) elif isinstance(ret, DispatchCommandBuilder): pass elif isinstance(ret, DispatchCommand): raise RuntimeError(f'{f.__name__} already frozen') else: raise TypeError() return ret
[docs] def validator_for(self, arg: str, caster: Callable[[str], T] | None = None, validator: Validator | None = None): try: p = self.signature.parameters[arg] except KeyError: print(f'unknown arg name : {arg} for function {self.func.__name__}', file=sys.stderr) return if caster is None: from .._types import caster_by_annotation if p.annotation is P.empty: raise RuntimeError(f'missing type : {self.func.__name__}({arg})') caster = caster_by_annotation(arg, p.annotation) # pyright: ignore[reportAssignmentType] self.validators[arg] = TypeCasterWithValidator(caster, validator)
[docs] def build(self, command: str, aliases: tuple[str, ...], order: float = 5, group: str | None = None, usage: str | None = None, hidden=False) -> DispatchCommand: ret = DispatchCommand(group, command, aliases, order, usage, self.func, self.validators, hidden) setattr(self.func, ARGCLZ_DISPATCH_COMMAND, ret) return ret
class TypeCasterWithValidator(Generic[T]): """ (internal) Do not use class directly. """ def __init__(self, caster: Callable[[str], T] | None, validator: Callable[[T], bool] | None): self.caster = caster self.validator = validator def __call__(self, raw_value: str) -> T: result: T if self.caster is not None: try: result = self.caster(raw_value) except BaseException: raise else: result = raw_value # pyright: ignore[reportAssignmentType] if self.validator is not None: try: fail = not self.validator(result) except BaseException: raise else: if fail: raise ValueError(f'fail validation : "{raw_value}"') return result