bpo-36959: Fix error messages for invalid ISO format string in _strptime() (GH-13408)

Previously some error messages complained about incompatible
combinations of directives that are not contained in the format string.

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
Gordon P. Hemsley 2023-12-26 14:26:17 -05:00 committed by GitHub
parent e5cce70df7
commit 4b2c3e8e43
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 42 deletions

View file

@ -224,35 +224,55 @@ class StrptimeTests(unittest.TestCase):
else:
self.fail("'%s' did not raise ValueError" % bad_format)
# Ambiguous or incomplete cases using ISO year/week/weekday directives
# 1. ISO week (%V) is specified, but the year is specified with %Y
# instead of %G
with self.assertRaises(ValueError):
_strptime._strptime("1999 50", "%Y %V")
# 2. ISO year (%G) and ISO week (%V) are specified, but weekday is not
with self.assertRaises(ValueError):
_strptime._strptime("1999 51", "%G %V")
# 3. ISO year (%G) and weekday are specified, but ISO week (%V) is not
for w in ('A', 'a', 'w', 'u'):
with self.assertRaises(ValueError):
_strptime._strptime("1999 51","%G %{}".format(w))
# 4. ISO year is specified alone (e.g. time.strptime('2015', '%G'))
with self.assertRaises(ValueError):
_strptime._strptime("2015", "%G")
# 5. Julian/ordinal day (%j) is specified with %G, but not %Y
with self.assertRaises(ValueError):
_strptime._strptime("1999 256", "%G %j")
# 6. Invalid ISO weeks
invalid_iso_weeks = [
"2019-00-1",
"2019-54-1",
"2021-53-1",
]
for invalid_iso_dtstr in invalid_iso_weeks:
with self.subTest(invalid_iso_dtstr):
with self.assertRaises(ValueError):
_strptime._strptime(invalid_iso_dtstr, "%G-%V-%u")
msg_week_no_year_or_weekday = r"ISO week directive '%V' must be used with " \
r"the ISO year directive '%G' and a weekday directive " \
r"\('%A', '%a', '%w', or '%u'\)."
msg_week_not_compatible = r"ISO week directive '%V' is incompatible with " \
r"the year directive '%Y'. Use the ISO year '%G' instead."
msg_julian_not_compatible = r"Day of the year directive '%j' is not " \
r"compatible with ISO year directive '%G'. Use '%Y' instead."
msg_year_no_week_or_weekday = r"ISO year directive '%G' must be used with " \
r"the ISO week directive '%V' and a weekday directive " \
r"\('%A', '%a', '%w', or '%u'\)."
locale_time = _strptime.LocaleTime()
# Ambiguous or incomplete cases using ISO year/week/weekday directives
subtests = [
# 1. ISO week (%V) is specified, but the year is specified with %Y
# instead of %G
("1999 50", "%Y %V", msg_week_no_year_or_weekday),
("1999 50 5", "%Y %V %u", msg_week_not_compatible),
# 2. ISO year (%G) and ISO week (%V) are specified, but weekday is not
("1999 51", "%G %V", msg_year_no_week_or_weekday),
# 3. ISO year (%G) and weekday are specified, but ISO week (%V) is not
("1999 {}".format(locale_time.f_weekday[5]), "%G %A",
msg_year_no_week_or_weekday),
("1999 {}".format(locale_time.a_weekday[5]), "%G %a",
msg_year_no_week_or_weekday),
("1999 5", "%G %w", msg_year_no_week_or_weekday),
("1999 5", "%G %u", msg_year_no_week_or_weekday),
# 4. ISO year is specified alone (e.g. time.strptime('2015', '%G'))
("2015", "%G", msg_year_no_week_or_weekday),
# 5. Julian/ordinal day (%j) is specified with %G, but not %Y
("1999 256", "%G %j", msg_julian_not_compatible),
("1999 50 5 256", "%G %V %u %j", msg_julian_not_compatible),
# ISO week specified alone
("50", "%V", msg_week_no_year_or_weekday),
# ISO year is unspecified, falling back to year
("50 5", "%V %u", msg_week_no_year_or_weekday),
# 6. Invalid ISO weeks
("2019-00-1", "%G-%V-%u",
"time data '2019-00-1' does not match format '%G-%V-%u'"),
("2019-54-1", "%G-%V-%u",
"time data '2019-54-1' does not match format '%G-%V-%u'"),
("2021-53-1", "%G-%V-%u", "Invalid week: 53"),
]
for (data_string, format, message) in subtests:
with self.subTest(data_string=data_string, format=format):
with self.assertRaisesRegex(ValueError, message):
_strptime._strptime(data_string, format)
def test_strptime_exception_context(self):
# check that this doesn't chain exceptions needlessly (see #17572)