FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

bpo-36959: Fix checks for invalid ISO date formats in _strptime by GPHemsley · Pull Request #13408 · python/cpython · GitHub

Repository navigation

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension .py  (2) .rst  (1) All 2 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
Prev Previous commit
Next Next commit
bpo-36959: Fix checks for invalid ISO date formats in _strptime
  • Loading branch information
GPHemsley committed May 19, 2019
commit 4e29c31f40859fe444b81586135374976482c309
28 changes: 14 additions & 14 deletions Lib/_strptime.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,6 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
tz = -1
gmtoff = None
gmtoff_fraction = 0
# Default to -1 to signify that values not known; not critical to have,
# though
iso_week = week_of_year = None
week_of_year_start = None
# weekday and julian defaulted to None so as to signal need to calculate
Expand Down Expand Up @@ -483,26 +481,28 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
else:
tz = value
break
# Deal with the cases where ambiguities arize

# Deal with the cases where ambiguities arise
# don't assume default values for ISO week/year
if year is None and iso_year is not None:
if iso_week is None or weekday is None:
raise ValueError("ISO year directive '%G' must be used with "
"the ISO week directive '%V' and a weekday "
"directive ('%A', '%a', '%w', or '%u').")
if julian is not None:
raise ValueError("Day of the year directive '%j' is not "
"compatible with ISO year directive '%G'. "
"Use '%Y' instead.")
elif week_of_year is None and iso_week is not None:
if weekday is None:
if iso_year is None and iso_week is not None:
if year is None or weekday is None:
raise ValueError("ISO week directive '%V' must be used with "
"the ISO year directive '%G' and a weekday "
"directive ('%A', '%a', '%w', or '%u').")
else:
raise ValueError("ISO week directive '%V' is incompatible with "
"the year directive '%Y'. Use the ISO year '%G' "
"instead.")
elif iso_year is not None:
if julian is not None:
raise ValueError("Day of the year directive '%j' is not "
"compatible with ISO year directive '%G'. "
"Use '%Y' instead.")
elif iso_week is None or weekday is None:
raise ValueError("ISO year directive '%G' must be used with "
"the ISO week directive '%V' and a weekday "
"directive ('%A', '%a', '%w', or '%u').")


leap_year_fix = False
if year is None:
Expand Down
60 changes: 42 additions & 18 deletions Lib/test/test_strptime.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -219,25 +219,49 @@ def test_ValueError(self):
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")
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),
]

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)
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Fix checks for invalid combinations of ISO format strings in strptime.

(This will change ValueError messages for certain invalid combinations.)

Patch by Gordon P. Hemsley.

Back | FazBrowse Home | New Git URL