From 78738af19356b9e03695e900438e888882934e81 Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Wed, 26 Jan 2022 08:27:54 +0900 Subject: [PATCH] Imported Upstream version 3.9.9 --- Doc/glossary.rst | 9 +++--- Doc/library/contextvars.rst | 2 +- Doc/library/copy.rst | 2 +- Doc/library/socket.rst | 2 +- Doc/whatsnew/3.9.rst | 4 --- Include/patchlevel.h | 4 +-- Lib/argparse.py | 13 ++++---- Lib/copy.py | 4 +-- Lib/importlib/metadata.py | 2 +- Lib/json/tool.py | 21 ++++++++----- Lib/pydoc_data/topics.py | 2 +- Lib/test/test_argparse.py | 6 ---- Lib/test/test_json/test_tool.py | 9 ++++++ Lib/test/test_syntax.py | 8 ++++- Lib/tkinter/test/test_ttk/test_extensions.py | 10 +++---- Misc/NEWS | 44 ++++++++++++++++++++++++++++ Modules/_ctypes/libffi_osx/README | 2 +- Objects/typeobject.c | 4 +-- PC/getpathp.c | 1 - PC/pylauncher.rc | 5 ++++ PC/pyshellext.rc | 6 ++++ PC/python_exe.rc | 6 ++++ PC/python_nt.rc | 6 ++++ PC/pythonw_exe.rc | 6 ++++ PC/sqlite3.rc | 6 ++++ PCbuild/get_externals.bat | 6 ++-- PCbuild/pythoncore.vcxproj | 2 +- PCbuild/tcltk.props | 2 +- Parser/pegen/pegen.c | 12 ++------ Parser/tokenizer.c | 1 - README.rst | 2 +- 31 files changed, 145 insertions(+), 64 deletions(-) diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 96d33ac..da9dc9c 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -485,12 +485,13 @@ Glossary :func:`functools.singledispatch` decorator, and :pep:`443`. generic type - A :term:`type` that can be parameterized; typically a container like - :class:`list`. Used for :term:`type hints ` and + A :term:`type` that can be parameterized; typically a + :ref:`container class` such as :class:`list` or + :class:`dict`. Used for :term:`type hints ` and :term:`annotations `. - See :pep:`483` for more details, and :mod:`typing` or - :ref:`generic alias type ` for its uses. + For more details, see :ref:`generic alias types`, + :pep:`483`, :pep:`484`, :pep:`585`, and the :mod:`typing` module. GIL See :term:`global interpreter lock`. diff --git a/Doc/library/contextvars.rst b/Doc/library/contextvars.rst index 14ac47f..be1dd0c 100644 --- a/Doc/library/contextvars.rst +++ b/Doc/library/contextvars.rst @@ -94,7 +94,7 @@ Context Variables # var.get() would raise a LookupError. -.. class:: contextvars.Token +.. class:: Token *Token* objects are returned by the :meth:`ContextVar.set` method. They can be passed to the :meth:`ContextVar.reset` method to revert diff --git a/Doc/library/copy.rst b/Doc/library/copy.rst index 0eb5a79..ce50c33 100644 --- a/Doc/library/copy.rst +++ b/Doc/library/copy.rst @@ -60,7 +60,7 @@ The :func:`deepcopy` function avoids these problems by: components copied. This module does not copy types like module, method, stack trace, stack frame, -file, socket, window, array, or any similar types. It does "copy" functions and +file, socket, window, or any similar types. It does "copy" functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the :mod:`pickle` module. diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index db94a2a..f0a1338 100755 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -552,7 +552,7 @@ Creating sockets The following functions all create :ref:`socket objects `. -.. function:: socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) +.. class:: socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) Create a new socket using the given address family, socket type and protocol number. The address family should be :const:`AF_INET` (the default), diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index c29715d..0662adb 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -1377,10 +1377,6 @@ Porting to Python 3.9 becomes an alias to the :c:func:`PyObject_NewVar` macro. They no longer access directly the :c:member:`PyTypeObject.tp_basicsize` member. - * :c:func:`PyType_HasFeature` now always calls :c:func:`PyType_GetFlags`. - Previously, it accessed directly the :c:member:`PyTypeObject.tp_flags` - member when the limited C API was not used. - * :c:func:`PyObject_GET_WEAKREFS_LISTPTR` macro was converted to a function: the macro accessed directly the :c:member:`PyTypeObject.tp_weaklistoffset` member. diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 8057ab9..293e51a 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -18,12 +18,12 @@ /*--start constants--*/ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 9 -#define PY_MICRO_VERSION 8 +#define PY_MICRO_VERSION 9 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.9.8" +#define PY_VERSION "3.9.9" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/argparse.py b/Lib/argparse.py index cb5345d..7c28547 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1209,8 +1209,7 @@ class _SubParsersAction(Action): # namespace for the relevant parts. subnamespace, arg_strings = parser.parse_known_args(arg_strings, None) for key, value in vars(subnamespace).items(): - if not hasattr(namespace, key): - setattr(namespace, key, value) + setattr(namespace, key, value) if arg_strings: vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, []) @@ -1844,6 +1843,11 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): if action.default is not SUPPRESS: setattr(namespace, action.dest, action.default) + # add any parser defaults that aren't present + for dest in self._defaults: + if not hasattr(namespace, dest): + setattr(namespace, dest, self._defaults[dest]) + # parse the arguments and exit if there are any errors if self.exit_on_error: try: @@ -1854,11 +1858,6 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): else: namespace, args = self._parse_known_args(args, namespace) - # add any parser defaults that aren't present - for dest in self._defaults: - if not hasattr(namespace, dest): - setattr(namespace, dest, self._defaults[dest]) - if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR): args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR)) delattr(namespace, _UNRECOGNIZED_ARGS_ATTR) diff --git a/Lib/copy.py b/Lib/copy.py index 41873f2..1081d43 100644 --- a/Lib/copy.py +++ b/Lib/copy.py @@ -39,8 +39,8 @@ Python's deep copy operation avoids these problems by: set of components copied This version does not copy types like module, class, function, method, -nor stack trace, stack frame, nor file, socket, window, nor array, nor -any similar types. +nor stack trace, stack frame, nor file, socket, window, nor any +similar types. Classes can use the same interfaces to control copying that they use to control pickling: they can define methods called __getinitargs__(), diff --git a/Lib/importlib/metadata.py b/Lib/importlib/metadata.py index ffa0cba..c6c7d31 100644 --- a/Lib/importlib/metadata.py +++ b/Lib/importlib/metadata.py @@ -419,7 +419,7 @@ class FastPath: def children(self): with suppress(Exception): - return os.listdir(self.root or '') + return os.listdir(self.root or '.') with suppress(Exception): return self.zip_children() return [] diff --git a/Lib/json/tool.py b/Lib/json/tool.py index 5dee0a7..0490b8c 100644 --- a/Lib/json/tool.py +++ b/Lib/json/tool.py @@ -13,6 +13,7 @@ Usage:: import argparse import json import sys +from pathlib import Path def main(): @@ -25,9 +26,9 @@ def main(): help='a JSON file to be validated or pretty-printed', default=sys.stdin) parser.add_argument('outfile', nargs='?', - type=argparse.FileType('w', encoding="utf-8"), + type=Path, help='write the output of infile to outfile', - default=sys.stdout) + default=None) parser.add_argument('--sort-keys', action='store_true', default=False, help='sort the output of dictionaries alphabetically by key') parser.add_argument('--no-ensure-ascii', dest='ensure_ascii', action='store_false', @@ -58,15 +59,21 @@ def main(): dump_args['indent'] = None dump_args['separators'] = ',', ':' - with options.infile as infile, options.outfile as outfile: + with options.infile as infile: try: if options.json_lines: objs = (json.loads(line) for line in infile) else: - objs = (json.load(infile), ) - for obj in objs: - json.dump(obj, outfile, **dump_args) - outfile.write('\n') + objs = (json.load(infile),) + + if options.outfile is None: + out = sys.stdout + else: + out = options.outfile.open('w', encoding='utf-8') + with out as outfile: + for obj in objs: + json.dump(obj, outfile, **dump_args) + outfile.write('\n') except ValueError as e: raise SystemExit(e) diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index 8567e30..890a616 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Fri Nov 5 20:19:23 2021 +# Autogenerated by Sphinx on Mon Nov 15 18:21:10 2021 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index c3c3a75..d79ac5a 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -3095,12 +3095,6 @@ class TestSetDefaults(TestCase): xparser.set_defaults(foo=2) self.assertEqual(NS(foo=2), parser.parse_args(['X'])) - def test_set_defaults_on_subparser_with_namespace(self): - parser = argparse.ArgumentParser() - xparser = parser.add_subparsers().add_parser('X') - xparser.set_defaults(foo=1) - self.assertEqual(NS(foo=2), parser.parse_args(['X'], NS(foo=2))) - def test_set_defaults_same_as_add_argument(self): parser = ErrorRaisingArgumentParser() parser.set_defaults(w='W', x='X', y='Y', z='Z') diff --git a/Lib/test/test_json/test_tool.py b/Lib/test/test_json/test_tool.py index fc2a7a4..d441bb1 100644 --- a/Lib/test/test_json/test_tool.py +++ b/Lib/test/test_json/test_tool.py @@ -130,6 +130,15 @@ class TestTool(unittest.TestCase): self.assertEqual(out, b'') self.assertEqual(err, b'') + def test_writing_in_place(self): + infile = self._create_infile() + rc, out, err = assert_python_ok('-m', 'json.tool', infile, infile) + with open(infile, "r", encoding="utf-8") as fp: + self.assertEqual(fp.read(), self.expect) + self.assertEqual(rc, 0) + self.assertEqual(out, b'') + self.assertEqual(err, b'') + def test_jsonlines(self): args = sys.executable, '-m', 'json.tool', '--json-lines' process = subprocess.run(args, input=self.jsonlines_raw, capture_output=True, text=True, check=True) diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index eaa94ea..46f27d0 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -953,7 +953,13 @@ def func2(): def test_invalid_line_continuation_error_position(self): self._check_error(r"a = 3 \ 4", "unexpected character after line continuation character", - lineno=1, offset=(10 if support.use_old_parser() else 9)) + lineno=1, offset=8) + self._check_error('1,\\#\n2', + "unexpected character after line continuation character", + lineno=1, offset=4) + self._check_error('\nfgdfgf\n1,\\#\n2\n', + "unexpected character after line continuation character", + lineno=3, offset=4) def test_invalid_line_continuation_left_recursive(self): # Check bpo-42218: SyntaxErrors following left-recursive rules diff --git a/Lib/tkinter/test/test_ttk/test_extensions.py b/Lib/tkinter/test/test_ttk/test_extensions.py index 7fc1ebb..1220c48 100644 --- a/Lib/tkinter/test/test_ttk/test_extensions.py +++ b/Lib/tkinter/test/test_ttk/test_extensions.py @@ -307,14 +307,14 @@ class OptionMenuTest(AbstractTkTest, unittest.TestCase): items = ('a', 'b', 'c') textvar = tkinter.StringVar(self.root) def cb_test(*args): - self.assertEqual(textvar.get(), items[1]) - success.append(True) + success.append(textvar.get()) optmenu = ttk.OptionMenu(self.root, textvar, "a", *items) optmenu.pack() - cb_name = textvar.trace("w", cb_test) + cb_name = textvar.trace_add("write", cb_test) optmenu['menu'].invoke(1) - self.assertEqual(success, [True]) - textvar.trace_vdelete("w", cb_name) + self.assertEqual(success, ['b']) + self.assertEqual(textvar.get(), 'b') + textvar.trace_remove("write", cb_name) optmenu.destroy() diff --git a/Misc/NEWS b/Misc/NEWS index 7e68c91..9cebf20 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,50 @@ Python News +++++++++++ +What's New in Python 3.9.9 final? +================================= + +*Release date: 2021-11-15* + +Core and Builtins +----------------- + +- bpo-45738: Fix computation of error location for invalid continuation + characters in the parser. Patch by Pablo Galindo. + +Library +------- + +- bpo-45235: Reverted an argparse bugfix that caused regression in the + handling of default arguments for subparsers. This prevented leaf level + arguments from taking precedence over root level arguments. + +- bpo-45765: In importlib.metadata, fix distribution discovery for an empty + path. + +- bpo-45644: In-place JSON file formatting using ``python3 -m json.tool + infile infile`` now works correctly, previously it left the file empty. + Patch by Chris Wesseling. + +Documentation +------------- + +- bpo-45772: ``socket.socket`` documentation is corrected to a class from a + function. + +- bpo-45392: Update the docstring of the :class:`type` built-in to remove a + redundant line and to mention keyword arguments for the constructor. + +Windows +------- + +- bpo-45732: Updates bundled Tcl/Tk to 8.6.12. + +- bpo-45720: Internal reference to :file:`shlwapi.dll` was dropped to help + improve startup time. This DLL will no longer be loaded at the start of + every Python process. + + What's New in Python 3.9.8 final? ================================= diff --git a/Modules/_ctypes/libffi_osx/README b/Modules/_ctypes/libffi_osx/README index 69e46cb..54f00e3 100644 --- a/Modules/_ctypes/libffi_osx/README +++ b/Modules/_ctypes/libffi_osx/README @@ -165,7 +165,7 @@ for checking. It will be one of the following: Before making the call, the VALUES vector should be initialized with pointers to the appropriate argument values. -To call the the function using the initialized ffi_cif, use the +To call the function using the initialized ffi_cif, use the ffi_call function: void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index feae25f..1cdf80b 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3673,10 +3673,8 @@ static PyMethodDef type_methods[] = { }; PyDoc_STRVAR(type_doc, -/* this text signature cannot be accurate yet. will fix. --larry */ -"type(object_or_name, bases, dict)\n" "type(object) -> the object's type\n" -"type(name, bases, dict) -> a new type"); +"type(name, bases, dict, **kwds) -> a new type"); static int type_traverse(PyTypeObject *type, visitproc visit, void *arg) diff --git a/PC/getpathp.c b/PC/getpathp.c index dc5b201..7c0eeab 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -91,7 +91,6 @@ #include #include -#include #ifdef HAVE_SYS_TYPES_H #include diff --git a/PC/pylauncher.rc b/PC/pylauncher.rc index d21f9b6..ff7e71e 100644 --- a/PC/pylauncher.rc +++ b/PC/pylauncher.rc @@ -2,6 +2,11 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/pyshellext.rc b/PC/pyshellext.rc index fc607e9..af797ce 100644 --- a/PC/pyshellext.rc +++ b/PC/pyshellext.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/python_exe.rc b/PC/python_exe.rc index 5eba899..c3d3bff 100644 --- a/PC/python_exe.rc +++ b/PC/python_exe.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/python_nt.rc b/PC/python_nt.rc index 6fd872c..ae64fbd 100644 --- a/PC/python_nt.rc +++ b/PC/python_nt.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 2 RT_MANIFEST "python.manifest" diff --git a/PC/pythonw_exe.rc b/PC/pythonw_exe.rc index 562652b..38570b7 100644 --- a/PC/pythonw_exe.rc +++ b/PC/pythonw_exe.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/sqlite3.rc b/PC/sqlite3.rc index d2c18f8..9ae2aa0 100644 --- a/PC/sqlite3.rc +++ b/PC/sqlite3.rc @@ -2,6 +2,12 @@ #include +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 2 RT_MANIFEST "python.manifest" diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index c3a7748..9dd0866 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -55,8 +55,8 @@ set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.3.0 if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1l set libraries=%libraries% sqlite-3.35.5.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.9.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.9.0 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.12.0 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.12.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tix-8.4.3.6 set libraries=%libraries% xz-5.2.2 set libraries=%libraries% zlib-1.2.11 @@ -78,7 +78,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.3.0 if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1l -if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.9.0 +if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.12.0 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 for %%b in (%binaries%) do ( diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index c942e9e..1df62ca 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -106,7 +106,7 @@ _Py_HAVE_ZLIB;%(PreprocessorDefinitions) - version.lib;shlwapi.lib;ws2_32.lib;pathcch.lib;%(AdditionalDependencies) + version.lib;ws2_32.lib;pathcch.lib;%(AdditionalDependencies) diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props index d2f9496..e804cc5 100644 --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -4,7 +4,7 @@ 8 6 - 9 + 12 0 $(TclMajorVersion) $(TclMinorVersion) diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c index 98de05c..efcf9ac 100644 --- a/Parser/pegen/pegen.c +++ b/Parser/pegen/pegen.c @@ -348,14 +348,7 @@ tokenizer_error(Parser *p) msg = "too many levels of indentation"; break; case E_LINECONT: { - char* loc = strrchr(p->tok->buf, '\n'); - const char* last_char = p->tok->cur - 1; - if (loc != NULL && loc != last_char) { - col_offset = p->tok->cur - loc - 1; - p->tok->buf = loc; - } else { - col_offset = last_char - p->tok->buf - 1; - } + col_offset = p->tok->cur - p->tok->buf - 1; msg = "unexpected character after line continuation character"; break; } @@ -363,7 +356,8 @@ tokenizer_error(Parser *p) msg = "unknown parsing error"; } - RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno, col_offset, msg); + RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno, + col_offset >= 0 ? col_offset : 0, msg); return -1; } diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 1a57db9..41bfdb8 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1752,7 +1752,6 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) c = tok_nextc(tok); if (c != '\n') { tok->done = E_LINECONT; - tok->cur = tok->inp; return ERRORTOKEN; } c = tok_nextc(tok); diff --git a/README.rst b/README.rst index ef78796..b808463 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -This is Python version 3.9.8 +This is Python version 3.9.9 ============================ .. image:: https://travis-ci.org/python/cpython.svg?branch=3.9 -- 2.7.4