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/http.client.rst b/Doc/library/http.client.rst index eb8c1e198e2b09..bf1f2e3920783d 100644 --- a/Doc/library/http.client.rst +++ b/Doc/library/http.client.rst @@ -264,7 +264,10 @@ HTTPConnection Objects encode_chunked=False) This will send a request to the server using the HTTP request - method *method* and the selector *url*. + method *method* and the request URI *url*. The provided *url* must be + an absolute path to conform with :rfc:`RFC 2616 §5.1.2 <2616#section-5.1.2>` + (unless connecting to an HTTP proxy server or using the ``OPTIONS`` or + ``CONNECT`` methods). If *body* is specified, the specified data is sent after the headers are finished. It may be a :class:`str`, a :term:`bytes-like object`, an @@ -279,7 +282,10 @@ HTTPConnection Objects iterable are sent as is until the iterable is exhausted. The *headers* argument should be a mapping of extra HTTP headers to send - with the request. + with the request. A :rfc:`Host header <2616#section-14.23>` + must be provided to conform with :rfc:`RFC 2616 §5.1.2 <2616#section-5.1.2>` + (unless connecting to an HTTP proxy server or using the ``OPTIONS`` or + ``CONNECT`` methods). If *headers* contains neither Content-Length nor Transfer-Encoding, but there is a request body, one of those @@ -298,6 +304,16 @@ HTTPConnection Objects HTTPConnection object assumes that all encoding is handled by the calling code. If it is ``True``, the body will be chunk-encoded. + For example, to perform a ``GET`` request to ``https://docs.python.org/3/``:: + + >>> import http.client + >>> host = "docs.python.org" + >>> conn = http.client.HTTPSConnection(host) + >>> conn.request("GET", "/3/", headers={"Host": host}) + >>> response = conn.getresponse() + >>> print(response.status, response.reason) + 200 OK + .. note:: Chunked transfer encoding has been added to the HTTP protocol version 1.1. Unless the HTTP server is known to handle HTTP 1.1, 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/cpython/genobject.h b/Include/cpython/genobject.h index 18b8ce913e6e31..7856481b5db300 100644 --- a/Include/cpython/genobject.h +++ b/Include/cpython/genobject.h @@ -77,6 +77,8 @@ PyAPI_FUNC(PyObject *) PyAsyncGen_New(PyFrameObject *, #define PyAsyncGen_CheckExact(op) Py_IS_TYPE((op), &PyAsyncGen_Type) +#define PyAsyncGenASend_CheckExact(op) Py_IS_TYPE((op), &_PyAsyncGenASend_Type) + #undef _PyGenObject_HEAD 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/dataclasses.py b/Lib/dataclasses.py index b0b8a773b7594f..3eacba840db426 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1324,11 +1324,18 @@ def _asdict_inner(obj, dict_factory): if type(obj) in _ATOMIC_TYPES: return obj elif _is_dataclass_instance(obj): - result = [] - for f in fields(obj): - value = _asdict_inner(getattr(obj, f.name), dict_factory) - result.append((f.name, value)) - return dict_factory(result) + # fast path for the common case + if dict_factory is dict: + return { + f.name: _asdict_inner(getattr(obj, f.name), dict) + for f in fields(obj) + } + else: + result = [] + for f in fields(obj): + value = _asdict_inner(getattr(obj, f.name), dict_factory) + result.append((f.name, value)) + return dict_factory(result) elif isinstance(obj, tuple) and hasattr(obj, '_fields'): # obj is a namedtuple. Recurse into it, but the returned # object is another namedtuple of the same type. This is 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_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py index 3a74b821eaee49..a7c6245825ff86 100644 --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -262,15 +262,16 @@ def test_reload(self): def test_try_registration(self): # Assert that the PyState_{Find,Add,Remove}Module C API doesn't work. - module = self.load_module() - with self.subTest('PyState_FindModule'): - self.assertEqual(module.call_state_registration_func(0), None) - with self.subTest('PyState_AddModule'): - with self.assertRaises(SystemError): - module.call_state_registration_func(1) - with self.subTest('PyState_RemoveModule'): - with self.assertRaises(SystemError): - module.call_state_registration_func(2) + with util.uncache(self.name): + module = self.load_module() + with self.subTest('PyState_FindModule'): + self.assertEqual(module.call_state_registration_func(0), None) + with self.subTest('PyState_AddModule'): + with self.assertRaises(SystemError): + module.call_state_registration_func(1) + with self.subTest('PyState_RemoveModule'): + with self.assertRaises(SystemError): + module.call_state_registration_func(2) def test_load_submodule(self): # Test loading a simulated submodule. 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/Lib/test/test_socket.py b/Lib/test/test_socket.py index bb7bf436d2d721..68cdc6eaa91375 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1622,7 +1622,7 @@ def test_getaddrinfo_int_port_overflow(self): from _testcapi import ULONG_MAX, LONG_MAX, LONG_MIN try: - socket.getaddrinfo(None, ULONG_MAX + 1) + socket.getaddrinfo(None, ULONG_MAX + 1, type=socket.SOCK_STREAM) except OverflowError: # Platforms differ as to what values consitute a getaddrinfo() error # return. Some fail for LONG_MAX+1, others ULONG_MAX+1, and Windows @@ -1632,28 +1632,28 @@ def test_getaddrinfo_int_port_overflow(self): pass try: - socket.getaddrinfo(None, LONG_MAX + 1) + socket.getaddrinfo(None, LONG_MAX + 1, type=socket.SOCK_STREAM) except OverflowError: self.fail("Either no error or socket.gaierror expected.") except socket.gaierror: pass try: - socket.getaddrinfo(None, LONG_MAX - 0xffff + 1) + socket.getaddrinfo(None, LONG_MAX - 0xffff + 1, type=socket.SOCK_STREAM) except OverflowError: self.fail("Either no error or socket.gaierror expected.") except socket.gaierror: pass try: - socket.getaddrinfo(None, LONG_MIN - 1) + socket.getaddrinfo(None, LONG_MIN - 1, type=socket.SOCK_STREAM) except OverflowError: self.fail("Either no error or socket.gaierror expected.") except socket.gaierror: pass - socket.getaddrinfo(None, 0) # No error expected. - socket.getaddrinfo(None, 0xffff) # No error expected. + socket.getaddrinfo(None, 0, type=socket.SOCK_STREAM) # No error expected. + socket.getaddrinfo(None, 0xffff, type=socket.SOCK_STREAM) # No error expected. def test_getnameinfo(self): # only IP addresses are allowed diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py index dcdbb1cc64fd28..e324babdd5ed0b 100644 --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -1042,6 +1042,32 @@ def test_issue14072(self): self.assertEqual(p2.scheme, 'tel') self.assertEqual(p2.path, '+31641044153') + def test_invalid_bracketed_hosts(self): + self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[192.0.2.146]/Path?Query') + self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[important.com:8000]/Path?Query') + self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v123r.IP]/Path?Query') + self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v12ae]/Path?Query') + self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v.IP]/Path?Query') + self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v123.]/Path?Query') + self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v]/Path?Query') + self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af::2309::fae7:1234]/Path?Query') + self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af:2309::fae7:1234:2342:438e:192.0.2.146]/Path?Query') + self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@]v6a.ip[/Path') + + def test_splitting_bracketed_hosts(self): + p1 = urllib.parse.urlsplit('scheme://user@[v6a.ip]/path?query') + self.assertEqual(p1.hostname, 'v6a.ip') + self.assertEqual(p1.username, 'user') + self.assertEqual(p1.path, '/path') + p2 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7%test]/path?query') + self.assertEqual(p2.hostname, '0439:23af:2309::fae7%test') + self.assertEqual(p2.username, 'user') + self.assertEqual(p2.path, '/path') + p3 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7:1234:192.0.2.146%test]/path?query') + self.assertEqual(p3.hostname, '0439:23af:2309::fae7:1234:192.0.2.146%test') + self.assertEqual(p3.username, 'user') + self.assertEqual(p3.path, '/path') + def test_port_casting_failure_message(self): message = "Port could not be cast to integer value as 'oracle'" p1 = urllib.parse.urlparse('http://Server=sde; Service=sde:oracle') diff --git a/Lib/typing.py b/Lib/typing.py index 0dacdd9031a776..4f8cba88632d6a 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1896,7 +1896,7 @@ def __init_subclass__(cls, *args, **kwargs): base.__origin__ is Generic): if gvars is not None: raise TypeError( - "Cannot inherit from Generic[...] multiple types.") + "Cannot inherit from Generic[...] multiple times.") gvars = base.__parameters__ if gvars is not None: tvarset = set(tvars) diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index 777b7c53efe565..da0073969bff0b 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -33,6 +33,7 @@ import re import types import warnings +import ipaddress __all__ = ["urlparse", "urlunparse", "urljoin", "urldefrag", "urlsplit", "urlunsplit", "urlencode", "parse_qs", @@ -427,6 +428,17 @@ def _checknetloc(netloc): raise ValueError("netloc '" + netloc + "' contains invalid " + "characters under NFKC normalization") +# Valid bracketed hosts are defined in +# https://www.rfc-editor.org/rfc/rfc3986#page-49 and https://url.spec.whatwg.org/ +def _check_bracketed_host(hostname): + if hostname.startswith('v'): + if not re.match(r"\Av[a-fA-F0-9]+\..+\Z", hostname): + raise ValueError(f"IPvFuture address is invalid") + else: + ip = ipaddress.ip_address(hostname) # Throws Value Error if not IPv6 or IPv4 + if isinstance(ip, ipaddress.IPv4Address): + raise ValueError(f"An IPv4 address cannot be in brackets") + # typed=True avoids BytesWarnings being emitted during cache key # comparison since this API supports both bytes and str input. @functools.lru_cache(typed=True) @@ -466,12 +478,14 @@ def urlsplit(url, scheme='', allow_fragments=True): break else: scheme, url = url[:i].lower(), url[i+1:] - if url[:2] == '//': netloc, url = _splitnetloc(url, 2) if (('[' in netloc and ']' not in netloc) or (']' in netloc and '[' not in netloc)): raise ValueError("Invalid IPv6 URL") + if '[' in netloc and ']' in netloc: + bracketed_host = netloc.partition('[')[2].partition(']')[0] + _check_bracketed_host(bracketed_host) if allow_fragments and '#' in url: url, fragment = url.split('#', 1) if '?' in url: 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-04-26-09-54-25.gh-issue-103848.aDSnpR.rst b/Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst new file mode 100644 index 00000000000000..81e5904aa6cca2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst @@ -0,0 +1,2 @@ +Add checks to ensure that ``[`` bracketed ``]`` hosts found by +:func:`urllib.parse.urlsplit` are of IPv6 or IPvFuture format. 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/Misc/NEWS.d/next/Library/2023-05-10-19-33-36.gh-issue-103000.j0KSfD.rst b/Misc/NEWS.d/next/Library/2023-05-10-19-33-36.gh-issue-103000.j0KSfD.rst new file mode 100644 index 00000000000000..f84ec5c8b3caf6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-05-10-19-33-36.gh-issue-103000.j0KSfD.rst @@ -0,0 +1,2 @@ +Improve performance of :func:`dataclasses.asdict` for the common case where +*dict_factory* is ``dict``. Patch by David C Ellis. diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index c05407b5d61815..ee4eca70e2af8f 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -730,9 +730,11 @@ PyInit__io(void) "UnsupportedOperation", PyExc_OSError, PyExc_ValueError); if (state->unsupported_operation == NULL) goto fail; - if (PyModule_AddObject(m, "UnsupportedOperation", - Py_NewRef(state->unsupported_operation)) < 0) + if (PyModule_AddObjectRef(m, "UnsupportedOperation", + state->unsupported_operation) < 0) + { goto fail; + } /* BlockingIOError, for compatibility */ if (PyModule_AddObjectRef(m, "BlockingIOError", @@ -770,7 +772,7 @@ PyInit__io(void) // PyRawIOBase_Type(PyIOBase_Type) subclasses ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, state->PyRawIOBase_Type); -#ifdef MS_WINDOWS +#ifdef HAVE_WINDOWS_CONSOLE_IO ADD_TYPE(m, state->PyWindowsConsoleIO_Type, &winconsoleio_spec, state->PyRawIOBase_Type); #endif @@ -785,7 +787,6 @@ PyInit__io(void) return m; fail: - Py_XDECREF(state->unsupported_operation); Py_DECREF(m); return NULL; } diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 1bf301c9cf0a94..44d651338e6975 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -34,9 +34,13 @@ extern PyType_Spec winconsoleio_spec; * with args=NULL, and return a new reference. * BUT when args=Py_True is passed, they return a borrowed reference. */ -extern PyObject* _PyIOBase_check_readable(PyObject *self, PyObject *args); -extern PyObject* _PyIOBase_check_writable(PyObject *self, PyObject *args); -extern PyObject* _PyIOBase_check_seekable(PyObject *self, PyObject *args); +typedef struct _io_state _PyIO_State; // Forward decl. +extern PyObject* _PyIOBase_check_readable(_PyIO_State *state, + PyObject *self, PyObject *args); +extern PyObject* _PyIOBase_check_writable(_PyIO_State *state, + PyObject *self, PyObject *args); +extern PyObject* _PyIOBase_check_seekable(_PyIO_State *state, + PyObject *self, PyObject *args); extern PyObject* _PyIOBase_check_closed(PyObject *self, PyObject *args); /* Helper for finalization. @@ -140,7 +144,7 @@ extern Py_off_t PyNumber_AsOff_t(PyObject *item, PyObject *err); extern PyModuleDef _PyIO_Module; -typedef struct { +struct _io_state { int initialized; PyObject *unsupported_operation; @@ -158,10 +162,10 @@ typedef struct { PyTypeObject *PyStringIO_Type; PyTypeObject *PyTextIOBase_Type; PyTypeObject *PyTextIOWrapper_Type; -#ifdef MS_WINDOWS +#ifdef HAVE_WINDOWS_CONSOLE_IO PyTypeObject *PyWindowsConsoleIO_Type; #endif -} _PyIO_State; +}; #define IO_MOD_STATE(mod) ((_PyIO_State *)PyModule_GetState(mod)) #define IO_STATE() _PyIO_get_module_state() diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 723d16b47fef9f..c7ae60281c2f58 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -106,17 +106,18 @@ _io__BufferedIOBase_readinto1_impl(PyObject *self, Py_buffer *buffer) } static PyObject * -bufferediobase_unsupported(const char *message) +bufferediobase_unsupported(_PyIO_State *state, const char *message) { - _PyIO_State *state = IO_STATE(); - if (state != NULL) - PyErr_SetString(state->unsupported_operation, message); + PyErr_SetString(state->unsupported_operation, message); return NULL; } /*[clinic input] _io._BufferedIOBase.detach + cls: defining_class + / + Disconnect this buffer from its underlying raw stream and return it. After the raw stream has been detached, the buffer is in an unusable @@ -124,62 +125,92 @@ state. [clinic start generated code]*/ static PyObject * -_io__BufferedIOBase_detach_impl(PyObject *self) -/*[clinic end generated code: output=754977c8d10ed88c input=822427fb58fe4169]*/ +_io__BufferedIOBase_detach_impl(PyObject *self, PyTypeObject *cls) +/*[clinic end generated code: output=b87b135d67cd4448 input=0b61a7b4357c1ea7]*/ { - return bufferediobase_unsupported("detach"); + _PyIO_State *state = IO_STATE(); + 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]*/ { - return bufferediobase_unsupported("read"); + _PyIO_State *state = IO_STATE(); + 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]*/ { - return bufferediobase_unsupported("read1"); + _PyIO_State *state = IO_STATE(); + 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]*/ { - return bufferediobase_unsupported("write"); + _PyIO_State *state = IO_STATE(); + return bufferediobase_unsupported(state, "write"); } @@ -1222,8 +1253,10 @@ _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence) CHECK_CLOSED(self, "seek of closed file") - if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL) + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + if (_PyIOBase_check_seekable(state, self->raw, Py_True) == NULL) { return NULL; + } target = PyNumber_AsOff_t(targetobj, PyExc_ValueError); if (target == -1 && PyErr_Occurred()) @@ -1298,7 +1331,8 @@ _io__Buffered_truncate_impl(buffered *self, PyObject *pos) CHECK_INITIALIZED(self) CHECK_CLOSED(self, "truncate of closed file") if (!self->writable) { - return bufferediobase_unsupported("truncate"); + _PyIO_State *state = IO_STATE(); + return bufferediobase_unsupported(state, "truncate"); } if (!ENTER_BUFFERED(self)) return NULL; @@ -1419,8 +1453,10 @@ _io_BufferedReader___init___impl(buffered *self, PyObject *raw, self->ok = 0; self->detached = 0; - if (_PyIOBase_check_readable(raw, Py_True) == NULL) + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + if (_PyIOBase_check_readable(state, raw, Py_True) == NULL) { return -1; + } Py_XSETREF(self->raw, Py_NewRef(raw)); self->buffer_size = buffer_size; @@ -1431,7 +1467,6 @@ _io_BufferedReader___init___impl(buffered *self, PyObject *raw, return -1; _bufferedreader_reset_buf(self); - _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); self->fast_closed_checks = ( Py_IS_TYPE(self, state->PyBufferedReader_Type) && Py_IS_TYPE(raw, state->PyFileIO_Type) @@ -1774,8 +1809,10 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw, self->ok = 0; self->detached = 0; - if (_PyIOBase_check_writable(raw, Py_True) == NULL) + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + if (_PyIOBase_check_writable(state, raw, Py_True) == NULL) { return -1; + } Py_INCREF(raw); Py_XSETREF(self->raw, raw); @@ -1788,7 +1825,6 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw, _bufferedwriter_reset_buf(self); self->pos = 0; - _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); self->fast_closed_checks = ( Py_IS_TYPE(self, state->PyBufferedWriter_Type) && Py_IS_TYPE(raw, state->PyFileIO_Type) @@ -2092,12 +2128,14 @@ _io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader, PyObject *writer, Py_ssize_t buffer_size) /*[clinic end generated code: output=327e73d1aee8f984 input=620d42d71f33a031]*/ { - if (_PyIOBase_check_readable(reader, Py_True) == NULL) + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + if (_PyIOBase_check_readable(state, reader, Py_True) == NULL) { return -1; - if (_PyIOBase_check_writable(writer, Py_True) == NULL) + } + if (_PyIOBase_check_writable(state, writer, Py_True) == NULL) { return -1; + } - _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); self->reader = (buffered *) PyObject_CallFunction( (PyObject *)state->PyBufferedReader_Type, "On", reader, buffer_size); @@ -2290,12 +2328,16 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, self->ok = 0; self->detached = 0; - if (_PyIOBase_check_seekable(raw, Py_True) == NULL) + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + if (_PyIOBase_check_seekable(state, raw, Py_True) == NULL) { return -1; - if (_PyIOBase_check_readable(raw, Py_True) == NULL) + } + if (_PyIOBase_check_readable(state, raw, Py_True) == NULL) { return -1; - if (_PyIOBase_check_writable(raw, Py_True) == NULL) + } + if (_PyIOBase_check_writable(state, raw, Py_True) == NULL) { return -1; + } Py_INCREF(raw); Py_XSETREF(self->raw, raw); @@ -2309,7 +2351,6 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, _bufferedwriter_reset_buf(self); self->pos = 0; - _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); self->fast_closed_checks = (Py_IS_TYPE(self, state->PyBufferedRandom_Type) && Py_IS_TYPE(raw, state->PyFileIO_Type)); @@ -2324,11 +2365,11 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, 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 d44321bb8b960e..a898b01899babe 100644 --- a/Modules/_io/clinic/bufferedio.c.h +++ b/Modules/_io/clinic/bufferedio.c.h @@ -92,15 +92,178 @@ PyDoc_STRVAR(_io__BufferedIOBase_detach__doc__, "state."); #define _IO__BUFFEREDIOBASE_DETACH_METHODDEF \ - {"detach", (PyCFunction)_io__BufferedIOBase_detach, METH_NOARGS, _io__BufferedIOBase_detach__doc__}, + {"detach", _PyCFunction_CAST(_io__BufferedIOBase_detach), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__BufferedIOBase_detach__doc__}, static PyObject * -_io__BufferedIOBase_detach_impl(PyObject *self); +_io__BufferedIOBase_detach_impl(PyObject *self, PyTypeObject *cls); static PyObject * -_io__BufferedIOBase_detach(PyObject *self, PyObject *Py_UNUSED(ignored)) +_io__BufferedIOBase_detach(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _io__BufferedIOBase_detach_impl(self); + if (nargs) { + PyErr_SetString(PyExc_TypeError, "detach() takes no arguments"); + return NULL; + } + 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__, @@ -714,4 +877,4 @@ _io_BufferedRandom___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=8412b10c04259bb8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c4ea041ccc91b5d2 input=a9049054013a1b77]*/ diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 682ed000eb1fd9..ca13866c33fba6 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -71,11 +71,9 @@ PyDoc_STRVAR(iobase_doc, /* Internal methods */ static PyObject * -iobase_unsupported(const char *message) +iobase_unsupported(_PyIO_State *state, const char *message) { - _PyIO_State *state = IO_STATE(); - if (state != NULL) - PyErr_SetString(state->unsupported_operation, message); + PyErr_SetString(state->unsupported_operation, message); return NULL; } @@ -97,7 +95,8 @@ PyDoc_STRVAR(iobase_seek_doc, static PyObject * iobase_seek(PyObject *self, PyObject *args) { - return iobase_unsupported("seek"); + _PyIO_State *state = IO_STATE(); + return iobase_unsupported(state, "seek"); } /*[clinic input] @@ -122,7 +121,8 @@ PyDoc_STRVAR(iobase_truncate_doc, static PyObject * iobase_truncate(PyObject *self, PyObject *args) { - return iobase_unsupported("truncate"); + _PyIO_State *state = IO_STATE(); + return iobase_unsupported(state, "truncate"); } static int @@ -204,6 +204,27 @@ _PyIOBase_check_closed(PyObject *self, PyObject *args) Py_RETURN_NONE; } +static PyObject * +iobase_check_seekable(PyObject *self, PyObject *args) +{ + _PyIO_State *state = IO_STATE(); + return _PyIOBase_check_seekable(state, self, args); +} + +static PyObject * +iobase_check_readable(PyObject *self, PyObject *args) +{ + _PyIO_State *state = IO_STATE(); + return _PyIOBase_check_readable(state, self, args); +} + +static PyObject * +iobase_check_writable(PyObject *self, PyObject *args) +{ + _PyIO_State *state = IO_STATE(); + return _PyIOBase_check_writable(state, self, args); +} + /* XXX: IOBase thinks it has to maintain its own internal state in `__IOBase_closed` and call flush() by itself, but it is redundant with whatever behaviour a non-trivial derived class will implement. */ @@ -372,14 +393,14 @@ _io__IOBase_seekable_impl(PyObject *self) } PyObject * -_PyIOBase_check_seekable(PyObject *self, PyObject *args) +_PyIOBase_check_seekable(_PyIO_State *state, PyObject *self, PyObject *args) { PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(seekable)); if (res == NULL) return NULL; if (res != Py_True) { Py_CLEAR(res); - iobase_unsupported("File or stream is not seekable."); + iobase_unsupported(state, "File or stream is not seekable."); return NULL; } if (args == Py_True) { @@ -405,14 +426,14 @@ _io__IOBase_readable_impl(PyObject *self) /* May be called with any object */ PyObject * -_PyIOBase_check_readable(PyObject *self, PyObject *args) +_PyIOBase_check_readable(_PyIO_State *state, PyObject *self, PyObject *args) { PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(readable)); if (res == NULL) return NULL; if (res != Py_True) { Py_CLEAR(res); - iobase_unsupported("File or stream is not readable."); + iobase_unsupported(state, "File or stream is not readable."); return NULL; } if (args == Py_True) { @@ -438,14 +459,14 @@ _io__IOBase_writable_impl(PyObject *self) /* May be called with any object */ PyObject * -_PyIOBase_check_writable(PyObject *self, PyObject *args) +_PyIOBase_check_writable(_PyIO_State *state, PyObject *self, PyObject *args) { PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(writable)); if (res == NULL) return NULL; if (res != Py_True) { Py_CLEAR(res); - iobase_unsupported("File or stream is not writable."); + iobase_unsupported(state, "File or stream is not writable."); return NULL; } if (args == Py_True) { @@ -487,7 +508,8 @@ static PyObject * _io__IOBase_fileno_impl(PyObject *self) /*[clinic end generated code: output=7cc0973f0f5f3b73 input=4e37028947dc1cc8]*/ { - return iobase_unsupported("fileno"); + _PyIO_State *state = IO_STATE(); + return iobase_unsupported(state, "fileno"); } /*[clinic input] @@ -798,9 +820,9 @@ static PyMethodDef iobase_methods[] = { _IO__IOBASE_WRITABLE_METHODDEF {"_checkClosed", _PyIOBase_check_closed, METH_NOARGS}, - {"_checkSeekable", _PyIOBase_check_seekable, METH_NOARGS}, - {"_checkReadable", _PyIOBase_check_readable, METH_NOARGS}, - {"_checkWritable", _PyIOBase_check_writable, METH_NOARGS}, + {"_checkSeekable", iobase_check_seekable, METH_NOARGS}, + {"_checkReadable", iobase_check_readable, METH_NOARGS}, + {"_checkWritable", iobase_check_writable, METH_NOARGS}, _IO__IOBASE_FILENO_METHODDEF _IO__IOBASE_ISATTY_METHODDEF diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index fdb57cff7c04d6..58d9f2963aa93c 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -263,7 +263,7 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj, int fd_is_own = 0; HANDLE handle = NULL; -#ifdef Py_DEBUG +#ifdef NDEBUG _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); assert(PyObject_TypeCheck(self, state->PyWindowsConsoleIO_Type)); #endif 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/Objects/genobject.c b/Objects/genobject.c index 937d497753e970..9252c654934565 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -1406,9 +1406,6 @@ typedef struct _PyAsyncGenWrappedValue { #define _PyAsyncGenWrappedValue_CheckExact(o) \ Py_IS_TYPE(o, &_PyAsyncGenWrappedValue_Type) -#define PyAsyncGenASend_CheckExact(o) \ - Py_IS_TYPE(o, &_PyAsyncGenASend_Type) - static int async_gen_traverse(PyAsyncGenObject *gen, visitproc visit, void *arg) 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: diff --git a/Python/specialize.c b/Python/specialize.c index 79ccb03bd82643..5071d8ef9a495d 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -433,27 +433,28 @@ _PyCode_Quicken(PyCodeObject *code) #define SPEC_FAIL_COMPARE_OP_FLOAT_LONG 21 #define SPEC_FAIL_COMPARE_OP_LONG_FLOAT 22 -/* FOR_ITER */ -#define SPEC_FAIL_FOR_ITER_GENERATOR 10 -#define SPEC_FAIL_FOR_ITER_COROUTINE 11 -#define SPEC_FAIL_FOR_ITER_ASYNC_GENERATOR 12 -#define SPEC_FAIL_FOR_ITER_LIST 13 -#define SPEC_FAIL_FOR_ITER_TUPLE 14 -#define SPEC_FAIL_FOR_ITER_SET 15 -#define SPEC_FAIL_FOR_ITER_STRING 16 -#define SPEC_FAIL_FOR_ITER_BYTES 17 -#define SPEC_FAIL_FOR_ITER_RANGE 18 -#define SPEC_FAIL_FOR_ITER_ITERTOOLS 19 -#define SPEC_FAIL_FOR_ITER_DICT_KEYS 20 -#define SPEC_FAIL_FOR_ITER_DICT_ITEMS 21 -#define SPEC_FAIL_FOR_ITER_DICT_VALUES 22 -#define SPEC_FAIL_FOR_ITER_ENUMERATE 23 -#define SPEC_FAIL_FOR_ITER_MAP 24 -#define SPEC_FAIL_FOR_ITER_ZIP 25 -#define SPEC_FAIL_FOR_ITER_SEQ_ITER 26 -#define SPEC_FAIL_FOR_ITER_REVERSED_LIST 27 -#define SPEC_FAIL_FOR_ITER_CALLABLE 28 -#define SPEC_FAIL_FOR_ITER_ASCII_STRING 29 +/* FOR_ITER and SEND */ +#define SPEC_FAIL_ITER_GENERATOR 10 +#define SPEC_FAIL_ITER_COROUTINE 11 +#define SPEC_FAIL_ITER_ASYNC_GENERATOR 12 +#define SPEC_FAIL_ITER_LIST 13 +#define SPEC_FAIL_ITER_TUPLE 14 +#define SPEC_FAIL_ITER_SET 15 +#define SPEC_FAIL_ITER_STRING 16 +#define SPEC_FAIL_ITER_BYTES 17 +#define SPEC_FAIL_ITER_RANGE 18 +#define SPEC_FAIL_ITER_ITERTOOLS 19 +#define SPEC_FAIL_ITER_DICT_KEYS 20 +#define SPEC_FAIL_ITER_DICT_ITEMS 21 +#define SPEC_FAIL_ITER_DICT_VALUES 22 +#define SPEC_FAIL_ITER_ENUMERATE 23 +#define SPEC_FAIL_ITER_MAP 24 +#define SPEC_FAIL_ITER_ZIP 25 +#define SPEC_FAIL_ITER_SEQ_ITER 26 +#define SPEC_FAIL_ITER_REVERSED_LIST 27 +#define SPEC_FAIL_ITER_CALLABLE 28 +#define SPEC_FAIL_ITER_ASCII_STRING 29 +#define SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND 30 // UNPACK_SEQUENCE @@ -2099,66 +2100,69 @@ int _PySpecialization_ClassifyIterator(PyObject *iter) { if (PyGen_CheckExact(iter)) { - return SPEC_FAIL_FOR_ITER_GENERATOR; + return SPEC_FAIL_ITER_GENERATOR; } if (PyCoro_CheckExact(iter)) { - return SPEC_FAIL_FOR_ITER_COROUTINE; + return SPEC_FAIL_ITER_COROUTINE; } if (PyAsyncGen_CheckExact(iter)) { - return SPEC_FAIL_FOR_ITER_ASYNC_GENERATOR; + return SPEC_FAIL_ITER_ASYNC_GENERATOR; + } + if (PyAsyncGenASend_CheckExact(iter)) { + return SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND; } PyTypeObject *t = Py_TYPE(iter); if (t == &PyListIter_Type) { - return SPEC_FAIL_FOR_ITER_LIST; + return SPEC_FAIL_ITER_LIST; } if (t == &PyTupleIter_Type) { - return SPEC_FAIL_FOR_ITER_TUPLE; + return SPEC_FAIL_ITER_TUPLE; } if (t == &PyDictIterKey_Type) { - return SPEC_FAIL_FOR_ITER_DICT_KEYS; + return SPEC_FAIL_ITER_DICT_KEYS; } if (t == &PyDictIterValue_Type) { - return SPEC_FAIL_FOR_ITER_DICT_VALUES; + return SPEC_FAIL_ITER_DICT_VALUES; } if (t == &PyDictIterItem_Type) { - return SPEC_FAIL_FOR_ITER_DICT_ITEMS; + return SPEC_FAIL_ITER_DICT_ITEMS; } if (t == &PySetIter_Type) { - return SPEC_FAIL_FOR_ITER_SET; + return SPEC_FAIL_ITER_SET; } if (t == &PyUnicodeIter_Type) { - return SPEC_FAIL_FOR_ITER_STRING; + return SPEC_FAIL_ITER_STRING; } if (t == &PyBytesIter_Type) { - return SPEC_FAIL_FOR_ITER_BYTES; + return SPEC_FAIL_ITER_BYTES; } if (t == &PyRangeIter_Type) { - return SPEC_FAIL_FOR_ITER_RANGE; + return SPEC_FAIL_ITER_RANGE; } if (t == &PyEnum_Type) { - return SPEC_FAIL_FOR_ITER_ENUMERATE; + return SPEC_FAIL_ITER_ENUMERATE; } if (t == &PyMap_Type) { - return SPEC_FAIL_FOR_ITER_MAP; + return SPEC_FAIL_ITER_MAP; } if (t == &PyZip_Type) { - return SPEC_FAIL_FOR_ITER_ZIP; + return SPEC_FAIL_ITER_ZIP; } if (t == &PySeqIter_Type) { - return SPEC_FAIL_FOR_ITER_SEQ_ITER; + return SPEC_FAIL_ITER_SEQ_ITER; } if (t == &PyListRevIter_Type) { - return SPEC_FAIL_FOR_ITER_REVERSED_LIST; + return SPEC_FAIL_ITER_REVERSED_LIST; } if (t == &_PyUnicodeASCIIIter_Type) { - return SPEC_FAIL_FOR_ITER_ASCII_STRING; + return SPEC_FAIL_ITER_ASCII_STRING; } const char *name = t->tp_name; if (strncmp(name, "itertools", 9) == 0) { - return SPEC_FAIL_FOR_ITER_ITERTOOLS; + return SPEC_FAIL_ITER_ITERTOOLS; } if (strncmp(name, "callable_iterator", 17) == 0) { - return SPEC_FAIL_FOR_ITER_CALLABLE; + return SPEC_FAIL_ITER_CALLABLE; } return SPEC_FAIL_OTHER; } diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index a6f330d1502dad..2ae8a02aa6d285 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -4701,10 +4701,8 @@ def bad_node(self, node): c_default = "NULL" elif (isinstance(expr, ast.BinOp) or (isinstance(expr, ast.UnaryOp) and - not (isinstance(expr.operand, ast.Num) or - (hasattr(ast, 'Constant') and - isinstance(expr.operand, ast.Constant) and - type(expr.operand.value) in (int, float, complex))) + not (isinstance(expr.operand, ast.Constant) and + type(expr.operand.value) in {int, float, complex}) )): c_default = kwargs.get("c_default") if not (isinstance(c_default, str) and c_default): @@ -4806,14 +4804,10 @@ def bad_node(self, node): self.function.parameters[key] = p def parse_converter(self, annotation): - if (hasattr(ast, 'Constant') and - isinstance(annotation, ast.Constant) and + if (isinstance(annotation, ast.Constant) and type(annotation.value) is str): return annotation.value, True, {} - if isinstance(annotation, ast.Str): - return annotation.s, True, {} - if isinstance(annotation, ast.Name): return annotation.id, False, {} diff --git a/Tools/scripts/summarize_stats.py b/Tools/scripts/summarize_stats.py index 9188555fb5255d..9c881897c2de1d 100644 --- a/Tools/scripts/summarize_stats.py +++ b/Tools/scripts/summarize_stats.py @@ -230,6 +230,8 @@ def kind_to_text(kind, defines, opname): opname = "SUPER" elif opname.endswith("ATTR"): opname = "ATTR" + elif opname in ("FOR_ITER", "SEND"): + opname = "ITER" elif opname.endswith("SUBSCR"): opname = "SUBSCR" for name in defines[kind]: