From e999f60d40ce2dcec40a9cda4b6936a4740f09d4 Mon Sep 17 00:00:00 2001 From: noormichael Date: Mon, 22 Feb 2021 21:25:59 -0600 Subject: [PATCH 1/6] bpo-43295: Throw ValueError when datetime.strptime matches 'z' with '%z' (GH-43295) --- Lib/_strptime.py | 2 +- Lib/test/test_strptime.py | 5 +++++ .../Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst | 9 +++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst diff --git a/Lib/_strptime.py b/Lib/_strptime.py index 5df37f5f4b89d5c..b97dfcce1e8e4d7 100644 --- a/Lib/_strptime.py +++ b/Lib/_strptime.py @@ -201,7 +201,7 @@ def __init__(self, locale_time=None): #XXX: Does 'Y' need to worry about having less or more than # 4 digits? 'Y': r"(?P\d\d\d\d)", - 'z': r"(?P[+-]\d\d:?[0-5]\d(:?[0-5]\d(\.\d{1,6})?)?|Z)", + 'z': r"(?P[+-]\d\d:?[0-5]\d(:?[0-5]\d(\.\d{1,6})?)?|(?-i:Z))", 'A': self.__seqToRE(self.locale_time.f_weekday, 'A'), 'a': self.__seqToRE(self.locale_time.a_weekday, 'a'), 'B': self.__seqToRE(self.locale_time.f_month[1:], 'B'), diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index 55a0f426731a5db..5e66f4de4031583 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -466,6 +466,11 @@ def test_mar1_comes_after_feb29_even_when_omitting_the_year(self): time.strptime("Feb 29", "%b %d"), time.strptime("Mar 1", "%b %d")) + def test_timezone_offset_cannot_parse_z(self): + # Check ValueError is raised when matching "z" (ordinary letter) + # with "%z" (timezone offset) + self.assertRaises(ValueError, _strptime._strptime_time, "z", "%z") + class Strptime12AMPMTests(unittest.TestCase): """Test a _strptime regression in '%I %p' at 12 noon (12 PM)""" diff --git a/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst b/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst new file mode 100644 index 000000000000000..7f73cc63fb8494f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst @@ -0,0 +1,9 @@ +Previously, datetime.strptime would match 'z' with the format string '%z' +(for UTC offsets), throwing an IndexError by erroneously trying to parse 'z' +as a timestamp. As a special case, '%z' matches the string 'Z' which is +equivalent to the offset '+00:00', however this behavior is not defined for +lowercase 'z'. This change ensures a ValueError is thrown when encountering +the original example, as follows: + +>>> from datetime import datetime >>> datetime.strptime('z', '%z') +ValueError: time data 'z' does not match format '%z' From 018b7f9b985bf9e248960354f0aedbd197ebffbe Mon Sep 17 00:00:00 2001 From: noormichael Date: Mon, 22 Feb 2021 23:42:59 -0600 Subject: [PATCH 2/6] bpo-43295: Fix Documentation (GH-43295) --- .../next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst b/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst index 7f73cc63fb8494f..81263c2412a1666 100644 --- a/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst +++ b/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst @@ -5,5 +5,6 @@ equivalent to the offset '+00:00', however this behavior is not defined for lowercase 'z'. This change ensures a ValueError is thrown when encountering the original example, as follows: ->>> from datetime import datetime >>> datetime.strptime('z', '%z') +>>> from datetime import datetime +>>> datetime.strptime('z', '%z') ValueError: time data 'z' does not match format '%z' From ab99696fa5531633b00efc3ed69df735a310c8a9 Mon Sep 17 00:00:00 2001 From: noormichael Date: Tue, 23 Feb 2021 09:25:12 -0600 Subject: [PATCH 3/6] bpo-43295: Format Source Code in Documentation (GH-43295) --- .../next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst b/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst index 81263c2412a1666..0e4c0fd283aed6c 100644 --- a/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst +++ b/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst @@ -3,8 +3,8 @@ Previously, datetime.strptime would match 'z' with the format string '%z' as a timestamp. As a special case, '%z' matches the string 'Z' which is equivalent to the offset '+00:00', however this behavior is not defined for lowercase 'z'. This change ensures a ValueError is thrown when encountering -the original example, as follows: +the original example, as follows:: ->>> from datetime import datetime ->>> datetime.strptime('z', '%z') -ValueError: time data 'z' does not match format '%z' + >>> from datetime import datetime + >>> datetime.strptime('z', '%z') + ValueError: time data 'z' does not match format '%z' From 6ef4ebec63b9683a93d1c1298fd5f712886d8951 Mon Sep 17 00:00:00 2001 From: noormichael Date: Sat, 27 Feb 2021 20:07:42 -0600 Subject: [PATCH 4/6] bpo-43295: Addressed Feedback (GH-43295) --- Lib/test/datetimetester.py | 1 + Lib/test/test_strptime.py | 5 ----- .../Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst | 12 ++---------- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 775d3151ae29023..316cf0b8da7b488 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -2609,6 +2609,7 @@ def test_strptime(self): with self.assertRaises(ValueError): strptime("-2400", "%z") with self.assertRaises(ValueError): strptime("-000", "%z") + with self.assertRaises(ValueError): strptime("z", "%z") def test_strptime_single_digit(self): # bpo-34903: Check that single digit dates and times are allowed. diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index 5e66f4de4031583..55a0f426731a5db 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -466,11 +466,6 @@ def test_mar1_comes_after_feb29_even_when_omitting_the_year(self): time.strptime("Feb 29", "%b %d"), time.strptime("Mar 1", "%b %d")) - def test_timezone_offset_cannot_parse_z(self): - # Check ValueError is raised when matching "z" (ordinary letter) - # with "%z" (timezone offset) - self.assertRaises(ValueError, _strptime._strptime_time, "z", "%z") - class Strptime12AMPMTests(unittest.TestCase): """Test a _strptime regression in '%I %p' at 12 noon (12 PM)""" diff --git a/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst b/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst index 0e4c0fd283aed6c..bfab901a4d1ed1f 100644 --- a/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst +++ b/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst @@ -1,10 +1,2 @@ -Previously, datetime.strptime would match 'z' with the format string '%z' -(for UTC offsets), throwing an IndexError by erroneously trying to parse 'z' -as a timestamp. As a special case, '%z' matches the string 'Z' which is -equivalent to the offset '+00:00', however this behavior is not defined for -lowercase 'z'. This change ensures a ValueError is thrown when encountering -the original example, as follows:: - - >>> from datetime import datetime - >>> datetime.strptime('z', '%z') - ValueError: time data 'z' does not match format '%z' +Previously, :meth:`datetime.datetime.strptime` would fail with `IndexError` when the string `'z'` +was found for the `%z` format specifier. This has been fixed to properly raise `ValueError` instead. From 2c0eee448e1a65de8fce4315d58a09a8c61c269c Mon Sep 17 00:00:00 2001 From: noormichael Date: Sat, 27 Feb 2021 20:48:49 -0600 Subject: [PATCH 5/6] bpo-43295: Shorten Documentation (GH-43295) --- .../next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst b/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst index bfab901a4d1ed1f..26f11363137b10b 100644 --- a/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst +++ b/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst @@ -1,2 +1,2 @@ -Previously, :meth:`datetime.datetime.strptime` would fail with `IndexError` when the string `'z'` -was found for the `%z` format specifier. This has been fixed to properly raise `ValueError` instead. +:meth:`datetime.datetime.strptime` has been fixed to raise `ValueError` +instead of `IndexError` when matching `'z'` with the `%z` format specifier. From 901c1fe5a73109474a286189cf5b6b7132f1e423 Mon Sep 17 00:00:00 2001 From: noormichael Date: Tue, 2 Mar 2021 21:55:30 -0600 Subject: [PATCH 6/6] bpo-43295: Fix backquotes (GH-43295) --- .../next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst b/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst index 26f11363137b10b..ac9a5c96c9cedde 100644 --- a/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst +++ b/Misc/NEWS.d/next/Library/2021-02-22-22-54-40.bpo-43295.h_ffu7.rst @@ -1,2 +1,2 @@ -:meth:`datetime.datetime.strptime` has been fixed to raise `ValueError` -instead of `IndexError` when matching `'z'` with the `%z` format specifier. +:meth:`datetime.datetime.strptime` now raises ``ValueError`` instead of +``IndexError`` when matching ``'z'`` with the ``%z`` format specifier.