Skip to content

Commit 5c0a21c

Browse files
committed
Merge branch 'main' into superopt
* main: (24 commits) pythongh-98040: Move the Single-Phase Init Tests Out of test_imp (pythongh-102561) pythongh-83861: Fix datetime.astimezone() method (pythonGH-101545) pythongh-102856: Clean some of the PEP 701 tokenizer implementation (python#103634) pythongh-102856: Skip test_mismatched_parens in WASI builds (python#103633) pythongh-102856: Initial implementation of PEP 701 (python#102855) pythongh-103583: Add ref. dependency between multibytecodec modules (python#103589) pythongh-83004: Harden msvcrt further (python#103420) pythonGH-88342: clarify that `asyncio.as_completed` accepts generators yielding tasks (python#103626) pythongh-102778: IDLE - make sys.last_exc available in Shell after traceback (python#103314) pythongh-103582: Remove last references to `argparse.REMAINDER` from docs (python#103586) pythongh-103583: Always pass multibyte codec structs as const (python#103588) pythongh-103617: Fix compiler warning in _iomodule.c (python#103618) pythongh-103596: [Enum] do not shadow mixed-in methods/attributes (pythonGH-103600) pythonGH-100530: Change the error message for non-class class patterns (pythonGH-103576) pythongh-95299: Remove lingering setuptools reference in installer scripts (pythonGH-103613) [Doc] Fix a typo in optparse.rst (python#103504) pythongh-101100: Fix broken reference `__format__` in `string.rst` (python#103531) pythongh-95299: Stop installing setuptools as a part of ensurepip and venv (python#101039) pythonGH-103484: Docs: add linkcheck allowed redirects entries for most cases (python#103569) pythongh-67230: update whatsnew note for csv changes (python#103598) ...
2 parents e4466a7 + 6be7aee commit 5c0a21c

File tree

81 files changed

+7953
-5337
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+7953
-5337
lines changed

.gitattributes

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Lib/test/xmltestdata/* noeol
3434

3535
# Shell scripts should have LF even on Windows because of Cygwin
3636
Lib/venv/scripts/common/activate text eol=lf
37+
Lib/venv/scripts/posix/* text eol=lf
3738

3839
# CRLF files
3940
[attr]dos text eol=crlf

.github/workflows/verify-ensurepip-wheels.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Verify bundled pip and setuptools
1+
name: Verify bundled wheels
22

33
on:
44
workflow_dispatch:
@@ -29,5 +29,5 @@ jobs:
2929
- uses: actions/setup-python@v4
3030
with:
3131
python-version: '3'
32-
- name: Compare checksums of bundled pip and setuptools to ones published on PyPI
32+
- name: Compare checksum of bundled wheels to the ones published on PyPI
3333
run: ./Tools/build/verify_ensurepip_wheels.py

Doc/conf.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,14 @@
254254
# Options for the link checker
255255
# ----------------------------
256256

257-
# Ignore certain URLs.
258-
linkcheck_ignore = [r'https://bugs.python.org/(issue)?\d+']
259-
257+
linkcheck_allowed_redirects = {
258+
# bpo-NNNN -> BPO -> GH Issues
259+
r'https://bugs.python.org/issue\?@action=redirect&bpo=\d+': 'https://github.com/python/cpython/issues/\d+',
260+
# GH-NNNN used to refer to pull requests
261+
r'https://github.com/python/cpython/issues/\d+': 'https://github.com/python/cpython/pull/\d+',
262+
# :source:`something` linking files in the repository
263+
r'https://github.com/python/cpython/tree/.*': 'https://github.com/python/cpython/blob/.*'
264+
}
260265

261266
# Options for extensions
262267
# ----------------------

Doc/howto/enum.rst

+11-3
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@ inherits from :class:`Enum` itself.
3636

3737
.. note:: Case of Enum Members
3838

39-
Because Enums are used to represent constants we recommend using
40-
UPPER_CASE names for members, and will be using that style in our examples.
39+
Because Enums are used to represent constants, and to help avoid issues
40+
with name clashes between mixin-class methods/attributes and enum names,
41+
we strongly recommend using UPPER_CASE names for members, and will be using
42+
that style in our examples.
4143

4244
Depending on the nature of the enum a member's value may or may not be
4345
important, but either way that value can be used to get the corresponding
@@ -490,6 +492,10 @@ the :meth:`~Enum.__repr__` omits the inherited class' name. For example::
490492
Use the :func:`!dataclass` argument ``repr=False``
491493
to use the standard :func:`repr`.
492494

495+
.. versionchanged:: 3.12
496+
Only the dataclass fields are shown in the value area, not the dataclass'
497+
name.
498+
493499

494500
Pickling
495501
--------
@@ -992,7 +998,9 @@ but remain normal attributes.
992998
Enum members are instances of their enum class, and are normally accessed as
993999
``EnumClass.member``. In certain situations, such as writing custom enum
9941000
behavior, being able to access one member directly from another is useful,
995-
and is supported.
1001+
and is supported; however, in order to avoid name clashes between member names
1002+
and attributes/methods from mixed-in classes, upper-case names are strongly
1003+
recommended.
9961004

9971005
.. versionchanged:: 3.5
9981006

Doc/library/argparse.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ default_ Default value used when an argument is not provided
6767
dest_ Specify the attribute name used in the result namespace
6868
help_ Help message for an argument
6969
metavar_ Alternate display name for the argument as shown in help
70-
nargs_ Number of times the argument can be used :class:`int`, ``'?'``, ``'*'``, ``'+'``, or ``argparse.REMAINDER``
70+
nargs_ Number of times the argument can be used :class:`int`, ``'?'``, ``'*'``, or ``'+'``
7171
required_ Indicate whether an argument is required or optional ``True`` or ``False``
7272
type_ Automatically convert an argument to the given type :class:`int`, :class:`float`, ``argparse.FileType('w')``, or callable function
7373
====================== =========================================================== ==========================================================================================================================
@@ -2218,7 +2218,7 @@ support this parsing style.
22182218

22192219
These parsers do not support all the argparse features, and will raise
22202220
exceptions if unsupported features are used. In particular, subparsers,
2221-
``argparse.REMAINDER``, and mutually exclusive groups that include both
2221+
and mutually exclusive groups that include both
22222222
optionals and positionals are not supported.
22232223

22242224
The following example shows the difference between

Doc/library/asyncio-task.rst

+3
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,9 @@ Waiting Primitives
829829
Deprecation warning is emitted if not all awaitable objects in the *aws*
830830
iterable are Future-like objects and there is no running event loop.
831831

832+
.. versionchanged:: 3.12
833+
Added support for generators yielding tasks.
834+
832835

833836
Running in Threads
834837
==================

Doc/library/enum.rst

+4-3
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ Module Contents
119119
:func:`~enum.property`
120120

121121
Allows :class:`Enum` members to have attributes without conflicting with
122-
member names.
122+
member names. The ``value`` and ``name`` attributes are implemented this
123+
way.
123124

124125
:func:`unique`
125126

@@ -169,7 +170,7 @@ Data Types
169170
final *enum*, as well as creating the enum members, properly handling
170171
duplicates, providing iteration over the enum class, etc.
171172

172-
.. method:: EnumType.__call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
173+
.. method:: EnumType.__call__(cls, value, names=None, \*, module=None, qualname=None, type=None, start=1, boundary=None)
173174

174175
This method is called in two different ways:
175176

@@ -317,7 +318,7 @@ Data Types
317318
>>> PowersOfThree.SECOND.value
318319
9
319320

320-
.. method:: Enum.__init_subclass__(cls, **kwds)
321+
.. method:: Enum.__init_subclass__(cls, \**kwds)
321322

322323
A *classmethod* that is used to further configure subsequent subclasses.
323324
By default, does nothing.

Doc/library/optparse.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -2027,7 +2027,7 @@ Features of note:
20272027
values.ensure_value(attr, value)
20282028

20292029
If the ``attr`` attribute of ``values`` doesn't exist or is ``None``, then
2030-
ensure_value() first sets it to ``value``, and then returns 'value. This is
2030+
ensure_value() first sets it to ``value``, and then returns ``value``. This is
20312031
very handy for actions like ``"extend"``, ``"append"``, and ``"count"``, all
20322032
of which accumulate data in a variable and expect that variable to be of a
20332033
certain type (a list for the first two, an integer for the latter). Using

Doc/library/string.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,10 @@ Some simple format string examples::
254254
"Units destroyed: {players[0]}" # First element of keyword argument 'players'.
255255

256256
The *conversion* field causes a type coercion before formatting. Normally, the
257-
job of formatting a value is done by the :meth:`__format__` method of the value
257+
job of formatting a value is done by the :meth:`~object.__format__` method of the value
258258
itself. However, in some cases it is desirable to force a type to be formatted
259259
as a string, overriding its own definition of formatting. By converting the
260-
value to a string before calling :meth:`__format__`, the normal formatting logic
260+
value to a string before calling :meth:`~object.__format__`, the normal formatting logic
261261
is bypassed.
262262

263263
Three conversion flags are currently supported: ``'!s'`` which calls :func:`str`

Doc/library/token-list.inc

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Doc/library/venv.rst

+5-2
Original file line numberDiff line numberDiff line change
@@ -284,11 +284,14 @@ creation according to their needs, the :class:`EnvBuilder` class.
284284

285285
.. method:: upgrade_dependencies(context)
286286

287-
Upgrades the core venv dependency packages (currently ``pip`` and
288-
``setuptools``) in the environment. This is done by shelling out to the
287+
Upgrades the core venv dependency packages (currently ``pip``)
288+
in the environment. This is done by shelling out to the
289289
``pip`` executable in the environment.
290290

291291
.. versionadded:: 3.9
292+
.. versionchanged:: 3.12
293+
294+
``setuptools`` is no longer a core venv dependency.
292295

293296
.. method:: post_setup(context)
294297

Doc/using/venv-create.inc

+5-2
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,16 @@ The command, if run with ``-h``, will show the available options::
6161
environment (pip is bootstrapped by default)
6262
--prompt PROMPT Provides an alternative prompt prefix for this
6363
environment.
64-
--upgrade-deps Upgrade core dependencies: pip setuptools to the
64+
--upgrade-deps Upgrade core dependencies (pip) to the
6565
latest version in PyPI
6666
6767
Once an environment has been created, you may wish to activate it, e.g. by
6868
sourcing an activate script in its bin directory.
6969
70+
.. versionchanged:: 3.12
71+
72+
``setuptools`` is no longer a core venv dependency.
73+
7074
.. versionchanged:: 3.9
7175
Add ``--upgrade-deps`` option to upgrade pip + setuptools to the latest on PyPI
7276
@@ -104,4 +108,3 @@ invoked to bootstrap ``pip`` into the virtual environment.
104108
Multiple paths can be given to ``venv``, in which case an identical virtual
105109
environment will be created, according to the given options, at each provided
106110
path.
107-

Doc/whatsnew/3.12.rst

+21-2
Original file line numberDiff line numberDiff line change
@@ -250,15 +250,16 @@ asyncio
250250
:mod:`asyncio` does not support legacy generator-based coroutines.
251251
(Contributed by Kumar Aditya in :gh:`102748`.)
252252

253-
* :func:`asyncio.wait` now accepts generators yielding tasks.
253+
* :func:`asyncio.wait` and :func:`asyncio.as_completed` now accepts generators
254+
yielding tasks.
254255
(Contributed by Kumar Aditya in :gh:`78530`.)
255256

256257
csv
257258
---
258259

259260
* Add :data:`~csv.QUOTE_NOTNULL` and :data:`~csv.QUOTE_STRINGS` flags to
260261
provide finer grained control of ``None`` and empty strings by
261-
:class:`~csv.reader` and :class:`~csv.writer` objects.
262+
:class:`~csv.writer` objects.
262263

263264
inspect
264265
-------
@@ -731,6 +732,24 @@ Removed
731732
project can be installed: it still provides ``distutils``.
732733
(Contributed by Victor Stinner in :gh:`92584`.)
733734

735+
* Remove the bundled setuptools wheel from :mod:`ensurepip`,
736+
and stop installing setuptools in environments created by :mod:`venv`.
737+
738+
``pip (>= 22.1)`` does not require setuptools to be installed in the
739+
environment. ``setuptools``-based (and ``distutils``-based) packages
740+
can still be used with ``pip install``, since pip will provide
741+
``setuptools`` in the build environment it uses for building a
742+
package.
743+
744+
``easy_install``, ``pkg_resources``, ``setuptools`` and ``distutils``
745+
are no longer provided by default in environments created with
746+
``venv`` or bootstrapped with ``ensurepip``, since they are part of
747+
the ``setuptools`` package. For projects relying on these at runtime,
748+
the ``setuptools`` project should be declared as a dependency and
749+
installed separately (typically, using pip).
750+
751+
(Contributed by Pradyun Gedam in :gh:`95299`.)
752+
734753
* Removed many old deprecated :mod:`unittest` features:
735754

736755
- A number of :class:`~unittest.TestCase` method aliases:

Grammar/Tokens

+4
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,17 @@ ATEQUAL '@='
5353
RARROW '->'
5454
ELLIPSIS '...'
5555
COLONEQUAL ':='
56+
EXCLAMATION '!'
5657

5758
OP
5859
AWAIT
5960
ASYNC
6061
TYPE_IGNORE
6162
TYPE_COMMENT
6263
SOFT_KEYWORD
64+
FSTRING_START
65+
FSTRING_MIDDLE
66+
FSTRING_END
6367
ERRORTOKEN
6468

6569
# These aren't used by the C tokenizer but are needed for tokenize.py

Grammar/python.gram

+48-6
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ yield_stmt[stmt_ty]: y=yield_expr { _PyAST_Expr(y, EXTRA) }
194194

195195
assert_stmt[stmt_ty]: 'assert' a=expression b=[',' z=expression { z }] { _PyAST_Assert(a, b, EXTRA) }
196196

197-
import_stmt[stmt_ty]:
197+
import_stmt[stmt_ty]:
198198
| invalid_import
199199
| import_name
200200
| import_from
@@ -415,8 +415,8 @@ try_stmt[stmt_ty]:
415415
| invalid_try_stmt
416416
| 'try' &&':' b=block f=finally_block { _PyAST_Try(b, NULL, NULL, f, EXTRA) }
417417
| 'try' &&':' b=block ex[asdl_excepthandler_seq*]=except_block+ el=[else_block] f=[finally_block] { _PyAST_Try(b, ex, el, f, EXTRA) }
418-
| 'try' &&':' b=block ex[asdl_excepthandler_seq*]=except_star_block+ el=[else_block] f=[finally_block] {
419-
CHECK_VERSION(stmt_ty, 11, "Exception groups are",
418+
| 'try' &&':' b=block ex[asdl_excepthandler_seq*]=except_star_block+ el=[else_block] f=[finally_block] {
419+
CHECK_VERSION(stmt_ty, 11, "Exception groups are",
420420
_PyAST_TryStar(b, ex, el, f, EXTRA)) }
421421

422422

@@ -807,7 +807,7 @@ atom[expr_ty]:
807807
| 'True' { _PyAST_Constant(Py_True, NULL, EXTRA) }
808808
| 'False' { _PyAST_Constant(Py_False, NULL, EXTRA) }
809809
| 'None' { _PyAST_Constant(Py_None, NULL, EXTRA) }
810-
| &STRING strings
810+
| &(STRING|FSTRING_START) strings
811811
| NUMBER
812812
| &'(' (tuple | group | genexp)
813813
| &'[' (list | listcomp)
@@ -877,7 +877,26 @@ lambda_param[arg_ty]: a=NAME { _PyAST_arg(a->v.Name.id, NULL, NULL, EXTRA) }
877877
# LITERALS
878878
# ========
879879

880-
strings[expr_ty] (memo): a=STRING+ { _PyPegen_concatenate_strings(p, a) }
880+
fstring_middle[expr_ty]:
881+
| fstring_replacement_field
882+
| t=FSTRING_MIDDLE { _PyPegen_constant_from_token(p, t) }
883+
fstring_replacement_field[expr_ty]:
884+
| '{' a=(yield_expr | star_expressions) debug_expr="="? conversion=[fstring_conversion] format=[fstring_full_format_spec] '}' {
885+
_PyPegen_formatted_value(p, a, debug_expr, conversion, format, EXTRA)
886+
}
887+
| invalid_replacement_field
888+
fstring_conversion[expr_ty]:
889+
| conv_token="!" conv=NAME { _PyPegen_check_fstring_conversion(p, conv_token, conv) }
890+
fstring_full_format_spec[expr_ty]:
891+
| ':' spec=fstring_format_spec* { spec ? _PyAST_JoinedStr((asdl_expr_seq*)spec, EXTRA) : NULL }
892+
fstring_format_spec[expr_ty]:
893+
| t=FSTRING_MIDDLE { _PyPegen_constant_from_token(p, t) }
894+
| fstring_replacement_field
895+
fstring[expr_ty]:
896+
| a=FSTRING_START b=fstring_middle* c=FSTRING_END { _PyPegen_joined_str(p, a, (asdl_expr_seq*)b, c) }
897+
898+
string[expr_ty]: s[Token*]=STRING { _PyPegen_constant_from_string(p, s) }
899+
strings[expr_ty] (memo): a[asdl_expr_seq*]=(fstring|string)+ { _PyPegen_concatenate_strings(p, a, EXTRA) }
881900

882901
list[expr_ty]:
883902
| '[' a=[star_named_expressions] ']' { _PyAST_List(a, Load, EXTRA) }
@@ -1118,6 +1137,8 @@ invalid_expression:
11181137
_PyPegen_check_legacy_stmt(p, a) ? NULL : p->tokens[p->mark-1]->level == 0 ? NULL :
11191138
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Perhaps you forgot a comma?") }
11201139
| a=disjunction 'if' b=disjunction !('else'|':') { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "expected 'else' after 'if' expression") }
1140+
| a='lambda' [lambda_params] b=':' &(FSTRING_MIDDLE | fstring_replacement_field) {
1141+
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "f-string: lambda expressions are not allowed without parentheses") }
11211142

11221143
invalid_named_expression(memo):
11231144
| a=expression ':=' expression {
@@ -1241,7 +1262,7 @@ invalid_group:
12411262
invalid_import:
12421263
| a='import' dotted_name 'from' dotted_name {
12431264
RAISE_SYNTAX_ERROR_STARTING_FROM(a, "Did you mean to use 'from ... import ...' instead?") }
1244-
1265+
12451266
invalid_import_from_targets:
12461267
| import_from_as_names ',' NEWLINE {
12471268
RAISE_SYNTAX_ERROR("trailing comma not allowed without surrounding parentheses") }
@@ -1335,3 +1356,24 @@ invalid_kvpair:
13351356
| expression a=':' &('}'|',') {RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "expression expected after dictionary key and ':'") }
13361357
invalid_starred_expression:
13371358
| a='*' expression '=' b=expression { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "cannot assign to iterable argument unpacking") }
1359+
invalid_replacement_field:
1360+
| '{' a='=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '='") }
1361+
| '{' a='!' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '!'") }
1362+
| '{' a=':' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before ':'") }
1363+
| '{' a='}' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '}'") }
1364+
| '{' !(yield_expr | star_expressions) { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting a valid expression after '{'")}
1365+
| '{' (yield_expr | star_expressions) !('=' | '!' | ':' | '}') {
1366+
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '=', or '!', or ':', or '}'") }
1367+
| '{' (yield_expr | star_expressions) '=' !('!' | ':' | '}') {
1368+
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '!', or ':', or '}'") }
1369+
| '{' (yield_expr | star_expressions) '='? invalid_conversion_character
1370+
| '{' (yield_expr | star_expressions) '='? ['!' NAME] !(':' | '}') {
1371+
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting ':' or '}'") }
1372+
| '{' (yield_expr | star_expressions) '='? ['!' NAME] ':' fstring_format_spec* !'}' {
1373+
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '}', or format specs") }
1374+
| '{' (yield_expr | star_expressions) '='? ['!' NAME] !'}' {
1375+
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '}'") }
1376+
1377+
invalid_conversion_character:
1378+
| '!' &(':' | '}') { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: missing conversion character") }
1379+
| '!' !NAME { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: invalid conversion character") }

0 commit comments

Comments
 (0)