mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 04:44:44 +00:00
Fix a bug when using a non system default Python
This commit is contained in:
parent
5519bbb435
commit
07f2a470f7
5 changed files with 64 additions and 35 deletions
|
@ -9,8 +9,8 @@ use std::process;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::help_messages::{command_message, mode_message};
|
use crate::help_messages::{command_message, mode_message};
|
||||||
use crate::python_util::PythonVersion;
|
use crate::python_util::{detect_magic_number, get_python_version, PythonVersion};
|
||||||
use crate::serialize::get_magic_num_from_bytes;
|
use crate::serialize::{get_magic_num_from_bytes, get_ver_from_magic_num};
|
||||||
use crate::stdin::GLOBAL_STDIN;
|
use crate::stdin::GLOBAL_STDIN;
|
||||||
use crate::{power_assert, read_file};
|
use crate::{power_assert, read_file};
|
||||||
|
|
||||||
|
@ -293,6 +293,8 @@ impl ErgConfig {
|
||||||
.expect("the value of `--py-command` is not passed")
|
.expect("the value of `--py-command` is not passed")
|
||||||
.parse::<String>()
|
.parse::<String>()
|
||||||
.expect("the value of `-py-command` is not a valid Python command");
|
.expect("the value of `-py-command` is not a valid Python command");
|
||||||
|
cfg.py_magic_num = Some(detect_magic_number(&py_command));
|
||||||
|
cfg.target_version = Some(get_python_version(&py_command));
|
||||||
cfg.py_command = Some(Box::leak(py_command.into_boxed_str()));
|
cfg.py_command = Some(Box::leak(py_command.into_boxed_str()));
|
||||||
}
|
}
|
||||||
"--hex-py-magic-num" | "--hex-python-magic-number" => {
|
"--hex-py-magic-num" | "--hex-python-magic-number" => {
|
||||||
|
@ -303,14 +305,16 @@ impl ErgConfig {
|
||||||
let second_byte = u8::from_str_radix(&s_hex_magic_num[2..=3], 16).unwrap();
|
let second_byte = u8::from_str_radix(&s_hex_magic_num[2..=3], 16).unwrap();
|
||||||
let py_magic_num = get_magic_num_from_bytes(&[first_byte, second_byte, 0, 0]);
|
let py_magic_num = get_magic_num_from_bytes(&[first_byte, second_byte, 0, 0]);
|
||||||
cfg.py_magic_num = Some(py_magic_num);
|
cfg.py_magic_num = Some(py_magic_num);
|
||||||
|
cfg.target_version = Some(get_ver_from_magic_num(py_magic_num));
|
||||||
}
|
}
|
||||||
"--py-magic-num" | "--python-magic-number" => {
|
"--py-magic-num" | "--python-magic-number" => {
|
||||||
cfg.py_magic_num = Some(
|
let py_magic_num = args
|
||||||
args.next()
|
.next()
|
||||||
.expect("the value of `--py-magic-num` is not passed")
|
.expect("the value of `--py-magic-num` is not passed")
|
||||||
.parse::<u32>()
|
.parse::<u32>()
|
||||||
.expect("the value of `--py-magic-num` is not a number"),
|
.expect("the value of `--py-magic-num` is not a number");
|
||||||
);
|
cfg.py_magic_num = Some(py_magic_num);
|
||||||
|
cfg.target_version = Some(get_ver_from_magic_num(py_magic_num));
|
||||||
}
|
}
|
||||||
"--py-server-timeout" => {
|
"--py-server-timeout" => {
|
||||||
cfg.py_server_timeout = args
|
cfg.py_server_timeout = args
|
||||||
|
|
|
@ -380,23 +380,22 @@ pub fn which_python() -> String {
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detect_magic_number() -> u32 {
|
pub fn detect_magic_number(py_command: &str) -> u32 {
|
||||||
let out = if cfg!(windows) {
|
let out = if cfg!(windows) {
|
||||||
Command::new("cmd")
|
Command::new("cmd")
|
||||||
.arg("/C")
|
.arg("/C")
|
||||||
.arg(which_python())
|
.arg(py_command)
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg("import importlib.util as util;print(util.MAGIC_NUMBER.hex())")
|
.arg("import importlib.util as util;print(util.MAGIC_NUMBER.hex())")
|
||||||
.output()
|
.output()
|
||||||
.expect("cannot get the magic number from python")
|
.expect("cannot get the magic number from python")
|
||||||
} else {
|
} else {
|
||||||
let python_command = format!(
|
let exec_command = format!(
|
||||||
"{} -c 'import importlib.util as util;print(util.MAGIC_NUMBER.hex())'",
|
"{py_command} -c 'import importlib.util as util;print(util.MAGIC_NUMBER.hex())'",
|
||||||
which_python()
|
|
||||||
);
|
);
|
||||||
Command::new("sh")
|
Command::new("sh")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(python_command)
|
.arg(exec_command)
|
||||||
.output()
|
.output()
|
||||||
.expect("cannot get the magic number from python")
|
.expect("cannot get the magic number from python")
|
||||||
};
|
};
|
||||||
|
@ -406,6 +405,10 @@ pub fn detect_magic_number() -> u32 {
|
||||||
get_magic_num_from_bytes(&[first_byte, second_byte, 0, 0])
|
get_magic_num_from_bytes(&[first_byte, second_byte, 0, 0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn env_magic_number() -> u32 {
|
||||||
|
detect_magic_number(&which_python())
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct PythonVersion {
|
pub struct PythonVersion {
|
||||||
pub major: u8,
|
pub major: u8,
|
||||||
|
@ -454,23 +457,22 @@ impl std::str::FromStr for PythonVersion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn python_version() -> PythonVersion {
|
pub fn get_python_version(py_command: &str) -> PythonVersion {
|
||||||
let out = if cfg!(windows) {
|
let out = if cfg!(windows) {
|
||||||
Command::new("cmd")
|
Command::new("cmd")
|
||||||
.arg("/C")
|
.arg("/C")
|
||||||
.arg(which_python())
|
.arg(py_command)
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg("import sys;print(sys.version_info.major, sys.version_info.minor, sys.version_info.micro)")
|
.arg("import sys;print(sys.version_info.major, sys.version_info.minor, sys.version_info.micro)")
|
||||||
.output()
|
.output()
|
||||||
.expect("cannot get the python version")
|
.expect("cannot get the python version")
|
||||||
} else {
|
} else {
|
||||||
let python_command = format!(
|
let exec_command = format!(
|
||||||
"{} -c 'import sys;print(sys.version_info.major, sys.version_info.minor, sys.version_info.micro)'",
|
"{py_command} -c 'import sys;print(sys.version_info.major, sys.version_info.minor, sys.version_info.micro)'",
|
||||||
which_python()
|
|
||||||
);
|
);
|
||||||
Command::new("sh")
|
Command::new("sh")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(python_command)
|
.arg(exec_command)
|
||||||
.output()
|
.output()
|
||||||
.expect("cannot get the python version")
|
.expect("cannot get the python version")
|
||||||
};
|
};
|
||||||
|
@ -486,6 +488,10 @@ pub fn python_version() -> PythonVersion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn env_python_version() -> PythonVersion {
|
||||||
|
get_python_version(&which_python())
|
||||||
|
}
|
||||||
|
|
||||||
/// executes over a shell, cause `python` may not exist as an executable file (like pyenv)
|
/// executes over a shell, cause `python` may not exist as an executable file (like pyenv)
|
||||||
pub fn exec_pyc<S: Into<String>>(file: S, py_command: Option<&str>) -> Option<i32> {
|
pub fn exec_pyc<S: Into<String>>(file: S, py_command: Option<&str>) -> Option<i32> {
|
||||||
let command = py_command
|
let command = py_command
|
||||||
|
@ -499,10 +505,10 @@ pub fn exec_pyc<S: Into<String>>(file: S, py_command: Option<&str>) -> Option<i3
|
||||||
.spawn()
|
.spawn()
|
||||||
.expect("cannot execute python")
|
.expect("cannot execute python")
|
||||||
} else {
|
} else {
|
||||||
let python_command = format!("{command} {}", file.into());
|
let exec_command = format!("{command} {}", file.into());
|
||||||
Command::new("sh")
|
Command::new("sh")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(python_command)
|
.arg(exec_command)
|
||||||
.spawn()
|
.spawn()
|
||||||
.expect("cannot execute python")
|
.expect("cannot execute python")
|
||||||
};
|
};
|
||||||
|
@ -522,10 +528,10 @@ pub fn eval_pyc<S: Into<String>>(file: S, py_command: Option<&str>) -> String {
|
||||||
.spawn()
|
.spawn()
|
||||||
.expect("cannot execute python")
|
.expect("cannot execute python")
|
||||||
} else {
|
} else {
|
||||||
let python_command = format!("{command} {}", file.into());
|
let exec_command = format!("{command} {}", file.into());
|
||||||
Command::new("sh")
|
Command::new("sh")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(python_command)
|
.arg(exec_command)
|
||||||
.spawn()
|
.spawn()
|
||||||
.expect("cannot execute python")
|
.expect("cannot execute python")
|
||||||
};
|
};
|
||||||
|
@ -541,17 +547,17 @@ pub fn exec_py(code: &str) -> Option<i32> {
|
||||||
.spawn()
|
.spawn()
|
||||||
.expect("cannot execute python")
|
.expect("cannot execute python")
|
||||||
} else {
|
} else {
|
||||||
let python_command = format!("{} -c \"{}\"", which_python(), code);
|
let exec_command = format!("{} -c \"{}\"", which_python(), code);
|
||||||
Command::new("sh")
|
Command::new("sh")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(python_command)
|
.arg(exec_command)
|
||||||
.spawn()
|
.spawn()
|
||||||
.expect("cannot execute python")
|
.expect("cannot execute python")
|
||||||
};
|
};
|
||||||
child.wait().expect("python doesn't work").code()
|
child.wait().expect("python doesn't work").code()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn_py(code: &str) {
|
pub fn env_spawn_py(code: &str) {
|
||||||
if cfg!(windows) {
|
if cfg!(windows) {
|
||||||
Command::new(which_python())
|
Command::new(which_python())
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
|
@ -559,10 +565,27 @@ pub fn spawn_py(code: &str) {
|
||||||
.spawn()
|
.spawn()
|
||||||
.expect("cannot execute python");
|
.expect("cannot execute python");
|
||||||
} else {
|
} else {
|
||||||
let python_command = format!("{} -c \"{}\"", which_python(), code);
|
let exec_command = format!("{} -c \"{}\"", which_python(), code);
|
||||||
Command::new("sh")
|
Command::new("sh")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(python_command)
|
.arg(exec_command)
|
||||||
|
.spawn()
|
||||||
|
.expect("cannot execute python");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn_py(py_command: Option<&str>, code: &str) {
|
||||||
|
if cfg!(windows) {
|
||||||
|
Command::new(py_command.unwrap_or(&which_python()))
|
||||||
|
.arg("-c")
|
||||||
|
.arg(code)
|
||||||
|
.spawn()
|
||||||
|
.expect("cannot execute python");
|
||||||
|
} else {
|
||||||
|
let exec_command = format!("{} -c \"{}\"", py_command.unwrap_or(&which_python()), code);
|
||||||
|
Command::new("sh")
|
||||||
|
.arg("-c")
|
||||||
|
.arg(exec_command)
|
||||||
.spawn()
|
.spawn()
|
||||||
.expect("cannot execute python");
|
.expect("cannot execute python");
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ use erg_common::opcode308::Opcode308;
|
||||||
use erg_common::opcode310::Opcode310;
|
use erg_common::opcode310::Opcode310;
|
||||||
use erg_common::opcode311::{BinOpCode, Opcode311};
|
use erg_common::opcode311::{BinOpCode, Opcode311};
|
||||||
use erg_common::option_enum_unwrap;
|
use erg_common::option_enum_unwrap;
|
||||||
use erg_common::python_util::{python_version, PythonVersion};
|
use erg_common::python_util::{env_python_version, PythonVersion};
|
||||||
use erg_common::traits::{Locational, Stream};
|
use erg_common::traits::{Locational, Stream};
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
use erg_common::{
|
use erg_common::{
|
||||||
|
@ -144,7 +144,7 @@ pub struct CodeGenerator {
|
||||||
impl CodeGenerator {
|
impl CodeGenerator {
|
||||||
pub fn new(cfg: ErgConfig) -> Self {
|
pub fn new(cfg: ErgConfig) -> Self {
|
||||||
Self {
|
Self {
|
||||||
py_version: cfg.target_version.unwrap_or_else(python_version),
|
py_version: cfg.target_version.unwrap_or_else(env_python_version),
|
||||||
cfg,
|
cfg,
|
||||||
str_cache: CacheSet::new(),
|
str_cache: CacheSet::new(),
|
||||||
prelude_loaded: false,
|
prelude_loaded: false,
|
||||||
|
|
|
@ -11,7 +11,7 @@ use erg_common::opcode::CommonOpcode;
|
||||||
use erg_common::opcode308::Opcode308;
|
use erg_common::opcode308::Opcode308;
|
||||||
use erg_common::opcode310::Opcode310;
|
use erg_common::opcode310::Opcode310;
|
||||||
use erg_common::opcode311::{BinOpCode, Opcode311};
|
use erg_common::opcode311::{BinOpCode, Opcode311};
|
||||||
use erg_common::python_util::{detect_magic_number, PythonVersion};
|
use erg_common::python_util::{env_magic_number, PythonVersion};
|
||||||
use erg_common::serialize::*;
|
use erg_common::serialize::*;
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
|
|
||||||
|
@ -335,7 +335,9 @@ impl CodeObj {
|
||||||
);
|
);
|
||||||
bytes.append(&mut str_into_bytes(self.filename, false));
|
bytes.append(&mut str_into_bytes(self.filename, false));
|
||||||
bytes.append(&mut str_into_bytes(self.name, true));
|
bytes.append(&mut str_into_bytes(self.name, true));
|
||||||
bytes.append(&mut str_into_bytes(self.qualname, true));
|
if python_ver.minor >= Some(11) {
|
||||||
|
bytes.append(&mut str_into_bytes(self.qualname, true));
|
||||||
|
}
|
||||||
bytes.append(&mut self.firstlineno.to_le_bytes().to_vec());
|
bytes.append(&mut self.firstlineno.to_le_bytes().to_vec());
|
||||||
// lnotab is represented as PyStrObject
|
// lnotab is represented as PyStrObject
|
||||||
bytes.append(&mut raw_string_into_bytes(self.lnotab));
|
bytes.append(&mut raw_string_into_bytes(self.lnotab));
|
||||||
|
@ -380,7 +382,7 @@ impl CodeObj {
|
||||||
) -> std::io::Result<()> {
|
) -> std::io::Result<()> {
|
||||||
let mut file = File::create(path)?;
|
let mut file = File::create(path)?;
|
||||||
let mut bytes = Vec::with_capacity(16);
|
let mut bytes = Vec::with_capacity(16);
|
||||||
let py_magic_num = py_magic_num.unwrap_or_else(detect_magic_number);
|
let py_magic_num = py_magic_num.unwrap_or_else(env_magic_number);
|
||||||
let python_ver = get_ver_from_magic_num(py_magic_num);
|
let python_ver = get_ver_from_magic_num(py_magic_num);
|
||||||
bytes.append(&mut get_magic_num_bytes(py_magic_num).to_vec());
|
bytes.append(&mut get_magic_num_bytes(py_magic_num).to_vec());
|
||||||
bytes.append(&mut vec![0; 4]); // padding
|
bytes.append(&mut vec![0; 4]); // padding
|
||||||
|
|
|
@ -44,7 +44,7 @@ impl Runnable for DummyVM {
|
||||||
let port = find_available_port();
|
let port = find_available_port();
|
||||||
let code = include_str!("scripts/repl_server.py")
|
let code = include_str!("scripts/repl_server.py")
|
||||||
.replace("__PORT__", port.to_string().as_str());
|
.replace("__PORT__", port.to_string().as_str());
|
||||||
spawn_py(&code);
|
spawn_py(cfg.py_command, &code);
|
||||||
let addr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, port);
|
let addr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, port);
|
||||||
if !cfg.quiet_startup {
|
if !cfg.quiet_startup {
|
||||||
println!("Connecting to the REPL server...");
|
println!("Connecting to the REPL server...");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue