Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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_str.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ def test_literals(self):
# raw strings should not have unicode escapes
self.assertNotEqual(r"\u0020", " ")

@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: <class 'str'> is not <class 'test.test_str.StrSubclass'>
def test_ascii(self):
self.assertEqual(ascii('abc'), "'abc'")
self.assertEqual(ascii('ab\\c'), "'ab\\\\c'")
Expand Down
4 changes: 2 additions & 2 deletions crates/vm/src/cformat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn spec_format_bytes(
// Unlike strings, %r and %a are identical for bytes: the behaviour corresponds to
// %a for strings (not %r)
CFormatConversion::Repr | CFormatConversion::Ascii => {
let b = builtins::ascii(obj, vm)?.into();
let b = builtins::ascii(obj, vm)?.as_bytes().to_vec();
Ok(b)
}
CFormatConversion::Str | CFormatConversion::Bytes => {
Expand Down Expand Up @@ -132,7 +132,7 @@ fn spec_format_string(
match &spec.format_type {
CFormatType::String(conversion) => {
let result = match conversion {
CFormatConversion::Ascii => builtins::ascii(obj, vm)?.into(),
CFormatConversion::Ascii => builtins::ascii(obj, vm)?.as_wtf8().to_owned(),
CFormatConversion::Str => obj.str(vm)?.as_wtf8().to_owned(),
CFormatConversion::Repr => obj.repr(vm)?.as_wtf8().to_owned(),
CFormatConversion::Bytes => {
Expand Down
4 changes: 1 addition & 3 deletions crates/vm/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,7 @@ fn format_internal(
let argument = match conversion_spec.and_then(FormatConversion::from_char) {
Some(FormatConversion::Str) => argument.str(vm)?.into(),
Some(FormatConversion::Repr) => argument.repr(vm)?.into(),
Some(FormatConversion::Ascii) => {
vm.ctx.new_str(builtins::ascii(argument, vm)?).into()
}
Some(FormatConversion::Ascii) => builtins::ascii(argument, vm)?.into(),
Some(FormatConversion::Bytes) => {
vm.call_method(&argument, identifier!(vm, decode).as_str(), ())?
}
Expand Down
2 changes: 1 addition & 1 deletion crates/vm/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7104,7 +7104,7 @@ impl ExecutingFrame<'_> {
let value = match conversion {
ConvertValueOparg::Str => value.str(vm)?.into(),
ConvertValueOparg::Repr => value.repr(vm)?.into(),
ConvertValueOparg::Ascii => vm.ctx.new_str(builtins::ascii(value, vm)?).into(),
ConvertValueOparg::Ascii => builtins::ascii(value, vm)?.into(),
ConvertValueOparg::None => value,
};

Expand Down
9 changes: 6 additions & 3 deletions crates/vm/src/protocol/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,10 +370,13 @@ impl PyObject {
})
}

pub fn ascii(&self, vm: &VirtualMachine) -> PyResult<ascii::AsciiString> {
pub fn ascii(&self, vm: &VirtualMachine) -> PyResult<PyRef<PyStr>> {
let repr = self.repr(vm)?;
let ascii = to_ascii(repr.as_wtf8());
Ok(ascii)
if repr.as_wtf8().is_ascii() {
Ok(repr)
} else {
Ok(vm.ctx.new_str(to_ascii(repr.as_wtf8())))
}
}

pub fn str_utf8(&self, vm: &VirtualMachine) -> PyResult<PyRef<PyUtf8Str>> {
Expand Down
9 changes: 6 additions & 3 deletions crates/vm/src/stdlib/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,13 @@ mod builtins {
}

#[pyfunction]
pub fn ascii(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<ascii::AsciiString> {
pub fn ascii(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let repr = obj.repr(vm)?;
let ascii = to_ascii(repr.as_wtf8());
Ok(ascii)
if repr.as_wtf8().is_ascii() {
Ok(repr)
} else {
Ok(vm.ctx.new_str(to_ascii(repr.as_wtf8())))
}
}

#[pyfunction]
Expand Down
16 changes: 16 additions & 0 deletions extra_tests/snippets/builtin_ascii.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,19 @@
assert ascii(chr(0x10001)) == "'\\U00010001'"
assert ascii(chr(0x9999)) == "'\\u9999'"
assert ascii(chr(0x0A)) == "'\\n'"

class MyStr(str):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[auto-format] reported by reviewdog 🐶

Suggested change
class MyStr(str):
class MyStr(str):

pass

class Foo:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[auto-format] reported by reviewdog 🐶

Suggested change
class Foo:
class Foo:

def __repr__(self):
return MyStr("hello")

class Bar:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[auto-format] reported by reviewdog 🐶

Suggested change
class Bar:
class Bar:

def __repr__(self):
return MyStr("héllo")

assert type(ascii(Foo())) is MyStr
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[auto-format] reported by reviewdog 🐶

Suggested change
assert type(ascii(Foo())) is MyStr
assert type(ascii(Foo())) is MyStr

assert ascii(Foo()) == MyStr("hello")
assert type(ascii(Bar())) is str
assert ascii(Bar()) == "h\\xe9llo"
Loading