diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py index 32e472a66..c9d5e50dd 100644 --- a/Lib/test/string_tests.py +++ b/Lib/test/string_tests.py @@ -327,8 +327,6 @@ class BaseTest: self.checkequal('HELLO', 'HELLO', 'upper') self.checkraises(TypeError, 'hello', 'upper', 42) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_expandtabs(self): self.checkequal('abc\rab def\ng hi', 'abc\rab\tdef\ng\thi', 'expandtabs') diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index f7586919f..167fc003c 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -184,6 +184,12 @@ struct SplitLineArgs { keepends: OptionalArg, } +#[derive(FromArgs)] +struct ExpandtabsArgs { + #[pyarg(positional_or_keyword, optional = true)] + tabsize: OptionalArg, +} + #[pyimpl(flags(BASETYPE))] impl PyString { #[pyslot] @@ -1084,21 +1090,28 @@ impl PyString { } #[pymethod] - fn expandtabs(&self, tab_stop: OptionalArg) -> String { - let tab_stop = tab_stop.into_option().unwrap_or(8 as usize); + fn expandtabs(&self, args: ExpandtabsArgs) -> String { + let tab_stop = args.tabsize.unwrap_or(8); let mut expanded_str = String::with_capacity(self.value.len()); let mut tab_size = tab_stop; let mut col_count = 0 as usize; for ch in self.value.chars() { - // 0x0009 is tab - if ch == 0x0009 as char { - let num_spaces = tab_size - col_count; - col_count += num_spaces; - let expand = " ".repeat(num_spaces); - expanded_str.push_str(&expand); - } else { - expanded_str.push(ch); - col_count += 1; + match ch { + '\t' => { + let num_spaces = tab_size - col_count; + col_count += num_spaces; + let expand = " ".repeat(num_spaces); + expanded_str.push_str(&expand); + } + '\r' | '\n' => { + expanded_str.push(ch); + col_count = 0; + tab_size = 0; + } + _ => { + expanded_str.push(ch); + col_count += 1; + } } if col_count >= tab_size { tab_size += tab_stop;