Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
11 changes: 7 additions & 4 deletions Doc/builtins/stdtypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2569,10 +2569,13 @@ expression support in the :mod:`re` module).
>>> '\u3000'.isspace() # IDEOGRAPHIC SPACE
True

A character is *whitespace* if in the Unicode character database
(see :mod:`unicodedata`), either its general category is ``Zs``
("Separator, space"), or its bidirectional class is one of ``WS``,
``B``, or ``S``.
The whitespace characters are `as defined by Unicode
<https://www.unicode.org/reports/tr44/#White_Space>`_.

.. versionchanged:: 3.16
Previously used a different definition of whitespace characters,
which included the additional characters ``\x1c``, ``\x1d``,
``\x1e``, and ``\x1f``.

See also :meth:`isprintable`.

Expand Down
1 change: 1 addition & 0 deletions Lib/test/string_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,7 @@ def test_isspace(self):
self.checkequal(True, '\t', 'isspace')
self.checkequal(True, '\r', 'isspace')
self.checkequal(True, '\n', 'isspace')
self.checkequal(False, '\x1c', 'isspace')
self.checkequal(True, ' \t\r\n', 'isspace')
self.checkequal(False, ' \t\r\na', 'isspace')
self.checkraises(TypeError, 'abc', 'isspace', 42)
Expand Down
27 changes: 25 additions & 2 deletions Lib/test/test_str.py
Original file line number Diff line number Diff line change
Expand Up @@ -760,13 +760,21 @@ def test_isspace(self):

@support.requires_resource('cpu')
def test_isspace_invariant(self):
"""
Before Python 3.16, `str.isspace` used a certain formula
combining the General Category and the Bidirectional Class.

Since Python 3.16, we use the White_Space property that Unicode
now provides. Check that these differ only on U+001C..U+001F .
"""
for codepoint in range(sys.maxunicode + 1):
char = chr(codepoint)
bidirectional = unicodedata.bidirectional(char)
category = unicodedata.category(char)
self.assertEqual(char.isspace(),
(bidirectional in ('WS', 'B', 'S')
or category == 'Zs'))
((bidirectional in ('WS', 'B', 'S')
or category == 'Zs')
and codepoint not in range(0x1c, 0x20)))
Comment on lines +775 to +777

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.

Is this guaranteed to hold in future unicode versions? i.e. should it be tested on the string method if it's only testing the unicode database parsing and generation?


def test_isalnum(self):
super().test_isalnum()
Expand Down Expand Up @@ -840,6 +848,21 @@ def test_isnumeric(self):
'\U000104A0', '\U0001F107']:
self.assertTrue(ch.isnumeric(), '{!a} is numeric.'.format(ch))

def test_bytes_consistency(self):
"""Check str and bytes agree on character properties within ASCII."""
for codepoint in range(0x80):
char = chr(codepoint)
byte = bytes([codepoint])
# Including the codepoint in the tuple gets it printed on failure.
self.assertEqual(
(codepoint, char.islower(), char.isupper(), char.isalpha(),
char.isdigit(), char.isalnum(), char.isspace()),
(codepoint, byte.islower(), byte.isupper(), byte.isalpha(),
byte.isdigit(), byte.isalnum(), byte.isspace()))
self.assertEqual(
(codepoint, ord(char.lower()), ord(char.upper())),
(codepoint, ord(byte.lower()), ord(byte.upper())))

def test_isidentifier(self):
self.assertTrue("a".isidentifier())
self.assertTrue("Z".isidentifier())
Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_unicodedata.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ def download_test_data_file(filename):
class UnicodeMethodsTest(unittest.TestCase):

# update this, if the database changes
expectedchecksum = ('2bb59305a65254fee9cd6ef981cc3cab7551c60e'
expectedchecksum = ('a95371700ebbde3c78130d5e713bfdb6958dfb12'
if quicktest else
'bb69894a259aee5971445eca8e617a1686a432e2')
'56aaa60dc1f94b8876d521937c5788aa3dd62cc3')

def test_method_checksum(self):
h = hashlib.sha1()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
The definition of "whitespace" provided by :meth:`str.isspace` and
:c:func:`Py_UNICODE_ISSPACE` now follows Unicode's ``White_Space`` property.
This has the effect that the four characters ``\x1c``, ``\x1d``, ``\x1e``,
``\x1f`` are no longer treated as whitespace.
6 changes: 1 addition & 5 deletions Objects/unicodeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,11 +391,7 @@ const unsigned char _Py_ascii_whitespace[] = {
/* case 0x000D: * CARRIAGE RETURN */
0, 1, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
/* case 0x001C: * FILE SEPARATOR */
/* case 0x001D: * GROUP SEPARATOR */
/* case 0x001E: * RECORD SEPARATOR */
/* case 0x001F: * UNIT SEPARATOR */
0, 0, 0, 0, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0,
/* case 0x0020: * SPACE */
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
Expand Down
Loading
Loading