diff --git a/func_py/func.py b/func_py/func.py index 05e6607..653c6a9 100644 --- a/func_py/func.py +++ b/func_py/func.py @@ -40,7 +40,7 @@ class function: sig_g = signature(g) g_req_params = [v for k, v in sig_g.parameters.items() if v.default == _empty] - g_typed_req_params = [p if p.annotation == _empty else Parameter(name=p.name, annotation=Any, kind=Parameter.POSITIONAL_ONLY) for p in g_req_params] + g_typed_req_params = [p if p.annotation == _empty else Parameter(name=p.name, annotation=Any, kind=Parameter.POSITIONAL_OR_KEYWORD) for p in g_req_params] def h(*args, **kwargs): return f(g(*args, **kwargs)) @@ -49,18 +49,33 @@ class function: h.__signature__ = sig_g.replace(parameters=g_typed_req_params, return_annotation=Any if f_ret_type == _empty else f_ret_type) return function(h) + #TODO: complexity prop + + #TODO: getter for inverse function #TODO: implement fly weight pattern def __init__(self, f): self.original_func = f self.signature = signature(f) #TODO: change to support pattern matching: sig ((int, str), {"name": str}) - self.__signature__ = signature(f) + + sig = signature(f) + req_params = {k: v for k, v in sig.parameters.items() if v.default == _empty} + params = [] + for name, p in req_params.items(): + if p.annotation == _empty: + params.append( Parameter(name=name, annotation=Any, kind=Parameter.POSITIONAL_OR_KEYWORD) ) + else: + params.append(p) + + self.__signature__ = sig.replace(parameters=params, return_annotation=Any if sig.return_annotation == _empty else sig.return_annotation) + + self.cache = {} self.is_pure = True def __str__(self): - return str(signature(self.original_func)).replace(", /)", ")") + return str(self.__signature__) def __repr__(self): return str(self) @@ -77,14 +92,17 @@ class function: @property def required_args(self): - return [(k, v) for k, v in signature(self.original_func).parameters.items() if v.default == _empty] + return [(name, param) for name, param in self.__signature__.parameters.items() if param.default == _empty] + def __call__(self, *args, **kwargs): - if len(args) < len(self.required_args): - sig = signature(self.original_func) - f = partial(self.original_func, *args) - req_params = [v for k, v in sig.parameters.items() if v.default == _empty] - remaining_params = req_params[len(args):] + provided_req_kwargs = {k for k, p in self.required_args if k in kwargs} + num_given_req_args = len(args) + len(provided_req_kwargs) + + if num_given_req_args < len(self.required_args): + sig = self.__signature__ + f = partial(self.original_func, *args, **kwargs) + remaining_params = [v for k, v in sig.parameters.items() if v.default == _empty and k not in provided_req_kwargs][len(args):] f.__signature__ = sig.replace(parameters=remaining_params, return_annotation=Any if sig.return_annotation == _empty else sig.return_annotation) return function(f)