|
| 1 | +extern crate unicode_categories; |
1 | 2 | extern crate unicode_xid;
|
2 | 3 |
|
3 | 4 | use std::fmt;
|
@@ -27,6 +28,8 @@ use super::objsequence::PySliceableSequence;
|
27 | 28 | use super::objslice::PySlice;
|
28 | 29 | use super::objtype::{self, PyClassRef};
|
29 | 30 |
|
| 31 | +use unicode_categories::UnicodeCategories; |
| 32 | + |
30 | 33 | /// str(object='') -> str
|
31 | 34 | /// str(bytes_or_buffer[, encoding[, errors]]) -> str
|
32 | 35 | ///
|
@@ -519,6 +522,29 @@ impl PyString {
|
519 | 522 | }
|
520 | 523 | }
|
521 | 524 |
|
| 525 | + /// Return true if all characters in the string are printable or the string is empty, |
| 526 | + /// false otherwise. Nonprintable characters are those characters defined in the |
| 527 | + /// Unicode character database as `Other` or `Separator`, |
| 528 | + /// excepting the ASCII space (0x20) which is considered printable. |
| 529 | + /// |
| 530 | + /// All characters except those characters defined in the Unicode character |
| 531 | + /// database as following categories are considered printable. |
| 532 | + /// * Cc (Other, Control) |
| 533 | + /// * Cf (Other, Format) |
| 534 | + /// * Cs (Other, Surrogate) |
| 535 | + /// * Co (Other, Private Use) |
| 536 | + /// * Cn (Other, Not Assigned) |
| 537 | + /// * Zl Separator, Line ('\u2028', LINE SEPARATOR) |
| 538 | + /// * Zp Separator, Paragraph ('\u2029', PARAGRAPH SEPARATOR) |
| 539 | + /// * Zs (Separator, Space) other than ASCII space('\x20'). |
| 540 | + #[pymethod] |
| 541 | + fn isprintable(&self, _vm: &VirtualMachine) -> bool { |
| 542 | + self.value.chars().all(|c| match c { |
| 543 | + '\u{0020}' => true, |
| 544 | + _ => !(c.is_other_control() | c.is_separator()), |
| 545 | + }) |
| 546 | + } |
| 547 | + |
522 | 548 | // cpython's isspace ignores whitespace, including \t and \n, etc, unless the whole string is empty
|
523 | 549 | // which is why isspace is using is_ascii_whitespace. Same for isupper & islower
|
524 | 550 | #[pymethod]
|
|
0 commit comments