diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst index 145449b2dfbd9f..a72e9a820ef347 100644 --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -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 ^^^^^^^ diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst index 6275f96f7d4d19..797870b9d7e260 100644 --- a/Doc/library/hashlib.rst +++ b/Doc/library/hashlib.rst @@ -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 `_ for comprehensive review of tree diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 5ffa33d4e61f19..93af07ae5ac10f 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -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 diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index ebab1389f07e58..fb1c916b141a25 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -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 diff --git a/Include/internal/pycore_dict_state.h b/Include/internal/pycore_dict_state.h index d608088ed2d7ce..ece0f10ca25170 100644 --- a/Include/internal/pycore_dict_state.h +++ b/Include/internal/pycore_dict_state.h @@ -38,6 +38,11 @@ struct _Py_dict_state { PyDict_WatchCallback watchers[DICT_MAX_WATCHERS]; }; +#define _dict_state_INIT \ + { \ + .next_keys_version = 2, \ + } + #ifdef __cplusplus } diff --git a/Include/internal/pycore_dtoa.h b/Include/internal/pycore_dtoa.h index fb524770efed7c..4d9681d59a64f7 100644 --- a/Include/internal/pycore_dtoa.h +++ b/Include/internal/pycore_dtoa.h @@ -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 diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index a48461c0742872..3b1444f3429b9a 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -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, \ }, \ diff --git a/Include/pymath.h b/Include/pymath.h index 772b67e4977563..4c1e3d9984894b 100644 --- a/Include/pymath.h +++ b/Include/pymath.h @@ -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 */ diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 20ec1ce9d80374..25863c76f3086d 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -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 diff --git a/Lib/test/test_cmath.py b/Lib/test/test_cmath.py index cd2c6939105d40..57f80d5d8cd016 100644 --- a/Lib/test/test_cmath.py +++ b/Lib/test/test_cmath.py @@ -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") diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py index 51ba151505fb54..9180cca62b28b8 100644 --- a/Lib/test/test_complex.py +++ b/Lib/test/test_complex.py @@ -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: @@ -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") diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index f8350c1e4caa27..c4ee1e08251d63 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -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) diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index 433161c2dd4145..f282434c9a3359 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -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) diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index ee0ef9a34c385c..10dd604138a659 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -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) diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-08-10-34-55.gh-issue-104263.ctHWI8.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-08-10-34-55.gh-issue-104263.ctHWI8.rst new file mode 100644 index 00000000000000..342467cfcd4e75 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-05-08-10-34-55.gh-issue-104263.ctHWI8.rst @@ -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. diff --git a/Misc/NEWS.d/next/Library/2023-04-14-21-12-32.gh-issue-103538.M4FK_v.rst b/Misc/NEWS.d/next/Library/2023-04-14-21-12-32.gh-issue-103538.M4FK_v.rst new file mode 100644 index 00000000000000..32788307d6f33b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-04-14-21-12-32.gh-issue-103538.M4FK_v.rst @@ -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. diff --git a/Misc/NEWS.d/next/Library/2023-05-08-15-39-00.gh-issue-87695.f6iO7v.rst b/Misc/NEWS.d/next/Library/2023-05-08-15-39-00.gh-issue-87695.f6iO7v.rst new file mode 100644 index 00000000000000..7b677656bea308 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-05-08-15-39-00.gh-issue-87695.f6iO7v.rst @@ -0,0 +1,2 @@ +Fix issue where :meth:`pathlib.Path.glob` raised :exc:`OSError` when it +encountered a symlink to an overly long path. diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 289fa0a2900042..7a35d3ba2b96b1 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -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"); @@ -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} }; diff --git a/Modules/_io/clinic/bufferedio.c.h b/Modules/_io/clinic/bufferedio.c.h index f92bade7435f03..ff7db07e5c0e92 100644 --- a/Modules/_io/clinic/bufferedio.c.h +++ b/Modules/_io/clinic/bufferedio.c.h @@ -107,6 +107,165 @@ _io__BufferedIOBase_detach(PyObject *self, PyTypeObject *cls, PyObject *const *a return _io__BufferedIOBase_detach_impl(self, cls); } +PyDoc_STRVAR(_io__BufferedIOBase_read__doc__, +"read($self, /, *args)\n" +"--\n" +"\n" +"Read and return up to n bytes.\n" +"\n" +"If the argument is omitted, None, or negative, read and\n" +"return 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).\n" +"However, for interactive raw streams (as well as sockets and pipes),\n" +"at most one raw read will be issued, and a short result does not\n" +"imply that EOF is imminent.\n" +"\n" +"Return an empty bytes object on EOF.\n" +"\n" +"Return None if the underlying raw stream was open in non-blocking\n" +"mode and no data is available at the moment."); + +#define _IO__BUFFEREDIOBASE_READ_METHODDEF \ + {"read", _PyCFunction_CAST(_io__BufferedIOBase_read), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__BufferedIOBase_read__doc__}, + +static PyObject * +_io__BufferedIOBase_read_impl(PyObject *self, PyTypeObject *cls, + PyObject *args); + +static PyObject * +_io__BufferedIOBase_read(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "read", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *__clinic_args = NULL; + + args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + __clinic_args = args[0]; + return_value = _io__BufferedIOBase_read_impl(self, cls, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + +PyDoc_STRVAR(_io__BufferedIOBase_read1__doc__, +"read1($self, /, *args)\n" +"--\n" +"\n" +"Read and return up to n bytes, with at most one read() call to the underlying raw stream.\n" +"\n" +"Return an empty bytes object on EOF.\n" +"A short result does not imply that EOF is imminent."); + +#define _IO__BUFFEREDIOBASE_READ1_METHODDEF \ + {"read1", _PyCFunction_CAST(_io__BufferedIOBase_read1), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__BufferedIOBase_read1__doc__}, + +static PyObject * +_io__BufferedIOBase_read1_impl(PyObject *self, PyTypeObject *cls, + PyObject *args); + +static PyObject * +_io__BufferedIOBase_read1(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "read1", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *__clinic_args = NULL; + + args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + __clinic_args = args[0]; + return_value = _io__BufferedIOBase_read1_impl(self, cls, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + +PyDoc_STRVAR(_io__BufferedIOBase_write__doc__, +"write($self, /, *args)\n" +"--\n" +"\n" +"Write the given buffer to the IO stream.\n" +"\n" +"Return the number of bytes written, which is always\n" +"the length of b in bytes.\n" +"\n" +"Raise BlockingIOError if the buffer is full and the\n" +"underlying raw stream cannot accept more data at the moment."); + +#define _IO__BUFFEREDIOBASE_WRITE_METHODDEF \ + {"write", _PyCFunction_CAST(_io__BufferedIOBase_write), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__BufferedIOBase_write__doc__}, + +static PyObject * +_io__BufferedIOBase_write_impl(PyObject *self, PyTypeObject *cls, + PyObject *args); + +static PyObject * +_io__BufferedIOBase_write(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "write", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *__clinic_args = NULL; + + args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + __clinic_args = args[0]; + return_value = _io__BufferedIOBase_write_impl(self, cls, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(_io__Buffered_peek__doc__, "peek($self, size=0, /)\n" "--\n" @@ -733,4 +892,4 @@ _io_BufferedRandom___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=da047f54b16cb309 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=64b2b3f1414c5285 input=a9049054013a1b77]*/ diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 385a05932a77ed..4dada0b28f0559 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -3283,20 +3283,6 @@ PyInit__tkinter(void) } PyTclObject_Type = o; -#ifdef TK_AQUA - /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems - * start waking up. Note that Tcl_FindExecutable will do this, this - * code must be above it! The original warning from - * tkMacOSXAppInit.c is copied below. - * - * NB - You have to swap in the Tk Notifier BEFORE you start up the - * Tcl interpreter for now. It probably should work to do this - * in the other order, but for now it doesn't seem to. - * - */ - Tk_MacOSXSetupTkNotifier(); -#endif - /* This helps the dynamic loader; in Unicode aware Tcl versions it also helps Tcl find its encodings. */ diff --git a/Modules/cmathmodule.c b/Modules/cmathmodule.c index 914a697f8e173b..1a31bdc824bb03 100644 --- a/Modules/cmathmodule.c +++ b/Modules/cmathmodule.c @@ -8,7 +8,6 @@ #include "Python.h" #include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR -#include "pycore_dtoa.h" // _Py_dg_stdnan() /* we need DBL_MAX, DBL_MIN, DBL_EPSILON, DBL_MANT_DIG and FLT_RADIX from float.h. We assume that FLT_RADIX is either 2 or 16. */ #include @@ -88,53 +87,6 @@ else { #endif #define CM_SCALE_DOWN (-(CM_SCALE_UP+1)/2) -/* Constants cmath.inf, cmath.infj, cmath.nan, cmath.nanj. - cmath.nan and cmath.nanj are defined only when either - _PY_SHORT_FLOAT_REPR is 1 (which should be - the most common situation on machines using an IEEE 754 - representation), or Py_NAN is defined. */ - -static double -m_inf(void) -{ -#if _PY_SHORT_FLOAT_REPR == 1 - return _Py_dg_infinity(0); -#else - return Py_HUGE_VAL; -#endif -} - -static Py_complex -c_infj(void) -{ - Py_complex r; - r.real = 0.0; - r.imag = m_inf(); - return r; -} - -#if _PY_SHORT_FLOAT_REPR == 1 - -static double -m_nan(void) -{ -#if _PY_SHORT_FLOAT_REPR == 1 - return _Py_dg_stdnan(0); -#else - return Py_NAN; -#endif -} - -static Py_complex -c_nanj(void) -{ - Py_complex r; - r.real = 0.0; - r.imag = m_nan(); - return r; -} - -#endif /* forward declarations */ static Py_complex cmath_asinh_impl(PyObject *, Py_complex); @@ -1274,23 +1226,22 @@ cmath_exec(PyObject *mod) if (PyModule_AddObject(mod, "tau", PyFloat_FromDouble(Py_MATH_TAU)) < 0) { return -1; } - if (PyModule_AddObject(mod, "inf", PyFloat_FromDouble(m_inf())) < 0) { + if (PyModule_AddObject(mod, "inf", PyFloat_FromDouble(Py_INFINITY)) < 0) { return -1; } + Py_complex infj = {0.0, Py_INFINITY}; if (PyModule_AddObject(mod, "infj", - PyComplex_FromCComplex(c_infj())) < 0) { + PyComplex_FromCComplex(infj)) < 0) { return -1; } -#if _PY_SHORT_FLOAT_REPR == 1 - if (PyModule_AddObject(mod, "nan", PyFloat_FromDouble(m_nan())) < 0) { + if (PyModule_AddObject(mod, "nan", PyFloat_FromDouble(fabs(Py_NAN))) < 0) { return -1; } - if (PyModule_AddObject(mod, "nanj", - PyComplex_FromCComplex(c_nanj())) < 0) { + Py_complex nanj = {0.0, fabs(Py_NAN)}; + if (PyModule_AddObject(mod, "nanj", PyComplex_FromCComplex(nanj)) < 0) { return -1; } -#endif /* initialize special value tables */ diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 3737a9654575ab..f369b2c45ce3ba 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -59,7 +59,6 @@ raised for division by zero and mod by zero. #include "Python.h" #include "pycore_bitutils.h" // _Py_bit_length() #include "pycore_call.h" // _PyObject_CallNoArgs() -#include "pycore_dtoa.h" // _Py_dg_infinity() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_object.h" // _PyObject_LookupSpecial() @@ -389,34 +388,6 @@ lanczos_sum(double x) return num/den; } -/* Constant for +infinity, generated in the same way as float('inf'). */ - -static double -m_inf(void) -{ -#if _PY_SHORT_FLOAT_REPR == 1 - return _Py_dg_infinity(0); -#else - return Py_HUGE_VAL; -#endif -} - -/* Constant nan value, generated in the same way as float('nan'). */ -/* We don't currently assume that Py_NAN is defined everywhere. */ - -#if _PY_SHORT_FLOAT_REPR == 1 - -static double -m_nan(void) -{ -#if _PY_SHORT_FLOAT_REPR == 1 - return _Py_dg_stdnan(0); -#else - return Py_NAN; -#endif -} - -#endif static double m_tgamma(double x) @@ -435,7 +406,7 @@ m_tgamma(double x) if (x == 0.0) { errno = EDOM; /* tgamma(+-0.0) = +-inf, divide-by-zero */ - return copysign(Py_HUGE_VAL, x); + return copysign(Py_INFINITY, x); } /* integer arguments */ @@ -3938,7 +3909,7 @@ math_ulp_impl(PyObject *module, double x) if (Py_IS_INFINITY(x)) { return x; } - double inf = m_inf(); + double inf = Py_INFINITY; double x2 = nextafter(x, inf); if (Py_IS_INFINITY(x2)) { /* special case: x is the largest positive representable float */ @@ -3975,14 +3946,12 @@ math_exec(PyObject *module) if (PyModule_AddObject(module, "tau", PyFloat_FromDouble(Py_MATH_TAU)) < 0) { return -1; } - if (PyModule_AddObject(module, "inf", PyFloat_FromDouble(m_inf())) < 0) { + if (PyModule_AddObject(module, "inf", PyFloat_FromDouble(Py_INFINITY)) < 0) { return -1; } -#if _PY_SHORT_FLOAT_REPR == 1 - if (PyModule_AddObject(module, "nan", PyFloat_FromDouble(m_nan())) < 0) { + if (PyModule_AddObject(module, "nan", PyFloat_FromDouble(fabs(Py_NAN))) < 0) { return -1; } -#endif return 0; } diff --git a/Modules/tkappinit.c b/Modules/tkappinit.c index 67d6250318c616..4c4081e43a8e3d 100644 --- a/Modules/tkappinit.c +++ b/Modules/tkappinit.c @@ -23,54 +23,9 @@ Tcl_AppInit(Tcl_Interp *interp) { const char *_tkinter_skip_tk_init; -#ifdef TK_AQUA -#ifndef MAX_PATH_LEN -#define MAX_PATH_LEN 1024 -#endif - char tclLibPath[MAX_PATH_LEN], tkLibPath[MAX_PATH_LEN]; - Tcl_Obj* pathPtr; - - /* pre- Tcl_Init code copied from tkMacOSXAppInit.c */ - Tk_MacOSXOpenBundleResources (interp, "com.tcltk.tcllibrary", - tclLibPath, MAX_PATH_LEN, 0); - - if (tclLibPath[0] != '\0') { - Tcl_SetVar(interp, "tcl_library", tclLibPath, TCL_GLOBAL_ONLY); - Tcl_SetVar(interp, "tclDefaultLibrary", tclLibPath, TCL_GLOBAL_ONLY); - Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath, TCL_GLOBAL_ONLY); - } - - if (tclLibPath[0] != '\0') { - Tcl_SetVar(interp, "tcl_library", tclLibPath, TCL_GLOBAL_ONLY); - Tcl_SetVar(interp, "tclDefaultLibrary", tclLibPath, TCL_GLOBAL_ONLY); - Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath, TCL_GLOBAL_ONLY); - } -#endif if (Tcl_Init (interp) == TCL_ERROR) return TCL_ERROR; -#ifdef TK_AQUA - /* pre- Tk_Init code copied from tkMacOSXAppInit.c */ - Tk_MacOSXOpenBundleResources (interp, "com.tcltk.tklibrary", - tkLibPath, MAX_PATH_LEN, 1); - - if (tclLibPath[0] != '\0') { - pathPtr = Tcl_NewStringObj(tclLibPath, -1); - } else { - Tcl_Obj *pathPtr = TclGetLibraryPath(); - } - - if (tkLibPath[0] != '\0') { - Tcl_Obj *objPtr; - - Tcl_SetVar(interp, "tk_library", tkLibPath, TCL_GLOBAL_ONLY); - objPtr = Tcl_NewStringObj(tkLibPath, -1); - Tcl_ListObjAppendElement(NULL, pathPtr, objPtr); - } - - TclSetLibraryPath(pathPtr); -#endif - #ifdef WITH_XXX /* Initialize modules that don't require Tk */ #endif @@ -88,11 +43,6 @@ Tcl_AppInit(Tcl_Interp *interp) Tk_MainWindow(interp); -#ifdef TK_AQUA - TkMacOSXInitAppleEvents(interp); - TkMacOSXInitMenus(interp); -#endif - #ifdef WITH_PIL /* 0.2b5 and later -- not yet released as of May 14 */ { extern void TkImaging_Init(Tcl_Interp *); diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 2ef520044340ee..7436c113f37c4a 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -300,9 +300,19 @@ _PyDict_DebugMallocStats(FILE *out) static void free_keys_object(PyInterpreterState *interp, PyDictKeysObject *keys); +/* PyDictKeysObject has refcounts like PyObject does, so we have the + following two functions to mirror what Py_INCREF() and Py_DECREF() do. + (Keep in mind that PyDictKeysObject isn't actually a PyObject.) + Likewise a PyDictKeysObject can be immortal (e.g. Py_EMPTY_KEYS), + so we apply a naive version of what Py_INCREF() and Py_DECREF() do + for immortal objects. */ + static inline void dictkeys_incref(PyDictKeysObject *dk) { + if (dk->dk_refcnt == _Py_IMMORTAL_REFCNT) { + return; + } #ifdef Py_REF_DEBUG _Py_IncRefTotal(_PyInterpreterState_GET()); #endif @@ -312,6 +322,9 @@ dictkeys_incref(PyDictKeysObject *dk) static inline void dictkeys_decref(PyInterpreterState *interp, PyDictKeysObject *dk) { + if (dk->dk_refcnt == _Py_IMMORTAL_REFCNT) { + return; + } assert(dk->dk_refcnt > 0); #ifdef Py_REF_DEBUG _Py_DecRefTotal(_PyInterpreterState_GET()); @@ -447,7 +460,7 @@ estimate_log2_keysize(Py_ssize_t n) * (which cannot fail and thus can do no allocation). */ static PyDictKeysObject empty_keys_struct = { - 1, /* dk_refcnt */ + _Py_IMMORTAL_REFCNT, /* dk_refcnt */ 0, /* dk_log2_size */ 0, /* dk_log2_index_bytes */ DICT_KEYS_UNICODE, /* dk_kind */ @@ -779,6 +792,7 @@ clone_combined_dict_keys(PyDictObject *orig) assert(PyDict_Check(orig)); assert(Py_TYPE(orig)->tp_iter == (getiterfunc)dict_iter); assert(orig->ma_values == NULL); + assert(orig->ma_keys != Py_EMPTY_KEYS); assert(orig->ma_keys->dk_refcnt == 1); size_t keys_size = _PyDict_KeysSize(orig->ma_keys); @@ -833,7 +847,7 @@ PyObject * PyDict_New(void) { PyInterpreterState *interp = _PyInterpreterState_GET(); - dictkeys_incref(Py_EMPTY_KEYS); + /* We don't incref Py_EMPTY_KEYS here because it is immortal. */ return new_dict(interp, Py_EMPTY_KEYS, NULL, 0, 0); } @@ -1331,7 +1345,7 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp, Py_DECREF(value); return -1; } - dictkeys_decref(interp, Py_EMPTY_KEYS); + /* We don't decref Py_EMPTY_KEYS here because it is immortal. */ mp->ma_keys = newkeys; mp->ma_values = NULL; @@ -1529,14 +1543,10 @@ dictresize(PyInterpreterState *interp, PyDictObject *mp, // We can not use free_keys_object here because key's reference // are moved already. + if (oldkeys != Py_EMPTY_KEYS) { #ifdef Py_REF_DEBUG - _Py_DecRefTotal(_PyInterpreterState_GET()); + _Py_DecRefTotal(_PyInterpreterState_GET()); #endif - if (oldkeys == Py_EMPTY_KEYS) { - oldkeys->dk_refcnt--; - assert(oldkeys->dk_refcnt > 0); - } - else { assert(oldkeys->dk_kind != DICT_KEYS_SPLIT); assert(oldkeys->dk_refcnt == 1); #if PyDict_MAXFREELIST > 0 @@ -2080,8 +2090,8 @@ PyDict_Clear(PyObject *op) dictkeys_decref(interp, oldkeys); } else { - assert(oldkeys->dk_refcnt == 1); - dictkeys_decref(interp, oldkeys); + assert(oldkeys->dk_refcnt == 1); + dictkeys_decref(interp, oldkeys); } ASSERT_CONSISTENT(mp); } diff --git a/Objects/floatobject.c b/Objects/floatobject.c index d257857d9c619c..83a263c0d9c67e 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -2424,25 +2424,14 @@ PyFloat_Unpack2(const char *data, int le) f |= *p; if (e == 0x1f) { -#if _PY_SHORT_FLOAT_REPR == 0 if (f == 0) { /* Infinity */ return sign ? -Py_HUGE_VAL : Py_HUGE_VAL; } else { /* NaN */ - return sign ? -Py_NAN : Py_NAN; + return sign ? -fabs(Py_NAN) : fabs(Py_NAN); } -#else // _PY_SHORT_FLOAT_REPR == 1 - if (f == 0) { - /* Infinity */ - return _Py_dg_infinity(sign); - } - else { - /* NaN */ - return _Py_dg_stdnan(sign); - } -#endif // _PY_SHORT_FLOAT_REPR == 1 } x = (double)f / 1024.0; diff --git a/Python/dtoa.c b/Python/dtoa.c index 6ea60ac9946e0f..c5e343b82f74c5 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -273,11 +273,6 @@ typedef union { double d; ULong L[2]; } U; #define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) #define Big1 0xffffffff -/* Standard NaN used by _Py_dg_stdnan. */ - -#define NAN_WORD0 0x7ff80000 -#define NAN_WORD1 0 - /* Bits of the representation of positive infinity. */ #define POSINF_WORD0 0x7ff00000 @@ -1399,35 +1394,6 @@ bigcomp(U *rv, const char *s0, BCinfo *bc) return 0; } -/* Return a 'standard' NaN value. - - There are exactly two quiet NaNs that don't arise by 'quieting' signaling - NaNs (see IEEE 754-2008, section 6.2.1). If sign == 0, return the one whose - sign bit is cleared. Otherwise, return the one whose sign bit is set. -*/ - -double -_Py_dg_stdnan(int sign) -{ - U rv; - word0(&rv) = NAN_WORD0; - word1(&rv) = NAN_WORD1; - if (sign) - word0(&rv) |= Sign_bit; - return dval(&rv); -} - -/* Return positive or negative infinity, according to the given sign (0 for - * positive infinity, 1 for negative infinity). */ - -double -_Py_dg_infinity(int sign) -{ - U rv; - word0(&rv) = POSINF_WORD0; - word1(&rv) = POSINF_WORD1; - return sign ? -dval(&rv) : dval(&rv); -} double _Py_dg_strtod(const char *s00, char **se) diff --git a/Python/pystrtod.c b/Python/pystrtod.c index d77b846f0403f0..9bb060e3d11979 100644 --- a/Python/pystrtod.c +++ b/Python/pystrtod.c @@ -23,44 +23,6 @@ case_insensitive_match(const char *s, const char *t) return the NaN or Infinity as a double and set *endptr to point just beyond the successfully parsed portion of the string. On failure, return -1.0 and set *endptr to point to the start of the string. */ - -#if _PY_SHORT_FLOAT_REPR == 1 - -double -_Py_parse_inf_or_nan(const char *p, char **endptr) -{ - double retval; - const char *s; - int negate = 0; - - s = p; - if (*s == '-') { - negate = 1; - s++; - } - else if (*s == '+') { - s++; - } - if (case_insensitive_match(s, "inf")) { - s += 3; - if (case_insensitive_match(s, "inity")) - s += 5; - retval = _Py_dg_infinity(negate); - } - else if (case_insensitive_match(s, "nan")) { - s += 3; - retval = _Py_dg_stdnan(negate); - } - else { - s = p; - retval = -1.0; - } - *endptr = (char *)s; - return retval; -} - -#else - double _Py_parse_inf_or_nan(const char *p, char **endptr) { @@ -84,7 +46,7 @@ _Py_parse_inf_or_nan(const char *p, char **endptr) } else if (case_insensitive_match(s, "nan")) { s += 3; - retval = negate ? -Py_NAN : Py_NAN; + retval = negate ? -fabs(Py_NAN) : fabs(Py_NAN); } else { s = p; @@ -94,7 +56,6 @@ _Py_parse_inf_or_nan(const char *p, char **endptr) return retval; } -#endif /** * _PyOS_ascii_strtod: