mirror of
https://github.com/python/cpython.git
synced 2025-12-02 15:48:58 +00:00
Make sure time.strptime only accepts strings (and document the fact like
strftime). Already didn't accept bytes but make the check earlier. This also lifts the limitation of requiring ASCII. Closes issue #5236. Thanks Tennessee Leeuwenburg.
This commit is contained in:
parent
d687887b53
commit
7f6b4f86e3
5 changed files with 25 additions and 7 deletions
|
|
@ -358,15 +358,17 @@ The module defines the following functions and data items:
|
||||||
|
|
||||||
.. function:: strptime(string[, format])
|
.. function:: strptime(string[, format])
|
||||||
|
|
||||||
Parse a string representing a time according to a format. The return value is
|
Parse a string representing a time according to a format. The return value
|
||||||
a :class:`struct_time` as returned by :func:`gmtime` or :func:`localtime`.
|
is a :class:`struct_time` as returned by :func:`gmtime` or
|
||||||
|
:func:`localtime`.
|
||||||
|
|
||||||
The *format* parameter uses the same directives as those used by
|
The *format* parameter uses the same directives as those used by
|
||||||
:func:`strftime`; it defaults to ``"%a %b %d %H:%M:%S %Y"`` which matches the
|
:func:`strftime`; it defaults to ``"%a %b %d %H:%M:%S %Y"`` which matches the
|
||||||
formatting returned by :func:`ctime`. If *string* cannot be parsed according to
|
formatting returned by :func:`ctime`. If *string* cannot be parsed according
|
||||||
*format*, or if it has excess data after parsing, :exc:`ValueError` is raised.
|
to *format*, or if it has excess data after parsing, :exc:`ValueError` is
|
||||||
The default values used to fill in any missing data when more accurate values
|
raised. The default values used to fill in any missing data when more
|
||||||
cannot be inferred are ``(1900, 1, 1, 0, 0, 0, 0, 1, -1)``.
|
accurate values cannot be inferred are ``(1900, 1, 1, 0, 0, 0, 0, 1, -1)``.
|
||||||
|
Both *string* and *format* must be strings.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -262,7 +262,7 @@ class TimeRE(dict):
|
||||||
|
|
||||||
def compile(self, format):
|
def compile(self, format):
|
||||||
"""Return a compiled re object for the format string."""
|
"""Return a compiled re object for the format string."""
|
||||||
return re_compile(self.pattern(format), IGNORECASE | ASCII)
|
return re_compile(self.pattern(format), IGNORECASE)
|
||||||
|
|
||||||
_cache_lock = _thread_allocate_lock()
|
_cache_lock = _thread_allocate_lock()
|
||||||
# DO NOT modify _TimeRE_cache or _regex_cache without acquiring the cache lock
|
# DO NOT modify _TimeRE_cache or _regex_cache without acquiring the cache lock
|
||||||
|
|
@ -294,8 +294,15 @@ def _calc_julian_from_U_or_W(year, week_of_year, day_of_week, week_starts_Mon):
|
||||||
|
|
||||||
def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
|
def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
|
||||||
"""Return a time struct based on the input string and the format string."""
|
"""Return a time struct based on the input string and the format string."""
|
||||||
|
|
||||||
|
for index, arg in enumerate([data_string, format]):
|
||||||
|
if not isinstance(arg, str):
|
||||||
|
msg = "strptime() argument {} must be str, not {}"
|
||||||
|
raise TypeError(msg.format(arg, index))
|
||||||
|
|
||||||
global _TimeRE_cache, _regex_cache
|
global _TimeRE_cache, _regex_cache
|
||||||
with _cache_lock:
|
with _cache_lock:
|
||||||
|
|
||||||
if _getlang() != _TimeRE_cache.locale_time.lang:
|
if _getlang() != _TimeRE_cache.locale_time.lang:
|
||||||
_TimeRE_cache = TimeRE()
|
_TimeRE_cache = TimeRE()
|
||||||
_regex_cache.clear()
|
_regex_cache.clear()
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,11 @@ class TimeTestCase(unittest.TestCase):
|
||||||
self.fail("conversion specifier %r failed with '%s' input." %
|
self.fail("conversion specifier %r failed with '%s' input." %
|
||||||
(format, strf_output))
|
(format, strf_output))
|
||||||
|
|
||||||
|
def test_strptime_bytes(self):
|
||||||
|
# Make sure only strings are accepted as arguments to strptime.
|
||||||
|
self.assertRaises(TypeError, time.strptime, b'2009', "%Y")
|
||||||
|
self.assertRaises(TypeError, time.strptime, '2009', b'%Y')
|
||||||
|
|
||||||
def test_asctime(self):
|
def test_asctime(self):
|
||||||
time.asctime(time.gmtime(self.t))
|
time.asctime(time.gmtime(self.t))
|
||||||
self.assertRaises(TypeError, time.asctime, 0)
|
self.assertRaises(TypeError, time.asctime, 0)
|
||||||
|
|
|
||||||
|
|
@ -411,6 +411,7 @@ John J. Lee
|
||||||
Inyeol Lee
|
Inyeol Lee
|
||||||
Thomas Lee
|
Thomas Lee
|
||||||
Christopher Lee
|
Christopher Lee
|
||||||
|
Tennessee Leeuwenburg
|
||||||
Luc Lefebvre
|
Luc Lefebvre
|
||||||
Kip Lehman
|
Kip Lehman
|
||||||
Joerg Lehmann
|
Joerg Lehmann
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #5236: Change time.strptime() to only take strings. Didn't work with
|
||||||
|
bytes already but the failure was non-obvious.
|
||||||
|
|
||||||
- Issue #5177: Multiprocessing's SocketListener class now uses
|
- Issue #5177: Multiprocessing's SocketListener class now uses
|
||||||
socket.SO_REUSEADDR on all connections so that the user no longer needs
|
socket.SO_REUSEADDR on all connections so that the user no longer needs
|
||||||
to wait 120 seconds for the socket to expire.
|
to wait 120 seconds for the socket to expire.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue