@@ -759,28 +759,55 @@ impl<'a> Interpreter<'a> {
759
759
_state : & mut State ,
760
760
) -> BodyInterpretation {
761
761
use rustpython_vm as vm;
762
- let interp = vm:: Interpreter :: with_init ( vm:: Settings :: default ( ) , |vm| {
763
- //vm.add_native_modules(rustpython_stdlib::get_module_inits());
762
+
763
+ let mut settings = rustpython_vm:: Settings :: default ( ) ;
764
+
765
+ // add PYTHONPATH to sys.path
766
+ settings. path_list . extend ( get_paths ( "PDLPYTHONPATH" ) ) ;
767
+ settings. path_list . extend ( get_paths ( "PYTHONPATH" ) ) ;
768
+
769
+ if let Ok ( venv) = :: std:: env:: var ( "VIRTUAL_ENV" ) {
770
+ let path = :: std:: path:: PathBuf :: from ( venv) . join ( if cfg ! ( windows) {
771
+ "lib/site-packages"
772
+ } else {
773
+ // TODO generalize this!
774
+ "lib/python3.12/site-packages"
775
+ } ) ;
776
+ settings = settings. with_path ( path. display ( ) . to_string ( ) ) ;
777
+ }
778
+
779
+ let interp = vm:: Interpreter :: with_init ( settings, |vm| {
780
+ vm. add_native_modules ( rustpython_stdlib:: get_module_inits ( ) ) ;
764
781
vm. add_frozen ( rustpython_pylib:: FROZEN_STDLIB ) ;
765
782
} ) ;
766
783
interp. enter ( |vm| -> BodyInterpretation {
767
784
let scope = vm. new_scope_with_builtins ( ) ;
768
785
769
- // TODO vm.new_syntax_error(&err, Some(block.code.as_str()))
770
- let code_obj = match vm. compile (
771
- block. code . as_str ( ) ,
772
- vm:: compiler:: Mode :: Exec ,
786
+ // Sigh, this is copy-pasted from RustPython/src/lib.rs
787
+ // `run_rustpython` as of 20250416 commit hash
788
+ // a917da3b1. Without this (and also: importlib and
789
+ // encodings features on rustpython-vm crate), then
790
+ // pulling in venvs does not work.
791
+ match vm. run_code_string (
792
+ vm. new_scope_with_builtins ( ) ,
793
+ "import sys; sys.path.insert(0, '')" ,
773
794
"<embedded>" . to_owned ( ) ,
774
795
) {
775
- Ok ( x ) => Ok ( x ) ,
776
- Err ( exc) => Err ( PdlError :: from ( format ! (
777
- "Syntax error in Python code {:?}" ,
778
- exc
779
- ) ) ) ,
796
+ Ok ( _ ) => Ok ( ( ) ) ,
797
+ Err ( exc) => {
798
+ vm . print_exception ( exc ) ;
799
+ Err ( PdlError :: from ( "Error setting up Python site path" ) )
800
+ }
780
801
} ?;
802
+ let site_result = vm. import ( "site" , 0 ) ;
803
+ if site_result. is_err ( ) {
804
+ println ! (
805
+ "Failed to import site, consider adding the Lib directory to your RUSTPYTHONPATH \
806
+ environment variable",
807
+ ) ;
808
+ }
781
809
782
- // TODO vm.print_exception(exc);
783
- match vm. run_code_obj ( code_obj, scope. clone ( ) ) {
810
+ match vm. run_code_string ( scope. clone ( ) , block. code . as_str ( ) , "<embedded>" . to_owned ( ) ) {
784
811
Ok ( _) => Ok ( ( ) ) ,
785
812
Err ( exc) => {
786
813
vm. print_exception ( exc) ;
@@ -1500,3 +1527,30 @@ pub fn load_scope(
1500
1527
1501
1528
Ok ( scope)
1502
1529
}
1530
+
1531
+ /// Helper function to retrieve a sequence of paths from an environment variable.
1532
+ fn get_paths ( env_variable_name : & str ) -> impl Iterator < Item = String > + ' _ {
1533
+ :: std:: env:: var_os ( env_variable_name)
1534
+ . into_iter ( )
1535
+ . flat_map ( move |paths| {
1536
+ split_paths ( & paths)
1537
+ . map ( |path| {
1538
+ path. into_os_string ( )
1539
+ . into_string ( )
1540
+ . unwrap_or_else ( |_| panic ! ( "{env_variable_name} isn't valid unicode" ) )
1541
+ } )
1542
+ . collect :: < Vec < _ > > ( )
1543
+ } )
1544
+ }
1545
+
1546
+ #[ cfg( not( target_os = "wasi" ) ) ]
1547
+ pub ( crate ) use :: std:: env:: split_paths;
1548
+ #[ cfg( target_os = "wasi" ) ]
1549
+ pub ( crate ) fn split_paths < T : AsRef < std:: ffi:: OsStr > + ?Sized > (
1550
+ s : & T ,
1551
+ ) -> impl Iterator < Item = std:: path:: PathBuf > + ' _ {
1552
+ use std:: os:: wasi:: ffi:: OsStrExt ;
1553
+ let s = s. as_ref ( ) . as_bytes ( ) ;
1554
+ s. split ( |b| * b == b':' )
1555
+ . map ( |x| std:: ffi:: OsStr :: from_bytes ( x) . to_owned ( ) . into ( ) )
1556
+ }
0 commit comments