mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
- time.accept2dyear = True is now equivalent to time.accept2dyear = 1
- removed unnecessary struct_time to tuple conversion - added more unit tests (See issue #10827 for discussion.)
This commit is contained in:
parent
e40808a935
commit
a686725859
2 changed files with 60 additions and 35 deletions
|
@ -263,8 +263,48 @@ class TestLocale(unittest.TestCase):
|
||||||
# This should not cause an exception
|
# This should not cause an exception
|
||||||
time.strftime("%B", (2009,2,1,0,0,0,0,0,0))
|
time.strftime("%B", (2009,2,1,0,0,0,0,0,0))
|
||||||
|
|
||||||
|
class TestAccept2Year(unittest.TestCase):
|
||||||
|
accept2dyear = 1
|
||||||
|
def setUp(self):
|
||||||
|
self.saved_accept2dyear = time.accept2dyear
|
||||||
|
time.accept2dyear = self.accept2dyear
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
time.accept2dyear = self.saved_accept2dyear
|
||||||
|
|
||||||
|
def yearstr(self, y):
|
||||||
|
return time.strftime('%Y', (y,) + (0,) * 8)
|
||||||
|
|
||||||
|
def test_2dyear(self):
|
||||||
|
self.assertEqual(self.yearstr(0), '2000')
|
||||||
|
self.assertEqual(self.yearstr(69), '1969')
|
||||||
|
self.assertEqual(self.yearstr(68), '2068')
|
||||||
|
self.assertEqual(self.yearstr(99), '1999')
|
||||||
|
|
||||||
|
def test_invalid(self):
|
||||||
|
self.assertRaises(ValueError, self.yearstr, 1899)
|
||||||
|
self.assertRaises(ValueError, self.yearstr, 100)
|
||||||
|
self.assertRaises(ValueError, self.yearstr, -1)
|
||||||
|
|
||||||
|
class TestAccept2YearBool(TestAccept2Year):
|
||||||
|
accept2dyear = True
|
||||||
|
|
||||||
|
class TestDontAccept2Year(TestAccept2Year):
|
||||||
|
accept2dyear = 0
|
||||||
|
def test_2dyear(self):
|
||||||
|
self.assertRaises(ValueError, self.yearstr, 0)
|
||||||
|
self.assertRaises(ValueError, self.yearstr, 69)
|
||||||
|
self.assertRaises(ValueError, self.yearstr, 68)
|
||||||
|
self.assertRaises(ValueError, self.yearstr, 99)
|
||||||
|
|
||||||
|
class TestDontAccept2YearBool(TestDontAccept2Year):
|
||||||
|
accept2dyear = False
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
support.run_unittest(TimeTestCase, TestLocale)
|
support.run_unittest(TimeTestCase, TestLocale,
|
||||||
|
TestAccept2Year, TestAccept2YearBool,
|
||||||
|
TestDontAccept2Year, TestDontAccept2YearBool)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_main()
|
test_main()
|
||||||
|
|
|
@ -216,29 +216,6 @@ tmtotuple(struct tm *p)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
structtime_totuple(PyObject *t)
|
|
||||||
{
|
|
||||||
PyObject *x = NULL;
|
|
||||||
unsigned int i;
|
|
||||||
PyObject *v = PyTuple_New(9);
|
|
||||||
if (v == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i=0; i<9; i++) {
|
|
||||||
x = PyStructSequence_GET_ITEM(t, i);
|
|
||||||
Py_INCREF(x);
|
|
||||||
PyTuple_SET_ITEM(v, i, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PyErr_Occurred()) {
|
|
||||||
Py_XDECREF(v);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
time_convert(double when, struct tm * (*function)(const time_t *))
|
time_convert(double when, struct tm * (*function)(const time_t *))
|
||||||
{
|
{
|
||||||
|
@ -328,9 +305,6 @@ gettmarg(PyObject *args, struct tm *p)
|
||||||
t = args;
|
t = args;
|
||||||
Py_INCREF(t);
|
Py_INCREF(t);
|
||||||
}
|
}
|
||||||
else if (Py_TYPE(args) == &StructTimeType) {
|
|
||||||
t = structtime_totuple(args);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
"Tuple or struct_time argument required");
|
"Tuple or struct_time argument required");
|
||||||
|
@ -352,15 +326,18 @@ gettmarg(PyObject *args, struct tm *p)
|
||||||
}
|
}
|
||||||
Py_DECREF(t);
|
Py_DECREF(t);
|
||||||
|
|
||||||
|
/* XXX: Why 1900? If the goal is to interpret 2-digit years as those in
|
||||||
|
* 20th / 21st century according to the POSIX standard, we can just treat
|
||||||
|
* 0 <= y < 100 as special. Year 100 is probably too ambiguous and should
|
||||||
|
* be rejected, but years 101 through 1899 can be passed through.
|
||||||
|
*/
|
||||||
if (y < 1900) {
|
if (y < 1900) {
|
||||||
PyObject *accept = PyDict_GetItemString(moddict,
|
PyObject *accept = PyDict_GetItemString(moddict,
|
||||||
"accept2dyear");
|
"accept2dyear");
|
||||||
if (accept == NULL || !PyLong_CheckExact(accept) ||
|
int acceptval = accept != NULL && PyObject_IsTrue(accept);
|
||||||
!PyObject_IsTrue(accept)) {
|
if (acceptval == -1)
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"year >= 1900 required");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
if (acceptval) {
|
||||||
if (69 <= y && y <= 99)
|
if (69 <= y && y <= 99)
|
||||||
y += 1900;
|
y += 1900;
|
||||||
else if (0 <= y && y <= 68)
|
else if (0 <= y && y <= 68)
|
||||||
|
@ -371,6 +348,14 @@ gettmarg(PyObject *args, struct tm *p)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* XXX: When accept2dyear is false, we don't have to reject y < 1900.
|
||||||
|
* Consider removing the following else-clause. */
|
||||||
|
else {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"year out of range");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
p->tm_year = y - 1900;
|
p->tm_year = y - 1900;
|
||||||
p->tm_mon--;
|
p->tm_mon--;
|
||||||
p->tm_wday = (p->tm_wday + 1) % 7;
|
p->tm_wday = (p->tm_wday + 1) % 7;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue