Source code for neuralib.sqlp.func_dec

from __future__ import annotations

import functools
import inspect

from typing_extensions import LiteralString

from neuralib.util.func import create_fn
from . import expr

__all__ = ['as_func_expr']


[docs] def as_func_expr(f=None, *, func=expr.SqlFuncOper): # noinspection PyShadowingNames def _as_func_expr(f): func_name = f.__name__.upper() s = inspect.signature(f) para = [] code = [] locals = dict(__oper__=func, __func__=f) n_none = 0 for n, p in s.parameters.items(): if p.kind == inspect.Parameter.VAR_POSITIONAL: para.append('*' + n) n_none = -1 break elif p.default is inspect.Parameter.empty: para.append(n) elif p.default is None: para.append((n, 'None')) n_none += 1 else: raise RuntimeError() if p.annotation == 'LiteralString' or p.annotation == LiteralString: code.append(f'{n} = __literal__(repr({n}))') locals['__literal__'] = expr.SqlLiteral if func == expr.SqlFuncOper: func_call = '__func__,' else: func_call = '' if n_none == -1: args = ', '.join(para) code.append(f'return __oper__("{func_name}", {func_call} {args})') elif n_none == 0: args = ', '.join(para) code.append(f'return __oper__("{func_name}", {func_call} {args})') elif n_none == 1: assert isinstance(para[-1], tuple) z = para[-1][0] code.append(f'if {z} is None:') args = ', '.join(para[:-1]) code.append(f' return __oper__("{func_name}", {func_call} {args})') code.append('else:') args = args + ', ' + z code.append(f' return __oper__("{func_name}", {func_call} {args})') else: args = ', '.join(para[:-n_none]) for i in range(n_none, 0, -1): assert isinstance(para[-i], tuple) z = para[-i][0] code.append(f'if {z} is None:') code.append(f' return __oper__("{func_name}", {func_call} {args})') args = args + ', ' + z code.append(f'return __oper__("{func_name}", {func_call} {args})') ret = create_fn(f.__name__, para, '\n'.join(code), locals=locals) return functools.wraps(f)(ret) if f is None: return _as_func_expr else: return _as_func_expr(f)