mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2025-12-24 23:19:57 +00:00
* test: for builtin functions * test: expect fail for `datetime()` * feat: add `interval()` fn(WIP) * feat: `interval()` fn in builtin(UNTEST) * refactor: move `py_vec_obj_to_array` to util.rs * style: fmt * test: simple `interval()` cases * test: `interval()` with `last()`&`first()` * doc: `ts` param of `interval()` * log: common_telemetry for logging in script crate * doc: corrsponding test fn for each .ron file * feat: change to`mpsc` for schedule_job * test: schedule_job * dep: rm rustpython dep in common-function * refactor: mv `schedule_job` into `Script` trait * test: change to use `interval` to sample datapoint * feat: add gen_none_array for generate None Array * feat: impl Missing value for `prev`&`next` * test: `sum(prev(values))` * doc: add comment for why not support Float16 in `prev()` * feat: add `interval` in py side mock module * style: cargo fmt * refactor: according to comments * refactor: extract `apply_interval_function` * style: cargo fmt * refactor: remove `schedule()` * style: cargo fmt
83 lines
2.5 KiB
Python
83 lines
2.5 KiB
Python
"""
|
|
Note this is a mock library, if not connected to database,
|
|
it can only run on mock data and support by numpy
|
|
"""
|
|
from typing import Any
|
|
import numpy as np
|
|
from .greptime import i32,i64,f32,f64, vector, interval, prev, datetime, log, sum, sqrt, pow, nan, copr, coprocessor
|
|
|
|
import inspect
|
|
import functools
|
|
import ast
|
|
|
|
|
|
|
|
def mock_tester(
|
|
func,
|
|
env:dict,
|
|
table=None
|
|
):
|
|
"""
|
|
Mock tester helper function,
|
|
What it does is replace `@coprocessor` with `@mock_cpor` and add a keyword `env=env`
|
|
like `@mock_copr(args=...,returns=...,env=env)`
|
|
"""
|
|
code = inspect.getsource(func)
|
|
tree = ast.parse(code)
|
|
tree = HackyReplaceDecorator("env").visit(tree)
|
|
new_func = tree.body[0]
|
|
fn_name = new_func.name
|
|
|
|
code_obj = compile(tree, "<embedded>", "exec")
|
|
exec(code_obj)
|
|
|
|
ret = eval("{}()".format(fn_name))
|
|
return ret
|
|
|
|
def mock_copr(args, returns, sql=None, env:None|dict=None):
|
|
"""
|
|
This should not be used directly by user
|
|
"""
|
|
def decorator_copr(func):
|
|
@functools.wraps(func)
|
|
def wrapper_do_actual(*fn_args, **fn_kwargs):
|
|
|
|
real_args = [env[name] for name in args]
|
|
ret = func(*real_args)
|
|
return ret
|
|
|
|
return wrapper_do_actual
|
|
return decorator_copr
|
|
|
|
class HackyReplaceDecorator(ast.NodeTransformer):
|
|
"""
|
|
This class accept a `env` dict for environment to extract args from,
|
|
and put `env` dict in the param list of `mock_copr` decorator, i.e:
|
|
|
|
a `@copr(args=["a", "b"], returns=["c"])` with call like mock_helper(abc, env={"a":2, "b":3})
|
|
|
|
will be transform into `@mock_copr(args=["a", "b"], returns=["c"], env={"a":2, "b":3})`
|
|
"""
|
|
def __init__(self, env: str) -> None:
|
|
# just for add `env` keyword
|
|
self.env = env
|
|
|
|
def visit_FunctionDef(self, node: ast.FunctionDef) -> Any:
|
|
new_node = node
|
|
decorator_list = new_node.decorator_list
|
|
if len(decorator_list)!=1:
|
|
return node
|
|
|
|
deco = decorator_list[0]
|
|
if deco.func.id!="coprocessor" and deco.func.id !="copr":
|
|
raise Exception("Expect a @copr or @coprocessor, found {}.".format(deco.func.id))
|
|
deco.func = ast.Name(id="mock_copr", ctx=ast.Load())
|
|
new_kw = ast.keyword(arg="env", value=ast.Name(id=self.env, ctx=ast.Load()))
|
|
deco.keywords.append(new_kw)
|
|
|
|
# Tie up loose ends in the AST.
|
|
ast.copy_location(new_node, node)
|
|
ast.fix_missing_locations(new_node)
|
|
self.generic_visit(node)
|
|
return new_node
|