Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions Doc/c-api/long.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.

Return a new :c:type:`PyLongObject` object from *v*, or ``NULL`` on failure.

The current implementation keeps an array of integer objects for all integers
between ``-5`` and ``256``. When you create an int in that range you actually
just get back a reference to the existing object.
.. impl-detail::

CPython keeps an array of integer objects for all integers
between ``-5`` and ``256``. When you create an int in that range
you actually just get back a reference to the existing object.


.. c:function:: PyObject* PyLong_FromUnsignedLong(unsigned long v)
Expand Down
8 changes: 8 additions & 0 deletions Doc/library/getpass.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ The :mod:`getpass` module provides two functions:
If you call getpass from within IDLE, the input may be done in the
terminal you launched IDLE from rather than the idle window itself.

.. note::
On Unix systems, when *echo_char* is set, the terminal will be
configured to operate in
:manpage:`noncanonical mode <termios(3)#Canonical_and_noncanonical_mode>`.
In particular, this means that line editing shortcuts such as
:kbd:`Ctrl+U` will not work and may insert unexpected characters into
the input.

.. versionchanged:: 3.14
Added the *echo_char* parameter for keyboard feedback.

Expand Down
12 changes: 9 additions & 3 deletions Lib/test/test_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -1064,9 +1064,15 @@ def test_large_time(self):
if self.get_file_system(self.dirname) != "NTFS":
self.skipTest("requires NTFS")

large = 5000000000 # some day in 2128
os.utime(self.fname, (large, large))
self.assertEqual(os.stat(self.fname).st_mtime, large)
times = (
5000000000, # some day in 2128
# boundaries of the fast path cutoff in posixmodule.c:fill_time
-9223372037, -9223372036, 9223372035, 9223372036,
)
for large in times:
with self.subTest(large=large):
os.utime(self.fname, (large, large))
self.assertEqual(os.stat(self.fname).st_mtime, large)

def test_utime_invalid_arguments(self):
# seconds and nanoseconds parameters are mutually exclusive
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Speed up :func:`os.stat` for files with reasonable timestamps. Contributed
by Jeffrey Bosboom.
89 changes: 51 additions & 38 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2588,55 +2588,68 @@ static int
fill_time(PyObject *module, PyObject *v, int s_index, int f_index, int ns_index, time_t sec, unsigned long nsec)
{
assert(!PyErr_Occurred());

int res = -1;
PyObject *s_in_ns = NULL;
PyObject *ns_total = NULL;
PyObject *float_s = NULL;

PyObject *s = _PyLong_FromTime_t(sec);
PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
if (!(s && ns_fractional)) {
goto exit;
}

s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
if (!s_in_ns) {
goto exit;
}

ns_total = PyNumber_Add(s_in_ns, ns_fractional);
if (!ns_total)
goto exit;

float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
if (!float_s) {
goto exit;
}
#define SEC_TO_NS (1000000000LL)
assert(nsec < SEC_TO_NS);

if (s_index >= 0) {
PyObject *s = _PyLong_FromTime_t(sec);
if (s == NULL) {
return -1;
}
PyStructSequence_SET_ITEM(v, s_index, s);
s = NULL;
}

if (f_index >= 0) {
PyObject *float_s = PyFloat_FromDouble((double)sec + 1e-9 * nsec);
if (float_s == NULL) {
return -1;
}
PyStructSequence_SET_ITEM(v, f_index, float_s);
float_s = NULL;
}

int res = -1;
if (ns_index >= 0) {
PyStructSequence_SET_ITEM(v, ns_index, ns_total);
ns_total = NULL;
}
/* 1677-09-21 00:12:44 to 2262-04-11 23:47:15 UTC inclusive */
if ((LLONG_MIN/SEC_TO_NS) <= sec && sec <= (LLONG_MAX/SEC_TO_NS - 1)) {
PyObject *ns_total = PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
if (ns_total == NULL) {
return -1;
}
PyStructSequence_SET_ITEM(v, ns_index, ns_total);
assert(!PyErr_Occurred());
res = 0;
}
else {
PyObject *s_in_ns = NULL;
PyObject *ns_total = NULL;
PyObject *s = _PyLong_FromTime_t(sec);
PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
if (s == NULL || ns_fractional == NULL) {
goto exit;
}

assert(!PyErr_Occurred());
res = 0;
s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
if (s_in_ns == NULL) {
goto exit;
}

ns_total = PyNumber_Add(s_in_ns, ns_fractional);
if (ns_total == NULL) {
goto exit;
}
PyStructSequence_SET_ITEM(v, ns_index, ns_total);
assert(!PyErr_Occurred());
res = 0;

exit:
Py_XDECREF(s);
Py_XDECREF(ns_fractional);
Py_XDECREF(s_in_ns);
}
}

exit:
Py_XDECREF(s);
Py_XDECREF(ns_fractional);
Py_XDECREF(s_in_ns);
Py_XDECREF(ns_total);
Py_XDECREF(float_s);
return res;
#undef SEC_TO_NS
}

#ifdef MS_WINDOWS
Expand Down
Loading