Repository: RustPython/RustPython (language: rust)

Issue:
Add `-X int_max_str_digits` and `PYTHONINTMAXSTRDIGITS` environment variable
## Feature

Follow up to #5010 

These just set the value of `int_max_str_digits` via an implementation specific command line flag (`-X`) and/or the environment variable. These need to be accepted in `settings.rs` and stored in the `Settings` struct. `Flag::from_settings` should be updated to pass the value along.

`test_int_max_str_digits` in `test_cmd_line.py` is a good place to evaluate changes, hopefully (but not necessarily) the test might  will succeed after this change. You can run it locally with:

```bash
cargo run --release --features ssl,jit -- -m test -u all --slowest --fail-env-changed -v test_cmd_line`
```

to get some early feedback.


Discussion / hints:
Hi, can I work on this? TIA.
Sure, go for it!

Fix patch:
diff --git a/src/settings.rs b/src/settings.rs
index 836bb14012..6a47233353 100644
--- a/src/settings.rs
+++ b/src/settings.rs
@@ -227,6 +227,15 @@ fn settings_from(matches: &ArgMatches) -> (Settings, RunMode) {
     {
         settings.dont_write_bytecode = true;
     }
+    if !ignore_environment && env::var_os("PYTHONINTMAXSTRDIGITS").is_some() {
+        settings.int_max_str_digits = match env::var("PYTHONINTMAXSTRDIGITS").unwrap().parse() {
+            Ok(digits) if digits == 0 || digits >= 640 => digits,
+            _ => {
+                error!("Fatal Python error: config_init_int_max_str_digits: PYTHONINTMAXSTRDIGITS: invalid limit; must be >= 640 or 0 for unlimited.\nPython runtime state: preinitialized");
+                std::process::exit(1);
+            }
+        };
+    }
 
     settings.check_hash_based_pycs = matches
         .value_of("check-hash-based-pycs")
@@ -239,6 +248,7 @@ fn settings_from(matches: &ArgMatches) -> (Settings, RunMode) {
         settings.xopts.extend(xopts.map(|s| {
             let mut parts = s.splitn(2, '=');
             let name = parts.next().unwrap().to_owned();
+            let value = parts.next().map(ToOwned::to_owned);
             if name == "dev" {
                 dev_mode = true
             }
@@ -248,7 +258,16 @@ fn settings_from(matches: &ArgMatches) -> (Settings, RunMode) {
             if name == "no_sig_int" {
                 settings.no_sig_int = true;
             }
-            let value = parts.next().map(ToOwned::to_owned);
+            if name == "int_max_str_digits" {
+                settings.int_max_str_digits = match value.as_ref().unwrap().parse() {
+                    Ok(digits) if digits == 0 || digits >= 640 => digits,
+                    _ => {
+
+                    error!("Fatal Python error: config_init_int_max_str_digits: -X int_max_str_digits: invalid limit; must be >= 640 or 0 for unlimited.\nPython runtime state: preinitialized");
+                    std::process::exit(1);
+                    },
+                };
+            }
             (name, value)
         }));
     }
diff --git a/vm/src/stdlib/sys.rs b/vm/src/stdlib/sys.rs
index 027a67178c..3a3824b310 100644
--- a/vm/src/stdlib/sys.rs
+++ b/vm/src/stdlib/sys.rs
@@ -727,7 +727,7 @@ mod sys {
         /// -X utf8
         utf8_mode: u8,
         /// -X int_max_str_digits=number
-        int_max_str_digits: i8,
+        int_max_str_digits: i64,
         /// -P, `PYTHONSAFEPATH`
         safe_path: bool,
         /// -X warn_default_encoding, PYTHONWARNDEFAULTENCODING
@@ -753,7 +753,7 @@ mod sys {
                 isolated: settings.isolated as u8,
                 dev_mode: settings.dev_mode,
                 utf8_mode: settings.utf8_mode,
-                int_max_str_digits: -1,
+                int_max_str_digits: settings.int_max_str_digits,
                 safe_path: false,
                 warn_default_encoding: settings.warn_default_encoding as u8,
             }
diff --git a/vm/src/vm/mod.rs b/vm/src/vm/mod.rs
index 51fc9b87e5..05ad7ca5a0 100644
--- a/vm/src/vm/mod.rs
+++ b/vm/src/vm/mod.rs
@@ -151,6 +151,10 @@ impl VirtualMachine {
 
         let warnings = WarningsState::init_state(&ctx);
 
+        let int_max_str_digits = AtomicCell::new(match settings.int_max_str_digits {
+            -1 => 4300,
+            other => other,
+        } as usize);
         let mut vm = VirtualMachine {
             builtins,
             sys_module,
@@ -181,7 +185,7 @@ impl VirtualMachine {
                 before_forkers: PyMutex::default(),
                 after_forkers_child: PyMutex::default(),
                 after_forkers_parent: PyMutex::default(),
-                int_max_str_digits: AtomicCell::new(4300),
+                int_max_str_digits,
             }),
             initialized: false,
             recursion_depth: Cell::new(0),
diff --git a/vm/src/vm/setting.rs b/vm/src/vm/setting.rs
index 3b9c82cafc..508c50da78 100644
--- a/vm/src/vm/setting.rs
+++ b/vm/src/vm/setting.rs
@@ -43,6 +43,9 @@ pub struct Settings {
     /// -Xfoo[=bar]
     pub xopts: Vec<(String, Option<String>)>,
 
+    /// -X int_max_str_digits
+    pub int_max_str_digits: i64,
+
     /// -I
     pub isolated: bool,
 
@@ -118,6 +121,7 @@ impl Default for Settings {
             check_hash_based_pycs: "default".to_owned(),
             allow_external_library: cfg!(feature = "importlib"),
             utf8_mode: 1,
+            int_max_str_digits: -1,
             #[cfg(feature = "flame-it")]
             profile_output: None,
             #[cfg(feature = "flame-it")]


Test patch:
diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py
index 7f6af76d85..7e15bc8f88 100644
--- a/Lib/test/test_cmd_line.py
+++ b/Lib/test/test_cmd_line.py
@@ -933,8 +933,6 @@ def test_parsing_error(self):
         self.assertTrue(proc.stderr.startswith(err_msg), proc.stderr)
         self.assertNotEqual(proc.returncode, 0)
 
-    # TODO: RUSTPYTHON
-    @unittest.expectedFailure
     def test_int_max_str_digits(self):
         code = "import sys; print(sys.flags.int_max_str_digits, sys.get_int_max_str_digits())"