Merge 3.5.0a3 release engineering changes back into trunk.

This commit is contained in:
Larry Hastings 2015-03-30 01:50:00 -07:00
commit 09dab7a87e
35 changed files with 619 additions and 506 deletions

View File

@ -419,7 +419,7 @@ Writer Objects
:class:`Writer` objects (:class:`DictWriter` instances and objects returned by
the :func:`writer` function) have the following public methods. A *row* must be
a sequence of strings or numbers for :class:`Writer` objects and a dictionary
an iterable of strings or numbers for :class:`Writer` objects and a dictionary
mapping fieldnames to strings or numbers (by passing them through :func:`str`
first) for :class:`DictWriter` objects. Note that complex numbers are written
out surrounded by parens. This may cause some problems for other programs which
@ -431,6 +431,8 @@ read CSV files (assuming they support complex numbers at all).
Write the *row* parameter to the writer's file object, formatted according to
the current dialect.
.. versionchanged:: 3.5
Added support of arbitrary iterables.
.. method:: csvwriter.writerows(rows)

View File

@ -41,12 +41,16 @@ struct _Py_stat_struct {
PyAPI_FUNC(int) _Py_fstat(
int fd,
struct _Py_stat_struct *stat);
struct _Py_stat_struct *status);
PyAPI_FUNC(int) _Py_fstat_noraise(
int fd,
struct _Py_stat_struct *status);
#endif /* Py_LIMITED_API */
PyAPI_FUNC(int) _Py_stat(
PyObject *path,
struct stat *statbuf);
struct stat *status);
#ifndef Py_LIMITED_API
PyAPI_FUNC(int) _Py_open(

View File

@ -13,45 +13,26 @@ functions and constants
extern "C" {
#endif
#ifdef HAVE_GETTIMEOFDAY
typedef struct timeval _PyTime_timeval;
#ifdef PY_INT64_T
/* _PyTime_t: Python timestamp with subsecond precision. It can be used to
store a duration, and so indirectly a date (related to another date, like
UNIX epoch). */
typedef PY_INT64_T _PyTime_t;
#define _PyTime_MIN PY_LLONG_MIN
#define _PyTime_MAX PY_LLONG_MAX
#else
typedef struct {
time_t tv_sec; /* seconds since Jan. 1, 1970 */
long tv_usec; /* and microseconds */
} _PyTime_timeval;
# error "_PyTime_t need signed 64-bit integer type"
#endif
/* Structure used by time.get_clock_info() */
typedef struct {
const char *implementation;
int monotonic;
int adjustable;
double resolution;
} _Py_clock_info_t;
/* Similar to POSIX gettimeofday but cannot fail. If system gettimeofday
* fails or is not available, fall back to lower resolution clocks.
*/
PyAPI_FUNC(void) _PyTime_gettimeofday(_PyTime_timeval *tp);
typedef enum {
/* Round towards zero. */
_PyTime_ROUND_DOWN=0,
/* Round away from zero.
For example, used for timeout to wait "at least" N seconds. */
_PyTime_ROUND_UP,
/* Round towards minus infinity (-inf).
For example, used to read a clock. */
_PyTime_ROUND_FLOOR
_PyTime_ROUND_FLOOR=0,
/* Round towards infinity (+inf).
For example, used for timeout to wait "at least" N seconds. */
_PyTime_ROUND_CEILING
} _PyTime_round_t;
/* Convert a number of seconds, int or float, to time_t. */
PyAPI_FUNC(int) _PyTime_ObjectToTime_t(
PyObject *obj,
time_t *sec,
_PyTime_round_t);
/* Convert a time_t to a PyLong. */
PyAPI_FUNC(PyObject *) _PyLong_FromTime_t(
time_t sec);
@ -60,6 +41,12 @@ PyAPI_FUNC(PyObject *) _PyLong_FromTime_t(
PyAPI_FUNC(time_t) _PyLong_AsTime_t(
PyObject *obj);
/* Convert a number of seconds, int or float, to time_t. */
PyAPI_FUNC(int) _PyTime_ObjectToTime_t(
PyObject *obj,
time_t *sec,
_PyTime_round_t);
/* Convert a number of seconds, int or float, to a timeval structure.
usec is in the range [0; 999999] and rounded towards zero.
For example, -1.2 is converted to (-2, 800000). */
@ -78,22 +65,6 @@ PyAPI_FUNC(int) _PyTime_ObjectToTimespec(
long *nsec,
_PyTime_round_t);
/* Initialize time.
Return 0 on success, raise an exception and return -1 on error. */
PyAPI_FUNC(int) _PyTime_Init(void);
/****************** NEW _PyTime_t API **********************/
#ifdef PY_INT64_T
/* _PyTime_t: Python timestamp with subsecond precision. It can be used to
store a duration, and so indirectly a date (related to another date, like
UNIX epoch). */
typedef PY_INT64_T _PyTime_t;
#define _PyTime_MIN PY_LLONG_MIN
#define _PyTime_MAX PY_LLONG_MAX
#else
# error "_PyTime_t need signed 64-bit integer type"
#endif
/* Create a timestamp from a number of nanoseconds (C long). */
PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(PY_LONG_LONG ns);
@ -121,11 +92,17 @@ PyAPI_FUNC(PyObject *) _PyTime_AsNanosecondsObject(_PyTime_t t);
/* Convert a timestamp to a timeval structure (microsecond resolution).
tv_usec is always positive.
Return -1 if the conversion overflowed, return 0 on success. */
Raise an exception and return -1 if the conversion overflowed,
return 0 on success. */
PyAPI_FUNC(int) _PyTime_AsTimeval(_PyTime_t t,
struct timeval *tv,
_PyTime_round_t round);
/* Similar to _PyTime_AsTimeval(), but don't raise an exception on error. */
PyAPI_FUNC(int) _PyTime_AsTimeval_noraise(_PyTime_t t,
struct timeval *tv,
_PyTime_round_t round);
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE)
/* Convert a timestamp to a timespec structure (nanosecond resolution).
tv_nsec is always positive.
@ -133,6 +110,30 @@ PyAPI_FUNC(int) _PyTime_AsTimeval(_PyTime_t t,
PyAPI_FUNC(int) _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts);
#endif
/* Get the current time from the system clock.
The function cannot fail. _PyTime_Init() ensures that the system clock
works. */
PyAPI_FUNC(_PyTime_t) _PyTime_GetSystemClock(void);
/* Get the time of a monotonic clock, i.e. a clock that cannot go backwards.
The clock is not affected by system clock updates. The reference point of
the returned value is undefined, so that only the difference between the
results of consecutive calls is valid.
The function cannot fail. _PyTime_Init() ensures that a monotonic clock
is available and works. */
PyAPI_FUNC(_PyTime_t) _PyTime_GetMonotonicClock(void);
/* Structure used by time.get_clock_info() */
typedef struct {
const char *implementation;
int monotonic;
int adjustable;
double resolution;
} _Py_clock_info_t;
/* Get the current time from the system clock.
* Fill clock information if info is not NULL.
* Raise an exception and return -1 on error, return 0 on success.
@ -141,15 +142,6 @@ PyAPI_FUNC(int) _PyTime_GetSystemClockWithInfo(
_PyTime_t *t,
_Py_clock_info_t *info);
/* Get the time of a monotonic clock, i.e. a clock that cannot go backwards.
The clock is not affected by system clock updates. The reference point of
the returned value is undefined, so that only the difference between the
results of consecutive calls is valid.
The function cannot fail. _PyTime_Init() ensures that a monotonic clock
is available and works. */
PyAPI_FUNC(_PyTime_t) _PyTime_GetMonotonicClock(void);
/* Get the time of a monotonic clock, i.e. a clock that cannot go backwards.
The clock is not affected by system clock updates. The reference point of
the returned value is undefined, so that only the difference between the
@ -163,6 +155,10 @@ PyAPI_FUNC(int) _PyTime_GetMonotonicClockWithInfo(
_Py_clock_info_t *info);
/* Initialize time.
Return 0 on success, raise an exception and return -1 on error. */
PyAPI_FUNC(int) _PyTime_Init(void);
#ifdef __cplusplus
}
#endif

View File

@ -147,16 +147,13 @@ class DictWriter:
if wrong_fields:
raise ValueError("dict contains fields not in fieldnames: "
+ ", ".join([repr(x) for x in wrong_fields]))
return [rowdict.get(key, self.restval) for key in self.fieldnames]
return (rowdict.get(key, self.restval) for key in self.fieldnames)
def writerow(self, rowdict):
return self.writer.writerow(self._dict_to_list(rowdict))
def writerows(self, rowdicts):
rows = []
for rowdict in rowdicts:
rows.append(self._dict_to_list(rowdict))
return self.writer.writerows(rows)
return self.writer.writerows(map(self._dict_to_list, rowdicts))
# Guard Sniffer's type checking against builds that exclude complex()
try:

View File

@ -71,6 +71,7 @@ import re
import urllib # For urllib.parse.unquote
from string import hexdigits
from collections import OrderedDict
from operator import itemgetter
from email import _encoded_words as _ew
from email import errors
from email import utils
@ -1098,15 +1099,34 @@ class MimeParameters(TokenList):
params[name] = []
params[name].append((token.section_number, token))
for name, parts in params.items():
parts = sorted(parts)
# XXX: there might be more recovery we could do here if, for
# example, this is really a case of a duplicate attribute name.
parts = sorted(parts, key=itemgetter(0))
first_param = parts[0][1]
charset = first_param.charset
# Our arbitrary error recovery is to ignore duplicate parameters,
# to use appearance order if there are duplicate rfc 2231 parts,
# and to ignore gaps. This mimics the error recovery of get_param.
if not first_param.extended and len(parts) > 1:
if parts[1][0] == 0:
parts[1][1].defects.append(errors.InvalidHeaderDefect(
'duplicate parameter name; duplicate(s) ignored'))
parts = parts[:1]
# Else assume the *0* was missing...note that this is different
# from get_param, but we registered a defect for this earlier.
value_parts = []
charset = parts[0][1].charset
for i, (section_number, param) in enumerate(parts):
i = 0
for section_number, param in parts:
if section_number != i:
param.defects.append(errors.InvalidHeaderDefect(
"inconsistent multipart parameter numbering"))
# We could get fancier here and look for a complete
# duplicate extended parameter and ignore the second one
# seen. But we're not doing that. The old code didn't.
if not param.extended:
param.defects.append(errors.InvalidHeaderDefect(
'duplicate parameter name; duplicate ignored'))
continue
else:
param.defects.append(errors.InvalidHeaderDefect(
"inconsistent RFC2231 parameter numbering"))
i += 1
value = param.param_value
if param.extended:
try:

View File

@ -1031,7 +1031,7 @@ class saved_test_environment:
# to a thread, so check processes first.
'multiprocessing.process._dangling', 'threading._dangling',
'sysconfig._CONFIG_VARS', 'sysconfig._INSTALL_SCHEMES',
'support.TESTFN', 'locale', 'warnings.showwarning',
'files', 'locale', 'warnings.showwarning',
)
def get_sys_argv(self):
@ -1187,20 +1187,16 @@ class saved_test_environment:
sysconfig._INSTALL_SCHEMES.clear()
sysconfig._INSTALL_SCHEMES.update(saved[2])
def get_support_TESTFN(self):
if os.path.isfile(support.TESTFN):
result = 'f'
elif os.path.isdir(support.TESTFN):
result = 'd'
else:
result = None
return result
def restore_support_TESTFN(self, saved_value):
if saved_value is None:
if os.path.isfile(support.TESTFN):
os.unlink(support.TESTFN)
elif os.path.isdir(support.TESTFN):
shutil.rmtree(support.TESTFN)
def get_files(self):
return sorted(fn + ('/' if os.path.isdir(fn) else '')
for fn in os.listdir())
def restore_files(self, saved_value):
fn = support.TESTFN
if fn not in saved_value and (fn + '/') not in saved_value:
if os.path.isfile(fn):
support.unlink(fn)
elif os.path.isdir(fn):
support.rmtree(fn)
_lc = [getattr(locale, lc) for lc in dir(locale)
if lc.startswith('LC_')]

View File

@ -186,6 +186,14 @@ class Test_Csv(unittest.TestCase):
self._write_test(['a',1,'p,q'], 'a,1,p\\,q',
escapechar='\\', quoting = csv.QUOTE_NONE)
def test_write_iterable(self):
self._write_test(iter(['a', 1, 'p,q']), 'a,1,"p,q"')
self._write_test(iter(['a', 1, None]), 'a,1,')
self._write_test(iter([]), '')
self._write_test(iter([None]), '""')
self._write_error_test(csv.Error, iter([None]), quoting=csv.QUOTE_NONE)
self._write_test(iter([None, None]), ',')
def test_writerows(self):
class BrokenFile:
def write(self, buf):

View File

@ -2456,6 +2456,115 @@ class TestParser(TestParserMixin, TestEmailBase):
";foo", ";foo", ";foo", [errors.InvalidHeaderDefect]*3
)
@parameterize
class Test_parse_mime_parameters(TestParserMixin, TestEmailBase):
def mime_parameters_as_value(self,
value,
tl_str,
tl_value,
params,
defects):
mime_parameters = self._test_parse_x(parser.parse_mime_parameters,
value, tl_str, tl_value, defects)
self.assertEqual(mime_parameters.token_type, 'mime-parameters')
self.assertEqual(list(mime_parameters.params), params)
mime_parameters_params = {
'simple': (
'filename="abc.py"',
' filename="abc.py"',
'filename=abc.py',
[('filename', 'abc.py')],
[]),
'multiple_keys': (
'filename="abc.py"; xyz=abc',
' filename="abc.py"; xyz="abc"',
'filename=abc.py; xyz=abc',
[('filename', 'abc.py'), ('xyz', 'abc')],
[]),
'split_value': (
"filename*0*=iso-8859-1''%32%30%31%2E; filename*1*=%74%69%66",
' filename="201.tif"',
"filename*0*=iso-8859-1''%32%30%31%2E; filename*1*=%74%69%66",
[('filename', '201.tif')],
[]),
# Note that it is undefined what we should do for error recovery when
# there are duplicate parameter names or duplicate parts in a split
# part. We choose to ignore all duplicate parameters after the first
# and to take duplicate or missing rfc 2231 parts in apperance order.
# This is backward compatible with get_param's behavior, but the
# decisions are arbitrary.
'duplicate_key': (
'filename=abc.gif; filename=def.tiff',
' filename="abc.gif"',
"filename=abc.gif; filename=def.tiff",
[('filename', 'abc.gif')],
[errors.InvalidHeaderDefect]),
'duplicate_key_with_split_value': (
"filename*0*=iso-8859-1''%32%30%31%2E; filename*1*=%74%69%66;"
" filename=abc.gif",
' filename="201.tif"',
"filename*0*=iso-8859-1''%32%30%31%2E; filename*1*=%74%69%66;"
" filename=abc.gif",
[('filename', '201.tif')],
[errors.InvalidHeaderDefect]),
'duplicate_key_with_split_value_other_order': (
"filename=abc.gif; "
" filename*0*=iso-8859-1''%32%30%31%2E; filename*1*=%74%69%66",
' filename="abc.gif"',
"filename=abc.gif;"
" filename*0*=iso-8859-1''%32%30%31%2E; filename*1*=%74%69%66",
[('filename', 'abc.gif')],
[errors.InvalidHeaderDefect]),
'duplicate_in_split_value': (
"filename*0*=iso-8859-1''%32%30%31%2E; filename*1*=%74%69%66;"
" filename*1*=abc.gif",
' filename="201.tifabc.gif"',
"filename*0*=iso-8859-1''%32%30%31%2E; filename*1*=%74%69%66;"
" filename*1*=abc.gif",
[('filename', '201.tifabc.gif')],
[errors.InvalidHeaderDefect]),
'missing_split_value': (
"filename*0*=iso-8859-1''%32%30%31%2E; filename*3*=%74%69%66;",
' filename="201.tif"',
"filename*0*=iso-8859-1''%32%30%31%2E; filename*3*=%74%69%66;",
[('filename', '201.tif')],
[errors.InvalidHeaderDefect]),
'duplicate_and_missing_split_value': (
"filename*0*=iso-8859-1''%32%30%31%2E; filename*3*=%74%69%66;"
" filename*3*=abc.gif",
' filename="201.tifabc.gif"',
"filename*0*=iso-8859-1''%32%30%31%2E; filename*3*=%74%69%66;"
" filename*3*=abc.gif",
[('filename', '201.tifabc.gif')],
[errors.InvalidHeaderDefect]*2),
# Here we depart from get_param and assume the *0* was missing.
'duplicate_with_broken_split_value': (
"filename=abc.gif; "
" filename*2*=iso-8859-1''%32%30%31%2E; filename*3*=%74%69%66",
' filename="abc.gif201.tif"',
"filename=abc.gif;"
" filename*2*=iso-8859-1''%32%30%31%2E; filename*3*=%74%69%66",
[('filename', 'abc.gif201.tif')],
# Defects are apparent missing *0*, and two 'out of sequence'.
[errors.InvalidHeaderDefect]*3),
}
@parameterize
class Test_parse_mime_version(TestParserMixin, TestEmailBase):

View File

@ -272,9 +272,18 @@ class FormatTest(unittest.TestCase):
#test_exc(unicode('abc %\u3000','raw-unicode-escape'), 1, ValueError,
# "unsupported format character '?' (0x3000) at index 5")
test_exc('%d', '1', TypeError, "%d format: a number is required, not str")
test_exc('%x', '1', TypeError, "%x format: a number is required, not str")
test_exc('%x', 3.14, TypeError, "%x format: an integer is required, not float")
test_exc('%g', '1', TypeError, "a float is required")
test_exc('no format', '1', TypeError,
"not all arguments converted during string formatting")
test_exc('%c', -1, OverflowError, "%c arg not in range(0x110000)")
test_exc('%c', sys.maxunicode+1, OverflowError,
"%c arg not in range(0x110000)")
#test_exc('%c', 2**128, OverflowError, "%c arg not in range(0x110000)")
test_exc('%c', 3.14, TypeError, "%c requires int or char")
test_exc('%c', 'ab', TypeError, "%c requires int or char")
test_exc('%c', b'x', TypeError, "%c requires int or char")
if maxsize == 2**31-1:
# crashes 2.2.1 and earlier:
@ -339,6 +348,8 @@ class FormatTest(unittest.TestCase):
"%d format: a number is required, not str")
test_exc(b'%d', b'1', TypeError,
"%d format: a number is required, not bytes")
test_exc(b'%x', 3.14, TypeError,
"%x format: an integer is required, not float")
test_exc(b'%g', '1', TypeError, "float argument required, not str")
test_exc(b'%g', b'1', TypeError, "float argument required, not bytes")
test_exc(b'no format', 7, TypeError,
@ -347,11 +358,17 @@ class FormatTest(unittest.TestCase):
"not all arguments converted during bytes formatting")
test_exc(b'no format', bytearray(b'1'), TypeError,
"not all arguments converted during bytes formatting")
test_exc(b"%c", -1, TypeError,
"%c requires an integer in range(256) or a single byte")
test_exc(b"%c", 256, TypeError,
"%c requires an integer in range(256) or a single byte")
test_exc(b"%c", 2**128, TypeError,
"%c requires an integer in range(256) or a single byte")
test_exc(b"%c", b"Za", TypeError,
"%c requires an integer in range(256) or a single byte")
test_exc(b"%c", "Yb", TypeError,
test_exc(b"%c", "Y", TypeError,
"%c requires an integer in range(256) or a single byte")
test_exc(b"%c", 3.14, TypeError,
"%c requires an integer in range(256) or a single byte")
test_exc(b"%b", "Xc", TypeError,
"%b requires bytes, or an object that implements __bytes__, not 'str'")

View File

@ -24,17 +24,12 @@ TIME_MINYEAR = -TIME_MAXYEAR - 1
SEC_TO_NS = 10 ** 9
class _PyTime(enum.IntEnum):
# Round towards zero
ROUND_DOWN = 0
# Round away from zero
ROUND_UP = 1
# Round towards -Infinity
ROUND_FLOOR = 2
# Round towards minus infinity (-inf)
ROUND_FLOOR = 0
# Round towards infinity (+inf)
ROUND_CEILING = 1
ALL_ROUNDING_METHODS = (
_PyTime.ROUND_UP,
_PyTime.ROUND_DOWN,
_PyTime.ROUND_FLOOR)
ALL_ROUNDING_METHODS = (_PyTime.ROUND_FLOOR, _PyTime.ROUND_CEILING)
class TimeTestCase(unittest.TestCase):
@ -614,24 +609,24 @@ class TestPytime(unittest.TestCase):
def test_time_t(self):
from _testcapi import pytime_object_to_time_t
for obj, time_t, rnd in (
# Round towards zero
(0, 0, _PyTime.ROUND_DOWN),
(-1, -1, _PyTime.ROUND_DOWN),
(-1.0, -1, _PyTime.ROUND_DOWN),
(-1.9, -1, _PyTime.ROUND_DOWN),
(1.0, 1, _PyTime.ROUND_DOWN),
(1.9, 1, _PyTime.ROUND_DOWN),
# Round away from zero
(0, 0, _PyTime.ROUND_UP),
(-1, -1, _PyTime.ROUND_UP),
(-1.0, -1, _PyTime.ROUND_UP),
(-1.9, -2, _PyTime.ROUND_UP),
(1.0, 1, _PyTime.ROUND_UP),
(1.9, 2, _PyTime.ROUND_UP),
# Round towards minus infinity (-inf)
(0, 0, _PyTime.ROUND_FLOOR),
(-1, -1, _PyTime.ROUND_FLOOR),
(-1.0, -1, _PyTime.ROUND_FLOOR),
(-1.9, -2, _PyTime.ROUND_FLOOR),
(1.0, 1, _PyTime.ROUND_FLOOR),
(1.9, 1, _PyTime.ROUND_FLOOR),
# Round towards infinity (+inf)
(0, 0, _PyTime.ROUND_CEILING),
(-1, -1, _PyTime.ROUND_CEILING),
(-1.0, -1, _PyTime.ROUND_CEILING),
(-1.9, -1, _PyTime.ROUND_CEILING),
(1.0, 1, _PyTime.ROUND_CEILING),
(1.9, 2, _PyTime.ROUND_CEILING),
):
self.assertEqual(pytime_object_to_time_t(obj, rnd), time_t)
rnd = _PyTime.ROUND_DOWN
rnd = _PyTime.ROUND_FLOOR
for invalid in self.invalid_values:
self.assertRaises(OverflowError,
pytime_object_to_time_t, invalid, rnd)
@ -640,39 +635,39 @@ class TestPytime(unittest.TestCase):
def test_timespec(self):
from _testcapi import pytime_object_to_timespec
for obj, timespec, rnd in (
# Round towards zero
(0, (0, 0), _PyTime.ROUND_DOWN),
(-1, (-1, 0), _PyTime.ROUND_DOWN),
(-1.0, (-1, 0), _PyTime.ROUND_DOWN),
(1e-9, (0, 1), _PyTime.ROUND_DOWN),
(1e-10, (0, 0), _PyTime.ROUND_DOWN),
(-1e-9, (-1, 999999999), _PyTime.ROUND_DOWN),
(-1e-10, (-1, 999999999), _PyTime.ROUND_DOWN),
(-1.2, (-2, 800000000), _PyTime.ROUND_DOWN),
(0.9999999999, (0, 999999999), _PyTime.ROUND_DOWN),
(1.1234567890, (1, 123456789), _PyTime.ROUND_DOWN),
(1.1234567899, (1, 123456789), _PyTime.ROUND_DOWN),
(-1.1234567890, (-2, 876543211), _PyTime.ROUND_DOWN),
(-1.1234567891, (-2, 876543210), _PyTime.ROUND_DOWN),
# Round away from zero
(0, (0, 0), _PyTime.ROUND_UP),
(-1, (-1, 0), _PyTime.ROUND_UP),
(-1.0, (-1, 0), _PyTime.ROUND_UP),
(1e-9, (0, 1), _PyTime.ROUND_UP),
(1e-10, (0, 1), _PyTime.ROUND_UP),
(-1e-9, (-1, 999999999), _PyTime.ROUND_UP),
(-1e-10, (-1, 999999999), _PyTime.ROUND_UP),
(-1.2, (-2, 800000000), _PyTime.ROUND_UP),
(0.9999999999, (1, 0), _PyTime.ROUND_UP),
(1.1234567890, (1, 123456790), _PyTime.ROUND_UP),
(1.1234567899, (1, 123456790), _PyTime.ROUND_UP),
(-1.1234567890, (-2, 876543211), _PyTime.ROUND_UP),
(-1.1234567891, (-2, 876543210), _PyTime.ROUND_UP),
# Round towards minus infinity (-inf)
(0, (0, 0), _PyTime.ROUND_FLOOR),
(-1, (-1, 0), _PyTime.ROUND_FLOOR),
(-1.0, (-1, 0), _PyTime.ROUND_FLOOR),
(1e-9, (0, 1), _PyTime.ROUND_FLOOR),
(1e-10, (0, 0), _PyTime.ROUND_FLOOR),
(-1e-9, (-1, 999999999), _PyTime.ROUND_FLOOR),
(-1e-10, (-1, 999999999), _PyTime.ROUND_FLOOR),
(-1.2, (-2, 800000000), _PyTime.ROUND_FLOOR),
(0.9999999999, (0, 999999999), _PyTime.ROUND_FLOOR),
(1.1234567890, (1, 123456789), _PyTime.ROUND_FLOOR),
(1.1234567899, (1, 123456789), _PyTime.ROUND_FLOOR),
(-1.1234567890, (-2, 876543211), _PyTime.ROUND_FLOOR),
(-1.1234567891, (-2, 876543210), _PyTime.ROUND_FLOOR),
# Round towards infinity (+inf)
(0, (0, 0), _PyTime.ROUND_CEILING),
(-1, (-1, 0), _PyTime.ROUND_CEILING),
(-1.0, (-1, 0), _PyTime.ROUND_CEILING),
(1e-9, (0, 1), _PyTime.ROUND_CEILING),
(1e-10, (0, 1), _PyTime.ROUND_CEILING),
(-1e-9, (-1, 999999999), _PyTime.ROUND_CEILING),
(-1e-10, (0, 0), _PyTime.ROUND_CEILING),
(-1.2, (-2, 800000000), _PyTime.ROUND_CEILING),
(0.9999999999, (1, 0), _PyTime.ROUND_CEILING),
(1.1234567890, (1, 123456790), _PyTime.ROUND_CEILING),
(1.1234567899, (1, 123456790), _PyTime.ROUND_CEILING),
(-1.1234567890, (-2, 876543211), _PyTime.ROUND_CEILING),
(-1.1234567891, (-2, 876543211), _PyTime.ROUND_CEILING),
):
with self.subTest(obj=obj, round=rnd, timespec=timespec):
self.assertEqual(pytime_object_to_timespec(obj, rnd), timespec)
rnd = _PyTime.ROUND_DOWN
rnd = _PyTime.ROUND_FLOOR
for invalid in self.invalid_values:
self.assertRaises(OverflowError,
pytime_object_to_timespec, invalid, rnd)
@ -791,33 +786,26 @@ class TestPyTime_t(unittest.TestCase):
PyTime_FromSecondsObject(-9223372037.0, rnd)
# Conversion giving different results depending on the rounding method
UP = _PyTime.ROUND_UP
DOWN = _PyTime.ROUND_DOWN
FLOOR = _PyTime.ROUND_FLOOR
CEILING = _PyTime.ROUND_CEILING
for obj, ts, rnd in (
# close to zero
( 1e-10, 1, UP),
( 1e-10, 0, DOWN),
( 1e-10, 0, FLOOR),
(-1e-10, 0, DOWN),
(-1e-10, -1, UP),
( 1e-10, 1, CEILING),
(-1e-10, -1, FLOOR),
(-1e-10, 0, CEILING),
# test rounding of the last nanosecond
( 1.1234567899, 1123456790, UP),
( 1.1234567899, 1123456789, DOWN),
( 1.1234567899, 1123456789, FLOOR),
(-1.1234567899, -1123456789, DOWN),
(-1.1234567899, -1123456790, UP),
( 1.1234567899, 1123456790, CEILING),
(-1.1234567899, -1123456790, FLOOR),
(-1.1234567899, -1123456789, CEILING),
# close to 1 second
( 0.9999999999, 1000000000, UP),
( 0.9999999999, 999999999, DOWN),
( 0.9999999999, 999999999, FLOOR),
(-0.9999999999, -999999999, DOWN),
(-0.9999999999, -1000000000, UP),
( 0.9999999999, 1000000000, CEILING),
(-0.9999999999, -1000000000, FLOOR),
(-0.9999999999, -999999999, CEILING),
):
with self.subTest(obj=obj, round=rnd, timestamp=ts):
self.assertEqual(PyTime_FromSecondsObject(obj, rnd), ts)
@ -887,25 +875,20 @@ class TestPyTime_t(unittest.TestCase):
with self.subTest(nanoseconds=ns, timeval=tv, round=rnd):
self.assertEqual(PyTime_AsTimeval(ns, rnd), tv)
UP = _PyTime.ROUND_UP
DOWN = _PyTime.ROUND_DOWN
FLOOR = _PyTime.ROUND_FLOOR
CEILING = _PyTime.ROUND_CEILING
for ns, tv, rnd in (
# nanoseconds
(1, (0, 1), UP),
(1, (0, 0), DOWN),
(1, (0, 0), FLOOR),
(-1, (0, 0), DOWN),
(-1, (-1, 999999), UP),
(1, (0, 1), CEILING),
(-1, (-1, 999999), FLOOR),
(-1, (0, 0), CEILING),
# seconds + nanoseconds
(1234567001, (1, 234568), UP),
(1234567001, (1, 234567), DOWN),
(1234567001, (1, 234567), FLOOR),
(-1234567001, (-2, 765433), DOWN),
(-1234567001, (-2, 765432), UP),
(1234567001, (1, 234568), CEILING),
(-1234567001, (-2, 765432), FLOOR),
(-1234567001, (-2, 765433), CEILING),
):
with self.subTest(nanoseconds=ns, timeval=tv, round=rnd):
self.assertEqual(PyTime_AsTimeval(ns, rnd), tv)

View File

@ -2,6 +2,32 @@
Python News
+++++++++++
What's New in Python 3.5.0 alpha 4?
===================================
Release date: XXX
Core and Builtins
-----------------
Library
-------
- Issue #23752: When built from an existing file descriptor, io.FileIO() now
only calls fstat() once. Before fstat() was called twice, which was not
necessary.
Build
-----
Tests
-----
Tools/Demos
-----------
What's New in Python 3.5.0 alpha 3?
===================================
@ -10,6 +36,9 @@ Release date: 2015-03-28
Core and Builtins
-----------------
- Issue #23466: %c, %o, %x, and %X in bytes formatting now raise TypeError on
non-integer input.
- Issue #23573: Increased performance of string search operations (str.find,
str.index, str.count, the in operator, str.split, str.partition) with
arguments of different kinds (UCS1, UCS2, UCS4).
@ -30,6 +59,14 @@ Core and Builtins
Library
-------
- Issue #23171: csv.Writer.writerow() now supports arbitrary iterables.
- Issue #23745: The new email header parser now handles duplicate MIME
parameter names without error, similar to how get_param behaves.
- Issue #22117: Fix os.utime(), it now rounds the timestamp towards minus
infinity (-inf) instead of rounding towards zero.
- Issue #14260: The groupindex attribute of regular expression pattern object
now is non-modifiable mapping.
@ -176,6 +213,9 @@ Build
Tests
-----
- Issue #22390: test.regrtest now emits a warning if temporary files or
directories are left after running a test.
- Issue #23583: Added tests for standard IO streams in IDLE.
- Issue #22289: Prevent test_urllib2net failures due to ftp connection timeout.

View File

@ -1009,7 +1009,7 @@ join_reset(WriterObj *self)
*/
static Py_ssize_t
join_append_data(WriterObj *self, unsigned int field_kind, void *field_data,
Py_ssize_t field_len, int quote_empty, int *quoted,
Py_ssize_t field_len, int *quoted,
int copy_phase)
{
DialectObj *dialect = self->dialect;
@ -1071,18 +1071,6 @@ join_append_data(WriterObj *self, unsigned int field_kind, void *field_data,
ADDCH(c);
}
/* If field is empty check if it needs to be quoted.
*/
if (i == 0 && quote_empty) {
if (dialect->quoting == QUOTE_NONE) {
PyErr_Format(_csvstate_global->error_obj,
"single empty field record must be quoted");
return -1;
}
else
*quoted = 1;
}
if (*quoted) {
if (copy_phase)
ADDCH(dialect->quotechar);
@ -1126,7 +1114,7 @@ join_check_rec_size(WriterObj *self, Py_ssize_t rec_len)
}
static int
join_append(WriterObj *self, PyObject *field, int *quoted, int quote_empty)
join_append(WriterObj *self, PyObject *field, int quoted)
{
unsigned int field_kind = -1;
void *field_data = NULL;
@ -1141,7 +1129,7 @@ join_append(WriterObj *self, PyObject *field, int *quoted, int quote_empty)
field_len = PyUnicode_GET_LENGTH(field);
}
rec_len = join_append_data(self, field_kind, field_data, field_len,
quote_empty, quoted, 0);
&quoted, 0);
if (rec_len < 0)
return 0;
@ -1150,7 +1138,7 @@ join_append(WriterObj *self, PyObject *field, int *quoted, int quote_empty)
return 0;
self->rec_len = join_append_data(self, field_kind, field_data, field_len,
quote_empty, quoted, 1);
&quoted, 1);
self->num_fields++;
return 1;
@ -1181,37 +1169,30 @@ join_append_lineterminator(WriterObj *self)
}
PyDoc_STRVAR(csv_writerow_doc,
"writerow(sequence)\n"
"writerow(iterable)\n"
"\n"
"Construct and write a CSV record from a sequence of fields. Non-string\n"
"Construct and write a CSV record from an iterable of fields. Non-string\n"
"elements will be converted to string.");
static PyObject *
csv_writerow(WriterObj *self, PyObject *seq)
{
DialectObj *dialect = self->dialect;
Py_ssize_t len, i;
PyObject *line, *result;
PyObject *iter, *field, *line, *result;
if (!PySequence_Check(seq))
return PyErr_Format(_csvstate_global->error_obj, "sequence expected");
len = PySequence_Length(seq);
if (len < 0)
return NULL;
iter = PyObject_GetIter(seq);
if (iter == NULL)
return PyErr_Format(_csvstate_global->error_obj,
"iterable expected, not %.200s",
seq->ob_type->tp_name);
/* Join all fields in internal buffer.
*/
join_reset(self);
for (i = 0; i < len; i++) {
PyObject *field;
while ((field = PyIter_Next(iter))) {
int append_ok;
int quoted;
field = PySequence_GetItem(seq, i);
if (field == NULL)
return NULL;
switch (dialect->quoting) {
case QUOTE_NONNUMERIC:
quoted = !PyNumber_Check(field);
@ -1225,11 +1206,11 @@ csv_writerow(WriterObj *self, PyObject *seq)
}
if (PyUnicode_Check(field)) {
append_ok = join_append(self, field, &quoted, len == 1);
append_ok = join_append(self, field, quoted);
Py_DECREF(field);
}
else if (field == Py_None) {
append_ok = join_append(self, NULL, &quoted, len == 1);
append_ok = join_append(self, NULL, quoted);
Py_DECREF(field);
}
else {
@ -1237,19 +1218,37 @@ csv_writerow(WriterObj *self, PyObject *seq)
str = PyObject_Str(field);
Py_DECREF(field);
if (str == NULL)
if (str == NULL) {
Py_DECREF(iter);
return NULL;
append_ok = join_append(self, str, &quoted, len == 1);
}
append_ok = join_append(self, str, quoted);
Py_DECREF(str);
}
if (!append_ok)
if (!append_ok) {
Py_DECREF(iter);
return NULL;
}
}
Py_DECREF(iter);
if (PyErr_Occurred())
return NULL;
if (self->num_fields > 0 && self->rec_size == 0) {
if (dialect->quoting == QUOTE_NONE) {
PyErr_Format(_csvstate_global->error_obj,
"single empty field record must be quoted");
return NULL;
}
self->num_fields--;
if (!join_append(self, NULL, 1))
return NULL;
}
/* Add line terminator.
*/
if (!join_append_lineterminator(self))
return 0;
return NULL;
line = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
(void *) self->rec, self->rec_len);
@ -1261,9 +1260,9 @@ csv_writerow(WriterObj *self, PyObject *seq)
}
PyDoc_STRVAR(csv_writerows_doc,
"writerows(sequence of sequences)\n"
"writerows(iterable of iterables)\n"
"\n"
"Construct and write a series of sequences to a csv file. Non-string\n"
"Construct and write a series of iterables to a csv file. Non-string\n"
"elements will be converted to string.");
static PyObject *

View File

@ -7,6 +7,10 @@
#include <time.h>
#ifdef MS_WINDOWS
# include <winsock2.h> /* struct timeval */
#endif
/* Differentiate between building the core module and building extension
* modules.
*/
@ -2459,7 +2463,7 @@ date_local_from_object(PyObject *cls, PyObject *obj)
struct tm *tm;
time_t t;
if (_PyTime_ObjectToTime_t(obj, &t, _PyTime_ROUND_DOWN) == -1)
if (_PyTime_ObjectToTime_t(obj, &t, _PyTime_ROUND_FLOOR) == -1)
return NULL;
tm = localtime(&t);
@ -4091,8 +4095,11 @@ datetime_from_timestamp(PyObject *cls, TM_FUNC f, PyObject *timestamp,
time_t timet;
long us;
if (_PyTime_ObjectToTimeval(timestamp, &timet, &us, _PyTime_ROUND_DOWN) == -1)
if (_PyTime_ObjectToTimeval(timestamp,
&timet, &us, _PyTime_ROUND_FLOOR) == -1)
return NULL;
assert(0 <= us && us <= 999999);
return datetime_from_timet_and_us(cls, f, timet, (int)us, tzinfo);
}
@ -4103,10 +4110,14 @@ datetime_from_timestamp(PyObject *cls, TM_FUNC f, PyObject *timestamp,
static PyObject *
datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
{
_PyTime_timeval t;
_PyTime_gettimeofday(&t);
return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec,
tzinfo);
_PyTime_t ts = _PyTime_GetSystemClock();
struct timeval tv;
if (_PyTime_AsTimeval(ts, &tv, _PyTime_ROUND_FLOOR) < 0)
return NULL;
assert(0 <= tv.tv_usec && tv.tv_usec <= 999999);
return datetime_from_timet_and_us(cls, f, tv.tv_sec, tv.tv_usec, tzinfo);
}
/*[clinic input]

View File

@ -177,28 +177,6 @@ fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return (PyObject *) self;
}
static int
check_fd(int fd)
{
struct _Py_stat_struct buf;
if (_Py_fstat(fd, &buf) < 0 &&
#ifdef MS_WINDOWS
GetLastError() == ERROR_INVALID_HANDLE
#else
errno == EBADF
#endif
) {
PyObject *exc;
char *msg = strerror(EBADF);
exc = PyObject_CallFunction(PyExc_OSError, "(is)",
EBADF, msg);
PyErr_SetObject(PyExc_OSError, exc);
Py_XDECREF(exc);
return -1;
}
return 0;
}
#ifdef O_CLOEXEC
extern int _Py_open_cloexec_works;
#endif
@ -355,8 +333,6 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
#endif
if (fd >= 0) {
if (check_fd(fd))
goto error;
self->fd = fd;
self->closefd = closefd;
}
@ -423,10 +399,8 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
}
self->blksize = DEFAULT_BUFFER_SIZE;
if (_Py_fstat(self->fd, &fdfstat) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
if (_Py_fstat(self->fd, &fdfstat) < 0)
goto error;
}
#if defined(S_ISDIR) && defined(EISDIR)
/* On Unix, open will succeed for directories.
In Python, there should be no file objects referring to
@ -613,7 +587,7 @@ new_buffersize(fileio *self, size_t currentsize)
static PyObject *
fileio_readall(fileio *self)
{
struct _Py_stat_struct st;
struct _Py_stat_struct status;
Py_off_t pos, end;
PyObject *result;
Py_ssize_t bytes_read = 0;
@ -630,8 +604,8 @@ fileio_readall(fileio *self)
#else
pos = lseek(self->fd, 0L, SEEK_CUR);
#endif
if (_Py_fstat(self->fd, &st) == 0)
end = st.st_size;
if (_Py_fstat_noraise(self->fd, &status) == 0)
end = status.st_size;
else
end = (Py_off_t)-1;

View File

@ -2441,14 +2441,10 @@ fail:
if (saved_state) {
PyObject *type, *value, *traceback;
PyErr_Fetch(&type, &value, &traceback);
res = _PyObject_CallMethodId(self->decoder, &PyId_setstate, "(O)", saved_state);
_PyErr_ChainExceptions(type, value, traceback);
Py_DECREF(saved_state);
if (res == NULL)
return NULL;
Py_DECREF(res);
PyErr_Restore(type, value, traceback);
Py_XDECREF(res);
}
return NULL;
}

View File

@ -254,10 +254,9 @@ _close_open_fds_safe(int start_fd, PyObject* py_fds_to_keep)
{
int fd_dir_fd;
fd_dir_fd = _Py_open(FD_DIR, O_RDONLY);
fd_dir_fd = _Py_open_noraise(FD_DIR, O_RDONLY);
if (fd_dir_fd == -1) {
/* No way to get a list of open fds. */
PyErr_Clear();
_close_fds_by_brute_force(start_fd, py_fds_to_keep);
return;
} else {

View File

@ -1637,7 +1637,7 @@ check_socket_and_wait_for_timeout(PySocketSockObject *s, int writing)
/* s->sock_timeout is in seconds, timeout in ms */
timeout = (int)_PyTime_AsMilliseconds(s->sock_timeout,
_PyTime_ROUND_UP);
_PyTime_ROUND_CEILING);
PySSL_BEGIN_ALLOW_THREADS
rc = poll(&pollfd, 1, timeout);
@ -1651,9 +1651,7 @@ check_socket_and_wait_for_timeout(PySocketSockObject *s, int writing)
if (!_PyIsSelectable_fd(s->sock_fd))
return SOCKET_TOO_LARGE_FOR_SELECT;
/* conversion was already checked for overflow when
the timeout was set */
(void)_PyTime_AsTimeval(s->sock_timeout, &tv, _PyTime_ROUND_UP);
_PyTime_AsTimeval_noraise(s->sock_timeout, &tv, _PyTime_ROUND_CEILING);
FD_ZERO(&fds);
FD_SET(s->sock_fd, &fds);

View File

@ -15,7 +15,7 @@
#include <signal.h>
#ifdef MS_WINDOWS
# include <winsock2.h>
# include <winsock2.h> /* struct timeval */
#endif
#ifdef WITH_THREAD
@ -2634,8 +2634,7 @@ run_in_subinterp(PyObject *self, PyObject *args)
static int
check_time_rounding(int round)
{
if (round != _PyTime_ROUND_DOWN && round != _PyTime_ROUND_UP
&& round != _PyTime_ROUND_FLOOR) {
if (round != _PyTime_ROUND_FLOOR && round != _PyTime_ROUND_CEILING) {
PyErr_SetString(PyExc_ValueError, "invalid rounding");
return -1;
}
@ -3427,11 +3426,8 @@ test_PyTime_AsTimeval(PyObject *self, PyObject *args)
if (check_time_rounding(round) < 0)
return NULL;
t = _PyTime_FromNanoseconds(ns);
if (_PyTime_AsTimeval(t, &tv, round) < 0) {
PyErr_SetString(PyExc_OverflowError,
"timeout doesn't fit into C timeval");
if (_PyTime_AsTimeval(t, &tv, round) < 0)
return NULL;
}
seconds = PyLong_FromLong((PY_LONG_LONG)tv.tv_sec);
if (seconds == NULL)

View File

@ -59,7 +59,7 @@ acquire_timed(PyThread_type_lock lock, _PyTime_t timeout)
endtime = _PyTime_GetMonotonicClock() + timeout;
do {
microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_UP);
microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_CEILING);
/* first a simple non-blocking try without releasing the GIL */
r = PyThread_acquire_lock_timed(lock, 0, 0);
@ -110,7 +110,8 @@ lock_acquire_parse_args(PyObject *args, PyObject *kwds,
return -1;
if (timeout_obj
&& _PyTime_FromSecondsObject(timeout, timeout_obj, _PyTime_ROUND_UP) < 0)
&& _PyTime_FromSecondsObject(timeout,
timeout_obj, _PyTime_ROUND_CEILING) < 0)
return -1;
if (!blocking && *timeout != unset_timeout ) {
@ -128,7 +129,7 @@ lock_acquire_parse_args(PyObject *args, PyObject *kwds,
else if (*timeout != unset_timeout) {
_PyTime_t microseconds;
microseconds = _PyTime_AsMicroseconds(*timeout, _PyTime_ROUND_UP);
microseconds = _PyTime_AsMicroseconds(*timeout, _PyTime_ROUND_CEILING);
if (microseconds >= PY_TIMEOUT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"timeout value is too large");

View File

@ -753,9 +753,11 @@ Py_Main(int argc, wchar_t **argv)
}
{
struct _Py_stat_struct sb;
if (_Py_fstat(fileno(fp), &sb) == 0 &&
if (_Py_fstat_noraise(fileno(fp), &sb) == 0 &&
S_ISDIR(sb.st_mode)) {
fprintf(stderr, "%ls: '%ls' is a directory, cannot continue\n", argv[0], filename);
fprintf(stderr,
"%ls: '%ls' is a directory, cannot continue\n",
argv[0], filename);
fclose(fp);
return 1;
}

View File

@ -465,15 +465,13 @@ mmap_size_method(mmap_object *self,
#ifdef UNIX
{
struct _Py_stat_struct buf;
if (-1 == _Py_fstat(self->fd, &buf)) {
PyErr_SetFromErrno(PyExc_OSError);
struct _Py_stat_struct status;
if (_Py_fstat(self->fd, &status) == -1)
return NULL;
}
#ifdef HAVE_LARGEFILE_SUPPORT
return PyLong_FromLongLong(buf.st_size);
return PyLong_FromLongLong(status.st_size);
#else
return PyLong_FromLong(buf.st_size);
return PyLong_FromLong(status.st_size);
#endif
}
#endif /* UNIX */
@ -1112,7 +1110,7 @@ _GetMapSize(PyObject *o, const char* param)
static PyObject *
new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
{
struct _Py_stat_struct st;
struct _Py_stat_struct status;
mmap_object *m_obj;
PyObject *map_size_obj = NULL;
Py_ssize_t map_size;
@ -1177,25 +1175,26 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
if (fd != -1)
(void)fcntl(fd, F_FULLFSYNC);
#endif
if (fd != -1 && _Py_fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
if (fd != -1 && _Py_fstat_noraise(fd, &status) == 0
&& S_ISREG(status.st_mode)) {
if (map_size == 0) {
if (st.st_size == 0) {
if (status.st_size == 0) {
PyErr_SetString(PyExc_ValueError,
"cannot mmap an empty file");
return NULL;
}
if (offset >= st.st_size) {
if (offset >= status.st_size) {
PyErr_SetString(PyExc_ValueError,
"mmap offset is greater than file size");
return NULL;
}
if (st.st_size - offset > PY_SSIZE_T_MAX) {
if (status.st_size - offset > PY_SSIZE_T_MAX) {
PyErr_SetString(PyExc_ValueError,
"mmap length is too large");
return NULL;
}
map_size = (Py_ssize_t) (st.st_size - offset);
} else if (offset + map_size > st.st_size) {
map_size = (Py_ssize_t) (status.st_size - offset);
} else if (offset + map_size > status.st_size) {
PyErr_SetString(PyExc_ValueError,
"mmap length is greater than file size");
return NULL;

View File

@ -351,7 +351,7 @@ static int win32_can_symlink = 0;
#ifdef MS_WINDOWS
# define STAT win32_stat
# define LSTAT win32_lstat
# define FSTAT _Py_fstat
# define FSTAT _Py_fstat_noraise
# define STRUCT_STAT struct _Py_stat_struct
#else
# define STAT stat
@ -6127,9 +6127,9 @@ os_utime_impl(PyModuleDef *module, path_t *path, PyObject *times, PyObject *ns,
}
utime.now = 0;
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
&a_sec, &a_nsec, _PyTime_ROUND_DOWN) == -1 ||
&a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
&m_sec, &m_nsec, _PyTime_ROUND_DOWN) == -1) {
&m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
goto exit;
}
utime.atime_s = a_sec;

View File

@ -209,13 +209,13 @@ select_select(PyObject *self, PyObject *args)
else {
_PyTime_t ts;
if (_PyTime_FromSecondsObject(&ts, tout, _PyTime_ROUND_UP) < 0) {
if (_PyTime_FromSecondsObject(&ts, tout, _PyTime_ROUND_CEILING) < 0) {
PyErr_SetString(PyExc_TypeError,
"timeout must be a float or None");
return NULL;
}
if (_PyTime_AsTimeval(ts, &tv, _PyTime_ROUND_UP) == -1)
if (_PyTime_AsTimeval(ts, &tv, _PyTime_ROUND_CEILING) == -1)
return NULL;
if (tv.tv_sec < 0) {
PyErr_SetString(PyExc_ValueError, "timeout must be non-negative");
@ -2014,7 +2014,8 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args)
else {
_PyTime_t ts;
if (_PyTime_FromSecondsObject(&ts, otimeout, _PyTime_ROUND_UP) < 0) {
if (_PyTime_FromSecondsObject(&ts,
otimeout, _PyTime_ROUND_CEILING) < 0) {
PyErr_Format(PyExc_TypeError,
"timeout argument must be an number "
"or None, got %.200s",

View File

@ -503,7 +503,7 @@ signal_siginterrupt(PyObject *self, PyObject *args)
static PyObject *
signal_set_wakeup_fd(PyObject *self, PyObject *args)
{
struct _Py_stat_struct st;
struct _Py_stat_struct status;
#ifdef MS_WINDOWS
PyObject *fdobj;
SOCKET_T sockfd, old_sockfd;
@ -559,10 +559,8 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args)
return NULL;
}
if (_Py_fstat(fd, &st) != 0) {
PyErr_SetExcFromWindowsErr(PyExc_OSError, GetLastError());
if (_Py_fstat(fd, &status) != 0)
return NULL;
}
/* on Windows, a file cannot be set to non-blocking mode */
}
@ -591,10 +589,8 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args)
return NULL;
}
if (_Py_fstat(fd, &st) != 0) {
PyErr_SetFromErrno(PyExc_OSError);
if (_Py_fstat(fd, &status) != 0)
return NULL;
}
blocking = _Py_get_blocking(fd);
if (blocking < 0)
@ -977,7 +973,8 @@ signal_sigtimedwait(PyObject *self, PyObject *args)
&signals, &timeout_obj))
return NULL;
if (_PyTime_FromSecondsObject(&timeout, timeout_obj, _PyTime_ROUND_UP) < 0)
if (_PyTime_FromSecondsObject(&timeout,
timeout_obj, _PyTime_ROUND_CEILING) < 0)
return NULL;
if (timeout < 0) {

View File

@ -633,7 +633,7 @@ internal_select_ex(PySocketSockObject *s, int writing, _PyTime_t interval)
pollfd.events = writing ? POLLOUT : POLLIN;
/* s->sock_timeout is in seconds, timeout in ms */
timeout = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_UP);
timeout = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING);
assert(timeout <= INT_MAX);
timeout_int = (int)timeout;
@ -641,9 +641,7 @@ internal_select_ex(PySocketSockObject *s, int writing, _PyTime_t interval)
n = poll(&pollfd, 1, timeout_int);
Py_END_ALLOW_THREADS;
#else
/* conversion was already checked for overflow when
the timeout was set */
(void)_PyTime_AsTimeval(interval, &tv, _PyTime_ROUND_UP);
_PyTime_AsTimeval_noraise(interval, &tv, _PyTime_ROUND_CEILING);
FD_ZERO(&fds);
FD_SET(s->sock_fd, &fds);
@ -2193,7 +2191,8 @@ socket_parse_timeout(_PyTime_t *timeout, PyObject *timeout_obj)
return 0;
}
if (_PyTime_FromSecondsObject(timeout, timeout_obj, _PyTime_ROUND_UP) < 0)
if (_PyTime_FromSecondsObject(timeout,
timeout_obj, _PyTime_ROUND_CEILING) < 0)
return -1;
if (*timeout < 0) {
@ -2202,10 +2201,10 @@ socket_parse_timeout(_PyTime_t *timeout, PyObject *timeout_obj)
}
#ifdef MS_WINDOWS
overflow = (_PyTime_AsTimeval(timeout, &tv, _PyTime_ROUND_UP) < 0);
overflow = (_PyTime_AsTimeval(timeout, &tv, _PyTime_ROUND_CEILING) < 0);
#endif
#ifndef HAVE_POLL
timeout = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_UP);
timeout = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING);
overflow = (timeout > INT_MAX);
#endif
if (overflow) {
@ -2454,9 +2453,7 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
struct timeval tv;
int conv;
/* conversion was already checked for overflow when
the timeout was set */
(void)_PyTime_AsTimeval(s->sock_timeout, &tv, _PyTime_ROUND_UP);
_PyTime_AsTimeval_noraise(s->sock_timeout, &tv, _PyTime_ROUND_CEILING);
Py_BEGIN_ALLOW_THREADS
FD_ZERO(&fds);

View File

@ -221,7 +221,7 @@ static PyObject *
time_sleep(PyObject *self, PyObject *obj)
{
_PyTime_t secs;
if (_PyTime_FromSecondsObject(&secs, obj, _PyTime_ROUND_UP))
if (_PyTime_FromSecondsObject(&secs, obj, _PyTime_ROUND_CEILING))
return NULL;
if (secs < 0) {
PyErr_SetString(PyExc_ValueError,
@ -1405,11 +1405,8 @@ pysleep(_PyTime_t secs)
do {
#ifndef MS_WINDOWS
if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_UP) < 0) {
PyErr_SetString(PyExc_OverflowError,
"delay doesn't fit into C timeval");
if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0)
return -1;
}
Py_BEGIN_ALLOW_THREADS
err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout);
@ -1423,7 +1420,7 @@ pysleep(_PyTime_t secs)
return -1;
}
#else
millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_UP);
millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING);
if (millisecs > (double)ULONG_MAX) {
PyErr_SetString(PyExc_OverflowError,
"sleep length is too large");

View File

@ -433,7 +433,41 @@ formatfloat(PyObject *v, int flags, int prec, int type)
return result;
}
Py_LOCAL_INLINE(int)
static PyObject *
formatlong(PyObject *v, int flags, int prec, int type)
{
PyObject *result, *iobj;
if (type == 'i')
type = 'd';
if (PyLong_Check(v))
return _PyUnicode_FormatLong(v, flags & F_ALT, prec, type);
if (PyNumber_Check(v)) {
/* make sure number is a type of integer for o, x, and X */
if (type == 'o' || type == 'x' || type == 'X')
iobj = PyNumber_Index(v);
else
iobj = PyNumber_Long(v);
if (iobj == NULL) {
if (!PyErr_ExceptionMatches(PyExc_TypeError))
return NULL;
}
else if (!PyLong_Check(iobj))
Py_CLEAR(iobj);
if (iobj != NULL) {
result = _PyUnicode_FormatLong(iobj, flags & F_ALT, prec, type);
Py_DECREF(iobj);
return result;
}
}
PyErr_Format(PyExc_TypeError,
"%%%c format: %s is required, not %.200s", type,
(type == 'o' || type == 'x' || type == 'X') ? "an integer"
: "a number",
Py_TYPE(v)->tp_name);
return NULL;
}
static int
byte_converter(PyObject *arg, char *p)
{
if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1) {
@ -445,12 +479,29 @@ byte_converter(PyObject *arg, char *p)
return 1;
}
else {
long ival = PyLong_AsLong(arg);
if (0 <= ival && ival <= 255) {
PyObject *iobj;
long ival;
int overflow;
/* make sure number is a type of integer */
if (PyLong_Check(arg)) {
ival = PyLong_AsLongAndOverflow(arg, &overflow);
}
else {
iobj = PyNumber_Index(arg);
if (iobj == NULL) {
if (!PyErr_ExceptionMatches(PyExc_TypeError))
return 0;
goto onError;
}
ival = PyLong_AsLongAndOverflow(iobj, &overflow);
Py_DECREF(iobj);
}
if (!overflow && 0 <= ival && ival <= 255) {
*p = (char)ival;
return 1;
}
}
onError:
PyErr_SetString(PyExc_TypeError,
"%c requires an integer in range(256) or a single byte");
return 0;
@ -561,7 +612,6 @@ _PyBytes_Format(PyObject *format, PyObject *args)
int prec = -1;
int c = '\0';
int fill;
PyObject *iobj;
PyObject *v = NULL;
PyObject *temp = NULL;
const char *pbuf = NULL;
@ -747,28 +797,7 @@ _PyBytes_Format(PyObject *format, PyObject *args)
case 'o':
case 'x':
case 'X':
if (c == 'i')
c = 'd';
iobj = NULL;
if (PyNumber_Check(v)) {
if ((PyLong_Check(v))) {
iobj = v;
Py_INCREF(iobj);
}
else {
iobj = PyNumber_Long(v);
if (iobj != NULL && !PyLong_Check(iobj))
Py_CLEAR(iobj);
}
}
if (iobj == NULL) {
PyErr_Format(PyExc_TypeError,
"%%%c format: a number is required, "
"not %.200s", c, Py_TYPE(v)->tp_name);
goto error;
}
temp = _PyUnicode_FormatLong(iobj, flags & F_ALT, prec, c);
Py_DECREF(iobj);
temp = formatlong(v, flags, prec, c);
if (!temp)
goto error;
assert(PyUnicode_IS_ASCII(temp));

View File

@ -900,11 +900,9 @@ PyObject_ClearWeakRefs(PyObject *object)
if (*list != NULL) {
PyWeakReference *current = *list;
Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
int restore_error = PyErr_Occurred() ? 1 : 0;
PyObject *err_type, *err_value, *err_tb;
if (restore_error)
PyErr_Fetch(&err_type, &err_value, &err_tb);
PyErr_Fetch(&err_type, &err_value, &err_tb);
if (count == 1) {
PyObject *callback = current->wr_callback;
@ -922,8 +920,7 @@ PyObject_ClearWeakRefs(PyObject *object)
tuple = PyTuple_New(count * 2);
if (tuple == NULL) {
if (restore_error)
PyErr_Fetch(&err_type, &err_value, &err_tb);
_PyErr_ChainExceptions(err_type, err_value, err_tb);
return;
}
@ -954,7 +951,7 @@ PyObject_ClearWeakRefs(PyObject *object)
}
Py_DECREF(tuple);
}
if (restore_error)
PyErr_Restore(err_type, err_value, err_tb);
assert(!PyErr_Occurred());
PyErr_Restore(err_type, err_value, err_tb);
}
}

View File

@ -35,7 +35,7 @@ main(int argc, char *argv[])
{
char *inpath, *outpath;
FILE *infile = NULL, *outfile = NULL;
struct _Py_stat_struct st;
struct _Py_stat_struct status;
size_t text_size, data_size, n;
char *text = NULL;
unsigned char *data;
@ -54,11 +54,11 @@ main(int argc, char *argv[])
fprintf(stderr, "cannot open '%s' for reading\n", inpath);
goto error;
}
if (_Py_fstat(fileno(infile), &st)) {
if (_Py_fstat_noraise(fileno(infile), &status)) {
fprintf(stderr, "cannot fstat '%s'\n", inpath);
goto error;
}
text_size = st.st_size;
text_size = status.st_size;
text = (char *) malloc(text_size + 1);
if (text == NULL) {
fprintf(stderr, "could not allocate %ld bytes\n", (long) text_size);

View File

@ -71,22 +71,20 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname,
if (fp != NULL) {
int i;
struct _Py_stat_struct statb;
if (_Py_fstat(fileno(fp), &statb) == -1) {
PyErr_SetFromErrno(PyExc_IOError);
struct _Py_stat_struct status;
if (_Py_fstat(fileno(fp), &status) == -1)
return NULL;
}
for (i = 0; i < nhandles; i++) {
if (statb.st_dev == handles[i].dev &&
statb.st_ino == handles[i].ino) {
if (status.st_dev == handles[i].dev &&
status.st_ino == handles[i].ino) {
p = (dl_funcptr) dlsym(handles[i].handle,
funcname);
return p;
}
}
if (nhandles < 128) {
handles[nhandles].dev = statb.st_dev;
handles[nhandles].ino = statb.st_ino;
handles[nhandles].dev = status.st_dev;
handles[nhandles].ino = status.st_ino;
}
}

View File

@ -565,7 +565,8 @@ attributes_to_mode(DWORD attr)
}
void
_Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag, struct _Py_stat_struct *result)
_Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag,
struct _Py_stat_struct *result)
{
memset(result, 0, sizeof(*result));
result->st_mode = attributes_to_mode(info->dwFileAttributes);
@ -595,9 +596,12 @@ _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag,
files larger than 2 GB. fstat() may fail with EOVERFLOW on files larger
than 2 GB because the file size type is an signed 32-bit integer: see issue
#23152.
*/
On Windows, set the last Windows error and return nonzero on error. On
POSIX, set errno and return nonzero on error. Fill status and return 0 on
success. */
int
_Py_fstat(int fd, struct _Py_stat_struct *result)
_Py_fstat_noraise(int fd, struct _Py_stat_struct *status)
{
#ifdef MS_WINDOWS
BY_HANDLE_FILE_INFORMATION info;
@ -619,22 +623,21 @@ _Py_fstat(int fd, struct _Py_stat_struct *result)
SetLastError(ERROR_INVALID_HANDLE);
return -1;
}
memset(result, 0, sizeof(*result));
memset(status, 0, sizeof(*status));
type = GetFileType(h);
if (type == FILE_TYPE_UNKNOWN) {
DWORD error = GetLastError();
if (error != 0) {
if (error != 0)
return -1;
}
/* else: valid but unknown file */
}
if (type != FILE_TYPE_DISK) {
if (type == FILE_TYPE_CHAR)
result->st_mode = _S_IFCHR;
status->st_mode = _S_IFCHR;
else if (type == FILE_TYPE_PIPE)
result->st_mode = _S_IFIFO;
status->st_mode = _S_IFIFO;
return 0;
}
@ -642,15 +645,48 @@ _Py_fstat(int fd, struct _Py_stat_struct *result)
return -1;
}
_Py_attribute_data_to_stat(&info, 0, result);
_Py_attribute_data_to_stat(&info, 0, status);
/* specific to fstat() */
result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
status->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
return 0;
#else
return fstat(fd, result);
return fstat(fd, status);
#endif
}
/* Return information about a file.
On POSIX, use fstat().
On Windows, use GetFileType() and GetFileInformationByHandle() which support
files larger than 2 GB. fstat() may fail with EOVERFLOW on files larger
than 2 GB because the file size type is an signed 32-bit integer: see issue
#23152.
Raise an exception and return -1 on error. On Windows, set the last Windows
error on error. On POSIX, set errno on error. Fill status and return 0 on
success.
The GIL must be held. */
int
_Py_fstat(int fd, struct _Py_stat_struct *status)
{
int res;
Py_BEGIN_ALLOW_THREADS
res = _Py_fstat_noraise(fd, status);
Py_END_ALLOW_THREADS
if (res != 0) {
#ifdef MS_WINDOWS
PyErr_SetFromWindowsErr(0);
#else
PyErr_SetFromErrno(PyExc_OSError);
#endif
return -1;
}
return 0;
}
/* Call _wstat() on Windows, or encode the path to the filesystem encoding and
call stat() otherwise. Only fill st_mode attribute on Windows.

View File

@ -1486,7 +1486,7 @@ static off_t
getfilesize(FILE *fp)
{
struct _Py_stat_struct st;
if (_Py_fstat(fileno(fp), &st) != 0)
if (_Py_fstat_noraise(fileno(fp), &st) != 0)
return -1;
#if SIZEOF_OFF_T == 4
else if (st.st_size >= INT_MAX)

View File

@ -19,106 +19,6 @@
#define MS_TO_NS (MS_TO_US * US_TO_NS)
#define SEC_TO_NS (SEC_TO_MS * MS_TO_NS)
static int
pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info, int raise)
{
#ifdef MS_WINDOWS
FILETIME system_time;
ULARGE_INTEGER large;
ULONGLONG microseconds;
assert(info == NULL || raise);
GetSystemTimeAsFileTime(&system_time);
large.u.LowPart = system_time.dwLowDateTime;
large.u.HighPart = system_time.dwHighDateTime;
/* 11,644,473,600,000,000: number of microseconds between
the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
days). */
microseconds = large.QuadPart / 10 - 11644473600000000;
tp->tv_sec = microseconds / SEC_TO_US;
tp->tv_usec = microseconds % SEC_TO_US;
if (info) {
DWORD timeAdjustment, timeIncrement;
BOOL isTimeAdjustmentDisabled, ok;
info->implementation = "GetSystemTimeAsFileTime()";
info->monotonic = 0;
ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
&isTimeAdjustmentDisabled);
if (!ok) {
PyErr_SetFromWindowsErr(0);
return -1;
}
info->resolution = timeIncrement * 1e-7;
info->adjustable = 1;
}
#else /* MS_WINDOWS */
int err;
#ifdef HAVE_CLOCK_GETTIME
struct timespec ts;
#endif
assert(info == NULL || raise);
#ifdef HAVE_CLOCK_GETTIME
err = clock_gettime(CLOCK_REALTIME, &ts);
if (err) {
if (raise)
PyErr_SetFromErrno(PyExc_OSError);
return -1;
}
tp->tv_sec = ts.tv_sec;
tp->tv_usec = ts.tv_nsec / US_TO_NS;
if (info) {
struct timespec res;
info->implementation = "clock_gettime(CLOCK_REALTIME)";
info->monotonic = 0;
info->adjustable = 1;
if (clock_getres(CLOCK_REALTIME, &res) == 0)
info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
else
info->resolution = 1e-9;
}
#else /* HAVE_CLOCK_GETTIME */
/* test gettimeofday() */
#ifdef GETTIMEOFDAY_NO_TZ
err = gettimeofday(tp);
#else
err = gettimeofday(tp, (struct timezone *)NULL);
#endif
if (err) {
if (raise)
PyErr_SetFromErrno(PyExc_OSError);
return -1;
}
if (info) {
info->implementation = "gettimeofday()";
info->resolution = 1e-6;
info->monotonic = 0;
info->adjustable = 1;
}
#endif /* !HAVE_CLOCK_GETTIME */
#endif /* !MS_WINDOWS */
assert(0 <= tp->tv_usec && tp->tv_usec < SEC_TO_US);
return 0;
}
void
_PyTime_gettimeofday(_PyTime_timeval *tp)
{
if (pygettimeofday(tp, NULL, 0) < 0) {
/* cannot happen, _PyTime_Init() checks that pygettimeofday() works */
assert(0);
tp->tv_sec = 0;
tp->tv_usec = 0;
}
}
static void
error_time_t_overflow(void)
{
@ -174,18 +74,16 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
}
floatpart *= denominator;
if (round == _PyTime_ROUND_UP) {
if (intpart >= 0) {
floatpart = ceil(floatpart);
if (floatpart >= denominator) {
floatpart = 0.0;
intpart += 1.0;
}
}
else {
floatpart = floor(floatpart);
if (round == _PyTime_ROUND_CEILING) {
floatpart = ceil(floatpart);
if (floatpart >= denominator) {
floatpart = 0.0;
intpart += 1.0;
}
}
else {
floatpart = floor(floatpart);
}
*sec = (time_t)intpart;
err = intpart - (double)*sec;
@ -213,12 +111,10 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
double d, intpart, err;
d = PyFloat_AsDouble(obj);
if (round == _PyTime_ROUND_UP) {
if (d >= 0)
d = ceil(d);
else
d = floor(d);
}
if (round == _PyTime_ROUND_CEILING)
d = ceil(d);
else
d = floor(d);
(void)modf(d, &intpart);
*sec = (time_t)intpart;
@ -251,8 +147,6 @@ _PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
}
/****************** NEW _PyTime_t API **********************/
static void
_PyTime_overflow(void)
{
@ -260,14 +154,6 @@ _PyTime_overflow(void)
"timestamp too large to convert to C _PyTime_t");
}
int
_PyTime_RoundTowardsInfinity(int is_neg, _PyTime_round_t round)
{
if (round == _PyTime_ROUND_FLOOR)
return 0;
return ((round == _PyTime_ROUND_UP) ^ is_neg);
}
_PyTime_t
_PyTime_FromNanoseconds(PY_LONG_LONG ns)
{
@ -296,7 +182,7 @@ _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts, int raise)
*tp = t;
return res;
}
#else
#elif !defined(MS_WINDOWS)
static int
_PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise)
{
@ -321,13 +207,14 @@ int
_PyTime_FromSecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round)
{
if (PyFloat_Check(obj)) {
double d, err;
/* volatile avoids unsafe optimization on float enabled by gcc -O3 */
volatile double d, err;
/* convert to a number of nanoseconds */
d = PyFloat_AsDouble(obj);
d *= 1e9;
if (_PyTime_RoundTowardsInfinity(d < 0, round))
if (round == _PyTime_ROUND_CEILING)
d = ceil(d);
else
d = floor(d);
@ -393,7 +280,7 @@ _PyTime_Multiply(_PyTime_t t, unsigned int multiply, _PyTime_round_t round)
_PyTime_t k;
if (multiply < SEC_TO_NS) {
k = SEC_TO_NS / multiply;
if (_PyTime_RoundTowardsInfinity(t < 0, round))
if (round == _PyTime_ROUND_CEILING)
return (t + k - 1) / k;
else
return t / k;
@ -417,8 +304,9 @@ _PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round)
return _PyTime_Multiply(t, 1000 * 1000, round);
}
int
_PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
static int
_PyTime_AsTimeval_impl(_PyTime_t t, struct timeval *tv, _PyTime_round_t round,
int raise)
{
_PyTime_t secs, ns;
int res = 0;
@ -453,7 +341,7 @@ _PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
res = -1;
#endif
if (_PyTime_RoundTowardsInfinity(tv->tv_sec < 0, round))
if (round == _PyTime_ROUND_CEILING)
tv->tv_usec = (int)((ns + US_TO_NS - 1) / US_TO_NS);
else
tv->tv_usec = (int)(ns / US_TO_NS);
@ -463,9 +351,25 @@ _PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
tv->tv_sec += 1;
}
if (res && raise)
_PyTime_overflow();
assert(0 <= tv->tv_usec && tv->tv_usec <= 999999);
return res;
}
int
_PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
{
return _PyTime_AsTimeval_impl(t, tv, round, 1);
}
int
_PyTime_AsTimeval_noraise(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
{
return _PyTime_AsTimeval_impl(t, tv, round, 0);
}
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE)
int
_PyTime_AsTimespec(_PyTime_t t, struct timespec *ts)
@ -484,6 +388,8 @@ _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts)
return -1;
}
ts->tv_nsec = nsec;
assert(0 <= ts->tv_nsec && ts->tv_nsec <= 999999999);
return 0;
}
#endif
@ -577,6 +483,20 @@ pygettimeofday_new(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
return 0;
}
_PyTime_t
_PyTime_GetSystemClock(void)
{
_PyTime_t t;
if (pygettimeofday_new(&t, NULL, 0) < 0) {
/* should not happen, _PyTime_Init() checked the clock at startup */
assert(0);
/* use a fixed value instead of a random value from the stack */
t = 0;
}
return t;
}
int
_PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
{
@ -715,13 +635,8 @@ _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
int
_PyTime_Init(void)
{
_PyTime_timeval tv;
_PyTime_t t;
/* ensure that the system clock works */
if (pygettimeofday(&tv, NULL, 1) < 0)
return -1;
/* ensure that the system clock works */
if (_PyTime_GetSystemClockWithInfo(&t, NULL) < 0)
return -1;

View File

@ -221,7 +221,7 @@ dev_urandom_python(char *buffer, Py_ssize_t size)
if (urandom_cache.fd >= 0) {
/* Does the fd point to the same thing as before? (issue #21207) */
if (_Py_fstat(urandom_cache.fd, &st)
if (_Py_fstat_noraise(urandom_cache.fd, &st)
|| st.st_dev != urandom_cache.st_dev
|| st.st_ino != urandom_cache.st_ino) {
/* Something changed: forget the cached fd (but don't close it,
@ -250,7 +250,6 @@ dev_urandom_python(char *buffer, Py_ssize_t size)
}
else {
if (_Py_fstat(fd, &st)) {
PyErr_SetFromErrno(PyExc_OSError);
close(fd);
return -1;
}

View File

@ -1690,7 +1690,7 @@ _PySys_Init(void)
#if !defined(MS_WINDOWS)
{
struct _Py_stat_struct sb;
if (_Py_fstat(fileno(stdin), &sb) == 0 &&
if (_Py_fstat_noraise(fileno(stdin), &sb) == 0 &&
S_ISDIR(sb.st_mode)) {
/* There's nothing more we can do. */
/* Py_FatalError() will core dump, so just exit. */