Skip to content

Commit e4be882

Browse files
committed
Miscellaneous cli-related parity fixes
1 parent adc05e6 commit e4be882

17 files changed

+225
-228
lines changed

Cargo.lock

-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ rustpython-stdlib = { workspace = true, optional = true, features = ["compiler"]
3131
rustpython-vm = { workspace = true, features = ["compiler"] }
3232
rustpython-parser = { workspace = true }
3333

34-
atty = { workspace = true }
3534
cfg-if = { workspace = true }
3635
log = { workspace = true }
3736
flame = { workspace = true, optional = true }
@@ -141,7 +140,6 @@ rustpython-format= { version = "0.4.0" }
141140

142141
ahash = "0.8.11"
143142
ascii = "1.0"
144-
atty = "0.2.14"
145143
bitflags = "2.4.1"
146144
bstr = "1"
147145
cfg-if = "1.0"

Lib/test/test_cmd_line.py

-16
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,6 @@ def test_run_module(self):
177177
# All good if module is located and run successfully
178178
assert_python_ok('-m', 'timeit', '-n', '1')
179179

180-
# TODO: RUSTPYTHON
181-
@unittest.expectedFailure
182180
def test_run_module_bug1764407(self):
183181
# -m and -i need to play well together
184182
# Runs the timeit module and checks the __main__
@@ -335,8 +333,6 @@ def test_osx_android_utf8(self):
335333
self.assertEqual(stdout, expected)
336334
self.assertEqual(p.returncode, 0)
337335

338-
# TODO: RUSTPYTHON
339-
@unittest.expectedFailure
340336
def test_non_interactive_output_buffering(self):
341337
code = textwrap.dedent("""
342338
import sys
@@ -352,8 +348,6 @@ def test_non_interactive_output_buffering(self):
352348
'False False False\n'
353349
'False False True\n')
354350

355-
# TODO: RUSTPYTHON
356-
@unittest.expectedFailure
357351
def test_unbuffered_output(self):
358352
# Test expected operation of the '-u' switch
359353
for stream in ('stdout', 'stderr'):
@@ -447,25 +441,19 @@ def check_input(self, code, expected):
447441
stdout, stderr = proc.communicate()
448442
self.assertEqual(stdout.rstrip(), expected)
449443

450-
# TODO: RUSTPYTHON
451-
@unittest.skipIf(sys.platform.startswith('win'), "TODO: RUSTPYTHON windows has \n troubles")
452444
def test_stdin_readline(self):
453445
# Issue #11272: check that sys.stdin.readline() replaces '\r\n' by '\n'
454446
# on Windows (sys.stdin is opened in binary mode)
455447
self.check_input(
456448
"import sys; print(repr(sys.stdin.readline()))",
457449
b"'abc\\n'")
458450

459-
# TODO: RUSTPYTHON
460-
@unittest.skipIf(sys.platform.startswith('win'), "TODO: RUSTPYTHON windows has \n troubles")
461451
def test_builtin_input(self):
462452
# Issue #11272: check that input() strips newlines ('\n' or '\r\n')
463453
self.check_input(
464454
"print(repr(input()))",
465455
b"'abc'")
466456

467-
# TODO: RUSTPYTHON
468-
@unittest.skipIf(sys.platform.startswith('win'), "TODO: RUSTPYTHON windows has \n troubles")
469457
def test_output_newline(self):
470458
# Issue 13119 Newline for print() should be \r\n on Windows.
471459
code = """if 1:
@@ -632,8 +620,6 @@ def test_unknown_options(self):
632620
self.assertEqual(err.splitlines().count(b'Unknown option: -a'), 1)
633621
self.assertEqual(b'', out)
634622

635-
# TODO: RUSTPYTHON
636-
@unittest.expectedFailure
637623
@unittest.skipIf(interpreter_requires_environment(),
638624
'Cannot run -I tests when PYTHON env vars are required.')
639625
def test_isolatedmode(self):
@@ -662,8 +648,6 @@ def test_isolatedmode(self):
662648
cwd=tmpdir)
663649
self.assertEqual(out.strip(), b"ok")
664650

665-
# TODO: RUSTPYTHON
666-
@unittest.expectedFailure
667651
def test_sys_flags_set(self):
668652
# Issue 31845: a startup refactoring broke reading flags from env vars
669653
for value, expected in (("", 0), ("1", 1), ("text", 1), ("2", 2)):

Lib/test/test_repl.py

-2
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,6 @@ def test_multiline_string_parsing(self):
9292
output = kill_python(p)
9393
self.assertEqual(p.returncode, 0)
9494

95-
# TODO: RUSTPYTHON
96-
@unittest.expectedFailure
9795
def test_close_stdin(self):
9896
user_input = dedent('''
9997
import os

src/interpreter.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub type InitHook = Box<dyn FnOnce(&mut VirtualMachine)>;
1616
/// use rustpython_vm::Settings;
1717
/// // Override your settings here.
1818
/// let mut settings = Settings::default();
19-
/// settings.debug = true;
19+
/// settings.debug = 1;
2020
/// // You may want to add paths to `rustpython_vm::Settings::path_list` to allow import python libraries.
2121
/// settings.path_list.push("".to_owned()); // add current working directory
2222
/// let interpreter = rustpython::InterpreterConfig::new()

src/lib.rs

+49-47
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,14 @@ mod interpreter;
5050
mod settings;
5151
mod shell;
5252

53-
use atty::Stream;
5453
use rustpython_vm::{scope::Scope, PyResult, VirtualMachine};
55-
use std::{env, process::ExitCode};
54+
use std::env;
55+
use std::io::IsTerminal;
56+
use std::process::ExitCode;
5657

5758
pub use interpreter::InterpreterConfig;
5859
pub use rustpython_vm as vm;
59-
pub use settings::{opts_with_clap, RunMode};
60+
pub use settings::{opts_with_clap, InstallPipMode, RunMode};
6061

6162
/// The main cli of the `rustpython` interpreter. This function will return `std::process::ExitCode`
6263
/// based on the return code of the python code ran through the cli.
@@ -73,9 +74,6 @@ pub fn run(init: impl FnOnce(&mut VirtualMachine) + 'static) -> ExitCode {
7374

7475
let (settings, run_mode) = opts_with_clap();
7576

76-
// Be quiet if "quiet" arg is set OR stdin is not connected to a terminal
77-
let quiet_var = settings.quiet || !atty::is(Stream::Stdin);
78-
7977
// don't translate newlines (\r\n <=> \n)
8078
#[cfg(windows)]
8179
{
@@ -97,7 +95,7 @@ pub fn run(init: impl FnOnce(&mut VirtualMachine) + 'static) -> ExitCode {
9795
config = config.init_hook(Box::new(init));
9896

9997
let interp = config.interpreter();
100-
let exitcode = interp.run(move |vm| run_rustpython(vm, run_mode, quiet_var));
98+
let exitcode = interp.run(move |vm| run_rustpython(vm, run_mode));
10199

102100
ExitCode::from(exitcode)
103101
}
@@ -117,7 +115,6 @@ fn setup_main_module(vm: &VirtualMachine) -> PyResult<Scope> {
117115
Ok(scope)
118116
}
119117

120-
#[cfg(feature = "ssl")]
121118
fn get_pip(scope: Scope, vm: &VirtualMachine) -> PyResult<()> {
122119
let get_getpip = rustpython_vm::py_compile!(
123120
source = r#"\
@@ -128,7 +125,7 @@ __import__("io").TextIOWrapper(
128125
mode = "eval"
129126
);
130127
eprintln!("downloading get-pip.py...");
131-
let getpip_code = vm.run_code_obj(vm.ctx.new_code(get_getpip), scope.clone())?;
128+
let getpip_code = vm.run_code_obj(vm.ctx.new_code(get_getpip), vm.new_scope_with_builtins())?;
132129
let getpip_code: rustpython_vm::builtins::PyStrRef = getpip_code
133130
.downcast()
134131
.expect("TextIOWrapper.read() should return str");
@@ -137,29 +134,21 @@ __import__("io").TextIOWrapper(
137134
Ok(())
138135
}
139136

140-
#[cfg(feature = "ssl")]
141-
fn ensurepip(_: Scope, vm: &VirtualMachine) -> PyResult<()> {
142-
vm.run_module("ensurepip")
143-
}
144-
145-
fn install_pip(_installer: &str, _scope: Scope, vm: &VirtualMachine) -> PyResult<()> {
146-
#[cfg(feature = "ssl")]
147-
{
148-
match _installer {
149-
"ensurepip" => ensurepip(_scope, vm),
150-
"get-pip" => get_pip(_scope, vm),
151-
_ => unreachable!(),
152-
}
137+
fn install_pip(installer: InstallPipMode, scope: Scope, vm: &VirtualMachine) -> PyResult<()> {
138+
if cfg!(not(feature = "ssl")) {
139+
return Err(vm.new_exception_msg(
140+
vm.ctx.exceptions.system_error.to_owned(),
141+
"install-pip requires rustpython be build with '--features=ssl'".to_owned(),
142+
));
153143
}
154144

155-
#[cfg(not(feature = "ssl"))]
156-
Err(vm.new_exception_msg(
157-
vm.ctx.exceptions.system_error.to_owned(),
158-
"install-pip requires rustpython be build with '--features=ssl'".to_owned(),
159-
))
145+
match installer {
146+
InstallPipMode::Ensurepip => vm.run_module("ensurepip"),
147+
InstallPipMode::GetPip => get_pip(scope, vm),
148+
}
160149
}
161150

162-
fn run_rustpython(vm: &VirtualMachine, run_mode: RunMode, quiet: bool) -> PyResult<()> {
151+
fn run_rustpython(vm: &VirtualMachine, run_mode: RunMode) -> PyResult<()> {
163152
#[cfg(feature = "flame-it")]
164153
let main_guard = flame::start_guard("RustPython main");
165154

@@ -183,33 +172,46 @@ fn run_rustpython(vm: &VirtualMachine, run_mode: RunMode, quiet: bool) -> PyResu
183172
);
184173
}
185174

186-
match run_mode {
175+
let is_repl = matches!(run_mode, RunMode::Repl);
176+
if !vm.state.settings.quiet
177+
&& (vm.state.settings.verbose > 0 || (is_repl && std::io::stdin().is_terminal()))
178+
{
179+
eprintln!(
180+
"Welcome to the magnificent Rust Python {} interpreter \u{1f631} \u{1f596}",
181+
env!("CARGO_PKG_VERSION")
182+
);
183+
eprintln!(
184+
"RustPython {}.{}.{}",
185+
vm::version::MAJOR,
186+
vm::version::MINOR,
187+
vm::version::MICRO,
188+
);
189+
190+
eprintln!("Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.");
191+
}
192+
let res = match run_mode {
187193
RunMode::Command(command) => {
188194
debug!("Running command {}", command);
189-
vm.run_code_string(scope, &command, "<stdin>".to_owned())?;
195+
vm.run_code_string(scope.clone(), &command, "<stdin>".to_owned())
196+
.map(drop)
190197
}
191198
RunMode::Module(module) => {
192199
debug!("Running module {}", module);
193-
vm.run_module(&module)?;
194-
}
195-
RunMode::InstallPip(installer) => {
196-
install_pip(&installer, scope, vm)?;
200+
vm.run_module(&module)
197201
}
198-
RunMode::ScriptInteractive(script, interactive) => {
199-
if let Some(script) = script {
200-
debug!("Running script {}", &script);
201-
vm.run_script(scope.clone(), &script)?;
202-
} else if !quiet {
203-
println!(
204-
"Welcome to the magnificent Rust Python {} interpreter \u{1f631} \u{1f596}",
205-
crate_version!()
206-
);
207-
}
208-
if interactive {
209-
shell::run_shell(vm, scope)?;
210-
}
202+
RunMode::InstallPip(installer) => install_pip(installer, scope.clone(), vm),
203+
RunMode::Script(script) => {
204+
debug!("Running script {}", &script);
205+
vm.run_script(scope.clone(), &script)
211206
}
207+
RunMode::Repl => Ok(()),
208+
};
209+
if is_repl || vm.state.settings.inspect {
210+
shell::run_shell(vm, scope)?;
211+
} else {
212+
res?;
212213
}
214+
213215
#[cfg(feature = "flame-it")]
214216
{
215217
main_guard.end();

0 commit comments

Comments
 (0)