Skip to content

Commit c45701e

Browse files
mgmacias95pablogsalJelleZijlstra
authored
gh-102856: Add changes related to PEP 701 in 3.12 What's New docs (#104824)
Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com> Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
1 parent 7b00940 commit c45701e

File tree

1 file changed

+135
-16
lines changed

1 file changed

+135
-16
lines changed

Doc/whatsnew/3.12.rst

+135-16
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ Summary -- Release highlights
6666
6767
.. PEP-sized items next.
6868
69+
New grammar features:
70+
71+
* :pep:`701`: Syntactic formalization of f-strings
72+
6973
New typing features:
7074

7175
* :pep:`688`: Making the buffer protocol accessible in Python
@@ -136,22 +140,70 @@ Improved Error Messages
136140
New Features
137141
============
138142

139-
* Add :ref:`perf_profiling` through the new
140-
environment variable :envvar:`PYTHONPERFSUPPORT`,
141-
the new command-line option :option:`-X perf <-X>`,
142-
as well as the new :func:`sys.activate_stack_trampoline`,
143-
:func:`sys.deactivate_stack_trampoline`,
144-
and :func:`sys.is_stack_trampoline_active` APIs.
145-
(Design by Pablo Galindo. Contributed by Pablo Galindo and Christian Heimes
146-
with contributions from Gregory P. Smith [Google] and Mark Shannon
147-
in :gh:`96123`.)
148-
* The extraction methods in :mod:`tarfile`, and :func:`shutil.unpack_archive`,
149-
have a new a *filter* argument that allows limiting tar features than may be
150-
surprising or dangerous, such as creating files outside the destination
151-
directory.
152-
See :ref:`tarfile-extraction-filter` for details.
153-
In Python 3.14, the default will switch to ``'data'``.
154-
(Contributed by Petr Viktorin in :pep:`706`.)
143+
.. _whatsnew312-pep701:
144+
145+
PEP 701: Syntactic formalization of f-strings
146+
---------------------------------------------
147+
148+
:pep:`701` lifts some restrictions on the usage of f-strings. Expression components
149+
inside f-strings can now be any valid Python expression including backslashes,
150+
unicode escaped sequences, multi-line expressions, comments and strings reusing the
151+
same quote as the containing f-string. Let's cover these in detail:
152+
153+
* Quote reuse: in Python 3.11, reusing the same quotes as the containing f-string
154+
raises a :exc:`SyntaxError`, forcing the user to either use other available
155+
quotes (like using double quotes or triple quotes if the f-string uses single
156+
quotes). In Python 3.12, you can now do things like this:
157+
158+
>>> songs = ['Take me back to Eden', 'Alkaline', 'Ascensionism']
159+
>>> f"This is the playlist: {", ".join(songs)}"
160+
'This is the playlist: Take me back to Eden, Alkaline, Ascensionism
161+
162+
Note that before this change there was no explicit limit in how f-strings can
163+
be nested, but the fact that string quotes cannot be reused inside the
164+
expression component of f-strings made it impossible to nest f-strings
165+
arbitrarily. In fact, this is the most nested f-string that could be written:
166+
167+
>>> f"""{f'''{f'{f"{1+1}"}'}'''}"""
168+
'2'
169+
170+
As now f-strings can contain any valid Python expression inside expression
171+
components, it is now possible to nest f-strings arbitrarily:
172+
173+
>>> f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}"
174+
'2'
175+
176+
* Multi-line expressions and comments: In Python 3.11, f-strings expressions
177+
must be defined in a single line even if outside f-strings expressions could
178+
span multiple lines (like literal lists being defined over multiple lines),
179+
making them harder to read. In Python 3.12 you can now define expressions
180+
spaning multiple lines and include comments on them:
181+
182+
>>> f"This is the playlist: {", ".join([
183+
... 'Take me back to Eden', # My, my, those eyes like fire
184+
... 'Alkaline', # Not acid nor alkaline
185+
... 'Ascensionism' # Take to the broken skies at last
186+
... ])}"
187+
'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'
188+
189+
* Backslashes and unicode characters: before Python 3.12 f-string expressions
190+
couldn't contain any ``\`` character. This also affected unicode escaped
191+
sequences (such as ``\N{snowman}``) as these contain the ``\N`` part that
192+
previously could not be part of expression components of f-strings. Now, you
193+
can define expressions like this:
194+
195+
>>> print(f"This is the playlist: {"\n".join(songs)}")
196+
This is the playlist: Take me back to Eden
197+
Alkaline
198+
Ascensionism
199+
>>> print(f"This is the playlist: {"\N{BLACK HEART SUIT}".join(songs)}")
200+
This is the playlist: Take me back to Eden♥Alkaline♥Ascensionism
201+
202+
See :pep:`701` for more details.
203+
204+
(Contributed by Pablo Galindo, Batuhan Taskaya, Lysandros Nikolaou, Cristián
205+
Maureira-Fredes and Marta Gómez in :gh:`102856`. PEP written by Pablo Galindo,
206+
Batuhan Taskaya, Lysandros Nikolaou and Marta Gómez).
155207

156208
.. _whatsnew312-pep709:
157209

@@ -223,6 +275,24 @@ See :pep:`692` for more details.
223275
Other Language Changes
224276
======================
225277

278+
* Add :ref:`perf_profiling` through the new
279+
environment variable :envvar:`PYTHONPERFSUPPORT`,
280+
the new command-line option :option:`-X perf <-X>`,
281+
as well as the new :func:`sys.activate_stack_trampoline`,
282+
:func:`sys.deactivate_stack_trampoline`,
283+
and :func:`sys.is_stack_trampoline_active` APIs.
284+
(Design by Pablo Galindo. Contributed by Pablo Galindo and Christian Heimes
285+
with contributions from Gregory P. Smith [Google] and Mark Shannon
286+
in :gh:`96123`.)
287+
288+
* The extraction methods in :mod:`tarfile`, and :func:`shutil.unpack_archive`,
289+
have a new a *filter* argument that allows limiting tar features than may be
290+
surprising or dangerous, such as creating files outside the destination
291+
directory.
292+
See :ref:`tarfile-extraction-filter` for details.
293+
In Python 3.14, the default will switch to ``'data'``.
294+
(Contributed by Petr Viktorin in :pep:`706`.)
295+
226296
* :class:`types.MappingProxyType` instances are now hashable if the underlying
227297
mapping is hashable.
228298
(Contributed by Serhiy Storchaka in :gh:`87995`.)
@@ -543,6 +613,14 @@ tkinter
543613
like ``create_*()`` methods.
544614
(Contributed by Serhiy Storchaka in :gh:`94473`.)
545615

616+
tokenize
617+
--------
618+
619+
* The :mod:`tokenize` module includes the changes introduced in :pep:`701`. (
620+
Contributed by Marta Gómez Macías and Pablo Galindo in :gh:`102856`.)
621+
See :ref:`whatsnew312-porting-to-python312` for more information on the
622+
changes to the :mod:`tokenize` module.
623+
546624
types
547625
-----
548626

@@ -687,6 +765,11 @@ Optimizations
687765
* Speed up :class:`asyncio.Task` creation by deferring expensive string formatting.
688766
(Contributed by Itamar O in :gh:`103793`.)
689767

768+
* The :func:`tokenize.tokenize` and :func:`tokenize.generate_tokens` functions are
769+
up to 64% faster as a side effect of the changes required to cover :pep:`701` in
770+
the :mod:`tokenize` module. (Contributed by Marta Gómez Macías and Pablo Galindo
771+
in :gh:`102856`.)
772+
690773

691774
CPython bytecode changes
692775
========================
@@ -1130,6 +1213,8 @@ Removed
11301213
Iceape, Firebird, and Firefox versions 35 and below (:gh:`102871`).
11311214

11321215

1216+
.. _whatsnew312-porting-to-python312:
1217+
11331218
Porting to Python 3.12
11341219
======================
11351220

@@ -1201,6 +1286,40 @@ Changes in the Python API
12011286
that may be surprising or dangerous.
12021287
See :ref:`tarfile-extraction-filter` for details.
12031288

1289+
* The output of the :func:`tokenize.tokenize` and :func:`tokenize.generate_tokens`
1290+
functions is now changed due to the changes introduced in :pep:`701`. This
1291+
means that ``STRING`` tokens are not emitted any more for f-strings and the
1292+
tokens described in :pep:`701` are now produced instead: ``FSTRING_START``,
1293+
``FSRING_MIDDLE`` and ``FSTRING_END`` are now emitted for f-string "string"
1294+
parts in addition to the appropriate tokens for the tokenization in the
1295+
expression components. For example for the f-string ``f"start {1+1} end"``
1296+
the old version of the tokenizer emitted::
1297+
1298+
1,0-1,18: STRING 'f"start {1+1} end"'
1299+
1300+
while the new version emits::
1301+
1302+
1,0-1,2: FSTRING_START 'f"'
1303+
1,2-1,8: FSTRING_MIDDLE 'start '
1304+
1,8-1,9: OP '{'
1305+
1,9-1,10: NUMBER '1'
1306+
1,10-1,11: OP '+'
1307+
1,11-1,12: NUMBER '1'
1308+
1,12-1,13: OP '}'
1309+
1,13-1,17: FSTRING_MIDDLE ' end'
1310+
1,17-1,18: FSTRING_END '"'
1311+
1312+
Aditionally, there may be some minor behavioral changes as a consecuence of the
1313+
changes required to support :pep:`701`. Some of these changes include:
1314+
1315+
* Some final ``DEDENT`` tokens are now emitted within the bounds of the
1316+
input. This means that for a file containing 3 lines, the old version of the
1317+
tokenizer returned a ``DEDENT`` token in line 4 whilst the new version returns
1318+
the token in line 3.
1319+
1320+
* The ``type`` attribute of the tokens emitted when tokenizing some invalid Python
1321+
characters such as ``!`` has changed from ``ERRORTOKEN`` to ``OP``.
1322+
12041323
Build Changes
12051324
=============
12061325

0 commit comments

Comments
 (0)