Skip to content
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
1 change: 0 additions & 1 deletion Lib/test/test_cmd_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,6 @@ def test_undecodable_code(self):
if not stdout.startswith(pattern):
raise AssertionError("%a doesn't start with %a" % (stdout, pattern))

@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.skipIf(sys.platform == 'win32',
'Windows has a native unicode API')
def test_invalid_utf8_arg(self):
Expand Down
4 changes: 3 additions & 1 deletion crates/stdlib/src/syslog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,10 @@ mod syslog {
if let Some(argv) = vm.state.config.settings.argv.first()
&& !argv.is_empty()
{
let argv = vm.fsdecode(argv.clone());
let argv = argv.as_wtf8();
return Some(
PyStr::from(match argv.find('\\') {
PyStr::from(match argv.as_bytes().iter().position(|&b| b == b'\\') {
Some(value) => &argv[value..],
None => argv,
})
Expand Down
19 changes: 13 additions & 6 deletions crates/vm/src/getpath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use crate::vm::{Paths, Settings};
use std::env;
use std::ffi::OsString;
use std::io::{self, Read};
use std::path::{Path, PathBuf};

Expand Down Expand Up @@ -622,13 +623,19 @@ fn env_executable_override() -> Option<String> {

/// CALCULATE program_name: `argv[0]`, with the executable suffix added when
/// only the suffixed file exists.
fn program_name() -> String {
let program_name = env::args()
fn program_name() -> OsString {
let program_name = env::args_os()
.next()
.filter(|arg| !arg.is_empty())
.unwrap_or_else(|| platform::DEFAULT_PROGRAM_NAME.to_owned());
if cfg!(windows) && !program_name.to_lowercase().ends_with(".exe") {
let suffixed = format!("{program_name}.exe");
.unwrap_or_else(|| platform::DEFAULT_PROGRAM_NAME.into());
if cfg!(windows)
&& !program_name
.to_string_lossy()
.to_lowercase()
.ends_with(".exe")
{
let mut suffixed = program_name.clone();
suffixed.push(".exe");
if Path::new(&suffixed).is_file() {
return suffixed;
}
Expand All @@ -651,7 +658,7 @@ fn get_executable_path() -> Option<PathBuf> {
}
#[cfg(target_arch = "wasm32")]
{
let exec_arg = env::args().next()?;
let exec_arg = env::args_os().next()?;
Some(PathBuf::from(exec_arg))
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/vm/src/stdlib/sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ pub mod sys {
.settings
.argv
.iter()
.map(|arg| vm.ctx.new_str(arg.clone()).into())
.map(|arg| vm.fsdecode(arg.clone()).into())
.collect()
}

Expand Down Expand Up @@ -708,7 +708,7 @@ pub mod sys {

#[pyattr]
fn orig_argv(vm: &VirtualMachine) -> Vec<PyObjectRef> {
env::args().map(|arg| vm.ctx.new_str(arg).into()).collect()
env::args_os().map(|arg| vm.fsdecode(arg).into()).collect()
}

#[pyattr]
Expand Down
6 changes: 3 additions & 3 deletions crates/vm/src/vm/setting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::ffi::OsString;
#[derive(Debug, Clone, Default)]
pub struct Paths {
/// program_name: the name the interpreter was invoked as
pub program_name: String,
pub program_name: OsString,
/// sys.executable
pub executable: String,
/// sys._base_executable (original interpreter in venv)
Expand Down Expand Up @@ -77,8 +77,8 @@ pub struct Settings {
pub pycache_prefix: Option<OsString>,
// int parse_argv;
// PyWideStringList orig_argv;
/// sys.argv
pub argv: Vec<String>,
/// sys.argv, decoded with the filesystem encoding during sys initialization.
pub argv: Vec<OsString>,

// spell-checker:ignore Xfoo
/// -Xfoo[=bar]
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ fn run_file(vm: &VirtualMachine, scope: Scope, argv0: &str) -> PyResult<u32> {
}

fn cant_open_file(vm: &VirtualMachine, path: &str, err: &std::io::Error) -> PyResult<u32> {
let program_name = &vm.state.config.paths.program_name;
let program_name = vm.fsdecode(vm.state.config.paths.program_name.clone());
let filename_repr = vm.ctx.new_str(path).as_object().repr(vm)?;
let errno = err.raw_os_error().unwrap_or(2);
let strerror = vm::host_env::errno::strerror_string(errno).unwrap_or_default();
Expand Down
17 changes: 10 additions & 7 deletions src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use lexopt::Arg::{Long, Short, Value};
use lexopt::ValueExt;
use rustpython_vm::{Settings, vm::CheckHashPycsMode};
use std::env;
use std::ffi::OsString;

pub enum RunMode {
Script(String),
Expand Down Expand Up @@ -112,13 +113,15 @@ file : program read from script file
arg ...: arguments passed to program in sys.argv[1:]
";

fn parse_args() -> Result<(CliArgs, RunMode, Vec<String>), lexopt::Error> {
fn parse_args() -> Result<(CliArgs, RunMode, Vec<OsString>), lexopt::Error> {
let mut args = CliArgs::default();
let mut parser = lexopt::Parser::from_env();
fn argv(argv0: String, mut parser: lexopt::Parser) -> Result<Vec<String>, lexopt::Error> {
core::iter::once(Ok(argv0))
.chain(parser.raw_args()?.map(|arg| arg.string()))
.collect()
fn argv(argv0: String, mut parser: lexopt::Parser) -> Result<Vec<OsString>, lexopt::Error> {
// Arguments after the entry point are filesystem-encoded data, not
// necessarily Unicode. Decode only when constructing Python strings.
Ok(core::iter::once(argv0.into())
.chain(parser.raw_args()?)
.collect())
}
while let Some(arg) = parser.next()? {
match arg {
Expand Down Expand Up @@ -171,15 +174,15 @@ fn parse_args() -> Result<(CliArgs, RunMode, Vec<String>), lexopt::Error> {

Long("install-pip") => {
let (mode, argv) = if let Some(val) = parser.optional_value() {
(val.parse()?, vec![val.string()?])
(val.parse()?, vec![val])
} else if let Ok(argv0) = parser.value() {
let mode = argv0.parse()?;
(mode, argv(argv0.string()?, parser)?)
} else {
(
InstallPipMode::Ensurepip,
["ensurepip", "--upgrade", "--default-pip"]
.map(str::to_owned)
.map(OsString::from)
.into(),
)
};
Expand Down
Loading