@@ -66,6 +66,10 @@ Summary -- Release highlights
66
66
67
67
.. PEP-sized items next.
68
68
69
+ New grammar features:
70
+
71
+ * :pep: `701 `: Syntactic formalization of f-strings
72
+
69
73
New typing features:
70
74
71
75
* :pep: `688 `: Making the buffer protocol accessible in Python
@@ -136,22 +140,70 @@ Improved Error Messages
136
140
New Features
137
141
============
138
142
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).
155
207
156
208
.. _whatsnew312-pep709 :
157
209
@@ -223,6 +275,24 @@ See :pep:`692` for more details.
223
275
Other Language Changes
224
276
======================
225
277
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
+
226
296
* :class: `types.MappingProxyType ` instances are now hashable if the underlying
227
297
mapping is hashable.
228
298
(Contributed by Serhiy Storchaka in :gh: `87995 `.)
@@ -543,6 +613,14 @@ tkinter
543
613
like ``create_*() `` methods.
544
614
(Contributed by Serhiy Storchaka in :gh: `94473 `.)
545
615
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
+
546
624
types
547
625
-----
548
626
@@ -687,6 +765,11 @@ Optimizations
687
765
* Speed up :class: `asyncio.Task ` creation by deferring expensive string formatting.
688
766
(Contributed by Itamar O in :gh: `103793 `.)
689
767
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
+
690
773
691
774
CPython bytecode changes
692
775
========================
@@ -1130,6 +1213,8 @@ Removed
1130
1213
Iceape, Firebird, and Firefox versions 35 and below (:gh: `102871 `).
1131
1214
1132
1215
1216
+ .. _whatsnew312-porting-to-python312 :
1217
+
1133
1218
Porting to Python 3.12
1134
1219
======================
1135
1220
@@ -1201,6 +1286,40 @@ Changes in the Python API
1201
1286
that may be surprising or dangerous.
1202
1287
See :ref: `tarfile-extraction-filter ` for details.
1203
1288
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
+
1204
1323
Build Changes
1205
1324
=============
1206
1325
0 commit comments