mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-18 16:02:10 +00:00
migrate all jsonschema parser to wasms
This commit is contained in:
+1
-1
@@ -54,7 +54,7 @@ COPY /openflow.openapi.yaml /openflow.openapi.yaml
|
||||
COPY /backend/windmill-api/build_openapi.sh /backend/windmill-api/build_openapi.sh
|
||||
|
||||
RUN cd /backend/windmill-api && . ./build_openapi.sh
|
||||
COPY /backend/parsers/windmill-parser-py-wasm/pkg/ /backend/windmill-parser-py-wasm/pkg/
|
||||
COPY /backend/parsers/windmill-parser-wasm/pkg/ /backend/parsers/windmill-parser-wasm/pkg/
|
||||
|
||||
RUN npm run generate-backend-client
|
||||
ENV NODE_OPTIONS "--max-old-space-size=8192"
|
||||
|
||||
Vendored
+2
-1
@@ -5,5 +5,6 @@
|
||||
"./parsers/windmill-parser-ts-wasm/Cargo.toml",
|
||||
"./parsers/windmill-parser-ts-wasm/Cargo.toml",
|
||||
"./parsers/windmill-parser-ts-wasm/Cargo.toml"
|
||||
]
|
||||
],
|
||||
"rust-analyzer.showUnlinkedFileNotification": false
|
||||
}
|
||||
|
||||
Generated
+18
-18
@@ -4766,12 +4766,6 @@ version = "0.3.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-general-category"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2281c8c1d221438e373249e065ca4989c4c36952c211ff21a0ee91c44a3869e7"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-id"
|
||||
version = "0.3.3"
|
||||
@@ -5233,10 +5227,7 @@ dependencies = [
|
||||
"windmill-audit",
|
||||
"windmill-common",
|
||||
"windmill-parser",
|
||||
"windmill-parser-bash",
|
||||
"windmill-parser-go",
|
||||
"windmill-parser-py",
|
||||
"windmill-parser-ts",
|
||||
"windmill-parser-py-imports",
|
||||
"windmill-queue",
|
||||
]
|
||||
|
||||
@@ -5308,13 +5299,9 @@ name = "windmill-parser-bash"
|
||||
version = "1.109.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"phf 0.11.1",
|
||||
"regex",
|
||||
"serde_json",
|
||||
"unicode-general-category",
|
||||
"windmill-common",
|
||||
"windmill-parser",
|
||||
]
|
||||
|
||||
@@ -5325,15 +5312,23 @@ dependencies = [
|
||||
"anyhow",
|
||||
"gosyn",
|
||||
"itertools",
|
||||
"phf 0.11.1",
|
||||
"unicode-general-category",
|
||||
"windmill-common",
|
||||
"windmill-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py"
|
||||
version = "1.109.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools",
|
||||
"rustpython-parser",
|
||||
"serde_json",
|
||||
"windmill-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py-imports"
|
||||
version = "1.109.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools",
|
||||
@@ -5361,13 +5356,17 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-ts-wasm"
|
||||
name = "windmill-parser-wasm"
|
||||
version = "1.109.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde_json",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
"windmill-parser",
|
||||
"windmill-parser-bash",
|
||||
"windmill-parser-go",
|
||||
"windmill-parser-py",
|
||||
"windmill-parser-ts",
|
||||
]
|
||||
|
||||
@@ -5432,6 +5431,7 @@ dependencies = [
|
||||
"windmill-parser-bash",
|
||||
"windmill-parser-go",
|
||||
"windmill-parser-py",
|
||||
"windmill-parser-py-imports",
|
||||
"windmill-parser-ts",
|
||||
"windmill-queue",
|
||||
]
|
||||
|
||||
+4
-2
@@ -14,9 +14,11 @@ members = [
|
||||
"./windmill-api-client",
|
||||
"./parsers/windmill-parser",
|
||||
"./parsers/windmill-parser-ts",
|
||||
"./parsers/windmill-parser-ts-wasm",
|
||||
"./parsers/windmill-parser-wasm",
|
||||
"./parsers/windmill-parser-go",
|
||||
"./parsers/windmill-parser-bash",
|
||||
"./parsers/windmill-parser-py",
|
||||
"./parsers/windmill-parser-py-imports",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
@@ -74,6 +76,7 @@ windmill-audit = { path = "./windmill-audit" }
|
||||
windmill-parser = { path = "./parsers/windmill-parser" }
|
||||
windmill-parser-ts = { path = "./parsers/windmill-parser-ts" }
|
||||
windmill-parser-py = { path = "./parsers/windmill-parser-py" }
|
||||
windmill-parser-py-imports = { path = "./parsers/windmill-parser-py-imports" }
|
||||
windmill-parser-go = { path = "./parsers/windmill-parser-go" }
|
||||
windmill-parser-bash = { path = "./parsers/windmill-parser-bash" }
|
||||
axum = { version = "^0", features = ["headers"] }
|
||||
@@ -132,7 +135,6 @@ swc_common = "0.29.39"
|
||||
swc_ecma_parser = "0.128.2"
|
||||
swc_ecma_ast = "0.98.1"
|
||||
base64 = "0.21.0"
|
||||
unicode-general-category = "^0"
|
||||
hmac = "0.12.1"
|
||||
sha2 = "0.10.6"
|
||||
sqlx = { version = "^0", features = [
|
||||
|
||||
@@ -10,10 +10,6 @@ path = "./src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
windmill-parser.workspace = true
|
||||
windmill-common.workspace = true
|
||||
phf.workspace = true
|
||||
unicode-general-category.workspace = true
|
||||
itertools.workspace = true
|
||||
anyhow.workspace = true
|
||||
regex.workspace = true
|
||||
lazy_static.workspace = true
|
||||
|
||||
@@ -7,15 +7,13 @@ use serde_json::json;
|
||||
use std::collections::HashMap;
|
||||
use windmill_parser::{Arg, MainArgSignature, Typ};
|
||||
|
||||
pub fn parse_bash_sig(code: &str) -> windmill_common::error::Result<MainArgSignature> {
|
||||
pub fn parse_bash_sig(code: &str) -> anyhow::Result<MainArgSignature> {
|
||||
let parsed = parse_file(&code)?;
|
||||
if let Some(x) = parsed {
|
||||
let args = x;
|
||||
Ok(MainArgSignature { star_args: false, star_kwargs: false, args })
|
||||
} else {
|
||||
Err(windmill_common::error::Error::BadRequest(
|
||||
"Error parsing bash script".to_string(),
|
||||
))
|
||||
Err(anyhow!("Error parsing bash script".to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,6 @@ path = "./src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
windmill-parser.workspace = true
|
||||
windmill-common.workspace = true
|
||||
phf.workspace = true
|
||||
unicode-general-category.workspace = true
|
||||
itertools.workspace = true
|
||||
anyhow.workspace = true
|
||||
gosyn.workspace = true
|
||||
@@ -8,7 +8,7 @@ use itertools::Itertools;
|
||||
|
||||
use windmill_parser::{Arg, MainArgSignature, ObjectProperty, Typ};
|
||||
|
||||
pub fn parse_go_sig(code: &str) -> windmill_common::error::Result<MainArgSignature> {
|
||||
pub fn parse_go_sig(code: &str) -> anyhow::Result<MainArgSignature> {
|
||||
let filtered_code = filter_non_main(code);
|
||||
let file = parse_source(&filtered_code).map_err(|x| anyhow::anyhow!(x.to_string()))?;
|
||||
if let Some(func) = file.decl.iter().find_map(|x| match x {
|
||||
@@ -27,13 +27,11 @@ pub fn parse_go_sig(code: &str) -> windmill_common::error::Result<MainArgSignatu
|
||||
.collect_vec();
|
||||
Ok(MainArgSignature { star_args: false, star_kwargs: false, args })
|
||||
} else {
|
||||
Err(windmill_common::error::Error::BadRequest(
|
||||
"no main function found".to_string(),
|
||||
))
|
||||
Err(anyhow::anyhow!("no main function found".to_string(),))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_go_imports(code: &str) -> windmill_common::error::Result<Vec<String>> {
|
||||
pub fn parse_go_imports(code: &str) -> anyhow::Result<Vec<String>> {
|
||||
let file =
|
||||
parse_source(filter_non_imports(code)).map_err(|x| anyhow::anyhow!(x.to_string()))?;
|
||||
let mut imports: Vec<String> = file
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
[package]
|
||||
name = "windmill-parser-py-imports"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
authors.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "windmill_parser_py_imports"
|
||||
path = "./src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
windmill-parser.workspace = true
|
||||
windmill-common.workspace = true
|
||||
rustpython-parser.workspace = true
|
||||
phf.workspace = true
|
||||
itertools.workspace = true
|
||||
regex.workspace = true
|
||||
serde_json.workspace = true
|
||||
anyhow.workspace = true
|
||||
lazy_static.workspace = true
|
||||
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
* Author: Ruben Fiszel
|
||||
* Copyright: Windmill Labs, Inc 2022
|
||||
* This file and its contents are licensed under the AGPLv3 License.
|
||||
* Please see the included NOTICE for copyright information and
|
||||
* LICENSE-AGPL for a copy of the license.
|
||||
*/
|
||||
|
||||
use itertools::Itertools;
|
||||
use lazy_static::lazy_static;
|
||||
use phf::phf_map;
|
||||
use regex::Regex;
|
||||
|
||||
use windmill_common::error;
|
||||
|
||||
use rustpython_parser::ast::{Located, StmtKind};
|
||||
use rustpython_parser::parser::parse_program;
|
||||
|
||||
const DEF_MAIN: &str = "def main(";
|
||||
|
||||
static PYTHON_IMPORTS_REPLACEMENT: phf::Map<&'static str, &'static str> = phf_map! {
|
||||
"psycopg2" => "psycopg2-binary",
|
||||
"psycopg" => "psycopg[binary, pool]",
|
||||
"yaml" => "pyyaml",
|
||||
"git" => "GitPython",
|
||||
"u" => "requests",
|
||||
"f" => "requests",
|
||||
"." => "requests",
|
||||
"shopify" => "ShopifyAPI",
|
||||
"seleniumwire" => "selenium-wire",
|
||||
"openbb-terminal" => "openbb[all]",
|
||||
"riskfolio" => "riskfolio-lib",
|
||||
"smb" => "pysmb",
|
||||
};
|
||||
|
||||
fn replace_import(x: String) -> String {
|
||||
PYTHON_IMPORTS_REPLACEMENT
|
||||
.get(&x)
|
||||
.map(|x| x.to_owned())
|
||||
.unwrap_or(&x)
|
||||
.to_string()
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref RE: Regex = Regex::new(r"^\#\s?(\S+)$").unwrap();
|
||||
}
|
||||
|
||||
pub fn parse_python_imports(code: &str) -> error::Result<Vec<String>> {
|
||||
let find_requirements = code
|
||||
.lines()
|
||||
.find_position(|x| x.starts_with("#requirements:") || x.starts_with("# requirements:"));
|
||||
if let Some((pos, _)) = find_requirements {
|
||||
let lines = code
|
||||
.lines()
|
||||
.skip(pos + 1)
|
||||
.map_while(|x| {
|
||||
RE.captures(x)
|
||||
.map(|x| x.get(1).unwrap().as_str().to_string())
|
||||
})
|
||||
.collect();
|
||||
Ok(lines)
|
||||
} else {
|
||||
let code = code.split(DEF_MAIN).next().unwrap_or("");
|
||||
let ast = parse_program(code, "main.py").map_err(|e| {
|
||||
error::Error::ExecutionErr(format!("Error parsing code: {}", e.to_string()))
|
||||
})?;
|
||||
let mut imports: Vec<String> = ast
|
||||
.into_iter()
|
||||
.filter_map(|x| match x {
|
||||
Located { node, .. } => match node {
|
||||
StmtKind::Import { names } => Some(
|
||||
names
|
||||
.into_iter()
|
||||
.map(|x| {
|
||||
let name = x.node.name;
|
||||
if name.starts_with('.') {
|
||||
".".to_string()
|
||||
} else {
|
||||
name.split('.').next().unwrap_or("").to_string()
|
||||
}
|
||||
})
|
||||
.map(replace_import)
|
||||
.collect::<Vec<String>>(),
|
||||
),
|
||||
StmtKind::ImportFrom { level: Some(i), .. } if i > 0 => {
|
||||
Some(vec!["requests".to_string()])
|
||||
}
|
||||
StmtKind::ImportFrom { level: _, module: Some(mod_), names: _ } => {
|
||||
let imprt = mod_.split('.').next().unwrap_or("").replace("_", "-");
|
||||
Some(vec![replace_import(imprt)])
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
})
|
||||
.flatten()
|
||||
.filter(|x| !STDIMPORTS.contains(&x.as_str()))
|
||||
.unique()
|
||||
.collect();
|
||||
imports.sort();
|
||||
Ok(imports)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_parse_python_imports() -> anyhow::Result<()> {
|
||||
//let code = "print(2 + 3, fd=sys.stderr)";
|
||||
let code = "
|
||||
|
||||
import os
|
||||
import wmill
|
||||
from zanzibar.estonie import talin
|
||||
import matplotlib.pyplot as plt
|
||||
from . import tests
|
||||
|
||||
def main():
|
||||
pass
|
||||
|
||||
";
|
||||
let r = parse_python_imports(code)?;
|
||||
// println!("{}", serde_json::to_string(&r)?);
|
||||
assert_eq!(r, vec!["matplotlib", "requests", "wmill", "zanzibar"]);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_python_imports2() -> anyhow::Result<()> {
|
||||
//let code = "print(2 + 3, fd=sys.stderr)";
|
||||
let code = "
|
||||
#requirements:
|
||||
#burkina=0.4
|
||||
#nigeria
|
||||
#
|
||||
#congo
|
||||
|
||||
import os
|
||||
import wmill
|
||||
from zanzibar.estonie import talin
|
||||
|
||||
def main():
|
||||
pass
|
||||
|
||||
";
|
||||
let r = parse_python_imports(code)?;
|
||||
println!("{}", serde_json::to_string(&r)?);
|
||||
assert_eq!(r, vec!["burkina=0.4", "nigeria"]);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
const STDIMPORTS: [&str; 301] = [
|
||||
"__future__",
|
||||
"_abc",
|
||||
"_aix_support",
|
||||
"_ast",
|
||||
"_asyncio",
|
||||
"_bisect",
|
||||
"_blake2",
|
||||
"_bootsubprocess",
|
||||
"_bz2",
|
||||
"_codecs",
|
||||
"_codecs_cn",
|
||||
"_codecs_hk",
|
||||
"_codecs_iso2022",
|
||||
"_codecs_jp",
|
||||
"_codecs_kr",
|
||||
"_codecs_tw",
|
||||
"_collections",
|
||||
"_collections_abc",
|
||||
"_compat_pickle",
|
||||
"_compression",
|
||||
"_contextvars",
|
||||
"_crypt",
|
||||
"_csv",
|
||||
"_ctypes",
|
||||
"_curses",
|
||||
"_curses_panel",
|
||||
"_datetime",
|
||||
"_dbm",
|
||||
"_decimal",
|
||||
"_elementtree",
|
||||
"_frozen_importlib",
|
||||
"_frozen_importlib_external",
|
||||
"_functools",
|
||||
"_gdbm",
|
||||
"_hashlib",
|
||||
"_heapq",
|
||||
"_imp",
|
||||
"_io",
|
||||
"_json",
|
||||
"_locale",
|
||||
"_lsprof",
|
||||
"_lzma",
|
||||
"_markupbase",
|
||||
"_md5",
|
||||
"_msi",
|
||||
"_multibytecodec",
|
||||
"_multiprocessing",
|
||||
"_opcode",
|
||||
"_operator",
|
||||
"_osx_support",
|
||||
"_overlapped",
|
||||
"_pickle",
|
||||
"_posixshmem",
|
||||
"_posixsubprocess",
|
||||
"_py_abc",
|
||||
"_pydecimal",
|
||||
"_pyio",
|
||||
"_queue",
|
||||
"_random",
|
||||
"_sha1",
|
||||
"_sha256",
|
||||
"_sha3",
|
||||
"_sha512",
|
||||
"_signal",
|
||||
"_sitebuiltins",
|
||||
"_socket",
|
||||
"_sqlite3",
|
||||
"_sre",
|
||||
"_ssl",
|
||||
"_stat",
|
||||
"_statistics",
|
||||
"_string",
|
||||
"_strptime",
|
||||
"_struct",
|
||||
"_symtable",
|
||||
"_thread",
|
||||
"_threading_local",
|
||||
"_tkinter",
|
||||
"_tracemalloc",
|
||||
"_uuid",
|
||||
"_warnings",
|
||||
"_weakref",
|
||||
"_weakrefset",
|
||||
"_winapi",
|
||||
"_zoneinfo",
|
||||
"abc",
|
||||
"aifc",
|
||||
"antigravity",
|
||||
"argparse",
|
||||
"array",
|
||||
"ast",
|
||||
"asynchat",
|
||||
"asyncio",
|
||||
"asyncore",
|
||||
"atexit",
|
||||
"audioop",
|
||||
"base64",
|
||||
"bdb",
|
||||
"binascii",
|
||||
"binhex",
|
||||
"bisect",
|
||||
"builtins",
|
||||
"bz2",
|
||||
"cProfile",
|
||||
"calendar",
|
||||
"cgi",
|
||||
"cgitb",
|
||||
"chunk",
|
||||
"cmath",
|
||||
"cmd",
|
||||
"code",
|
||||
"codecs",
|
||||
"codeop",
|
||||
"collections",
|
||||
"colorsys",
|
||||
"compileall",
|
||||
"concurrent",
|
||||
"configparser",
|
||||
"contextlib",
|
||||
"contextvars",
|
||||
"copy",
|
||||
"copyreg",
|
||||
"crypt",
|
||||
"csv",
|
||||
"ctypes",
|
||||
"curses",
|
||||
"dataclasses",
|
||||
"datetime",
|
||||
"dbm",
|
||||
"decimal",
|
||||
"difflib",
|
||||
"dis",
|
||||
"distutils",
|
||||
"doctest",
|
||||
"email",
|
||||
"encodings",
|
||||
"ensurepip",
|
||||
"enum",
|
||||
"errno",
|
||||
"faulthandler",
|
||||
"fcntl",
|
||||
"filecmp",
|
||||
"fileinput",
|
||||
"fnmatch",
|
||||
"fractions",
|
||||
"ftplib",
|
||||
"functools",
|
||||
"gc",
|
||||
"genericpath",
|
||||
"getopt",
|
||||
"getpass",
|
||||
"gettext",
|
||||
"glob",
|
||||
"graphlib",
|
||||
"grp",
|
||||
"gzip",
|
||||
"hashlib",
|
||||
"heapq",
|
||||
"hmac",
|
||||
"html",
|
||||
"http",
|
||||
"idlelib",
|
||||
"imaplib",
|
||||
"imghdr",
|
||||
"imp",
|
||||
"importlib",
|
||||
"inspect",
|
||||
"io",
|
||||
"ipaddress",
|
||||
"itertools",
|
||||
"json",
|
||||
"keyword",
|
||||
"lib2to3",
|
||||
"linecache",
|
||||
"locale",
|
||||
"logging",
|
||||
"lzma",
|
||||
"mailbox",
|
||||
"mailcap",
|
||||
"marshal",
|
||||
"math",
|
||||
"mimetypes",
|
||||
"mmap",
|
||||
"modulefinder",
|
||||
"msilib",
|
||||
"msvcrt",
|
||||
"multiprocessing",
|
||||
"netrc",
|
||||
"nis",
|
||||
"nntplib",
|
||||
"nt",
|
||||
"ntpath",
|
||||
"nturl2path",
|
||||
"numbers",
|
||||
"opcode",
|
||||
"operator",
|
||||
"optparse",
|
||||
"os",
|
||||
"ossaudiodev",
|
||||
"pathlib",
|
||||
"pdb",
|
||||
"pickle",
|
||||
"pickletools",
|
||||
"pipes",
|
||||
"pkgutil",
|
||||
"platform",
|
||||
"plistlib",
|
||||
"poplib",
|
||||
"posix",
|
||||
"posixpath",
|
||||
"pprint",
|
||||
"profile",
|
||||
"pstats",
|
||||
"pty",
|
||||
"pwd",
|
||||
"py_compile",
|
||||
"pyclbr",
|
||||
"pydoc",
|
||||
"pydoc_data",
|
||||
"pyexpat",
|
||||
"queue",
|
||||
"quopri",
|
||||
"random",
|
||||
"re",
|
||||
"readline",
|
||||
"reprlib",
|
||||
"resource",
|
||||
"rlcompleter",
|
||||
"runpy",
|
||||
"sched",
|
||||
"secrets",
|
||||
"select",
|
||||
"selectors",
|
||||
"shelve",
|
||||
"shlex",
|
||||
"shutil",
|
||||
"signal",
|
||||
"site",
|
||||
"smtpd",
|
||||
"smtplib",
|
||||
"sndhdr",
|
||||
"socket",
|
||||
"socketserver",
|
||||
"spwd",
|
||||
"sqlite3",
|
||||
"sre_compile",
|
||||
"sre_constants",
|
||||
"sre_parse",
|
||||
"ssl",
|
||||
"stat",
|
||||
"statistics",
|
||||
"string",
|
||||
"stringprep",
|
||||
"struct",
|
||||
"subprocess",
|
||||
"sunau",
|
||||
"symtable",
|
||||
"sys",
|
||||
"sysconfig",
|
||||
"syslog",
|
||||
"tabnanny",
|
||||
"tarfile",
|
||||
"telnetlib",
|
||||
"tempfile",
|
||||
"termios",
|
||||
"textwrap",
|
||||
"this",
|
||||
"threading",
|
||||
"time",
|
||||
"timeit",
|
||||
"tkinter",
|
||||
"token",
|
||||
"tokenize",
|
||||
"trace",
|
||||
"traceback",
|
||||
"tracemalloc",
|
||||
"tty",
|
||||
"turtle",
|
||||
"turtledemo",
|
||||
"types",
|
||||
"typing",
|
||||
"unicodedata",
|
||||
"unittest",
|
||||
"urllib",
|
||||
"uu",
|
||||
"uuid",
|
||||
"venv",
|
||||
"warnings",
|
||||
"wave",
|
||||
"weakref",
|
||||
"webbrowser",
|
||||
"winreg",
|
||||
"winsound",
|
||||
"wsgiref",
|
||||
"xdrlib",
|
||||
"xml",
|
||||
"xmlrpc",
|
||||
"zipapp",
|
||||
"zipfile",
|
||||
"zipimport",
|
||||
"",
|
||||
];
|
||||
@@ -10,11 +10,7 @@ path = "./src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
windmill-parser.workspace = true
|
||||
windmill-common.workspace = true
|
||||
rustpython-parser.workspace = true
|
||||
phf.workspace = true
|
||||
itertools.workspace = true
|
||||
regex.workspace = true
|
||||
serde_json.workspace = true
|
||||
anyhow.workspace = true
|
||||
lazy_static.workspace = true
|
||||
@@ -9,12 +9,8 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use itertools::Itertools;
|
||||
use lazy_static::lazy_static;
|
||||
use phf::phf_map;
|
||||
use regex::Regex;
|
||||
|
||||
use serde_json::json;
|
||||
use windmill_common::error;
|
||||
use windmill_parser::{json_to_typ, Arg, MainArgSignature, Typ};
|
||||
|
||||
use rustpython_parser::ast::{Constant, ExprKind, Located, StmtKind};
|
||||
@@ -57,16 +53,13 @@ fn filter_non_main(code: &str) -> String {
|
||||
return filtered_code;
|
||||
}
|
||||
|
||||
pub fn parse_python_signature(code: &str) -> error::Result<MainArgSignature> {
|
||||
pub fn parse_python_signature(code: &str) -> anyhow::Result<MainArgSignature> {
|
||||
let filtered_code = filter_non_main(code);
|
||||
if filtered_code.is_empty() {
|
||||
return Err(error::Error::BadRequest(
|
||||
"No main function found".to_string(),
|
||||
));
|
||||
return Err(anyhow::anyhow!("No main function found".to_string(),));
|
||||
}
|
||||
let ast = parse_program(&filtered_code, "main.py").map_err(|e| {
|
||||
error::Error::ExecutionErr(format!("Error parsing code: {}", e.to_string()))
|
||||
})?;
|
||||
let ast = parse_program(&filtered_code, "main.py")
|
||||
.map_err(|e| anyhow::anyhow!("Error parsing code: {}", e.to_string()))?;
|
||||
let param = ast.into_iter().find_map(|x| match x {
|
||||
Located { node: StmtKind::FunctionDef { name, args, .. }, .. } if &name == "main" => {
|
||||
Some(*args)
|
||||
@@ -120,7 +113,7 @@ pub fn parse_python_signature(code: &str) -> error::Result<MainArgSignature> {
|
||||
.collect(),
|
||||
})
|
||||
} else {
|
||||
Err(error::Error::ExecutionErr(
|
||||
Err(anyhow::anyhow!(
|
||||
"main function was not findable".to_string(),
|
||||
))
|
||||
}
|
||||
@@ -171,89 +164,6 @@ fn constant_to_value(c: &Constant) -> serde_json::Value {
|
||||
}
|
||||
}
|
||||
|
||||
static PYTHON_IMPORTS_REPLACEMENT: phf::Map<&'static str, &'static str> = phf_map! {
|
||||
"psycopg2" => "psycopg2-binary",
|
||||
"psycopg" => "psycopg[binary, pool]",
|
||||
"yaml" => "pyyaml",
|
||||
"git" => "GitPython",
|
||||
"u" => "requests",
|
||||
"f" => "requests",
|
||||
"." => "requests",
|
||||
"shopify" => "ShopifyAPI",
|
||||
"seleniumwire" => "selenium-wire",
|
||||
"openbb-terminal" => "openbb[all]",
|
||||
"riskfolio" => "riskfolio-lib",
|
||||
"smb" => "pysmb",
|
||||
};
|
||||
|
||||
fn replace_import(x: String) -> String {
|
||||
PYTHON_IMPORTS_REPLACEMENT
|
||||
.get(&x)
|
||||
.map(|x| x.to_owned())
|
||||
.unwrap_or(&x)
|
||||
.to_string()
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref RE: Regex = Regex::new(r"^\#\s?(\S+)$").unwrap();
|
||||
}
|
||||
|
||||
pub fn parse_python_imports(code: &str) -> error::Result<Vec<String>> {
|
||||
let find_requirements = code
|
||||
.lines()
|
||||
.find_position(|x| x.starts_with("#requirements:") || x.starts_with("# requirements:"));
|
||||
if let Some((pos, _)) = find_requirements {
|
||||
let lines = code
|
||||
.lines()
|
||||
.skip(pos + 1)
|
||||
.map_while(|x| {
|
||||
RE.captures(x)
|
||||
.map(|x| x.get(1).unwrap().as_str().to_string())
|
||||
})
|
||||
.collect();
|
||||
Ok(lines)
|
||||
} else {
|
||||
let code = code.split(DEF_MAIN).next().unwrap_or("");
|
||||
let ast = parse_program(code, "main.py").map_err(|e| {
|
||||
error::Error::ExecutionErr(format!("Error parsing code: {}", e.to_string()))
|
||||
})?;
|
||||
let mut imports: Vec<String> = ast
|
||||
.into_iter()
|
||||
.filter_map(|x| match x {
|
||||
Located { node, .. } => match node {
|
||||
StmtKind::Import { names } => Some(
|
||||
names
|
||||
.into_iter()
|
||||
.map(|x| {
|
||||
let name = x.node.name;
|
||||
if name.starts_with('.') {
|
||||
".".to_string()
|
||||
} else {
|
||||
name.split('.').next().unwrap_or("").to_string()
|
||||
}
|
||||
})
|
||||
.map(replace_import)
|
||||
.collect::<Vec<String>>(),
|
||||
),
|
||||
StmtKind::ImportFrom { level: Some(i), .. } if i > 0 => {
|
||||
Some(vec!["requests".to_string()])
|
||||
}
|
||||
StmtKind::ImportFrom { level: _, module: Some(mod_), names: _ } => {
|
||||
let imprt = mod_.split('.').next().unwrap_or("").replace("_", "-");
|
||||
Some(vec![replace_import(imprt)])
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
})
|
||||
.flatten()
|
||||
.filter(|x| !STDIMPORTS.contains(&x.as_str()))
|
||||
.unique()
|
||||
.collect();
|
||||
imports.sort();
|
||||
Ok(imports)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
@@ -441,354 +351,4 @@ def main(test1: str,
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_python_imports() -> anyhow::Result<()> {
|
||||
//let code = "print(2 + 3, fd=sys.stderr)";
|
||||
let code = "
|
||||
|
||||
import os
|
||||
import wmill
|
||||
from zanzibar.estonie import talin
|
||||
import matplotlib.pyplot as plt
|
||||
from . import tests
|
||||
|
||||
def main():
|
||||
pass
|
||||
|
||||
";
|
||||
let r = parse_python_imports(code)?;
|
||||
// println!("{}", serde_json::to_string(&r)?);
|
||||
assert_eq!(r, vec!["matplotlib", "requests", "wmill", "zanzibar"]);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_python_imports2() -> anyhow::Result<()> {
|
||||
//let code = "print(2 + 3, fd=sys.stderr)";
|
||||
let code = "
|
||||
#requirements:
|
||||
#burkina=0.4
|
||||
#nigeria
|
||||
#
|
||||
#congo
|
||||
|
||||
import os
|
||||
import wmill
|
||||
from zanzibar.estonie import talin
|
||||
|
||||
def main():
|
||||
pass
|
||||
|
||||
";
|
||||
let r = parse_python_imports(code)?;
|
||||
println!("{}", serde_json::to_string(&r)?);
|
||||
assert_eq!(r, vec!["burkina=0.4", "nigeria"]);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
const STDIMPORTS: [&str; 301] = [
|
||||
"__future__",
|
||||
"_abc",
|
||||
"_aix_support",
|
||||
"_ast",
|
||||
"_asyncio",
|
||||
"_bisect",
|
||||
"_blake2",
|
||||
"_bootsubprocess",
|
||||
"_bz2",
|
||||
"_codecs",
|
||||
"_codecs_cn",
|
||||
"_codecs_hk",
|
||||
"_codecs_iso2022",
|
||||
"_codecs_jp",
|
||||
"_codecs_kr",
|
||||
"_codecs_tw",
|
||||
"_collections",
|
||||
"_collections_abc",
|
||||
"_compat_pickle",
|
||||
"_compression",
|
||||
"_contextvars",
|
||||
"_crypt",
|
||||
"_csv",
|
||||
"_ctypes",
|
||||
"_curses",
|
||||
"_curses_panel",
|
||||
"_datetime",
|
||||
"_dbm",
|
||||
"_decimal",
|
||||
"_elementtree",
|
||||
"_frozen_importlib",
|
||||
"_frozen_importlib_external",
|
||||
"_functools",
|
||||
"_gdbm",
|
||||
"_hashlib",
|
||||
"_heapq",
|
||||
"_imp",
|
||||
"_io",
|
||||
"_json",
|
||||
"_locale",
|
||||
"_lsprof",
|
||||
"_lzma",
|
||||
"_markupbase",
|
||||
"_md5",
|
||||
"_msi",
|
||||
"_multibytecodec",
|
||||
"_multiprocessing",
|
||||
"_opcode",
|
||||
"_operator",
|
||||
"_osx_support",
|
||||
"_overlapped",
|
||||
"_pickle",
|
||||
"_posixshmem",
|
||||
"_posixsubprocess",
|
||||
"_py_abc",
|
||||
"_pydecimal",
|
||||
"_pyio",
|
||||
"_queue",
|
||||
"_random",
|
||||
"_sha1",
|
||||
"_sha256",
|
||||
"_sha3",
|
||||
"_sha512",
|
||||
"_signal",
|
||||
"_sitebuiltins",
|
||||
"_socket",
|
||||
"_sqlite3",
|
||||
"_sre",
|
||||
"_ssl",
|
||||
"_stat",
|
||||
"_statistics",
|
||||
"_string",
|
||||
"_strptime",
|
||||
"_struct",
|
||||
"_symtable",
|
||||
"_thread",
|
||||
"_threading_local",
|
||||
"_tkinter",
|
||||
"_tracemalloc",
|
||||
"_uuid",
|
||||
"_warnings",
|
||||
"_weakref",
|
||||
"_weakrefset",
|
||||
"_winapi",
|
||||
"_zoneinfo",
|
||||
"abc",
|
||||
"aifc",
|
||||
"antigravity",
|
||||
"argparse",
|
||||
"array",
|
||||
"ast",
|
||||
"asynchat",
|
||||
"asyncio",
|
||||
"asyncore",
|
||||
"atexit",
|
||||
"audioop",
|
||||
"base64",
|
||||
"bdb",
|
||||
"binascii",
|
||||
"binhex",
|
||||
"bisect",
|
||||
"builtins",
|
||||
"bz2",
|
||||
"cProfile",
|
||||
"calendar",
|
||||
"cgi",
|
||||
"cgitb",
|
||||
"chunk",
|
||||
"cmath",
|
||||
"cmd",
|
||||
"code",
|
||||
"codecs",
|
||||
"codeop",
|
||||
"collections",
|
||||
"colorsys",
|
||||
"compileall",
|
||||
"concurrent",
|
||||
"configparser",
|
||||
"contextlib",
|
||||
"contextvars",
|
||||
"copy",
|
||||
"copyreg",
|
||||
"crypt",
|
||||
"csv",
|
||||
"ctypes",
|
||||
"curses",
|
||||
"dataclasses",
|
||||
"datetime",
|
||||
"dbm",
|
||||
"decimal",
|
||||
"difflib",
|
||||
"dis",
|
||||
"distutils",
|
||||
"doctest",
|
||||
"email",
|
||||
"encodings",
|
||||
"ensurepip",
|
||||
"enum",
|
||||
"errno",
|
||||
"faulthandler",
|
||||
"fcntl",
|
||||
"filecmp",
|
||||
"fileinput",
|
||||
"fnmatch",
|
||||
"fractions",
|
||||
"ftplib",
|
||||
"functools",
|
||||
"gc",
|
||||
"genericpath",
|
||||
"getopt",
|
||||
"getpass",
|
||||
"gettext",
|
||||
"glob",
|
||||
"graphlib",
|
||||
"grp",
|
||||
"gzip",
|
||||
"hashlib",
|
||||
"heapq",
|
||||
"hmac",
|
||||
"html",
|
||||
"http",
|
||||
"idlelib",
|
||||
"imaplib",
|
||||
"imghdr",
|
||||
"imp",
|
||||
"importlib",
|
||||
"inspect",
|
||||
"io",
|
||||
"ipaddress",
|
||||
"itertools",
|
||||
"json",
|
||||
"keyword",
|
||||
"lib2to3",
|
||||
"linecache",
|
||||
"locale",
|
||||
"logging",
|
||||
"lzma",
|
||||
"mailbox",
|
||||
"mailcap",
|
||||
"marshal",
|
||||
"math",
|
||||
"mimetypes",
|
||||
"mmap",
|
||||
"modulefinder",
|
||||
"msilib",
|
||||
"msvcrt",
|
||||
"multiprocessing",
|
||||
"netrc",
|
||||
"nis",
|
||||
"nntplib",
|
||||
"nt",
|
||||
"ntpath",
|
||||
"nturl2path",
|
||||
"numbers",
|
||||
"opcode",
|
||||
"operator",
|
||||
"optparse",
|
||||
"os",
|
||||
"ossaudiodev",
|
||||
"pathlib",
|
||||
"pdb",
|
||||
"pickle",
|
||||
"pickletools",
|
||||
"pipes",
|
||||
"pkgutil",
|
||||
"platform",
|
||||
"plistlib",
|
||||
"poplib",
|
||||
"posix",
|
||||
"posixpath",
|
||||
"pprint",
|
||||
"profile",
|
||||
"pstats",
|
||||
"pty",
|
||||
"pwd",
|
||||
"py_compile",
|
||||
"pyclbr",
|
||||
"pydoc",
|
||||
"pydoc_data",
|
||||
"pyexpat",
|
||||
"queue",
|
||||
"quopri",
|
||||
"random",
|
||||
"re",
|
||||
"readline",
|
||||
"reprlib",
|
||||
"resource",
|
||||
"rlcompleter",
|
||||
"runpy",
|
||||
"sched",
|
||||
"secrets",
|
||||
"select",
|
||||
"selectors",
|
||||
"shelve",
|
||||
"shlex",
|
||||
"shutil",
|
||||
"signal",
|
||||
"site",
|
||||
"smtpd",
|
||||
"smtplib",
|
||||
"sndhdr",
|
||||
"socket",
|
||||
"socketserver",
|
||||
"spwd",
|
||||
"sqlite3",
|
||||
"sre_compile",
|
||||
"sre_constants",
|
||||
"sre_parse",
|
||||
"ssl",
|
||||
"stat",
|
||||
"statistics",
|
||||
"string",
|
||||
"stringprep",
|
||||
"struct",
|
||||
"subprocess",
|
||||
"sunau",
|
||||
"symtable",
|
||||
"sys",
|
||||
"sysconfig",
|
||||
"syslog",
|
||||
"tabnanny",
|
||||
"tarfile",
|
||||
"telnetlib",
|
||||
"tempfile",
|
||||
"termios",
|
||||
"textwrap",
|
||||
"this",
|
||||
"threading",
|
||||
"time",
|
||||
"timeit",
|
||||
"tkinter",
|
||||
"token",
|
||||
"tokenize",
|
||||
"trace",
|
||||
"traceback",
|
||||
"tracemalloc",
|
||||
"tty",
|
||||
"turtle",
|
||||
"turtledemo",
|
||||
"types",
|
||||
"typing",
|
||||
"unicodedata",
|
||||
"unittest",
|
||||
"urllib",
|
||||
"uu",
|
||||
"uuid",
|
||||
"venv",
|
||||
"warnings",
|
||||
"wave",
|
||||
"weakref",
|
||||
"webbrowser",
|
||||
"winreg",
|
||||
"winsound",
|
||||
"wsgiref",
|
||||
"xdrlib",
|
||||
"xml",
|
||||
"xmlrpc",
|
||||
"zipapp",
|
||||
"zipfile",
|
||||
"zipimport",
|
||||
"",
|
||||
];
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "windmill-parser-ts-wasm",
|
||||
"version": "1.109.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "windmill-parser-ts-wasm",
|
||||
"version": "1.109.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"name": "windmill-parser-ts-wasm",
|
||||
"collaborators": [
|
||||
"Ruben Fiszel <ruben@windmill.dev>"
|
||||
],
|
||||
"version": "1.109.1",
|
||||
"files": [
|
||||
"windmill_parser_ts_wasm_bg.wasm",
|
||||
"windmill_parser_ts_wasm.js",
|
||||
"windmill_parser_ts_wasm.d.ts"
|
||||
],
|
||||
"module": "windmill_parser_ts_wasm.js",
|
||||
"types": "windmill_parser_ts_wasm.d.ts",
|
||||
"sideEffects": [
|
||||
"./snippets/*"
|
||||
]
|
||||
}
|
||||
Binary file not shown.
@@ -1,13 +0,0 @@
|
||||
use serde_json;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use windmill_parser_ts::parse_deno_signature;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn parse_deno_wasm(code: &str) -> String {
|
||||
let r = parse_deno_signature(code, false);
|
||||
if let Ok(r) = r {
|
||||
return serde_json::to_string(&r).unwrap();
|
||||
} else {
|
||||
return "{\"type\": \"Invalid\"}".to_string();
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax, TsConfig};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
pub fn parse_deno_signature(code: &str, skip_dflt: bool) -> Result<MainArgSignature, String> {
|
||||
pub fn parse_deno_signature(code: &str, skip_dflt: bool) -> anyhow::Result<MainArgSignature> {
|
||||
let cm: Lrc<SourceMap> = Default::default();
|
||||
let fm = cm.new_source_file(FileName::Custom("main.ts".into()), code.into());
|
||||
let lexer = Lexer::new(
|
||||
@@ -42,7 +42,7 @@ pub fn parse_deno_signature(code: &str, skip_dflt: bool) -> Result<MainArgSignat
|
||||
|
||||
let ast = parser
|
||||
.parse_module()
|
||||
.map_err(|_| format!("Error while parsing code, it is invalid typescript"))?
|
||||
.map_err(|_| anyhow::anyhow!("Error while parsing code, it is invalid typescript"))?
|
||||
.body;
|
||||
|
||||
// println!("{ast:?}");
|
||||
@@ -61,18 +61,18 @@ pub fn parse_deno_signature(code: &str, skip_dflt: bool) -> Result<MainArgSignat
|
||||
args: params
|
||||
.into_iter()
|
||||
.map(|x| parse_param(x, &cm, skip_dflt))
|
||||
.collect::<Result<Vec<Arg>, String>>()?,
|
||||
.collect::<anyhow::Result<Vec<Arg>>>()?,
|
||||
};
|
||||
Ok(r)
|
||||
} else {
|
||||
Err(
|
||||
Err(anyhow::anyhow!(
|
||||
"main function was not findable (expected to find 'export function main(...)'"
|
||||
.to_string(),
|
||||
)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_param(x: Param, cm: &Lrc<SourceMap>, skip_dflt: bool) -> Result<Arg, String> {
|
||||
fn parse_param(x: Param, cm: &Lrc<SourceMap>, skip_dflt: bool) -> anyhow::Result<Arg> {
|
||||
let r = match x.pat {
|
||||
Pat::Ident(ident) => {
|
||||
let (name, typ, nullable) = binding_ident_to_arg(&ident);
|
||||
@@ -87,7 +87,7 @@ fn parse_param(x: Param, cm: &Lrc<SourceMap>, skip_dflt: bool) -> Result<Arg, St
|
||||
Pat::Assign(AssignPat { left, right, .. }) => {
|
||||
let (name, mut typ, _nullable) =
|
||||
left.as_ident().map(binding_ident_to_arg).ok_or_else(|| {
|
||||
format!(
|
||||
anyhow::anyhow!(
|
||||
"parameter syntax unsupported: `{}`",
|
||||
cm.span_to_snippet(left.span())
|
||||
.unwrap_or_else(|_| cm.span_to_string(left.span()))
|
||||
@@ -120,7 +120,7 @@ fn parse_param(x: Param, cm: &Lrc<SourceMap>, skip_dflt: bool) -> Result<Arg, St
|
||||
}
|
||||
Ok(Arg { otyp: None, name, typ, default: dflt, has_default: true })
|
||||
}
|
||||
_ => Err(format!(
|
||||
_ => Err(anyhow::anyhow!(
|
||||
"parameter syntax unsupported: `{}`",
|
||||
cm.span_to_snippet(x.span())
|
||||
.unwrap_or_else(|_| cm.span_to_string(x.span()))
|
||||
@@ -280,6 +280,6 @@ pub fn eval_sync(code: &str) -> Result<serde_json::Value, String> {
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub fn eval_sync(code: &str) -> Result<serde_json::Value, String> {
|
||||
pub fn eval_sync(_code: &str) -> Result<serde_json::Value, String> {
|
||||
panic!("eval_sync is only available in wasm32")
|
||||
}
|
||||
|
||||
+7
-3
@@ -1,19 +1,23 @@
|
||||
[package]
|
||||
name = "windmill-parser-ts-wasm"
|
||||
name = "windmill-parser-wasm"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
authors.workspace = true
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
name = "windmill_parser_ts_wasm"
|
||||
name = "windmill_parser_wasm"
|
||||
path = "./src/lib.rs"
|
||||
|
||||
[dev-dependencies]
|
||||
windmill-parser.workspace = true
|
||||
wasm-bindgen-test.workspace = true
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
windmill-parser.workspace = true
|
||||
windmill-parser-go.workspace = true
|
||||
windmill-parser-bash.workspace = true
|
||||
windmill-parser-py.workspace = true
|
||||
windmill-parser-ts.workspace = true
|
||||
wasm-bindgen.workspace = true
|
||||
serde_json.workspace = true
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "windmill-parser-wasm",
|
||||
"collaborators": [
|
||||
"Ruben Fiszel <ruben@windmill.dev>"
|
||||
],
|
||||
"version": "1.109.1",
|
||||
"files": [
|
||||
"windmill_parser_wasm_bg.wasm",
|
||||
"windmill_parser_wasm.js",
|
||||
"windmill_parser_wasm.d.ts"
|
||||
],
|
||||
"module": "windmill_parser_wasm.js",
|
||||
"types": "windmill_parser_wasm.d.ts",
|
||||
"sideEffects": [
|
||||
"./snippets/*"
|
||||
]
|
||||
}
|
||||
+20
-2
@@ -4,13 +4,31 @@
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_deno_wasm(code: string): string;
|
||||
export function parse_deno(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_bash(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_go(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_python(code: string): string;
|
||||
|
||||
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
||||
|
||||
export interface InitOutput {
|
||||
readonly memory: WebAssembly.Memory;
|
||||
readonly parse_deno_wasm: (a: number, b: number, c: number) => void;
|
||||
readonly parse_deno: (a: number, b: number, c: number) => void;
|
||||
readonly parse_bash: (a: number, b: number, c: number) => void;
|
||||
readonly parse_go: (a: number, b: number, c: number) => void;
|
||||
readonly parse_python: (a: number, b: number, c: number) => void;
|
||||
readonly __wbindgen_malloc: (a: number) => number;
|
||||
readonly __wbindgen_realloc: (a: number, b: number, c: number) => number;
|
||||
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
||||
+75
-6
@@ -201,14 +201,83 @@ function debugString(val) {
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_deno_wasm(code) {
|
||||
export function parse_deno(code) {
|
||||
let deferred2_0;
|
||||
let deferred2_1;
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
const ptr0 = passStringToWasm0(code, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.parse_deno_wasm(retptr, ptr0, len0);
|
||||
wasm.parse_deno(retptr, ptr0, len0);
|
||||
var r0 = getInt32Memory0()[retptr / 4 + 0];
|
||||
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
||||
deferred2_0 = r0;
|
||||
deferred2_1 = r1;
|
||||
return getStringFromWasm0(r0, r1);
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
wasm.__wbindgen_free(deferred2_0, deferred2_1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_bash(code) {
|
||||
let deferred2_0;
|
||||
let deferred2_1;
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
const ptr0 = passStringToWasm0(code, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.parse_bash(retptr, ptr0, len0);
|
||||
var r0 = getInt32Memory0()[retptr / 4 + 0];
|
||||
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
||||
deferred2_0 = r0;
|
||||
deferred2_1 = r1;
|
||||
return getStringFromWasm0(r0, r1);
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
wasm.__wbindgen_free(deferred2_0, deferred2_1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_go(code) {
|
||||
let deferred2_0;
|
||||
let deferred2_1;
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
const ptr0 = passStringToWasm0(code, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.parse_go(retptr, ptr0, len0);
|
||||
var r0 = getInt32Memory0()[retptr / 4 + 0];
|
||||
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
||||
deferred2_0 = r0;
|
||||
deferred2_1 = r1;
|
||||
return getStringFromWasm0(r0, r1);
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
wasm.__wbindgen_free(deferred2_0, deferred2_1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_python(code) {
|
||||
let deferred2_0;
|
||||
let deferred2_1;
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
const ptr0 = passStringToWasm0(code, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.parse_python(retptr, ptr0, len0);
|
||||
var r0 = getInt32Memory0()[retptr / 4 + 0];
|
||||
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
||||
deferred2_0 = r0;
|
||||
@@ -262,13 +331,13 @@ async function __wbg_load(module, imports) {
|
||||
function __wbg_get_imports() {
|
||||
const imports = {};
|
||||
imports.wbg = {};
|
||||
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
|
||||
takeObject(arg0);
|
||||
};
|
||||
imports.wbg.__wbg_eval_8130c2f52f1a6d39 = function(arg0, arg1) {
|
||||
const ret = eval(getStringFromWasm0(arg0, arg1));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
|
||||
takeObject(arg0);
|
||||
};
|
||||
imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
|
||||
const obj = getObject(arg1);
|
||||
const ret = typeof(obj) === 'string' ? obj : undefined;
|
||||
@@ -468,7 +537,7 @@ async function __wbg_init(input) {
|
||||
if (wasm !== undefined) return wasm;
|
||||
|
||||
if (typeof input === 'undefined') {
|
||||
input = new URL('windmill_parser_ts_wasm_bg.wasm', import.meta.url);
|
||||
input = new URL('windmill_parser_wasm_bg.wasm', import.meta.url);
|
||||
}
|
||||
const imports = __wbg_get_imports();
|
||||
|
||||
Binary file not shown.
+4
-1
@@ -1,7 +1,10 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export const memory: WebAssembly.Memory;
|
||||
export function parse_deno_wasm(a: number, b: number, c: number): void;
|
||||
export function parse_deno(a: number, b: number, c: number): void;
|
||||
export function parse_bash(a: number, b: number, c: number): void;
|
||||
export function parse_go(a: number, b: number, c: number): void;
|
||||
export function parse_python(a: number, b: number, c: number): void;
|
||||
export function __wbindgen_malloc(a: number): number;
|
||||
export function __wbindgen_realloc(a: number, b: number, c: number): number;
|
||||
export function __wbindgen_add_to_stack_pointer(a: number): number;
|
||||
@@ -0,0 +1,31 @@
|
||||
use serde_json;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use windmill_parser::MainArgSignature;
|
||||
|
||||
fn wrap_sig(r: anyhow::Result<MainArgSignature>) -> String {
|
||||
if let Ok(r) = r {
|
||||
return serde_json::to_string(&r).unwrap();
|
||||
} else {
|
||||
return "{\"type\": \"Invalid\"}".to_string();
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn parse_deno(code: &str) -> String {
|
||||
wrap_sig(windmill_parser_ts::parse_deno_signature(code, false))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn parse_bash(code: &str) -> String {
|
||||
wrap_sig(windmill_parser_bash::parse_bash_sig(code))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn parse_go(code: &str) -> String {
|
||||
wrap_sig(windmill_parser_go::parse_go_sig(code))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn parse_python(code: &str) -> String {
|
||||
wrap_sig(windmill_parser_py::parse_python_signature(code))
|
||||
}
|
||||
+2
-2
@@ -4,7 +4,7 @@ use windmill_parser::{Arg, MainArgSignature, ObjectProperty, Typ};
|
||||
use windmill_parser_ts::parse_deno_signature;
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn test_parse_deno_sig() -> Result<(), String> {
|
||||
fn test_parse_deno_sig() -> anyhow::Result<()> {
|
||||
let code = "
|
||||
export function main(test1?: string, test2: string = \"burkina\",
|
||||
test3: wmill.Resource<'postgres'>, b64: Base64, ls: Base64[],
|
||||
@@ -115,7 +115,7 @@ export function main(test1?: string, test2: string = \"burkina\",
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn test_parse_deno_sig_implicit_types() -> Result<(), String> {
|
||||
fn test_parse_deno_sig_implicit_types() -> anyhow::Result<()> {
|
||||
let code = "
|
||||
export function main(test2 = \"burkina\",
|
||||
bool = true,
|
||||
@@ -24,10 +24,7 @@ windmill-common = { workspace = true, features = [
|
||||
] }
|
||||
windmill-audit.workspace = true
|
||||
windmill-parser.workspace = true
|
||||
windmill-parser-ts.workspace = true
|
||||
windmill-parser-go.workspace = true
|
||||
windmill-parser-py.workspace = true
|
||||
windmill-parser-bash.workspace = true
|
||||
windmill-parser-py-imports.workspace = true
|
||||
tokio.workspace = true
|
||||
anyhow.workspace = true
|
||||
argon2.workspace = true
|
||||
|
||||
@@ -2278,90 +2278,6 @@ paths:
|
||||
items:
|
||||
type: string
|
||||
|
||||
/scripts/python/tojsonschema:
|
||||
post:
|
||||
summary: inspect python code to infer jsonschema of arguments
|
||||
operationId: pythonToJsonschema
|
||||
tags:
|
||||
- script
|
||||
requestBody:
|
||||
description: python code with the main function
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: parsed args
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/MainArgSignature"
|
||||
|
||||
/scripts/deno/tojsonschema:
|
||||
post:
|
||||
summary: inspect deno code to infer jsonschema of arguments
|
||||
operationId: denoToJsonschema
|
||||
tags:
|
||||
- script
|
||||
requestBody:
|
||||
description: deno code with the main function
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: parsed args
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/MainArgSignature"
|
||||
|
||||
/scripts/bash/tojsonschema:
|
||||
post:
|
||||
summary: inspect bash code to infer jsonschema of arguments
|
||||
operationId: bashToJsonschema
|
||||
tags:
|
||||
- script
|
||||
requestBody:
|
||||
description: bash code with the main function
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: parsed args
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/MainArgSignature"
|
||||
|
||||
/scripts/go/tojsonschema:
|
||||
post:
|
||||
summary: inspect go code to infer jsonschema of arguments
|
||||
operationId: goToJsonschema
|
||||
tags:
|
||||
- script
|
||||
requestBody:
|
||||
description: go code with the main function
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: parsed args
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/MainArgSignature"
|
||||
|
||||
/w/{workspace}/scripts/archive/p/{path}:
|
||||
post:
|
||||
summary: archive script by path
|
||||
|
||||
@@ -76,13 +76,6 @@ pub struct ScriptWDraft {
|
||||
|
||||
pub fn global_service() -> Router {
|
||||
Router::new()
|
||||
.route(
|
||||
"/python/tojsonschema",
|
||||
post(parse_python_code_to_jsonschema),
|
||||
)
|
||||
.route("/deno/tojsonschema", post(parse_deno_code_to_jsonschema))
|
||||
.route("/go/tojsonschema", post(parse_go_code_to_jsonschema))
|
||||
.route("/bash/tojsonschema", post(parse_bash_code_to_jsonschema))
|
||||
.route("/hub/list", get(list_hub_scripts))
|
||||
.route("/hub/get/*path", get(get_hub_script_by_path))
|
||||
.route("/hub/get_full/*path", get(get_full_hub_script_by_path))
|
||||
@@ -483,7 +476,7 @@ async fn create_script(
|
||||
if needs_lock_gen {
|
||||
let dependencies = match ns.language {
|
||||
ScriptLang::Python3 => {
|
||||
windmill_parser_py::parse_python_imports(&ns.content)?.join("\n")
|
||||
windmill_parser_py_imports::parse_python_imports(&ns.content)?.join("\n")
|
||||
}
|
||||
_ => ns.content,
|
||||
};
|
||||
@@ -916,20 +909,3 @@ fn result_to_sig_parsing(result: Result<MainArgSignature>) -> Json<SigParsing> {
|
||||
Err(e) => Json(SigParsing::Invalid { error: e.to_string() }),
|
||||
}
|
||||
}
|
||||
|
||||
async fn parse_python_code_to_jsonschema(Json(code): Json<String>) -> Json<SigParsing> {
|
||||
result_to_sig_parsing(windmill_parser_py::parse_python_signature(&code))
|
||||
}
|
||||
|
||||
async fn parse_deno_code_to_jsonschema(Json(code): Json<String>) -> Json<SigParsing> {
|
||||
result_to_sig_parsing(
|
||||
windmill_parser_ts::parse_deno_signature(&code, false).map_err(|e| Error::ExecutionErr(e)),
|
||||
)
|
||||
}
|
||||
async fn parse_go_code_to_jsonschema(Json(code): Json<String>) -> Json<SigParsing> {
|
||||
result_to_sig_parsing(windmill_parser_go::parse_go_sig(&code))
|
||||
}
|
||||
|
||||
async fn parse_bash_code_to_jsonschema(Json(code): Json<String>) -> Json<SigParsing> {
|
||||
result_to_sig_parsing(windmill_parser_bash::parse_bash_sig(&code))
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ windmill-parser.workspace = true
|
||||
windmill-parser-ts.workspace = true
|
||||
windmill-parser-go.workspace = true
|
||||
windmill-parser-py.workspace = true
|
||||
windmill-parser-py-imports.workspace = true
|
||||
windmill-parser-bash.workspace = true
|
||||
sqlx.workspace = true
|
||||
uuid.workspace = true
|
||||
|
||||
@@ -175,7 +175,8 @@ pub async fn handle_python_job(
|
||||
let requirements = match requirements_o {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
let requirements = windmill_parser_py::parse_python_imports(&inner_content)?.join("\n");
|
||||
let requirements =
|
||||
windmill_parser_py_imports::parse_python_imports(&inner_content)?.join("\n");
|
||||
if requirements.is_empty() {
|
||||
"".to_string()
|
||||
} else {
|
||||
|
||||
@@ -1755,7 +1755,7 @@ async fn handle_flow_dependency_job(
|
||||
};
|
||||
// sync with windmill-api/scripts
|
||||
let dependencies = match language {
|
||||
ScriptLang::Python3 => windmill_parser_py::parse_python_imports(&content)?.join("\n"),
|
||||
ScriptLang::Python3 => windmill_parser_py_imports::parse_python_imports(&content)?.join("\n"),
|
||||
_ => content.clone(),
|
||||
};
|
||||
let new_lock = capture_dependency_job(
|
||||
|
||||
@@ -53,7 +53,7 @@ COPY /backend/windmill-api/openapi.yaml /backend/windmill-api/openapi.yaml
|
||||
COPY /openflow.openapi.yaml /openflow.openapi.yaml
|
||||
COPY /backend/windmill-api/build_openapi.sh /backend/windmill-api/build_openapi.sh
|
||||
RUN cd /backend/windmill-api && . ./build_openapi.sh
|
||||
COPY /backend/parsers/windmill-parser-py-wasm/pkg/ /backend/windmill-parser-py-wasm/pkg/
|
||||
COPY /backend/parsers/windmill-parser-wasm/pkg/ /backend/parsers/windmill-parser-wasm/pkg/
|
||||
|
||||
RUN npm run generate-backend-client
|
||||
ENV NODE_OPTIONS "--max-old-space-size=8192"
|
||||
|
||||
Generated
+9
-5
@@ -36,7 +36,7 @@
|
||||
"svelte-timezone-picker": "^2.0.3",
|
||||
"tailwind-merge": "^1.12.0",
|
||||
"vscode-ws-jsonrpc": "3.0.0",
|
||||
"windmill-parser-ts-wasm": "file:../backend/parsers/windmill-parser-ts-wasm/pkg",
|
||||
"windmill-parser-wasm": "file:../backend/parsers/windmill-parser-wasm/pkg",
|
||||
"y-monaco": "^0.1.4",
|
||||
"y-websocket": "^1.5.0",
|
||||
"yjs": "^13.6.1"
|
||||
@@ -104,6 +104,10 @@
|
||||
},
|
||||
"../backend/parsers/windmill-parser-ts-wasm/pkg": {
|
||||
"name": "windmill-parser-ts-wasm",
|
||||
"version": "1.109.1",
|
||||
"extraneous": true
|
||||
},
|
||||
"../backend/parsers/windmill-parser-wasm/pkg": {
|
||||
"version": "1.109.1"
|
||||
},
|
||||
"node_modules/@alloc/quick-lru": {
|
||||
@@ -7699,8 +7703,8 @@
|
||||
"string-width": "^1.0.2 || 2 || 3 || 4"
|
||||
}
|
||||
},
|
||||
"node_modules/windmill-parser-ts-wasm": {
|
||||
"resolved": "../backend/parsers/windmill-parser-ts-wasm/pkg",
|
||||
"node_modules/windmill-parser-wasm": {
|
||||
"resolved": "../backend/parsers/windmill-parser-wasm/pkg",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/word-wrap": {
|
||||
@@ -13396,8 +13400,8 @@
|
||||
"string-width": "^1.0.2 || 2 || 3 || 4"
|
||||
}
|
||||
},
|
||||
"windmill-parser-ts-wasm": {
|
||||
"version": "file:../backend/parsers/windmill-parser-ts-wasm/pkg"
|
||||
"windmill-parser-wasm": {
|
||||
"version": "file:../backend/parsers/windmill-parser-wasm/pkg"
|
||||
},
|
||||
"word-wrap": {
|
||||
"version": "1.2.3",
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
"y-monaco": "^0.1.4",
|
||||
"y-websocket": "^1.5.0",
|
||||
"yjs": "^13.6.1",
|
||||
"windmill-parser-ts-wasm": "file:../backend/parsers/windmill-parser-ts-wasm/pkg"
|
||||
"windmill-parser-wasm": "file:../backend/parsers/windmill-parser-wasm/pkg"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@sveltejs/kit": "^1.20.1",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ScriptService, type MainArgSignature } from '$lib/gen'
|
||||
import type { MainArgSignature } from '$lib/gen'
|
||||
import { get, writable } from 'svelte/store'
|
||||
import type { Schema, SchemaProperty } from './common.js'
|
||||
import { sortObject } from './utils.js'
|
||||
import { tick } from 'svelte'
|
||||
import init, { parse_deno_wasm } from 'windmill-parser-ts-wasm'
|
||||
import wasmUrl from 'windmill-parser-ts-wasm/windmill_parser_ts_wasm_bg.wasm?url'
|
||||
import init, { parse_deno, parse_bash, parse_go, parse_python } from 'windmill-parser-wasm'
|
||||
import wasmUrl from 'windmill-parser-wasm/windmill_parser_wasm_bg.wasm?url'
|
||||
|
||||
init(wasmUrl)
|
||||
|
||||
@@ -24,19 +24,13 @@ export async function inferArgs(
|
||||
code = ' '
|
||||
}
|
||||
if (language == 'python3') {
|
||||
inferedSchema = await ScriptService.pythonToJsonschema({
|
||||
requestBody: code
|
||||
})
|
||||
inferedSchema = JSON.parse(parse_python(code))
|
||||
} else if (language == 'deno') {
|
||||
inferedSchema = JSON.parse(parse_deno_wasm(code))
|
||||
inferedSchema = JSON.parse(parse_deno(code))
|
||||
} else if (language == 'go') {
|
||||
inferedSchema = await ScriptService.goToJsonschema({
|
||||
requestBody: code
|
||||
})
|
||||
inferedSchema = JSON.parse(parse_go(code))
|
||||
} else if (language == 'bash') {
|
||||
inferedSchema = await ScriptService.bashToJsonschema({
|
||||
requestBody: code
|
||||
})
|
||||
inferedSchema = JSON.parse(parse_bash(code))
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user