mirror of
https://github.com/gorules/zen.git
synced 2026-10-04 00:02:18 +00:00
feat: expose expressions through bindings; (#86)
* feat: expose expressions through bindings; * fix fmt
This commit is contained in:
@@ -12,9 +12,10 @@ crate-type = ["cdylib"]
|
||||
[dependencies]
|
||||
async-trait = "0.1.68"
|
||||
anyhow = "1.0.71"
|
||||
pyo3 = { version = "0.18.3", features = ["anyhow", "serde"] }
|
||||
pythonize = "0.18.0"
|
||||
pyo3 = { version = "0.19.2", features = ["anyhow", "serde"] }
|
||||
pythonize = "0.19.0"
|
||||
serde = "1.0.163"
|
||||
serde_json = "1.0.96"
|
||||
futures = "0.3.28"
|
||||
zen-engine = { path = "../../core/engine" }
|
||||
zen-engine = { path = "../../core/engine" }
|
||||
zen-expression = { path = "../../core/expression" }
|
||||
@@ -28,7 +28,6 @@ class ZenEngine(unittest.TestCase):
|
||||
r2 = tableDecision.evaluate({"input": 5})
|
||||
r3 = tableDecision.evaluate({"input": 12})
|
||||
|
||||
print(r1)
|
||||
self.assertEqual(r1["result"]["output"], 20)
|
||||
self.assertEqual(r2["result"]["output"], 0)
|
||||
self.assertEqual(r3["result"]["output"], 10)
|
||||
@@ -42,5 +41,13 @@ class ZenEngine(unittest.TestCase):
|
||||
r = functionDecision.evaluate({"input": 15})
|
||||
self.assertEqual(r["result"]["output"], 30)
|
||||
|
||||
def test_evaluate_expression(self):
|
||||
result = zen.evaluate_expression("sum(a)", { "a": [1, 2, 3, 4] })
|
||||
self.assertEqual(result, 10)
|
||||
|
||||
def test_evaluate_unary_expression(self):
|
||||
result = zen.evaluate_unary_expression("'FR', 'ES', 'GB'", { "$": "GB" })
|
||||
self.assertEqual(result, True)
|
||||
|
||||
# run the test
|
||||
unittest.main()
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
use anyhow::{anyhow, Context};
|
||||
use pyo3::types::PyDict;
|
||||
use pyo3::{pyfunction, PyObject, PyResult, Python, ToPyObject};
|
||||
use pythonize::depythonize;
|
||||
use serde_json::Value;
|
||||
|
||||
use zen_expression::isolate::Isolate;
|
||||
|
||||
use crate::value::PyValue;
|
||||
|
||||
#[pyfunction]
|
||||
pub fn evaluate_expression(
|
||||
py: Python,
|
||||
expression: String,
|
||||
ctx: Option<&PyDict>,
|
||||
) -> PyResult<PyObject> {
|
||||
let isolate = Isolate::default();
|
||||
let ctx = ctx
|
||||
.map(|ctx| depythonize(ctx))
|
||||
.transpose()
|
||||
.context("Failed to convert context")?;
|
||||
|
||||
if let Some(env_value) = ctx {
|
||||
isolate.inject_env(&env_value);
|
||||
}
|
||||
|
||||
let result = isolate
|
||||
.run_standard(expression.as_str())
|
||||
.map_err(|e| anyhow!(serde_json::to_string(&e).unwrap_or_else(|_| e.to_string())))?;
|
||||
|
||||
Ok(PyValue(result).to_object(py))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
pub fn evaluate_unary_expression(
|
||||
py: Python,
|
||||
expression: String,
|
||||
ctx: &PyDict,
|
||||
) -> PyResult<PyObject> {
|
||||
let env_value: Value = depythonize(ctx).context("Failed to convert context")?;
|
||||
|
||||
let Some(env_object) = env_value.as_object() else {
|
||||
return Err(anyhow!("Context must be an object").into());
|
||||
};
|
||||
|
||||
if !env_object.contains_key("$") {
|
||||
return Err(anyhow!("Context must contain '$' reference.").into());
|
||||
}
|
||||
|
||||
let isolate = Isolate::default();
|
||||
isolate.inject_env(&env_value);
|
||||
|
||||
let result = isolate
|
||||
.run_unary(expression.as_str())
|
||||
.map_err(|e| anyhow!(serde_json::to_string(&e).unwrap_or_else(|_| e.to_string())))?;
|
||||
|
||||
Ok(PyValue(result).to_object(py))
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
use crate::decision::PyZenDecision;
|
||||
use crate::engine::PyZenEngine;
|
||||
use crate::expression::{evaluate_expression, evaluate_unary_expression};
|
||||
use pyo3::types::PyModule;
|
||||
use pyo3::{pymodule, PyResult, Python};
|
||||
use pyo3::{pymodule, wrap_pyfunction, PyResult, Python};
|
||||
|
||||
mod decision;
|
||||
mod engine;
|
||||
mod expression;
|
||||
mod loader;
|
||||
mod value;
|
||||
|
||||
@@ -12,5 +14,8 @@ mod value;
|
||||
fn zen(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_class::<PyZenEngine>()?;
|
||||
m.add_class::<PyZenDecision>()?;
|
||||
m.add_function(wrap_pyfunction!(evaluate_expression, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(evaluate_unary_expression, m)?)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user