const CODE: &str = "
import io, sys
def run(code):
stdout = io.StringIO()
sys.stdout = stdout
try:
exec(code, {}, {}) # maybe you'll want to do something with the locals+globals
finally:
sys.stdout = sys.__stdout__
return stdout.getvalue()
";
use rustpython_vm as vm;
// See: https://github.com/RustPython/RustPython/blob/d6c8247886ff504f77e8995b08d9a15c22dfa8a0/examples/mini_repl.rs
macro_rules! add_python_function {
( $scope:ident, $vm:ident, $src:literal $(,)? ) => {{
// compile the code to bytecode
let code = vm::py_compile!(source = $src);
// convert the rustpython_bytecode::CodeObject to a PyCodeRef
let code = $vm.new_code_object(code);
// run the python code in the scope to store the function
$vm.run_code_obj(code, $scope.clone())
}};
}
fn main() {
let res = execute(r#"print(sum(map(int,input().split(" "))))"#, "1 2 3 4 5");
println!("{}", res.expect("Failed executing"));
}
fn execute(code: &str, input: &str) -> Result<String, ()> {
vm::Interpreter::default().enter(|vm| {
let scope = vm.new_scope_with_builtins();
add_python_function!(
scope,
vm,
r#"
import _io, sys
def run(code, input):
stdout = _io.StringIO()
sys.stdin = _io.StringIO(input)
sys.stdout = stdout
try:
exec(code, {}, {}) # maybe you'll want to do something with the locals+globals
finally:
sys.stdout = sys.__stdout__
sys.stdin = sys.__stdin__
return stdout.getvalue()
"#
);
let run_input = format!("run('{}', '{}')", code, input); // TODO: escape quotes?
match vm
.compile(&run_input, vm::compile::Mode::Eval, "<embedded>".to_owned())
.map_err(|err| vm.new_syntax_error(&err))
.and_then(|code_obj| vm.run_code_obj(code_obj, scope.clone()))
{
Ok(output) => {
if !vm.is_none(&output) {
match vm.to_str(&output) {
Ok(s) => Ok(s.as_ref().to_owned()),
Err(e) => Err(()), // TODO
}
} else {
Err(()) // TODO
}
}
Err(e) => {
vm::exceptions::print_exception(vm, e);
Err(()) // TODO
}
}
})
}
run_input variable. I don't know how I can make it execute the run function with the bytecode as it's argument.
warning: unused import: `crate::builtins::dict::PyMapping`
--> vm/src/stdlib/os.rs:1406:9
|
1406 | use crate::builtins::dict::PyMapping;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
warning: unused import: `std::convert::TryFrom`
--> vm/src/stdlib/os.rs:1412:9
|
1412 | use std::convert::TryFrom;
| ^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> vm/src/stdlib/os.rs:162:33
|
162 | fn path_from_fd(raw_fd: i64) -> Result<PathBuf, String> {
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
...
175 | Err("fd not supported on wasi yet".to_owned());
| - help: consider removing this semicolon
|
= note: expected enum `std::result::Result<std::path::PathBuf, std::string::String>`
found unit type `()`
error: aborting due to previous error; 2 warnings emitted
For more information about this error, try `rustc --explain E0308`.
error: could not compile `rustpython-vm`
To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
ssl feature (cargo build --release --features ssl) and also maybe use the coolreader18/misc-fixes branch which fixes a regression that affected pip
ctypesrustpython -m pip install ipython
Finished release [optimized] target(s) in 0.16s
Running `rustpython/target/release/rustpython -m pip install ipython`
Defaulting to user installation because normal site-packages is not writeable
Collecting ipython
Using cached ipython-7.23.1-py3-none-any.whl (785 kB)
Requirement already satisfied: setuptools>=18.5 in /home/ryuta/.local/lib/rustpython3.9/site-packages (from ipython) (56.2.0)
Collecting jedi>=0.16
Downloading jedi-0.18.0-py2.py3-none-any.whl (1.4 MB)
|████████████████████████████████| 1.4 MB 29 kB/s
Collecting decorator
Downloading decorator-5.0.8-py3-none-any.whl (8.9 kB)
Collecting pickleshare
Downloading pickleshare-0.7.5-py2.py3-none-any.whl (6.9 kB)
Collecting traitlets>=4.2
Downloading traitlets-5.0.5-py3-none-any.whl (100 kB)
|████████████████████████████████| 100 kB 674 kB/s
Collecting prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0
Downloading prompt_toolkit-3.0.18-py3-none-any.whl (367 kB)
|████████████████████████████████| 367 kB 9.4 MB/s
Requirement already satisfied: pygments in /home/ryuta/.local/lib/rustpython3.9/site-packages (from ipython) (2.8.1)
Collecting backcall
Downloading backcall-0.2.0-py2.py3-none-any.whl (11 kB)
Collecting matplotlib-inline
Downloading matplotlib-inline-0.1.2.tar.gz (7.5 kB)
ERROR: Command errored out with exit status 1:
command: /home/ryuta/packages/rustpython/rustpython/target/release/rustpython -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-hbfr1vlb/matplotlib-inline_ed63da4beb514e6bb9e29ef16cfb17b8/setup.py'"'"'; __file__='"'"'/tmp/pip-install-hbfr1vlb/matplotlib-inline_ed63da4beb514e6bb9e29ef16cfb17b8/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-vrmiqp4g
cwd: /tmp/pip-install-hbfr1vlb/matplotlib-inline_ed63da4beb514e6bb9e29ef16cfb17b8/
Complete output (9 lines):
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/ryuta/.local/lib/rustpython3.9/site-packages/setuptools/__init__.py", line 18, in <module>
from setuptools.dist import Distribution
File "/home/ryuta/.local/lib/rustpython3.9/site-packages/setuptools/dist.py", line 36, in <module>
from setuptools import windows_support
File "/home/ryuta/.local/lib/rustpython3.9/site-packages/setuptools/windows_support.py", line 2, in <module>
import ctypes
ModuleNotFoundError: No module named 'ctypes'
----------------------------------------
WARNING: Discarding https://files.pythonhosted.org/packages/c1/fb/3361c4bf5ae8ffb9249132e70f4853ef511c0894a938fdff29320df55534/matplotlib-inline-0.1.2.tar.gz#sha256=f41d5ff73c9f5385775d5c0bc13b424535c8402fe70ea8210f93e11f3683993e (from https://pypi.org/simple/matplotlib-inline/) (requires-python:>=3.5). Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
Downloading matplotlib_inline-0.1.2-py3-none-any.whl (8.2 kB)
...
Collecting pexpect>4.3
Downloading pexpect-4.8.0-py2.py3-none-any.whl (59 kB)
|████████████████████████████████| 59 kB 355 kB/s
Collecting parso<0.9.0,>=0.8.0
Downloading parso-0.8.2-py2.py3-none-any.whl (94 kB)
|████████████████████████████████| 94 kB 180 kB/s
Collecting ptyprocess>=0.5
Downloading ptyprocess-0.7.0-py2.py3-none-any.whl (13 kB)
Collecting wcwidth
Downloading wcwidth-0.2.5-py2.py3-none-any.whl (30 kB)
Collecting ipython-genutils
Downloading ipython_genutils-0.2.0-py2.py3-none-any.whl (26 kB)
Installing collected packages: ipython-genutils, wcwidth, traitlets, ptyprocess, parso, prompt-toolkit, pickleshare, pexpect, matplotlib-inline, jedi, decorator, backcall, ipython
WARNING: The scripts iptest, iptest3, ipython and ipython3 are installed in '/home/ryuta/.local/bin' which is not on PATH.
Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed backcall-0.2.0 decorator-5.0.8 ipython-7.23.1 ipython-genutils-0.2.0 jedi-0.18.0 matplotlib-inline-0.1.2 parso-0.8.2 pexpect-4.8.0 pickleshare-0.7.5 prompt-toolkit-3.0.18 ptyprocess-0.7.0 traitlets-5.0.5 wcwidth-0.2.5