mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-19 00:02:03 +00:00
feat(python): type is automatically inferred from default parameters
This commit is contained in:
Generated
+1
-1
@@ -4353,7 +4353,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-audit"
|
||||
version = "0.1.0"
|
||||
version = "1.41.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"serde",
|
||||
|
||||
@@ -14,7 +14,7 @@ use regex::Regex;
|
||||
|
||||
use serde_json::json;
|
||||
use windmill_common::error;
|
||||
use windmill_parser::{Arg, MainArgSignature, Typ};
|
||||
use windmill_parser::{json_to_typ, Arg, MainArgSignature, Typ};
|
||||
|
||||
use rustpython_parser::{
|
||||
ast::{Constant, ExprKind, Located, StmtKind},
|
||||
@@ -22,6 +22,7 @@ use rustpython_parser::{
|
||||
};
|
||||
|
||||
const DEF_MAIN: &str = "def main(";
|
||||
const FUNCTION_CALL: &str = "<function call>";
|
||||
|
||||
fn filter_non_main(code: &str) -> String {
|
||||
let mut filtered_code = String::new();
|
||||
@@ -90,24 +91,32 @@ pub fn parse_python_signature(code: &str) -> error::Result<MainArgSignature> {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut typ = x.annotation.map_or(Typ::Unknown, |e| match *e {
|
||||
Located { node: ExprKind::Name { id, .. }, .. } => match id.as_ref() {
|
||||
"str" => Typ::Str(None),
|
||||
"float" => Typ::Float,
|
||||
"int" => Typ::Int,
|
||||
"bool" => Typ::Bool,
|
||||
"dict" => Typ::Object(vec![]),
|
||||
"list" => Typ::List(Box::new(Typ::Str(None))),
|
||||
"bytes" => Typ::Bytes,
|
||||
"datetime" => Typ::Datetime,
|
||||
"datetime.datetime" => Typ::Datetime,
|
||||
_ => Typ::Unknown,
|
||||
},
|
||||
_ => Typ::Unknown,
|
||||
});
|
||||
if typ == Typ::Unknown
|
||||
&& default.is_some()
|
||||
&& default != Some(json!(FUNCTION_CALL))
|
||||
{
|
||||
typ = json_to_typ(default.as_ref().unwrap());
|
||||
}
|
||||
Arg {
|
||||
otyp: None,
|
||||
name: x.arg,
|
||||
typ: x.annotation.map_or(Typ::Unknown, |e| match *e {
|
||||
Located { node: ExprKind::Name { id, .. }, .. } => match id.as_ref() {
|
||||
"str" => Typ::Str(None),
|
||||
"float" => Typ::Float,
|
||||
"int" => Typ::Int,
|
||||
"bool" => Typ::Bool,
|
||||
"dict" => Typ::Object(vec![]),
|
||||
"list" => Typ::List(Box::new(Typ::Str(None))),
|
||||
"bytes" => Typ::Bytes,
|
||||
"datetime" => Typ::Datetime,
|
||||
"datetime.datetime" => Typ::Datetime,
|
||||
_ => Typ::Unknown,
|
||||
},
|
||||
_ => Typ::Unknown,
|
||||
}),
|
||||
typ: typ,
|
||||
has_default: default.is_some(),
|
||||
default,
|
||||
}
|
||||
@@ -147,7 +156,7 @@ fn to_value(et: &ExprKind) -> Option<serde_json::Value> {
|
||||
.collect::<Vec<_>>();
|
||||
Some(json!(v))
|
||||
}
|
||||
ExprKind::Call { .. } => Some(json!("<function call>")),
|
||||
ExprKind::Call { .. } => Some(json!(FUNCTION_CALL)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -277,28 +286,28 @@ def main(test1: str, name: datetime.datetime = datetime.now(), byte: bytes = byt
|
||||
Arg {
|
||||
otyp: None,
|
||||
name: "f".to_string(),
|
||||
typ: Typ::Unknown,
|
||||
typ: Typ::Str(None),
|
||||
default: Some(json!("wewe")),
|
||||
has_default: true
|
||||
},
|
||||
Arg {
|
||||
otyp: None,
|
||||
name: "g".to_string(),
|
||||
typ: Typ::Unknown,
|
||||
typ: Typ::Int,
|
||||
default: Some(json!(21)),
|
||||
has_default: true
|
||||
},
|
||||
Arg {
|
||||
otyp: None,
|
||||
name: "h".to_string(),
|
||||
typ: Typ::Unknown,
|
||||
typ: Typ::List(Box::new(Typ::Int)),
|
||||
default: Some(json!([1, 2])),
|
||||
has_default: true
|
||||
},
|
||||
Arg {
|
||||
otyp: None,
|
||||
name: "i".to_string(),
|
||||
typ: Typ::Unknown,
|
||||
typ: Typ::Bool,
|
||||
default: Some(json!(true)),
|
||||
has_default: true
|
||||
},
|
||||
@@ -366,7 +375,7 @@ def main(test1: str,
|
||||
import os
|
||||
|
||||
def main(test1: str,
|
||||
name: datetime.datetime = datetime.now(),
|
||||
name = \"test\",
|
||||
byte: bytes = bytes(1)): return
|
||||
|
||||
";
|
||||
@@ -387,8 +396,8 @@ def main(test1: str,
|
||||
Arg {
|
||||
otyp: None,
|
||||
name: "name".to_string(),
|
||||
typ: Typ::Unknown,
|
||||
default: Some(json!("<function call>")),
|
||||
typ: Typ::Str(None),
|
||||
default: Some(json!("test")),
|
||||
has_default: true
|
||||
},
|
||||
Arg {
|
||||
|
||||
@@ -7,9 +7,8 @@
|
||||
*/
|
||||
use deno_core::{serde_v8, v8, JsRuntime, RuntimeOptions};
|
||||
use windmill_common::error;
|
||||
use windmill_parser::{Arg, MainArgSignature, ObjectProperty, Typ};
|
||||
use windmill_parser::{json_to_typ, Arg, MainArgSignature, ObjectProperty, Typ};
|
||||
|
||||
use serde_json::Value;
|
||||
use swc_common::{sync::Lrc, FileName, SourceMap, SourceMapper, Spanned};
|
||||
use swc_ecma_ast::{
|
||||
ArrayLit, AssignPat, BigInt, BindingIdent, Bool, Decl, ExportDecl, Expr, FnDecl, Ident, Lit,
|
||||
@@ -130,22 +129,6 @@ fn binding_ident_to_arg(BindingIdent { id, type_ann }: &BindingIdent) -> (String
|
||||
(id.sym.to_string(), typ, nullable)
|
||||
}
|
||||
|
||||
fn json_to_typ(js: &Value) -> Typ {
|
||||
match js {
|
||||
Value::String(_) => Typ::Str(None),
|
||||
Value::Number(n) if n.is_i64() => Typ::Int,
|
||||
Value::Number(_) => Typ::Float,
|
||||
Value::Bool(_) => Typ::Bool,
|
||||
Value::Object(o) => Typ::Object(
|
||||
o.iter()
|
||||
.map(|(k, v)| ObjectProperty { key: k.to_string(), typ: Box::new(json_to_typ(v)) })
|
||||
.collect(),
|
||||
),
|
||||
Value::Array(a) => Typ::List(Box::new(a.first().map(json_to_typ).unwrap_or(Typ::Unknown))),
|
||||
_ => Typ::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
fn tstype_to_typ(ts_type: &TsType) -> (Typ, bool) {
|
||||
//println!("{:?}", ts_type);
|
||||
match ts_type {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
use serde::Serialize;
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Serialize, Debug, PartialEq)]
|
||||
pub struct MainArgSignature {
|
||||
@@ -47,3 +48,19 @@ pub struct Arg {
|
||||
pub default: Option<serde_json::Value>,
|
||||
pub has_default: bool,
|
||||
}
|
||||
|
||||
pub fn json_to_typ(js: &Value) -> Typ {
|
||||
match js {
|
||||
Value::String(_) => Typ::Str(None),
|
||||
Value::Number(n) if n.is_i64() => Typ::Int,
|
||||
Value::Number(_) => Typ::Float,
|
||||
Value::Bool(_) => Typ::Bool,
|
||||
Value::Object(o) => Typ::Object(
|
||||
o.iter()
|
||||
.map(|(k, v)| ObjectProperty { key: k.to_string(), typ: Box::new(json_to_typ(v)) })
|
||||
.collect(),
|
||||
),
|
||||
Value::Array(a) => Typ::List(Box::new(a.first().map(json_to_typ).unwrap_or(Typ::Unknown))),
|
||||
_ => Typ::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
[package]
|
||||
name = "windmill-audit"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "windmill_audit"
|
||||
|
||||
@@ -10,8 +10,9 @@ The client is used to interact with windmill itself through its standard API.
|
||||
One can explore the methods available through autocompletion of \`wmill.XXX\`.
|
||||
"""
|
||||
|
||||
def main(name: str = "Nicolas Bourbaki",
|
||||
age: int = 42,
|
||||
def main(name = "Nicolas Bourbaki",
|
||||
age = 42,
|
||||
with_type: str,
|
||||
obj: dict = {"even": "dicts"},
|
||||
l: list = ["or", "lists!"],
|
||||
file_: bytes = bytes(0),
|
||||
@@ -22,7 +23,12 @@ def main(name: str = "Nicolas Bourbaki",
|
||||
print("and its acolytes..", age, obj, l, len(file_), dtime)
|
||||
# retrieve variables, including secrets by querying the windmill platform.
|
||||
# secret fetching is audited by windmill.
|
||||
secret = wmill.get_variable("g/all/pretty_secret")
|
||||
|
||||
try:
|
||||
secret = wmill.get_variable("g/all/pretty_secret")
|
||||
except:
|
||||
secret = "No secret yet at g/all/pretty_secret!"
|
||||
|
||||
print(f"The env variable at \`g/all/pretty_secret\`: {secret}")
|
||||
# interact with the windmill platform to get the version
|
||||
version = wmill.get_version()
|
||||
|
||||
Reference in New Issue
Block a user