Skip to content

Commit

Permalink
Pull in main
Browse files Browse the repository at this point in the history
  • Loading branch information
erlend-aasland committed May 10, 2023
2 parents 1505872 + e464ec9 commit 18e8c43
Show file tree
Hide file tree
Showing 27 changed files with 335 additions and 325 deletions.
1 change: 1 addition & 0 deletions Doc/howto/logging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ The flow of log event information in loggers and handlers is illustrated in the
following diagram.

.. image:: logging_flow.png
:class: invert-in-dark-mode

Loggers
^^^^^^^
Expand Down
1 change: 1 addition & 0 deletions Doc/library/hashlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ Constructor functions also accept the following tree hashing parameters:

.. figure:: hashlib-blake2-tree.png
:alt: Explanation of tree mode parameters.
:class: invert-in-dark-mode

See section 2.10 in `BLAKE2 specification
<https://www.blake2.net/blake2_20130129.pdf>`_ for comprehensive review of tree
Expand Down
1 change: 1 addition & 0 deletions Doc/library/pathlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ inherit from pure paths but also provide I/O operations.

.. image:: pathlib-inheritance.png
:align: center
:class: invert-in-dark-mode

If you've never used this module before or just aren't sure which class is
right for your task, :class:`Path` is most likely what you need. It instantiates
Expand Down
31 changes: 22 additions & 9 deletions Doc/library/typing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2876,24 +2876,37 @@ Introspection helpers
if a default value equal to ``None`` was set.
Now the annotation is returned unchanged.

.. function:: get_args(tp)
.. function:: get_origin(tp)

Provide basic introspection for generic types and special typing forms.

For a typing object of the form ``X[Y, Z, ...]`` these functions return
``X`` and ``(Y, Z, ...)``. If ``X`` is a generic alias for a builtin or
Get the unsubscripted version of a type: for a typing object of the form
``X[Y, Z, ...]`` return ``X``. If ``X`` is a generic alias for a builtin or
:mod:`collections` class, it gets normalized to the original class.
If ``X`` is an instance of :class:`ParamSpecArgs` or :class:`ParamSpecKwargs`,
return the underlying :class:`ParamSpec`.
Return ``None`` for unsupported objects.
Examples::

assert get_origin(str) is None
assert get_origin(Dict[str, int]) is dict
assert get_origin(Union[int, str]) is Union
P = ParamSpec('P')
assert get_origin(P.args) is P
assert get_origin(P.kwargs) is P

.. versionadded:: 3.8

.. function:: get_args(tp)

Get type arguments with all substitutions performed: for a typing object
of the form ``X[Y, Z, ...]`` return ``(Y, Z, ...)``.
If ``X`` is a union or :class:`Literal` contained in another
generic type, the order of ``(Y, Z, ...)`` may be different from the order
of the original arguments ``[Y, Z, ...]`` due to type caching.
For unsupported objects return ``None`` and ``()`` correspondingly.
Return ``()`` for unsupported objects.
Examples::

assert get_origin(Dict[str, int]) is dict
assert get_args(int) == ()
assert get_args(Dict[int, str]) == (int, str)

assert get_origin(Union[int, str]) is Union
assert get_args(Union[int, str]) == (int, str)

.. versionadded:: 3.8
Expand Down
5 changes: 5 additions & 0 deletions Include/internal/pycore_dict_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ struct _Py_dict_state {
PyDict_WatchCallback watchers[DICT_MAX_WATCHERS];
};

#define _dict_state_INIT \
{ \
.next_keys_version = 2, \
}


#ifdef __cplusplus
}
Expand Down
2 changes: 0 additions & 2 deletions Include/internal/pycore_dtoa.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ PyAPI_FUNC(double) _Py_dg_strtod(const char *str, char **ptr);
PyAPI_FUNC(char *) _Py_dg_dtoa(double d, int mode, int ndigits,
int *decpt, int *sign, char **rve);
PyAPI_FUNC(void) _Py_dg_freedtoa(char *s);
PyAPI_FUNC(double) _Py_dg_stdnan(int sign);
PyAPI_FUNC(double) _Py_dg_infinity(int sign);

#endif // _PY_SHORT_FLOAT_REPR == 1

Expand Down
4 changes: 1 addition & 3 deletions Include/internal/pycore_runtime_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,7 @@ extern PyTypeObject _PyExc_MemoryError;
}, \
}, \
.dtoa = _dtoa_state_INIT(&(INTERP)), \
.dict_state = { \
.next_keys_version = 2, \
}, \
.dict_state = _dict_state_INIT, \
.func_state = { \
.next_version = 1, \
}, \
Expand Down
25 changes: 11 additions & 14 deletions Include/pymath.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,27 +39,24 @@
// Return 1 if float or double arg is neither infinite nor NAN, else 0.
#define Py_IS_FINITE(X) isfinite(X)

/* HUGE_VAL is supposed to expand to a positive double infinity. Python
* uses Py_HUGE_VAL instead because some platforms are broken in this
* respect. We used to embed code in pyport.h to try to worm around that,
* but different platforms are broken in conflicting ways. If you're on
* a platform where HUGE_VAL is defined incorrectly, fiddle your Python
* config to #define Py_HUGE_VAL to something that works on your platform.
// Py_INFINITY: Value that evaluates to a positive double infinity.
#ifndef Py_INFINITY
# define Py_INFINITY ((double)INFINITY)
#endif

/* Py_HUGE_VAL should always be the same as Py_INFINITY. But historically
* this was not reliable and Python did not require IEEE floats and C99
* conformity. Prefer Py_INFINITY for new code.
*/
#ifndef Py_HUGE_VAL
# define Py_HUGE_VAL HUGE_VAL
#endif

// Py_NAN: Value that evaluates to a quiet Not-a-Number (NaN).
/* Py_NAN: Value that evaluates to a quiet Not-a-Number (NaN). The sign is
* undefined and normally not relevant, but e.g. fixed for float("nan").
*/
#if !defined(Py_NAN)
# if _Py__has_builtin(__builtin_nan)
// Built-in implementation of the ISO C99 function nan(): quiet NaN.
# define Py_NAN (__builtin_nan(""))
#else
// Use C99 NAN constant: quiet Not-A-Number.
// NAN is a float, Py_NAN is a double: cast to double.
# define Py_NAN ((double)NAN)
# endif
#endif

#endif /* Py_PYMATH_H */
4 changes: 2 additions & 2 deletions Lib/pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,11 @@ def _iterate_directories(self, parent_path, scandir):
for entry in entries:
entry_is_dir = False
try:
entry_is_dir = entry.is_dir()
entry_is_dir = entry.is_dir(follow_symlinks=False)
except OSError as e:
if not _ignore_error(e):
raise
if entry_is_dir and not entry.is_symlink():
if entry_is_dir:
path = parent_path._make_child_relpath(entry.name)
for p in self._iterate_directories(path, scandir):
yield p
Expand Down
5 changes: 5 additions & 0 deletions Lib/test/test_cmath.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ def test_infinity_and_nan_constants(self):
self.assertEqual(cmath.nan.imag, 0.0)
self.assertEqual(cmath.nanj.real, 0.0)
self.assertTrue(math.isnan(cmath.nanj.imag))
# Also check that the sign of all of these is positive:
self.assertEqual(math.copysign(1., cmath.nan.real), 1.)
self.assertEqual(math.copysign(1., cmath.nan.imag), 1.)
self.assertEqual(math.copysign(1., cmath.nanj.real), 1.)
self.assertEqual(math.copysign(1., cmath.nanj.imag), 1.)

# Check consistency with reprs.
self.assertEqual(repr(cmath.inf), "inf")
Expand Down
7 changes: 7 additions & 0 deletions Lib/test/test_complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,12 @@ class complex2(complex):
self.assertFloatsAreIdentical(z.real, x)
self.assertFloatsAreIdentical(z.imag, y)

def test_constructor_negative_nans_from_string(self):
self.assertEqual(copysign(1., complex("-nan").real), -1.)
self.assertEqual(copysign(1., complex("-nanj").imag), -1.)
self.assertEqual(copysign(1., complex("-nan-nanj").real), -1.)
self.assertEqual(copysign(1., complex("-nan-nanj").imag), -1.)

def test_underscores(self):
# check underscores
for lit in VALID_UNDERSCORE_LITERALS:
Expand Down Expand Up @@ -569,6 +575,7 @@ def test(v, expected, test_fn=self.assertEqual):
test(complex(NAN, 1), "(nan+1j)")
test(complex(1, NAN), "(1+nanj)")
test(complex(NAN, NAN), "(nan+nanj)")
test(complex(-NAN, -NAN), "(nan+nanj)")

test(complex(0, INF), "infj")
test(complex(0, -INF), "-infj")
Expand Down
5 changes: 1 addition & 4 deletions Lib/test/test_float.py
Original file line number Diff line number Diff line change
Expand Up @@ -1040,11 +1040,8 @@ def test_inf_signs(self):
self.assertEqual(copysign(1.0, float('inf')), 1.0)
self.assertEqual(copysign(1.0, float('-inf')), -1.0)

@unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
"applies only when using short float repr style")
def test_nan_signs(self):
# When using the dtoa.c code, the sign of float('nan') should
# be predictable.
# The sign of float('nan') should be predictable.
self.assertEqual(copysign(1.0, float('nan')), 1.0)
self.assertEqual(copysign(1.0, float('-nan')), -1.0)

Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_math.py
Original file line number Diff line number Diff line change
Expand Up @@ -1881,11 +1881,11 @@ def testIsinf(self):
self.assertFalse(math.isinf(0.))
self.assertFalse(math.isinf(1.))

@requires_IEEE_754
def test_nan_constant(self):
# `math.nan` must be a quiet NaN with positive sign bit
self.assertTrue(math.isnan(math.nan))
self.assertEqual(math.copysign(1., math.nan), 1.)

@requires_IEEE_754
def test_inf_constant(self):
self.assertTrue(math.isinf(math.inf))
self.assertGreater(math.inf, 0.0)
Expand Down
9 changes: 9 additions & 0 deletions Lib/test/test_pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1977,6 +1977,15 @@ def my_scandir(path):
subdir.chmod(000)
self.assertEqual(len(set(base.glob("*"))), 4)

@os_helper.skip_unless_symlink
def test_glob_long_symlink(self):
# See gh-87695
base = self.cls(BASE) / 'long_symlink'
base.mkdir()
bad_link = base / 'bad_link'
bad_link.symlink_to("bad" * 200)
self.assertEqual(sorted(base.glob('**/*')), [bad_link])

def _check_resolve(self, p, expected, strict=True):
q = p.resolve(strict)
self.assertEqual(q, expected)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Fix ``float("nan")`` to produce a quiet NaN on platforms (like MIPS) where
the meaning of the signalling / quiet bit is inverted from its usual
meaning. Also introduce a new macro ``Py_INFINITY`` matching C99's
``INFINITY``, and refactor internals to rely on C99's ``NAN`` and
``INFINITY`` macros instead of hard-coding bit patterns for infinities and
NaNs. Thanks Sebastian Berg.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Remove ``_tkinter`` module code guarded by definition of the ``TK_AQUA`` macro
which was only needed for Tk 8.4.7 or earlier and was never actually defined by
any build system or documented for manual use.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix issue where :meth:`pathlib.Path.glob` raised :exc:`OSError` when it
encountered a symlink to an overly long path.
100 changes: 63 additions & 37 deletions Modules/_io/bufferedio.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,56 +132,82 @@ _io__BufferedIOBase_detach_impl(PyObject *self, PyTypeObject *cls)
return bufferediobase_unsupported(state, "detach");
}

PyDoc_STRVAR(bufferediobase_read_doc,
"Read and return up to n bytes.\n"
"\n"
"If the argument is omitted, None, or negative, reads and\n"
"returns all data until EOF.\n"
"\n"
"If the argument is positive, and the underlying raw stream is\n"
"not 'interactive', multiple raw reads may be issued to satisfy\n"
"the byte count (unless EOF is reached first). But for\n"
"interactive raw streams (as well as sockets and pipes), at most\n"
"one raw read will be issued, and a short result does not imply\n"
"that EOF is imminent.\n"
"\n"
"Returns an empty bytes object on EOF.\n"
"\n"
"Returns None if the underlying raw stream was open in non-blocking\n"
"mode and no data is available at the moment.\n");
/*[clinic input]
_io._BufferedIOBase.read
cls: defining_class
/
*args: object
Read and return up to n bytes.
If the argument is omitted, None, or negative, read and
return all data until EOF.
If the argument is positive, and the underlying raw stream is
not 'interactive', multiple raw reads may be issued to satisfy
the byte count (unless EOF is reached first).
However, for interactive raw streams (as well as sockets and pipes),
at most one raw read will be issued, and a short result does not
imply that EOF is imminent.
Return an empty bytes object on EOF.
Return None if the underlying raw stream was open in non-blocking
mode and no data is available at the moment.
[clinic start generated code]*/

static PyObject *
bufferediobase_read(PyObject *self, PyObject *args)
_io__BufferedIOBase_read_impl(PyObject *self, PyTypeObject *cls,
PyObject *args)
/*[clinic end generated code: output=4521b30940fd7b67 input=390205758adc8510]*/
{
_PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
return bufferediobase_unsupported(state, "read");
}

PyDoc_STRVAR(bufferediobase_read1_doc,
"Read and return up to n bytes, with at most one read() call\n"
"to the underlying raw stream. A short result does not imply\n"
"that EOF is imminent.\n"
"\n"
"Returns an empty bytes object on EOF.\n");
/*[clinic input]
_io._BufferedIOBase.read1
cls: defining_class
/
*args: object
Read and return up to n bytes, with at most one read() call to the underlying raw stream.
Return an empty bytes object on EOF.
A short result does not imply that EOF is imminent.
[clinic start generated code]*/

static PyObject *
bufferediobase_read1(PyObject *self, PyObject *args)
_io__BufferedIOBase_read1_impl(PyObject *self, PyTypeObject *cls,
PyObject *args)
/*[clinic end generated code: output=636fd241c21e050a input=ef546a1238c5b41c]*/
{
_PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
return bufferediobase_unsupported(state, "read1");
}

PyDoc_STRVAR(bufferediobase_write_doc,
"Write the given buffer to the IO stream.\n"
"\n"
"Returns the number of bytes written, which is always the length of b\n"
"in bytes.\n"
"\n"
"Raises BlockingIOError if the buffer is full and the\n"
"underlying raw stream cannot accept more data at the moment.\n");
/*[clinic input]
_io._BufferedIOBase.write
cls: defining_class
/
*args: object
Write the given buffer to the IO stream.
Return the number of bytes written, which is always
the length of b in bytes.
Raise BlockingIOError if the buffer is full and the
underlying raw stream cannot accept more data at the moment.
[clinic start generated code]*/

static PyObject *
bufferediobase_write(PyObject *self, PyObject *args)
_io__BufferedIOBase_write_impl(PyObject *self, PyTypeObject *cls,
PyObject *args)
/*[clinic end generated code: output=d51feea4bcac9892 input=f79b72c4dccb3dc2]*/
{
_PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
return bufferediobase_unsupported(state, "write");
Expand Down Expand Up @@ -2354,11 +2380,11 @@ bufferediobase_traverse(PyObject *self, visitproc visit, void *arg)

static PyMethodDef bufferediobase_methods[] = {
_IO__BUFFEREDIOBASE_DETACH_METHODDEF
{"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
{"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
_IO__BUFFEREDIOBASE_READ_METHODDEF
_IO__BUFFEREDIOBASE_READ1_METHODDEF
_IO__BUFFEREDIOBASE_READINTO_METHODDEF
_IO__BUFFEREDIOBASE_READINTO1_METHODDEF
{"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
_IO__BUFFEREDIOBASE_WRITE_METHODDEF
{NULL, NULL}
};

Expand Down

0 comments on commit 18e8c43

Please sign in to comment.