Skip to content

Commit a7fc527

Browse files
committed
gh-158252: Merge the strptime whitespace fix
2 parents e859939 + 49ff84b commit a7fc527

3 files changed

Lines changed: 36 additions & 4 deletions

File tree

‎Lib/test/datetimetester.py‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,13 @@ def test_strptime_whitespace(self):
12811281
fmt = format_space.join(('%Y', '%m', '%d'))
12821282
self.assertEqual(date.strptime(text, fmt), date(2024, 2, 29))
12831283

1284+
def test_strptime_whitespace_before_adjacent_fields(self):
1285+
for separator in ('\x1c', '\x1d', '\x1e', '\x1f'):
1286+
with self.subTest(separator=separator):
1287+
text = f'2024{separator} 112'
1288+
fmt = f'%Y{separator}%d%m'
1289+
self.assertEqual(date.strptime(text, fmt), date(2024, 2, 11))
1290+
12841291
def test_strptime_single_digit(self):
12851292
# bpo-34903: Check that single digit dates are allowed.
12861293
strptime = date.strptime
@@ -3202,6 +3209,14 @@ def test_strptime_whitespace(self):
32023209
self.assertEqual(self.theclass.strptime(text, fmt),
32033210
self.theclass(2024, 2, 29, 12, 34, 56))
32043211

3212+
def test_strptime_whitespace_before_adjacent_fields(self):
3213+
for separator in ('\x1c', '\x1d', '\x1e', '\x1f'):
3214+
with self.subTest(separator=separator):
3215+
text = f'2024{separator} 112 34{separator} 123'
3216+
fmt = f'%Y{separator}%d%m %M{separator}%H%S'
3217+
self.assertEqual(self.theclass.strptime(text, fmt),
3218+
self.theclass(2024, 2, 11, 12, 34, 3))
3219+
32053220
def test_strptime_numeric_fallback(self):
32063221
cases = (
32073222
('2024\0-02-29', '%Y\0-%m-%d', (2024, 2, 29)),
@@ -4435,6 +4450,14 @@ def test_strptime_whitespace(self):
44354450
self.assertEqual(self.theclass.strptime(text, fmt),
44364451
self.theclass(12, 34, 56))
44374452

4453+
def test_strptime_whitespace_before_adjacent_fields(self):
4454+
for separator in ('\x1c', '\x1d', '\x1e', '\x1f'):
4455+
with self.subTest(separator=separator):
4456+
text = f'34{separator} 123'
4457+
fmt = f'%M{separator}%H%S'
4458+
self.assertEqual(self.theclass.strptime(text, fmt),
4459+
self.theclass(12, 34, 3))
4460+
44384461
def test_strptime_tz(self):
44394462
strptime = self.theclass.strptime
44404463
self.assertEqual(strptime("+0002", "%z").utcoffset(), 2 * MINUTE)

‎Lib/test/test_time.py‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,14 @@ def test_strptime_whitespace(self):
382382
self.assertEqual(time.strptime(text, fmt),
383383
(2024, 2, 29, 12, 34, 56, 3, 60, -1))
384384

385+
def test_strptime_whitespace_before_adjacent_fields(self):
386+
for separator in ('\x1c', '\x1d', '\x1e', '\x1f'):
387+
with self.subTest(separator=separator):
388+
text = f'2024{separator} 112 34{separator} 123'
389+
fmt = f'%Y{separator}%d%m %M{separator}%H%S'
390+
self.assertEqual(time.strptime(text, fmt),
391+
(2024, 2, 11, 12, 34, 3, 6, 42, -1))
392+
385393
def test_strptime_numeric_calendar(self):
386394
cases = (
387395
('0001-01-01', 1, 1, 1, 0, 1),

‎Python/_strptime.c‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -285,16 +285,17 @@ _PyTime_Strptime(PyObject *string, PyObject *format, _PyTime_StrptimeFields *fie
285285
}
286286
}
287287
unsigned char c = fmt[i];
288-
if (Py_ISSPACE(c)) {
289-
if (pos == length || !Py_ISSPACE(data[pos])) {
288+
/* Match regex \s, including ASCII separators U+001C through U+001F. */
289+
if (Py_UNICODE_ISSPACE(c)) {
290+
if (pos == length || !Py_UNICODE_ISSPACE(data[pos])) {
290291
return 0;
291292
}
292-
while (i + 1 < fmt_length && Py_ISSPACE(fmt[i + 1])) {
293+
while (i + 1 < fmt_length && Py_UNICODE_ISSPACE(fmt[i + 1])) {
293294
i++;
294295
}
295296
do {
296297
pos++;
297-
} while (pos < length && Py_ISSPACE(data[pos]));
298+
} while (pos < length && Py_UNICODE_ISSPACE(data[pos]));
298299
continue;
299300
}
300301
if (c != '%') {

0 commit comments

Comments
 (0)