Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Miscellaneous cli-related parity fixes #5442

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions 2 Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions 2 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ rustpython-stdlib = { workspace = true, optional = true, features = ["compiler"]
rustpython-vm = { workspace = true, features = ["compiler"] }
rustpython-parser = { workspace = true }

atty = { workspace = true }
cfg-if = { workspace = true }
log = { workspace = true }
flame = { workspace = true, optional = true }
Expand Down Expand Up @@ -141,7 +140,6 @@ rustpython-format= { version = "0.4.0" }

ahash = "0.8.11"
ascii = "1.0"
atty = "0.2.14"
bitflags = "2.4.1"
bstr = "1"
cfg-if = "1.0"
Expand Down
4 changes: 1 addition & 3 deletions 4 Lib/test/test_calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -845,9 +845,7 @@ def test_several_leapyears_in_range(self):


def conv(s):
# XXX RUSTPYTHON TODO: TextIOWrapper newline translation
return s.encode()
# return s.replace('\n', os.linesep).encode()
return s.replace('\n', os.linesep).encode()

class CommandLineTestCase(unittest.TestCase):
def run_ok(self, *args):
Expand Down
16 changes: 0 additions & 16 deletions 16 Lib/test/test_cmd_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,6 @@ def test_run_module(self):
# All good if module is located and run successfully
assert_python_ok('-m', 'timeit', '-n', '1')

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_run_module_bug1764407(self):
# -m and -i need to play well together
# Runs the timeit module and checks the __main__
Expand Down Expand Up @@ -335,8 +333,6 @@ def test_osx_android_utf8(self):
self.assertEqual(stdout, expected)
self.assertEqual(p.returncode, 0)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_non_interactive_output_buffering(self):
code = textwrap.dedent("""
import sys
Expand All @@ -352,8 +348,6 @@ def test_non_interactive_output_buffering(self):
'False False False\n'
'False False True\n')

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_unbuffered_output(self):
# Test expected operation of the '-u' switch
for stream in ('stdout', 'stderr'):
Expand Down Expand Up @@ -447,25 +441,19 @@ def check_input(self, code, expected):
stdout, stderr = proc.communicate()
self.assertEqual(stdout.rstrip(), expected)

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

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

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

# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.skipIf(interpreter_requires_environment(),
'Cannot run -I tests when PYTHON env vars are required.')
def test_isolatedmode(self):
Expand Down Expand Up @@ -662,8 +648,6 @@ def test_isolatedmode(self):
cwd=tmpdir)
self.assertEqual(out.strip(), b"ok")

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_sys_flags_set(self):
# Issue 31845: a startup refactoring broke reading flags from env vars
for value, expected in (("", 0), ("1", 1), ("text", 1), ("2", 2)):
Expand Down
1 change: 0 additions & 1 deletion 1 Lib/test/test_gzip.py
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,6 @@ def test_bad_params(self):
with self.assertRaises(ValueError):
gzip.open(self.filename, "rb", newline="\n")

@unittest.expectedFailureIfWindows("TODO: RUSTPYTHON")
def test_encoding(self):
# Test non-default encoding.
uncompressed = data1.decode("ascii") * 50
Expand Down
2 changes: 0 additions & 2 deletions 2 Lib/test/test_httpservers.py
Original file line number Diff line number Diff line change
Expand Up @@ -616,8 +616,6 @@ class request_handler(NoLogRequestHandler, CGIHTTPRequestHandler):
pass

linesep = os.linesep.encode('ascii')
# TODO: RUSTPYTHON
linesep = b'\n'

def setUp(self):
BaseTestCase.setUp(self)
Expand Down
2 changes: 0 additions & 2 deletions 2 Lib/test/test_repl.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,6 @@ def test_multiline_string_parsing(self):
output = kill_python(p)
self.assertEqual(p.returncode, 0)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_close_stdin(self):
user_input = dedent('''
import os
Expand Down
2 changes: 1 addition & 1 deletion 2 src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub type InitHook = Box<dyn FnOnce(&mut VirtualMachine)>;
/// use rustpython_vm::Settings;
/// // Override your settings here.
/// let mut settings = Settings::default();
/// settings.debug = true;
/// settings.debug = 1;
/// // You may want to add paths to `rustpython_vm::Settings::path_list` to allow import python libraries.
/// settings.path_list.push("".to_owned()); // add current working directory
/// let interpreter = rustpython::InterpreterConfig::new()
Expand Down
96 changes: 49 additions & 47 deletions 96 src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,14 @@ mod interpreter;
mod settings;
mod shell;

use atty::Stream;
use rustpython_vm::{scope::Scope, PyResult, VirtualMachine};
use std::{env, process::ExitCode};
use std::env;
use std::io::IsTerminal;
use std::process::ExitCode;

pub use interpreter::InterpreterConfig;
pub use rustpython_vm as vm;
pub use settings::{opts_with_clap, RunMode};
pub use settings::{opts_with_clap, InstallPipMode, RunMode};

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

let (settings, run_mode) = opts_with_clap();

// Be quiet if "quiet" arg is set OR stdin is not connected to a terminal
let quiet_var = settings.quiet || !atty::is(Stream::Stdin);

// don't translate newlines (\r\n <=> \n)
#[cfg(windows)]
{
Expand All @@ -97,7 +95,7 @@ pub fn run(init: impl FnOnce(&mut VirtualMachine) + 'static) -> ExitCode {
config = config.init_hook(Box::new(init));

let interp = config.interpreter();
let exitcode = interp.run(move |vm| run_rustpython(vm, run_mode, quiet_var));
let exitcode = interp.run(move |vm| run_rustpython(vm, run_mode));

ExitCode::from(exitcode)
}
Expand All @@ -117,7 +115,6 @@ fn setup_main_module(vm: &VirtualMachine) -> PyResult<Scope> {
Ok(scope)
}

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

#[cfg(feature = "ssl")]
fn ensurepip(_: Scope, vm: &VirtualMachine) -> PyResult<()> {
vm.run_module("ensurepip")
}

fn install_pip(_installer: &str, _scope: Scope, vm: &VirtualMachine) -> PyResult<()> {
#[cfg(feature = "ssl")]
{
match _installer {
"ensurepip" => ensurepip(_scope, vm),
"get-pip" => get_pip(_scope, vm),
_ => unreachable!(),
}
fn install_pip(installer: InstallPipMode, scope: Scope, vm: &VirtualMachine) -> PyResult<()> {
if cfg!(not(feature = "ssl")) {
return Err(vm.new_exception_msg(
vm.ctx.exceptions.system_error.to_owned(),
"install-pip requires rustpython be build with '--features=ssl'".to_owned(),
));
}

#[cfg(not(feature = "ssl"))]
Err(vm.new_exception_msg(
vm.ctx.exceptions.system_error.to_owned(),
"install-pip requires rustpython be build with '--features=ssl'".to_owned(),
))
match installer {
InstallPipMode::Ensurepip => vm.run_module("ensurepip"),
InstallPipMode::GetPip => get_pip(scope, vm),
}
}

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

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

match run_mode {
let is_repl = matches!(run_mode, RunMode::Repl);
if !vm.state.settings.quiet
&& (vm.state.settings.verbose > 0 || (is_repl && std::io::stdin().is_terminal()))
{
eprintln!(
"Welcome to the magnificent Rust Python {} interpreter \u{1f631} \u{1f596}",
env!("CARGO_PKG_VERSION")
);
eprintln!(
"RustPython {}.{}.{}",
vm::version::MAJOR,
vm::version::MINOR,
vm::version::MICRO,
);

eprintln!("Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.");
}
let res = match run_mode {
RunMode::Command(command) => {
debug!("Running command {}", command);
vm.run_code_string(scope, &command, "<stdin>".to_owned())?;
vm.run_code_string(scope.clone(), &command, "<stdin>".to_owned())
.map(drop)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a common convention to drop value from Result? It looks like drop is important logic here to me. If not, a weak suggestion.

Suggested change
.map(drop)
.map(|_| ())

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen .map(drop) a decent amount, yeah.

}
RunMode::Module(module) => {
debug!("Running module {}", module);
vm.run_module(&module)?;
}
RunMode::InstallPip(installer) => {
install_pip(&installer, scope, vm)?;
vm.run_module(&module)
}
RunMode::ScriptInteractive(script, interactive) => {
if let Some(script) = script {
debug!("Running script {}", &script);
vm.run_script(scope.clone(), &script)?;
} else if !quiet {
println!(
"Welcome to the magnificent Rust Python {} interpreter \u{1f631} \u{1f596}",
crate_version!()
);
}
if interactive {
shell::run_shell(vm, scope)?;
}
RunMode::InstallPip(installer) => install_pip(installer, scope.clone(), vm),
RunMode::Script(script) => {
debug!("Running script {}", &script);
vm.run_script(scope.clone(), &script)
}
RunMode::Repl => Ok(()),
};
if is_repl || vm.state.settings.inspect {
shell::run_shell(vm, scope)?;
} else {
res?;
}

#[cfg(feature = "flame-it")]
{
main_guard.end();
Expand Down
Loading
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.