Commit 454b3d4e authored by MichaelSaah's avatar MichaelSaah Committed by Victor Stinner

bpo-35066: _dateime.datetime.strftime copies trailing '%' (GH-10692)

Previously, calling the strftime() method on a datetime object with a
trailing '%' in the format string would result in an exception. However,
this only occured when the datetime C module was being used; the python
implementation did not match this behavior. Datetime is now PEP-399
compliant, and will not throw an exception on a trailing '%'.
parent 5bb146aa
...@@ -1351,6 +1351,17 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase): ...@@ -1351,6 +1351,17 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase):
#check that this standard extension works #check that this standard extension works
t.strftime("%f") t.strftime("%f")
def test_strftime_trailing_percent(self):
# bpo-35066: make sure trailing '%' doesn't cause
# datetime's strftime to complain
t = self.theclass(2005, 3, 2)
try:
_time.strftime('%')
except ValueError:
self.skipTest('time module does not support trailing %')
self.assertEqual(t.strftime('%'), '%')
self.assertEqual(t.strftime("m:%m d:%d y:%y %"), "m:03 d:02 y:05 %")
def test_format(self): def test_format(self):
dt = self.theclass(2007, 9, 10) dt = self.theclass(2007, 9, 10)
self.assertEqual(dt.__format__(''), str(dt)) self.assertEqual(dt.__format__(''), str(dt))
......
Previously, calling the strftime() method on a datetime object with a
trailing '%' in the format string would result in an exception. However,
this only occured when the datetime C module was being used; the python
implementation did not match this behavior. Datetime is now PEP-399
compliant, and will not throw an exception on a trailing '%'.
...@@ -1528,10 +1528,13 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, ...@@ -1528,10 +1528,13 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
ntoappend = 1; ntoappend = 1;
} }
else if ((ch = *pin++) == '\0') { else if ((ch = *pin++) == '\0') {
/* There's a lone trailing %; doesn't make sense. */ /* Null byte follows %, copy only '%'.
PyErr_SetString(PyExc_ValueError, "strftime format " *
"ends with raw %"); * Back the pin up one char so that we catch the null check
goto Done; * the next time through the loop.*/
pin--;
ptoappend = pin - 1;
ntoappend = 1;
} }
/* A % has been seen and ch is the character after it. */ /* A % has been seen and ch is the character after it. */
else if (ch == 'z') { else if (ch == 'z') {
...@@ -1616,7 +1619,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, ...@@ -1616,7 +1619,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
usednew += ntoappend; usednew += ntoappend;
assert(usednew <= totalnew); assert(usednew <= totalnew);
} /* end while() */ } /* end while() */
if (_PyBytes_Resize(&newfmt, usednew) < 0) if (_PyBytes_Resize(&newfmt, usednew) < 0)
goto Done; goto Done;
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment