Skip to content

Commit 70fb3f6

Browse files
committed
cpython compatible "".__repr__
Fixes #1390
1 parent 311b53d commit 70fb3f6

2 files changed

Lines changed: 34 additions & 7 deletions

File tree

tests/snippets/strings.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,3 +311,10 @@ def try_mutate_str():
311311
assert index_str[-1] == 'n'
312312

313313
assert_raises(TypeError, lambda: index_str['a'])
314+
315+
assert chr(9).__repr__() == "'\\t'"
316+
assert chr(99).__repr__() == "'c'"
317+
assert chr(999).__repr__() == "'ϧ'"
318+
assert chr(9999).__repr__() == "'✏'"
319+
assert chr(99999).__repr__() == "'𘚟'"
320+
assert chr(999999).__repr__() == "'\\U000f423f'"

vm/src/obj/objstr.rs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -318,16 +318,36 @@ impl PyString {
318318
formatted.push('\\');
319319
formatted.push(c);
320320
} else if c == '\n' {
321-
formatted.push('\\');
322-
formatted.push('n');
321+
formatted.push_str("\\n")
323322
} else if c == '\t' {
324-
formatted.push('\\');
325-
formatted.push('t');
323+
formatted.push_str("\\t");
326324
} else if c == '\r' {
327-
formatted.push('\\');
328-
formatted.push('r');
329-
} else {
325+
formatted.push_str("\\r");
326+
} else if c < ' ' || c as u32 == 0x7F {
327+
formatted.push_str(&format!("\\x{:02x}", c as u32));
328+
} else if c.is_ascii() {
330329
formatted.push(c);
330+
} else if c.is_other() || c.is_separator() {
331+
// According to python following categories aren't printable:
332+
// * Cc (Other, Control)
333+
// * Cf (Other, Format)
334+
// * Cs (Other, Surrogate)
335+
// * Co (Other, Private Use)
336+
// * Cn (Other, Not Assigned)
337+
// * Zl Separator, Line ('\u2028', LINE SEPARATOR)
338+
// * Zp Separator, Paragraph ('\u2029', PARAGRAPH SEPARATOR)
339+
// * Zs (Separator, Space) other than ASCII space('\x20').
340+
let code = c as u32;
341+
let escaped = if code < 0xff {
342+
format!("\\U{:02x}", code)
343+
} else if code < 0xffff {
344+
format!("\\U{:04x}", code)
345+
} else {
346+
format!("\\U{:08x}", code)
347+
};
348+
formatted.push_str(&escaped);
349+
} else {
350+
formatted.push(c)
331351
}
332352
}
333353
formatted.push(quote_char);

0 commit comments

Comments
 (0)