summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/time.rst4
-rw-r--r--Doc/library/timeit.rst30
-rw-r--r--Include/pytime.h4
-rw-r--r--Lib/test/test_descr.py16
-rw-r--r--Lib/test/test_time.py22
-rw-r--r--Lib/test/test_zipfile.py10
-rw-r--r--Lib/timeit.py14
-rw-r--r--Lib/zipfile.py5
-rw-r--r--Misc/NEWS2
-rw-r--r--Modules/timemodule.c62
-rw-r--r--Objects/descrobject.c44
-rw-r--r--Python/pytime.c18
12 files changed, 153 insertions, 78 deletions
diff --git a/Doc/library/time.rst b/Doc/library/time.rst
index 55285d1..0e1c6fb 100644
--- a/Doc/library/time.rst
+++ b/Doc/library/time.rst
@@ -168,11 +168,11 @@ The module defines the following functions and data items:
The name of the underlying C function used to get the clock value.
- .. attribute:: is_monotonic
+ .. attribute:: monotonic
``True`` if the clock cannot go backward, ``False`` otherwise.
- .. attribute:: is_adjusted
+ .. attribute:: adjusted
``True`` if the clock can be adjusted (e.g. by a NTP daemon), ``False``
otherwise.
diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst
index cd2d205..c41e59d 100644
--- a/Doc/library/timeit.rst
+++ b/Doc/library/timeit.rst
@@ -104,13 +104,7 @@ The module also defines three convenience functions:
.. function:: default_timer()
- Define a default timer, in a platform specific manner. On Windows,
- :func:`time.clock` has microsecond granularity but :func:`time.time`'s
- granularity is 1/60th of a second; on Unix, :func:`time.clock` has 1/100th of
- a second granularity and :func:`time.time` is much more precise. On either
- platform, :func:`default_timer` measures wall clock time, not the CPU
- time. This means that other processes running on the same computer may
- interfere with the timing.
+ The default timer, which is always :func:`time.perf_counter`.
.. function:: repeat(stmt='pass', setup='pass', timer=<default timer>, repeat=3, number=1000000)
@@ -149,13 +143,20 @@ Where the following options are understood:
statement to be executed once initially (default ``pass``)
+.. cmdoption:: -p, --process
+
+ measure process time, not wallclock time, using :func:`time.process_time`
+ instead of :func:`time.perf_counter`, which is the default
+
+ .. versionadded:: 3.3
+
.. cmdoption:: -t, --time
- use :func:`time.time` (default on all platforms but Windows)
+ use :func:`time.time` (deprecated)
.. cmdoption:: -c, --clock
- use :func:`time.clock` (default on Windows)
+ use :func:`time.clock` (deprecated)
.. cmdoption:: -v, --verbose
@@ -173,12 +174,11 @@ similarly.
If :option:`-n` is not given, a suitable number of loops is calculated by trying
successive powers of 10 until the total time is at least 0.2 seconds.
-:func:`default_timer` measurations can be affected by other programs running on
-the same machine, so
-the best thing to do when accurate timing is necessary is to repeat
-the timing a few times and use the best time. The :option:`-r` option is good
-for this; the default of 3 repetitions is probably enough in most cases. On
-Unix, you can use :func:`time.clock` to measure CPU time.
+:func:`default_timer` measurements can be affected by other programs running on
+the same machine, so the best thing to do when accurate timing is necessary is
+to repeat the timing a few times and use the best time. The :option:`-r`
+option is good for this; the default of 3 repetitions is probably enough in
+most cases. You can use :func:`time.process_time` to measure CPU time.
.. note::
diff --git a/Include/pytime.h b/Include/pytime.h
index a0cedb2..7442c6f 100644
--- a/Include/pytime.h
+++ b/Include/pytime.h
@@ -25,8 +25,8 @@ typedef struct {
/* Structure used by time.get_clock_info() */
typedef struct {
const char *implementation;
- int is_monotonic;
- int is_adjusted;
+ int monotonic;
+ int adjusted;
double resolution;
} _Py_clock_info_t;
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index b9b1c72..079f60b 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -1466,6 +1466,22 @@ order (MRO) for bases """
self.assertEqual(x, spam.spamlist)
self.assertEqual(a, a1)
self.assertEqual(d, d1)
+ spam_cm = spam.spamlist.__dict__['classmeth']
+ x2, a2, d2 = spam_cm(spam.spamlist, *a, **d)
+ self.assertEqual(x2, spam.spamlist)
+ self.assertEqual(a2, a1)
+ self.assertEqual(d2, d1)
+ class SubSpam(spam.spamlist): pass
+ x2, a2, d2 = spam_cm(SubSpam, *a, **d)
+ self.assertEqual(x2, SubSpam)
+ self.assertEqual(a2, a1)
+ self.assertEqual(d2, d1)
+ with self.assertRaises(TypeError):
+ spam_cm()
+ with self.assertRaises(TypeError):
+ spam_cm(spam.spamlist())
+ with self.assertRaises(TypeError):
+ spam_cm(list)
def test_staticmethods(self):
# Testing static methods...
diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py
index 06047cf..c8ce158 100644
--- a/Lib/test/test_time.py
+++ b/Lib/test/test_time.py
@@ -30,16 +30,16 @@ class TimeTestCase(unittest.TestCase):
def test_time(self):
time.time()
info = time.get_clock_info('time')
- self.assertEqual(info.is_monotonic, False)
+ self.assertFalse(info.monotonic)
if sys.platform != 'win32':
- self.assertEqual(info.is_adjusted, True)
+ self.assertTrue(info.adjusted)
def test_clock(self):
time.clock()
info = time.get_clock_info('clock')
- self.assertEqual(info.is_monotonic, True)
- self.assertEqual(info.is_adjusted, False)
+ self.assertTrue(info.monotonic)
+ self.assertFalse(info.adjusted)
@unittest.skipUnless(hasattr(time, 'clock_gettime'),
'need time.clock_gettime()')
@@ -370,11 +370,11 @@ class TimeTestCase(unittest.TestCase):
self.assertAlmostEqual(dt, 0.1, delta=0.2)
info = time.get_clock_info('monotonic')
- self.assertEqual(info.is_monotonic, True)
+ self.assertTrue(info.monotonic)
if sys.platform == 'linux':
- self.assertEqual(info.is_adjusted, True)
+ self.assertTrue(info.adjusted)
else:
- self.assertEqual(info.is_adjusted, False)
+ self.assertFalse(info.adjusted)
def test_perf_counter(self):
time.perf_counter()
@@ -386,8 +386,8 @@ class TimeTestCase(unittest.TestCase):
self.assertLess(stop - start, 0.01)
info = time.get_clock_info('process_time')
- self.assertEqual(info.is_monotonic, True)
- self.assertEqual(info.is_adjusted, False)
+ self.assertTrue(info.monotonic)
+ self.assertFalse(info.adjusted)
@unittest.skipUnless(hasattr(time, 'monotonic'),
'need time.monotonic')
@@ -433,12 +433,12 @@ class TimeTestCase(unittest.TestCase):
#self.assertIsInstance(info, dict)
self.assertIsInstance(info.implementation, str)
self.assertNotEqual(info.implementation, '')
- self.assertIsInstance(info.is_monotonic, bool)
+ self.assertIsInstance(info.monotonic, bool)
self.assertIsInstance(info.resolution, float)
# 0.0 < resolution <= 1.0
self.assertGreater(info.resolution, 0.0)
self.assertLessEqual(info.resolution, 1.0)
- self.assertIsInstance(info.is_adjusted, bool)
+ self.assertIsInstance(info.adjusted, bool)
self.assertRaises(ValueError, time.get_clock_info, 'xxx')
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
index dcf8f74..80d45f5 100644
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -828,6 +828,16 @@ class OtherTests(unittest.TestCase):
b'\x00\x00\x00\x00'),
}
+ def test_unsupported_version(self):
+ # File has an extract_version of 120
+ data = (b'PK\x03\x04x\x00\x00\x00\x00\x00!p\xa1@\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00xPK\x01\x02x\x03x\x00\x00\x00\x00'
+ b'\x00!p\xa1@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00\x00xPK\x05\x06'
+ b'\x00\x00\x00\x00\x01\x00\x01\x00/\x00\x00\x00\x1f\x00\x00\x00\x00\x00')
+ self.assertRaises(NotImplementedError, zipfile.ZipFile,
+ io.BytesIO(data), 'r')
+
def test_unicode_filenames(self):
with zipfile.ZipFile(TESTFN, "w") as zf:
zf.writestr("foo.txt", "Test for unicode filename")
diff --git a/Lib/timeit.py b/Lib/timeit.py
index 5efe4f9..4f7d28f 100644
--- a/Lib/timeit.py
+++ b/Lib/timeit.py
@@ -9,14 +9,15 @@ the Python Cookbook, published by O'Reilly.
Library usage: see the Timer class.
Command line usage:
- python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [-h] [--] [statement]
+ python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [-p] [-h] [--] [statement]
Options:
-n/--number N: how many times to execute 'statement' (default: see below)
-r/--repeat N: how many times to repeat the timer (default 3)
-s/--setup S: statement to be executed once initially (default 'pass')
- -t/--time: use time.time()
- -c/--clock: use time.clock()
+ -p/--process: use time.process_time() (default is time.perf_counter())
+ -t/--time: use time.time() (deprecated)
+ -c/--clock: use time.clock() (deprecated)
-v/--verbose: print raw timing results; repeat for more digits precision
-h/--help: print this usage message and exit
--: separate options from statement, use when statement starts with -
@@ -249,9 +250,10 @@ def main(args=None, *, _wrap_timer=None):
args = sys.argv[1:]
import getopt
try:
- opts, args = getopt.getopt(args, "n:s:r:tcvh",
+ opts, args = getopt.getopt(args, "n:s:r:tcpvh",
["number=", "setup=", "repeat=",
- "time", "clock", "verbose", "help"])
+ "time", "clock", "process",
+ "verbose", "help"])
except getopt.error as err:
print(err)
print("use -h/--help for command line help")
@@ -276,6 +278,8 @@ def main(args=None, *, _wrap_timer=None):
timer = time.time
if o in ("-c", "--clock"):
timer = time.clock
+ if o in ("-p", "--process"):
+ timer = time.process_time
if o in ("-v", "--verbose"):
if verbose:
precision += 1
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index f5564da..c53b127 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -57,6 +57,8 @@ ZIP_BZIP2 = 12
DEFAULT_VERSION = 20
ZIP64_VERSION = 45
BZIP2_VERSION = 46
+# we recognize (but not necessarily support) all features up to that version
+MAX_EXTRACT_VERSION = 46
# Below are some formats and associated data for reading/writing headers using
# the struct module. The names and structures of headers/records are those used
@@ -920,6 +922,9 @@ class ZipFile:
(x.create_version, x.create_system, x.extract_version, x.reserved,
x.flag_bits, x.compress_type, t, d,
x.CRC, x.compress_size, x.file_size) = centdir[1:12]
+ if x.extract_version > MAX_EXTRACT_VERSION:
+ raise NotImplementedError("zip file version %.1f" %
+ (x.extract_version / 10))
x.volume, x.internal_attr, x.external_attr = centdir[15:18]
# Convert date/time code to (year, month, day, hour, min, sec)
x._raw_time = t
diff --git a/Misc/NEWS b/Misc/NEWS
index e788404..6251da6 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@ What's New in Python 3.3.0 Alpha 3?
Core and Builtins
-----------------
+- Issue #14699: Fix calling the classmethod descriptor directly.
+
- Issue #14433: Prevent msvcrt crash in interactive prompt when stdin
is closed.
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 1e843b9..5961ac9 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -95,8 +95,8 @@ floatclock(_Py_clock_info_t *info)
if (info) {
info->implementation = "clock()";
info->resolution = 1.0 / (double)CLOCKS_PER_SEC;
- info->is_monotonic = 1;
- info->is_adjusted = 0;
+ info->monotonic = 1;
+ info->adjusted = 0;
}
return PyFloat_FromDouble((double)value / CLOCKS_PER_SEC);
}
@@ -131,8 +131,8 @@ win_perf_counter(_Py_clock_info_t *info, PyObject **result)
if (info) {
info->implementation = "QueryPerformanceCounter()";
info->resolution = 1.0 / (double)cpu_frequency;
- info->is_monotonic = 1;
- info->is_adjusted = 0;
+ info->monotonic = 1;
+ info->adjusted = 0;
}
*result = PyFloat_FromDouble(diff / (double)cpu_frequency);
return 0;
@@ -874,7 +874,7 @@ pymonotonic(_Py_clock_info_t *info)
info->implementation = "GetTickCount64()";
else
info->implementation = "GetTickCount()";
- info->is_monotonic = 1;
+ info->monotonic = 1;
ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
&isTimeAdjustmentDisabled);
if (!ok) {
@@ -882,7 +882,7 @@ pymonotonic(_Py_clock_info_t *info)
return NULL;
}
info->resolution = timeIncrement * 1e-7;
- info->is_adjusted = 0;
+ info->adjusted = 0;
}
return PyFloat_FromDouble(result);
@@ -902,8 +902,8 @@ pymonotonic(_Py_clock_info_t *info)
if (info) {
info->implementation = "mach_absolute_time()";
info->resolution = (double)timebase.numer / timebase.denom * 1e-9;
- info->is_monotonic = 1;
- info->is_adjusted = 0;
+ info->monotonic = 1;
+ info->adjusted = 0;
}
return PyFloat_FromDouble(secs);
@@ -924,14 +924,14 @@ pymonotonic(_Py_clock_info_t *info)
if (info) {
struct timespec res;
- info->is_monotonic = 1;
+ info->monotonic = 1;
info->implementation = function;
#if (defined(linux) || defined(__linux) || defined(__linux__)) \
&& !defined(CLOCK_HIGHRES)
/* CLOCK_MONOTONIC is adjusted on Linux */
- info->is_adjusted = 1;
+ info->adjusted = 1;
#else
- info->is_adjusted = 0;
+ info->adjusted = 0;
#endif
if (clock_getres(clk_id, &res) == 0)
info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
@@ -1023,8 +1023,8 @@ py_process_time(_Py_clock_info_t *info)
if (info) {
info->implementation = "GetProcessTimes()";
info->resolution = 1e-7;
- info->is_monotonic = 1;
- info->is_adjusted = 0;
+ info->monotonic = 1;
+ info->adjusted = 0;
}
return PyFloat_FromDouble(total * 1e-7);
#else
@@ -1052,8 +1052,8 @@ py_process_time(_Py_clock_info_t *info)
if (info) {
struct timespec res;
info->implementation = function;
- info->is_monotonic = 1;
- info->is_adjusted = 0;
+ info->monotonic = 1;
+ info->adjusted = 0;
if (clock_getres(clk_id, &res) == 0)
info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
else
@@ -1070,8 +1070,8 @@ py_process_time(_Py_clock_info_t *info)
total += ru.ru_stime.tv_sec + ru.ru_stime.tv_usec * 1e-6;
if (info) {
info->implementation = "getrusage(RUSAGE_SELF)";
- info->is_monotonic = 1;
- info->is_adjusted = 0;
+ info->monotonic = 1;
+ info->adjusted = 0;
info->resolution = 1e-6;
}
return PyFloat_FromDouble(total);
@@ -1099,8 +1099,8 @@ py_process_time(_Py_clock_info_t *info)
total += (double)t.tms_stime / ticks_per_second;
if (info) {
info->implementation = "times()";
- info->is_monotonic = 1;
- info->is_adjusted = 0;
+ info->monotonic = 1;
+ info->adjusted = 0;
info->resolution = 1.0 / ticks_per_second;
}
return PyFloat_FromDouble(total);
@@ -1132,8 +1132,8 @@ PyDoc_STRVAR(ClockInfo_docstring,
static PyStructSequence_Field ClockInfo_fields[] = {
{"implementation", "name of the underlying C function "
"used to get the clock value"},
- {"is_monotonic", "True if the clock cannot go backward, False otherwise"},
- {"is_adjusted", "True if the clock can be adjusted "
+ {"monotonic", "True if the clock cannot go backward, False otherwise"},
+ {"adjusted", "True if the clock can be adjusted "
"(e.g. by a NTP daemon), False otherwise"},
{"resolution", "resolution of the clock in seconds"},
{NULL, NULL}
@@ -1159,13 +1159,13 @@ time_get_clock_info(PyObject *self, PyObject *args)
#ifdef Py_DEBUG
info.implementation = NULL;
- info.is_monotonic = -1;
- info.is_adjusted = -1;
+ info.monotonic = -1;
+ info.adjusted = -1;
info.resolution = -1.0;
#else
info.implementation = "";
- info.is_monotonic = 0;
- info.is_adjusted = 0;
+ info.monotonic = 0;
+ info.adjusted = 0;
info.resolution = 1.0;
#endif
@@ -1201,14 +1201,14 @@ time_get_clock_info(PyObject *self, PyObject *args)
goto error;
PyStructSequence_SET_ITEM(result, 0, obj);
- assert(info.is_monotonic != -1);
- obj = PyBool_FromLong(info.is_monotonic);
+ assert(info.monotonic != -1);
+ obj = PyBool_FromLong(info.monotonic);
if (obj == NULL)
goto error;
PyStructSequence_SET_ITEM(result, 1, obj);
- assert(info.is_adjusted != -1);
- obj = PyBool_FromLong(info.is_adjusted);
+ assert(info.adjusted != -1);
+ obj = PyBool_FromLong(info.adjusted);
if (obj == NULL)
goto error;
PyStructSequence_SET_ITEM(result, 2, obj);
@@ -1487,8 +1487,8 @@ floattime(_Py_clock_info_t *info)
if (info) {
struct timespec res;
info->implementation = "clock_gettime(CLOCK_REALTIME)";
- info->is_monotonic = 0;
- info->is_adjusted = 1;
+ info->monotonic = 0;
+ info->adjusted = 1;
if (clock_getres(CLOCK_REALTIME, &res) == 0)
info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
else
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index b679c4bc..abcc002 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -257,14 +257,52 @@ static PyObject *
classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
PyObject *kwds)
{
- PyObject *func, *result;
+ Py_ssize_t argc;
+ PyObject *self, *func, *result;
- func = PyCFunction_New(descr->d_method, (PyObject *)PyDescr_TYPE(descr));
- if (func == NULL)
+ /* Make sure that the first argument is acceptable as 'self' */
+ assert(PyTuple_Check(args));
+ argc = PyTuple_GET_SIZE(args);
+ if (argc < 1) {
+ PyErr_Format(PyExc_TypeError,
+ "descriptor '%V' of '%.100s' "
+ "object needs an argument",
+ descr_name((PyDescrObject *)descr), "?",
+ PyDescr_TYPE(descr)->tp_name);
return NULL;
+ }
+ self = PyTuple_GET_ITEM(args, 0);
+ if (!PyType_Check(self)) {
+ PyErr_Format(PyExc_TypeError,
+ "descriptor '%V' requires a type "
+ "but received a '%.100s'",
+ descr_name((PyDescrObject *)descr), "?",
+ PyDescr_TYPE(descr)->tp_name,
+ self->ob_type->tp_name);
+ return NULL;
+ }
+ if (!PyType_IsSubtype((PyTypeObject *)self, PyDescr_TYPE(descr))) {
+ PyErr_Format(PyExc_TypeError,
+ "descriptor '%V' "
+ "requires a subtype of '%.100s' "
+ "but received '%.100s",
+ descr_name((PyDescrObject *)descr), "?",
+ PyDescr_TYPE(descr)->tp_name,
+ self->ob_type->tp_name);
+ return NULL;
+ }
+ func = PyCFunction_New(descr->d_method, self);
+ if (func == NULL)
+ return NULL;
+ args = PyTuple_GetSlice(args, 1, argc);
+ if (args == NULL) {
+ Py_DECREF(func);
+ return NULL;
+ }
result = PyEval_CallObjectWithKeywords(func, args, kwds);
Py_DECREF(func);
+ Py_DECREF(args);
return result;
}
diff --git a/Python/pytime.c b/Python/pytime.c
index ddd3088..0ffe799 100644
--- a/Python/pytime.c
+++ b/Python/pytime.c
@@ -40,14 +40,14 @@ pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info)
BOOL isTimeAdjustmentDisabled;
info->implementation = "GetSystemTimeAsFileTime()";
- info->is_monotonic = 0;
+ info->monotonic = 0;
(void) GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
&isTimeAdjustmentDisabled);
info->resolution = timeIncrement * 1e-7;
if (isTimeAdjustmentDisabled)
- info->is_adjusted = 0;
+ info->adjusted = 0;
else
- info->is_adjusted = 1;
+ info->adjusted = 1;
}
#else
/* There are three ways to get the time:
@@ -70,8 +70,8 @@ pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info)
if (info) {
info->implementation = "gettimeofday()";
info->resolution = 1e-6;
- info->is_monotonic = 0;
- info->is_adjusted = 1;
+ info->monotonic = 0;
+ info->adjusted = 1;
}
return;
}
@@ -86,8 +86,8 @@ pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info)
if (info) {
info->implementation = "ftime()";
info->resolution = 1e-3;
- info->is_monotonic = 0;
- info->is_adjusted = 1;
+ info->monotonic = 0;
+ info->adjusted = 1;
}
}
#else /* !HAVE_FTIME */
@@ -96,8 +96,8 @@ pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info)
if (info) {
info->implementation = "time()";
info->resolution = 1.0;
- info->is_monotonic = 0;
- info->is_adjusted = 1;
+ info->monotonic = 0;
+ info->adjusted = 1;
}
#endif /* !HAVE_FTIME */