@@ -17,14 +17,36 @@ use rustpython_vm::{
17
17
} ;
18
18
use std:: convert:: TryInto ;
19
19
20
+ use std:: env;
20
21
use std:: path:: PathBuf ;
21
22
use std:: process;
23
+ use std:: str:: FromStr ;
22
24
23
25
fn main ( ) {
24
26
#[ cfg( feature = "flame-it" ) ]
25
27
let main_guard = flame:: start_guard ( "RustPython main" ) ;
26
28
env_logger:: init ( ) ;
27
- let app = App :: new ( "RustPython" )
29
+ let app = App :: new ( "RustPython" ) ;
30
+ let matches = parse_arguments ( app) ;
31
+ let settings = create_settings ( & matches) ;
32
+ let vm = VirtualMachine :: new ( settings) ;
33
+
34
+ let res = run_rustpython ( & vm, & matches) ;
35
+ // See if any exception leaked out:
36
+ handle_exception ( & vm, res) ;
37
+
38
+ #[ cfg( feature = "flame-it" ) ]
39
+ {
40
+ main_guard. end ( ) ;
41
+ if let Err ( e) = write_profile ( & matches) {
42
+ error ! ( "Error writing profile information: {}" , e) ;
43
+ process:: exit ( 1 ) ;
44
+ }
45
+ }
46
+ }
47
+
48
+ fn parse_arguments < ' a > ( app : App < ' a , ' _ > ) -> ArgMatches < ' a > {
49
+ let app = app
28
50
. version ( crate_version ! ( ) )
29
51
. author ( crate_authors ! ( ) )
30
52
. about ( "Rust implementation of the Python language" )
@@ -62,6 +84,11 @@ fn main() {
62
84
. short ( "S" )
63
85
. help ( "don't imply 'import site' on initialization" ) ,
64
86
)
87
+ . arg (
88
+ Arg :: with_name ( "ignore-environment" )
89
+ . short ( "E" )
90
+ . help ( "Ignore environment variables PYTHON* such as PYTHONPATH" ) ,
91
+ )
65
92
. arg (
66
93
Arg :: with_name ( "c" )
67
94
. short ( "c" )
@@ -89,38 +116,92 @@ fn main() {
89
116
. takes_value ( true )
90
117
. help ( "the profile format to output the profiling information in" ) ,
91
118
) ;
92
- let matches = app. get_matches ( ) ;
93
-
94
- let opt_level: u8 = matches. occurrences_of ( "optimize" ) . try_into ( ) . unwrap ( ) ;
95
- let verbosity_level: u8 = matches. occurrences_of ( "verbose" ) . try_into ( ) . unwrap ( ) ;
119
+ app. get_matches ( )
120
+ }
96
121
97
- // Construct vm:
122
+ /// Create settings by examining command line arguments and environment
123
+ /// variables.
124
+ fn create_settings ( matches : & ArgMatches ) -> PySettings {
125
+ let ignore_environment = matches. is_present ( "ignore-environment" ) ;
98
126
let mut settings: PySettings = Default :: default ( ) ;
99
- settings. debug = matches. is_present ( "debug" ) ;
100
- settings. inspect = matches. is_present ( "inspect" ) ;
101
- settings. optimize = opt_level;
102
- settings. no_site = matches. is_present ( "no-site" ) ;
103
- settings. no_user_site = matches. is_present ( "no-user-site" ) ;
104
- settings. verbose = verbosity_level;
105
- settings. quiet = matches. is_present ( "quiet" ) ;
106
- let vm = VirtualMachine :: new ( settings) ;
127
+ settings. ignore_environment = ignore_environment;
107
128
108
- let res = run_rustpython ( & vm, matches) ;
109
- // See if any exception leaked out:
110
- handle_exception ( & vm, res) ;
129
+ if !ignore_environment {
130
+ settings. path_list . append ( & mut get_paths ( "RUSTPYTHONPATH" ) ) ;
131
+ settings. path_list . append ( & mut get_paths ( "PYTHONPATH" ) ) ;
132
+ }
111
133
112
- #[ cfg( feature = "flame-it" ) ]
134
+ // Now process command line flags:
135
+ if matches. is_present ( "debug" ) || ( !ignore_environment && env:: var_os ( "PYTHONDEBUG" ) . is_some ( ) )
113
136
{
114
- main_guard. end ( ) ;
115
- if let Err ( e) = write_profile ( matches) {
116
- error ! ( "Error writing profile information: {}" , e) ;
117
- process:: exit ( 1 ) ;
137
+ settings. debug = true ;
138
+ }
139
+
140
+ if matches. is_present ( "inspect" )
141
+ || ( !ignore_environment && env:: var_os ( "PYTHONINSPECT" ) . is_some ( ) )
142
+ {
143
+ settings. inspect = true ;
144
+ }
145
+
146
+ if matches. is_present ( "optimize" ) {
147
+ settings. optimize = matches. occurrences_of ( "optimize" ) . try_into ( ) . unwrap ( ) ;
148
+ } else if !ignore_environment {
149
+ if let Ok ( value) = get_env_var_value ( "PYTHONOPTIMIZE" ) {
150
+ settings. optimize = value;
118
151
}
119
152
}
153
+
154
+ if matches. is_present ( "verbose" ) {
155
+ settings. verbose = matches. occurrences_of ( "verbose" ) . try_into ( ) . unwrap ( ) ;
156
+ } else if !ignore_environment {
157
+ if let Ok ( value) = get_env_var_value ( "PYTHONVERBOSE" ) {
158
+ settings. verbose = value;
159
+ }
160
+ }
161
+
162
+ settings. no_site = matches. is_present ( "no-site" ) ;
163
+
164
+ if matches. is_present ( "no-user-site" )
165
+ || ( !ignore_environment && env:: var_os ( "PYTHONNOUSERSITE" ) . is_some ( ) )
166
+ {
167
+ settings. no_user_site = true ;
168
+ }
169
+
170
+ if matches. is_present ( "quiet" ) {
171
+ settings. quiet = true ;
172
+ }
173
+
174
+ settings
175
+ }
176
+
177
+ /// Get environment variable and turn it into integer.
178
+ fn get_env_var_value ( name : & str ) -> Result < u8 , std:: env:: VarError > {
179
+ env:: var ( name) . map ( |value| {
180
+ if let Ok ( value) = u8:: from_str ( & value) {
181
+ value
182
+ } else {
183
+ 1
184
+ }
185
+ } )
186
+ }
187
+
188
+ /// Helper function to retrieve a sequence of paths from an environment variable.
189
+ fn get_paths ( env_variable_name : & str ) -> Vec < String > {
190
+ let paths = env:: var_os ( env_variable_name) ;
191
+ match paths {
192
+ Some ( paths) => env:: split_paths ( & paths)
193
+ . map ( |path| {
194
+ path. into_os_string ( )
195
+ . into_string ( )
196
+ . unwrap_or_else ( |_| panic ! ( "{} isn't valid unicode" , env_variable_name) )
197
+ } )
198
+ . collect ( ) ,
199
+ None => vec ! [ ] ,
200
+ }
120
201
}
121
202
122
203
#[ cfg( feature = "flame-it" ) ]
123
- fn write_profile ( matches : ArgMatches ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
204
+ fn write_profile ( matches : & ArgMatches ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
124
205
use std:: fs:: File ;
125
206
126
207
enum ProfileFormat {
@@ -163,7 +244,7 @@ fn write_profile(matches: ArgMatches) -> Result<(), Box<dyn std::error::Error>>
163
244
Ok ( ( ) )
164
245
}
165
246
166
- fn run_rustpython ( vm : & VirtualMachine , matches : ArgMatches ) -> PyResult < ( ) > {
247
+ fn run_rustpython ( vm : & VirtualMachine , matches : & ArgMatches ) -> PyResult < ( ) > {
167
248
import:: init_importlib ( & vm, true ) ?;
168
249
169
250
if let Some ( paths) = option_env ! ( "BUILDTIME_RUSTPYTHONPATH" ) {
0 commit comments