diff options
-rw-r--r-- | Doc/library/time.rst | 4 | ||||
-rw-r--r-- | Doc/library/timeit.rst | 30 | ||||
-rw-r--r-- | Include/pytime.h | 4 | ||||
-rw-r--r-- | Lib/test/test_descr.py | 16 | ||||
-rw-r--r-- | Lib/test/test_time.py | 22 | ||||
-rw-r--r-- | Lib/test/test_zipfile.py | 10 | ||||
-rw-r--r-- | Lib/timeit.py | 14 | ||||
-rw-r--r-- | Lib/zipfile.py | 5 | ||||
-rw-r--r-- | Misc/NEWS | 2 | ||||
-rw-r--r-- | Modules/timemodule.c | 62 | ||||
-rw-r--r-- | Objects/descrobject.c | 44 | ||||
-rw-r--r-- | Python/pytime.c | 18 |
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 @@ -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 */ |