-
-
Notifications
You must be signed in to change notification settings - Fork 34.5k
Expand file tree
/
Copy path3.15.rst
More file actions
2167 lines (1575 loc) · 80.8 KB
/
3.15.rst
File metadata and controls
2167 lines (1575 loc) · 80.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
****************************
What's new in Python 3.15
****************************
:Editor: Hugo van Kemenade
.. Rules for maintenance:
* Anyone can add text to this document. Do not spend very much time
on the wording of your changes, because your text will probably
get rewritten to some degree.
* The maintainer will go through Misc/NEWS periodically and add
changes; it's therefore more important to add your changes to
Misc/NEWS than to this file.
* This is not a complete list of every single change; completeness
is the purpose of Misc/NEWS. Some changes I consider too small
or esoteric to include. If such a change is added to the text,
I'll just remove it. (This is another reason you shouldn't spend
too much time on writing your addition.)
* If you want to draw your new text to the attention of the
maintainer, add 'XXX' to the beginning of the paragraph or
section.
* It's OK to just add a fragmentary note about a change. For
example: "XXX Describe the transmogrify() function added to the
socket module." The maintainer will research the change and
write the necessary text.
* You can comment out your additions if you like, but it's not
necessary (especially when a final release is some months away).
* Credit the author of a patch or bugfix. Just the name is
sufficient; the e-mail address isn't necessary.
* It's helpful to add the issue number as a comment:
XXX Describe the transmogrify() function added to the socket
module.
(Contributed by P.Y. Developer in :gh:`12345`.)
This saves the maintainer the effort of going through the VCS log
when researching a change.
This article explains the new features in Python 3.15, compared to 3.14.
For full details, see the :ref:`changelog <changelog>`.
.. note::
Prerelease users should be aware that this document is currently in draft
form. It will be updated substantially as Python 3.15 moves towards release,
so it's worth checking back even after reading earlier versions.
Summary -- Release highlights
=============================
.. This section singles out the most important changes in Python 3.15.
Brevity is key.
.. PEP-sized items next.
* :pep:`810`: :ref:`Explicit lazy imports for faster startup times
<whatsnew315-lazy-imports>`
* :pep:`814`: :ref:`Add frozendict built-in type
<whatsnew315-frozendict>`
* :pep:`799`: :ref:`A dedicated profiling package for organizing Python
profiling tools <whatsnew315-profiling-package>`
* :pep:`799`: :ref:`Tachyon: High frequency statistical sampling profiler
<whatsnew315-sampling-profiler>`
* :pep:`798`: :ref:`Unpacking in comprehensions
<whatsnew315-unpacking-in-comprehensions>`
* :pep:`686`: :ref:`Python now uses UTF-8 as the default encoding
<whatsnew315-utf8-default>`
* :pep:`728`: ``TypedDict`` with typed extra items
* :pep:`747`: :ref:`Annotating type forms with TypeForm
<whatsnew315-typeform>`
* :pep:`782`: :ref:`A new PyBytesWriter C API to create a Python bytes object
<whatsnew315-pybyteswriter>`
* :pep:`803`: :ref:`Stable ABI for Free-Threaded Builds <whatsnew315-abi3t>`
* :ref:`The JIT compiler has been significantly upgraded <whatsnew315-jit>`
* :ref:`Improved error messages <whatsnew315-improved-error-messages>`
* :ref:`The official Windows 64-bit binaries now use the tail-calling interpreter
<whatsnew315-windows-tail-calling-interpreter>`
New features
============
.. _whatsnew315-lazy-imports:
:pep:`810`: Explicit lazy imports
---------------------------------
Large Python applications often suffer from slow startup times. A
significant contributor to this problem is the import system: when a module
is imported, Python must locate the file, read it from disk, compile it to
bytecode, and execute all top-level code. For applications with deep
dependency trees, this process can take seconds, even when most of the
imported code is never actually used during a particular run.
Developers have worked around this by moving imports inside functions, using
:mod:`importlib` to load modules on demand, or restructuring code to avoid
unnecessary dependencies. These approaches work but make code harder to read
and maintain, scatter import statements throughout the codebase, and require
discipline to apply consistently.
Python now provides a cleaner solution through explicit :keyword:`lazy`
imports using the new ``lazy`` soft keyword. When you mark an import as
lazy, Python defers the actual module loading until the imported name is
first used. This gives you the organizational benefits of declaring all
imports at the top of the file while only paying the loading cost for
modules you actually use.
The ``lazy`` keyword works with both ``import`` and ``from ... import``
statements. When you write ``lazy import heavy_module``, Python does not
immediately load the module. Instead, it creates a lightweight proxy object.
The actual module loading happens transparently when you first access the
name:
.. code-block:: python
lazy import json
lazy from pathlib import Path
print("Starting up...") # json and pathlib not loaded yet
data = json.loads('{"key": "value"}') # json loads here
p = Path(".") # pathlib loads here
This mechanism is particularly useful for applications that import many
modules at the top level but may only use a subset of them in any given run.
The deferred loading reduces startup latency without requiring code
restructuring or conditional imports scattered throughout the codebase.
In the case where loading a lazily imported module fails (for example, if
the module does not exist), Python raises the exception at the point of
first use rather than at import time. The associated traceback includes both
the location where the name was accessed and the original import statement,
making it straightforward to diagnose & debug the failure.
For cases where you want to enable lazy loading globally without modifying
source code, Python provides the :option:`-X lazy_imports <-X>` command-line
option and the :envvar:`PYTHON_LAZY_IMPORTS` environment variable. Both
accept three values: ``all`` makes all imports lazy by default, ``none``
disables lazy imports entirely (even explicit ``lazy`` statements become
eager), and ``normal`` (the default) respects the ``lazy`` keyword in source
code. The :func:`sys.set_lazy_imports` and :func:`sys.get_lazy_imports`
functions allow changing and querying this mode at runtime.
For more selective control, :func:`sys.set_lazy_imports_filter` accepts a
callable that determines whether a specific module should be loaded lazily.
The filter receives three arguments: the importing module's name (or
``None``), the imported module's name, and the fromlist (or ``None`` for
regular imports). It should return ``True`` to allow the import to be lazy,
or ``False`` to force eager loading. This allows patterns like making only
your own application's modules lazy while keeping third-party dependencies
eager:
.. code-block:: python
import sys
def myapp_filter(importing, imported, fromlist):
return imported.startswith("myapp.")
sys.set_lazy_imports_filter(myapp_filter)
sys.set_lazy_imports("all")
import myapp.slow_module # lazy (matches filter)
import json # eager (does not match filter)
The proxy type itself is available as :data:`types.LazyImportType` for code
that needs to detect lazy imports programmatically.
There are some restrictions on where the ``lazy`` keyword can be used. Lazy
imports are only permitted at module scope; using ``lazy`` inside a
function, class body, or ``try``/``except``/``finally`` block raises a
:exc:`SyntaxError`. Neither star imports nor future imports can be lazy
(``lazy from module import *`` and ``lazy from __future__ import ...`` both
raise :exc:`SyntaxError`).
.. seealso:: :pep:`810` for the full specification and rationale.
(Contributed by Pablo Galindo Salgado and Dino Viehland in :gh:`142349`.)
.. _whatsnew315-frozendict:
:pep:`814`: Add frozendict built-in type
----------------------------------------
A new :term:`immutable` type, :class:`frozendict`, is added to the :mod:`builtins` module.
It does not allow modification after creation. A :class:`!frozendict` is not a subclass of ``dict``;
it inherits directly from ``object``. A :class:`!frozendict` is :term:`hashable`
as long as all of its keys and values are hashable. A :class:`!frozendict` preserves
insertion order, but comparison does not take order into account.
For example::
>>> a = frozendict(x=1, y=2)
>>> a
frozendict({'x': 1, 'y': 2})
>>> a['z'] = 3
Traceback (most recent call last):
File "<python-input-2>", line 1, in <module>
a['z'] = 3
~^^^^^
TypeError: 'frozendict' object does not support item assignment
>>> b = frozendict(y=2, x=1)
>>> hash(a) == hash(b)
True
>>> a == b
True
The following standard library modules have been updated to accept
:class:`!frozendict`: :mod:`copy`, :mod:`decimal`, :mod:`json`, :mod:`marshal`,
:mod:`plistlib` (only for serialization), :mod:`pickle`, :mod:`pprint` and
:mod:`xml.etree.ElementTree`.
:func:`eval` and :func:`exec` accept :class:`!frozendict` for *globals*, and
:func:`type` and :meth:`str.maketrans` accept :class:`!frozendict` for *dict*.
Code checking for :class:`dict` type using ``isinstance(arg, dict)`` can be
updated to ``isinstance(arg, (dict, frozendict))`` to accept also the
:class:`!frozendict` type, or to ``isinstance(arg, collections.abc.Mapping)``
to accept also other mapping types such as :class:`~types.MappingProxyType`.
.. seealso:: :pep:`814` for the full specification and rationale.
(Contributed by Victor Stinner and Donghee Na in :gh:`141510`.)
.. _whatsnew315-profiling-package:
:pep:`799`: A dedicated profiling package
-----------------------------------------
A new :mod:`profiling` module has been added to organize Python's built-in
profiling tools under a single, coherent namespace. This module contains:
* :mod:`profiling.tracing`: deterministic function-call tracing (relocated from
``cProfile``).
* :mod:`profiling.sampling`: a new statistical sampling profiler (named Tachyon).
The ``cProfile`` module remains as an alias for backwards compatibility.
The :mod:`profile` module is deprecated and will be removed in Python 3.17.
.. seealso:: :pep:`799` for further details.
(Contributed by Pablo Galindo and László Kiss Kollár in :gh:`138122`.)
.. _whatsnew315-sampling-profiler:
Tachyon: High frequency statistical sampling profiler
-----------------------------------------------------
.. image:: ../library/tachyon-logo.png
:alt: Tachyon profiler logo
:align: center
:width: 200px
A new statistical sampling profiler (Tachyon) has been added as
:mod:`profiling.sampling`. This profiler enables low-overhead performance analysis of
running Python processes without requiring code modification or process restart.
Unlike deterministic profilers (such as :mod:`profiling.tracing`) that instrument
every function call, the sampling profiler periodically captures stack traces from
running processes. This approach provides virtually zero overhead while achieving
sampling rates of **up to 1,000,000 Hz**, making it the fastest sampling profiler
available for Python (at the time of its contribution) and ideal for debugging
performance issues in production environments. This capability is particularly
valuable for debugging performance issues in production systems where traditional
profiling approaches would be too intrusive.
Key features include:
* **Zero-overhead profiling**: Attach to any running Python process without
affecting its performance. Ideal for production debugging where you can't afford
to restart or slow down your application.
* **No code modification required**: Profile existing applications without restart.
Simply point the profiler at a running process by PID and start collecting data.
* **Flexible target modes**:
* Profile running processes by PID (``attach``) - attach to already-running applications
* Run and profile scripts directly (``run``) - profile from the very start of execution
* Execute and profile modules (``run -m``) - profile packages run as ``python -m module``
* **Multiple profiling modes**: Choose what to measure based on your performance investigation:
* **Wall-clock time** (``--mode wall``, default): Measures real elapsed time including I/O,
network waits, and blocking operations. Use this to understand where your program spends
calendar time, including when waiting for external resources.
* **CPU time** (``--mode cpu``): Measures only active CPU execution time, excluding I/O waits
and blocking. Use this to identify CPU-bound bottlenecks and optimize computational work.
* **GIL-holding time** (``--mode gil``): Measures time spent holding Python's Global Interpreter
Lock. Use this to identify which threads dominate GIL usage in multi-threaded applications.
* **Exception handling time** (``--mode exception``): Captures samples only from threads with
an active exception. Use this to analyze exception handling overhead.
* **Thread-aware profiling**: Option to profile all threads (``-a``) or just the main thread,
essential for understanding multi-threaded application behavior.
* **Multiple output formats**: Choose the visualization that best fits your workflow:
* ``--pstats``: Detailed tabular statistics compatible with :mod:`pstats`. Shows function-level
timing with direct and cumulative samples. Best for detailed analysis and integration with
existing Python profiling tools.
* ``--collapsed``: Generates collapsed stack traces (one line per stack). This format is
specifically designed for creating flame graphs with external tools like Brendan Gregg's
FlameGraph scripts or speedscope.
* ``--flamegraph``: Generates a self-contained interactive HTML flame graph using D3.js.
Opens directly in your browser for immediate visual analysis. Flame graphs show the call
hierarchy where width represents time spent, making it easy to spot bottlenecks at a glance.
* ``--gecko``: Generates Gecko Profiler format compatible with `Firefox Profiler
<https://profiler.firefox.com>`__. Upload the output to Firefox Profiler for advanced
timeline-based analysis with features like stack charts, markers, and network activity.
* ``--heatmap``: Generates an interactive HTML heatmap visualization with line-level sample
counts. Creates a directory with per-file heatmaps showing exactly where time is spent
at the source code level.
* **Live interactive mode**: Real-time TUI profiler with a top-like interface (``--live``).
Monitor performance as your application runs with interactive sorting and filtering.
* **Async-aware profiling**: Profile async/await code with task-based stack reconstruction
(``--async-aware``). See which coroutines are consuming time, with options to show only
running tasks or all tasks including those waiting.
* **Opcode-level profiling**: Gather bytecode opcode information for instruction-level
profiling (``--opcodes``). Shows which bytecode instructions are executing, including
specializations from the adaptive interpreter.
See :mod:`profiling.sampling` for the complete documentation, including all
available output formats, profiling modes, and configuration options.
(Contributed by Pablo Galindo and László Kiss Kollár in :gh:`135953` and :gh:`138122`.)
.. _whatsnew315-unpacking-in-comprehensions:
:pep:`798`: Unpacking in Comprehensions
---------------------------------------
List, set, and dictionary comprehensions, as well as generator expressions, now
support unpacking with ``*`` and ``**``. This extends the unpacking syntax
from :pep:`448` to comprehensions, providing a new syntax for combining an
arbitrary number of iterables or dictionaries into a single flat structure.
This new syntax is a direct alternative to nested comprehensions,
:func:`itertools.chain`, and :meth:`itertools.chain.from_iterable`. For
example::
>>> lists = [[1, 2], [3, 4], [5]]
>>> [*L for L in lists] # equivalent to [x for L in lists for x in L]
[1, 2, 3, 4, 5]
>>> sets = [{1, 2}, {2, 3}, {3, 4}]
>>> {*s for s in sets} # equivalent to {x for s in sets for x in s}
{1, 2, 3, 4}
>>> dicts = [{'a': 1}, {'b': 2}, {'a': 3}]
>>> {**d for d in dicts} # equivalent to {k: v for d in dicts for k,v in d.items()}
{'a': 3, 'b': 2}
Generator expressions can similarly use unpacking to yield values from multiple
iterables::
>>> gen = (*L for L in lists) # equivalent to (x for L in lists for x in L)
>>> list(gen)
[1, 2, 3, 4, 5]
This change also extends to asynchronous generator expressions, such that, for
example, ``(*a async for a in agen())`` is equivalent to ``(x async for a in
agen() for x in a)``.
.. seealso:: :pep:`798` for further details.
(Contributed by Adam Hartz in :gh:`143055`.)
.. _whatsnew315-abi3t:
:pep:`803`: ``abi3t`` -- Stable ABI for Free-Threaded Builds
------------------------------------------------------------
C extensions that target the :ref:`Stable ABI <stable-abi>` can now be
compiled for the new *Stable ABI for Free-Threaded Builds* (also known
as ``abi3t``), which makes them compatible with
:term:`free-threaded builds <free-threaded build>` of CPython.
This usually requires some non-trivial changes to the source code;
specifically:
- Switching to API introduced in :pep:`697` (Python 3.12), such as
negative :c:member:`~PyType_Spec.basicsize` and
:c:func:`PyObject_GetTypeData`, rather than making :c:type:`PyObject`
part of the instance struct; and
- Switching from a ``PyInit_`` function to a new export hook,
:c:func:`PyModExport_* <PyModExport_modulename>`, introduced for this
purpose in :pep:`793`.
Note that Stable ABI does not offer all the functionality that CPython
has to offer.
Extensions that cannot switch to ``abi3t`` should continue to build for
the existing Stable ABI (``abi3``) and the version-specific ABI for
free-threading (``cp315t``) separately.
Stable ABI for Free-Threaded Builds should typically
be selected in a build tool (such as, for example, Setuptools, meson-python,
scikit-build-core, or Maturin).
At the time of writing, these tools did **not** support ``abi3t``.
If this is the case for your tool, compile for ``cp315t`` separately.
If not using a build tool -- or when writing such a tool -- you can select
``abi3t`` by setting the macro :c:macro:`!Py_TARGET_ABI3T` as discussed
in :ref:`abi3-compiling`.
.. _whatsnew315-improved-error-messages:
Improved error messages
-----------------------
* The interpreter now provides more helpful suggestions in :exc:`AttributeError`
exceptions when accessing an attribute on an object that does not exist, but
a similar attribute is available through one of its members.
For example, if the object has an attribute that itself exposes the requested
name, the error message will suggest accessing it via that inner attribute:
.. code-block:: python
@dataclass
class Circle:
radius: float
@property
def area(self) -> float:
return pi * self.radius**2
class Container:
def __init__(self, inner: Circle) -> None:
self.inner = inner
circle = Circle(radius=4.0)
container = Container(circle)
print(container.area)
Running this code now produces a clearer suggestion:
.. code-block:: pycon
Traceback (most recent call last):
File "/home/pablogsal/github/python/main/lel.py", line 42, in <module>
print(container.area)
^^^^^^^^^^^^^^
AttributeError: 'Container' object has no attribute 'area'. Did you mean '.inner.area' instead of '.area'?
Other language changes
======================
.. _whatsnew315-utf8-default:
* Python now uses UTF-8_ as the default encoding, independent of the system's
environment. This means that I/O operations without an explicit encoding,
for example, ``open('flying-circus.txt')``, will use UTF-8.
UTF-8 is a widely-supported Unicode_ character encoding that has become a
*de facto* standard for representing text, including nearly every webpage
on the internet, many common file formats, programming languages, and more.
This only applies when no ``encoding`` argument is given. For best
compatibility between versions of Python, ensure that an explicit ``encoding``
argument is always provided. The :ref:`opt-in encoding warning <io-encoding-warning>`
can be used to identify code that may be affected by this change.
The special ``encoding='locale'`` argument uses the current locale
encoding, and has been supported since Python 3.10.
To retain the previous behaviour, Python's UTF-8 mode may be disabled with
the :envvar:`PYTHONUTF8=0 <PYTHONUTF8>` environment variable or the
:option:`-X utf8=0 <-X>` command-line option.
.. seealso:: :pep:`686` for further details.
.. _UTF-8: https://en.wikipedia.org/wiki/UTF-8
.. _Unicode: https://home.unicode.org/
(Contributed by Adam Turner in :gh:`133711`; PEP 686 written by Inada Naoki.)
* Several error messages incorrectly using the term "argument" have been corrected.
(Contributed by Stan Ulbrych in :gh:`133382`.)
* The interpreter now tries to provide a suggestion when
:func:`delattr` fails due to a missing attribute.
When an attribute name that closely resembles an existing attribute is used,
the interpreter will suggest the correct attribute name in the error message.
For example:
.. doctest::
>>> class A:
... pass
>>> a = A()
>>> a.abcde = 1
>>> del a.abcdf # doctest: +ELLIPSIS
Traceback (most recent call last):
...
AttributeError: 'A' object has no attribute 'abcdf'. Did you mean: 'abcde'?
(Contributed by Nikita Sobolev and Pranjal Prajapati in :gh:`136588`.)
* Unraisable exceptions are now highlighted with color by default. This can be
controlled by :ref:`environment variables <using-on-controlling-color>`.
(Contributed by Peter Bierma in :gh:`134170`.)
* The :meth:`~object.__repr__` of :class:`ImportError` and :class:`ModuleNotFoundError`
now shows "name" and "path" as ``name=<name>`` and ``path=<path>`` if they were given
as keyword arguments at construction time.
(Contributed by Serhiy Storchaka, Oleg Iarygin, and Yoav Nir in :gh:`74185`.)
* The :attr:`~object.__dict__` and :attr:`!__weakref__` descriptors now use a
single descriptor instance per interpreter, shared across all types that
need them.
This speeds up class creation, and helps avoid reference cycles.
(Contributed by Petr Viktorin in :gh:`135228`.)
* The :option:`-W` option and the :envvar:`PYTHONWARNINGS` environment variable
can now specify regular expressions instead of literal strings to match
the warning message and the module name, if the corresponding field starts
and ends with a forward slash (``/``).
(Contributed by Serhiy Storchaka in :gh:`134716`.)
* Functions that take timestamp or timeout arguments now accept any real
numbers (such as :class:`~decimal.Decimal` and :class:`~fractions.Fraction`),
not only integers or floats, although this does not improve precision.
(Contributed by Serhiy Storchaka in :gh:`67795`.)
.. _whatsnew315-bytearray-take-bytes:
* Added :meth:`bytearray.take_bytes(n=None, /) <bytearray.take_bytes>` to take
bytes out of a :class:`bytearray` without copying. This enables optimizing code
which must return :class:`bytes` after working with a mutable buffer of bytes
such as data buffering, network protocol parsing, encoding, decoding,
and compression. Common code patterns which can be optimized with
:func:`~bytearray.take_bytes` are listed below.
.. list-table:: Suggested optimizing refactors
:header-rows: 1
* - Description
- Old
- New
* - Return :class:`bytes` after working with :class:`bytearray`
- .. code:: python
def read() -> bytes:
buffer = bytearray(1024)
...
return bytes(buffer)
- .. code:: python
def read() -> bytes:
buffer = bytearray(1024)
...
return buffer.take_bytes()
* - Empty a buffer getting the bytes
- .. code:: python
buffer = bytearray(1024)
...
data = bytes(buffer)
buffer.clear()
- .. code:: python
buffer = bytearray(1024)
...
data = buffer.take_bytes()
* - Split a buffer at a specific separator
- .. code:: python
buffer = bytearray(b'abc\ndef')
n = buffer.find(b'\n')
data = bytes(buffer[:n + 1])
del buffer[:n + 1]
assert data == b'abc'
assert buffer == bytearray(b'def')
- .. code:: python
buffer = bytearray(b'abc\ndef')
n = buffer.find(b'\n')
data = buffer.take_bytes(n + 1)
* - Split a buffer at a specific separator; discard after the separator
- .. code:: python
buffer = bytearray(b'abc\ndef')
n = buffer.find(b'\n')
data = bytes(buffer[:n])
buffer.clear()
assert data == b'abc'
assert len(buffer) == 0
- .. code:: python
buffer = bytearray(b'abc\ndef')
n = buffer.find(b'\n')
buffer.resize(n)
data = buffer.take_bytes()
(Contributed by Cody Maloney in :gh:`139871`.)
* Many functions related to compiling or parsing Python code, such as
:func:`compile`, :func:`ast.parse`, :func:`symtable.symtable`,
and :func:`importlib.abc.InspectLoader.source_to_code`, now allow the module
name to be passed. It is needed to unambiguously :ref:`filter <warning-filter>`
syntax warnings by module name.
(Contributed by Serhiy Storchaka in :gh:`135801`.)
* Allowed defining the *__dict__* and *__weakref__* :ref:`__slots__ <slots>`
for any class.
(Contributed by Serhiy Storchaka in :gh:`41779`.)
* Allowed defining any :ref:`__slots__ <slots>` for a class derived from
:class:`tuple` (including classes created by :func:`collections.namedtuple`).
(Contributed by Serhiy Storchaka in :gh:`41779`.)
* The :class:`slice` type now supports subscription,
making it a :term:`generic type`.
(Contributed by James Hilton-Balfe in :gh:`128335`.)
* The class :class:`memoryview` now supports the :c:expr:`float complex` and
:c:expr:`double complex` C types: formatting characters ``'F'`` and ``'D'``
respectively.
(Contributed by Sergey B Kirpichev in :gh:`146151`.)
* Allow the *count* argument of :meth:`bytes.replace` to be a keyword.
(Contributed by Stan Ulbrych in :gh:`147856`.)
New modules
===========
math.integer
------------
This module provides access to the mathematical functions for integer
arguments (:pep:`791`).
(Contributed by Serhiy Storchaka in :gh:`81313`.)
Improved modules
================
argparse
--------
* The :class:`~argparse.BooleanOptionalAction` action supports now single-dash
long options and alternate prefix characters.
(Contributed by Serhiy Storchaka in :gh:`138525`.)
* Changed the *suggest_on_error* parameter of :class:`argparse.ArgumentParser` to
default to ``True``. This enables suggestions for mistyped arguments by default.
(Contributed by Jakob Schluse in :gh:`140450`.)
* Added backtick markup support in description and epilog text to highlight
inline code when color output is enabled.
(Contributed by Savannah Ostrowski in :gh:`142390`.)
array
-----
* Support the :c:expr:`float complex` and :c:expr:`double complex` C types:
formatting characters ``'F'`` and ``'D'`` respectively.
(Contributed by Sergey B Kirpichev in :gh:`146151`.)
* Support half-floats (16-bit IEEE 754 binary interchange format): formatting
character ``'e'``.
(Contributed by Sergey B Kirpichev in :gh:`146238`.)
base64
------
* Added the *pad* parameter in :func:`~base64.z85encode`.
(Contributed by Hauke Dämpfling in :gh:`143103`.)
* Added the *padded* parameter in
:func:`~base64.b32encode`, :func:`~base64.b32decode`,
:func:`~base64.b32hexencode`, :func:`~base64.b32hexdecode`,
:func:`~base64.b64encode`, :func:`~base64.b64decode`,
:func:`~base64.urlsafe_b64encode`, and :func:`~base64.urlsafe_b64decode`.
(Contributed by Serhiy Storchaka in :gh:`73613`.)
* Added the *wrapcol* parameter in :func:`~base64.b16encode`,
:func:`~base64.b32encode`, :func:`~base64.b32hexencode`,
:func:`~base64.b64encode`, :func:`~base64.b85encode`, and
:func:`~base64.z85encode`.
(Contributed by Serhiy Storchaka in :gh:`143214` and :gh:`146431`.)
* Added the *ignorechars* parameter in :func:`~base64.b16decode`,
:func:`~base64.b32decode`, :func:`~base64.b32hexdecode`,
:func:`~base64.b64decode`, :func:`~base64.b85decode`, and
:func:`~base64.z85decode`.
(Contributed by Serhiy Storchaka in :gh:`144001` and :gh:`146431`.)
binascii
--------
* Added functions for Base32 encoding:
- :func:`~binascii.b2a_base32` and :func:`~binascii.a2b_base32`
(Contributed by James Seo in :gh:`146192`.)
* Added functions for Ascii85, Base85, and Z85 encoding:
- :func:`~binascii.b2a_ascii85` and :func:`~binascii.a2b_ascii85`
- :func:`~binascii.b2a_base85` and :func:`~binascii.a2b_base85`
(Contributed by James Seo and Serhiy Storchaka in :gh:`101178`.)
* Added the *padded* parameter in
:func:`~binascii.b2a_base32`, :func:`~binascii.a2b_base32`,
:func:`~binascii.b2a_base64`, and :func:`~binascii.a2b_base64`.
(Contributed by Serhiy Storchaka in :gh:`73613`.)
* Added the *wrapcol* parameter in :func:`~binascii.b2a_base64`.
(Contributed by Serhiy Storchaka in :gh:`143214`.)
* Added the *alphabet* parameter in :func:`~binascii.b2a_base64` and
:func:`~binascii.a2b_base64`.
(Contributed by Serhiy Storchaka in :gh:`145980`.)
* Added the *ignorechars* parameter in :func:`~binascii.a2b_hex`,
:func:`~binascii.unhexlify`, and :func:`~binascii.a2b_base64`.
(Contributed by Serhiy Storchaka in :gh:`144001` and :gh:`146431`.)
calendar
--------
* Calendar pages generated by the :class:`calendar.HTMLCalendar` class now support
dark mode and have been migrated to the HTML5 standard for improved accessibility.
(Contributed by Jiahao Li and Hugo van Kemenade in :gh:`137634`.)
* The :mod:`calendar`'s :ref:`command-line <calendar-cli>` HTML output now
accepts the year-month option: ``python -m calendar -t html 2009 06``.
(Contributed by Pål Grønås Drange in :gh:`140212`.)
collections
-----------
* Added :meth:`!collections.Counter.__xor__` and
:meth:`!collections.Counter.__ixor__` to compute the symmetric difference
between :class:`~collections.Counter` objects.
(Contributed by Raymond Hettinger in :gh:`138682`.)
concurrent.futures
------------------
* Improved error reporting when a child process in a
:class:`concurrent.futures.ProcessPoolExecutor` terminates abruptly.
The resulting traceback will now tell you the PID and exit code of the
terminated process.
(Contributed by Jonathan Berg in :gh:`139486`.)
contextlib
----------
* Added support for arbitrary descriptors :meth:`!__enter__`,
:meth:`!__exit__`, :meth:`!__aenter__`, and :meth:`!__aexit__` in
:class:`~contextlib.ExitStack` and :class:`contextlib.AsyncExitStack`, for
consistency with the :keyword:`with` and :keyword:`async with` statements.
(Contributed by Serhiy Storchaka in :gh:`144386`.)
dataclasses
-----------
* Annotations for generated ``__init__`` methods no longer include internal
type names.
dbm
---
* Added new :meth:`!reorganize` methods to :mod:`dbm.dumb` and :mod:`dbm.sqlite3`
which allow to recover unused free space previously occupied by deleted entries.
(Contributed by Andrea Oliveri in :gh:`134004`.)
difflib
-------
.. _whatsnew315-color-difflib:
* Introduced the optional *color* parameter to :func:`difflib.unified_diff`,
enabling color output similar to :program:`git diff`.
This can be controlled by :ref:`environment variables
<using-on-controlling-color>`.
(Contributed by Douglas Thor in :gh:`133725`.)
* Improved the styling of HTML diff pages generated by the :class:`difflib.HtmlDiff`
class, and migrated the output to the HTML5 standard.
(Contributed by Jiahao Li in :gh:`134580`.)
functools
---------
* :func:`~functools.singledispatchmethod` now supports non-:term:`descriptor`
callables.
(Contributed by Serhiy Storchaka in :gh:`140873`.)
* :func:`~functools.singledispatchmethod` now dispatches on the second argument
if it wraps a regular method and is called as a class attribute.
(Contributed by Bartosz Sławecki in :gh:`143535`.)
hashlib
-------
* Ensure that hash functions guaranteed to be always *available* exist as
attributes of :mod:`hashlib` even if they will not work at runtime due to
missing backend implementations. For instance, ``hashlib.md5`` will no
longer raise :exc:`AttributeError` if OpenSSL is not available and Python
has been built without MD5 support.
(Contributed by Bénédikt Tran in :gh:`136929`.)
http.client
-----------
* A new *max_response_headers* keyword-only parameter has been added to
:class:`~http.client.HTTPConnection` and :class:`~http.client.HTTPSConnection`
constructors. This parameter overrides the default maximum number of allowed
response headers.
(Contributed by Alexander Enrique Urieles Nieto in :gh:`131724`.)
http.cookies
------------
* Allow '``"``' double quotes in cookie values.
(Contributed by Nick Burns and Senthil Kumaran in :gh:`92936`.)
http.server
-----------
* The logging of :mod:`~http.server.BaseHTTPRequestHandler`,
as used by the :ref:`command-line interface <http-server-cli>`,
is colored by default.
This can be controlled with :ref:`environment variables
<using-on-controlling-color>`.
(Contributed by Hugo van Kemenade in :gh:`146292`.)
inspect
-------
* Add parameters *inherit_class_doc* and *fallback_to_class_doc*
for :func:`~inspect.getdoc`.
(Contributed by Serhiy Storchaka in :gh:`132686`.)
json
----
* Add the *array_hook* parameter to :func:`~json.load` and
:func:`~json.loads` functions:
allow a callback for JSON literal array types to customize Python lists in
the resulting decoded object. Passing combined :class:`frozendict` to
*object_pairs_hook* param and :class:`tuple` to ``array_hook`` will yield a
deeply nested immutable Python structure representing the JSON data.
(Contributed by Joao S. O. Bueno in :gh:`146440`)
locale
------
* :func:`~locale.setlocale` now supports language codes with ``@``-modifiers.
``@``-modifiers are no longer silently removed in :func:`~locale.getlocale`,
but included in the language code.
(Contributed by Serhiy Storchaka in :gh:`137729`.)
* Undeprecate the :func:`locale.getdefaultlocale` function.
(Contributed by Victor Stinner in :gh:`130796`.)
math
----
* Add :func:`math.isnormal` and :func:`math.issubnormal` functions.
(Contributed by Sergey B Kirpichev in :gh:`132908`.)
* Add :func:`math.fmax`, :func:`math.fmin` and :func:`math.signbit` functions.
(Contributed by Bénédikt Tran in :gh:`135853`.)
mimetypes
---------
* Add ``application/dicom`` MIME type for ``.dcm`` extension.
(Contributed by Benedikt Johannes in :gh:`144217`.)
* Add ``application/efi``. (Contributed by Charlie Lin in :gh:`145720`.)
* Add ``application/node`` MIME type for ``.cjs`` extension.
(Contributed by John Franey in :gh:`140937`.)
* Add ``application/toml``. (Contributed by Gil Forcada in :gh:`139959`.)
* Add ``application/sql`` and ``application/vnd.sqlite3``.
(Contributed by Charlie Lin in :gh:`145698`.)
* Add the following MIME types:
- ``application/vnd.ms-cab-compressed`` for ``.cab`` extension
- ``application/vnd.ms-htmlhelp`` for ``.chm`` extension
- ``application/vnd.ms-officetheme`` for ``.thmx`` extension
(Contributed by Charlie Lin in :gh:`145718`.)
* Add ``image/jxl``. (Contributed by Foolbar in :gh:`144213`.)
* Rename ``application/x-texinfo`` to ``application/texinfo``.
(Contributed by Charlie Lin in :gh:`140165`.)
* Changed the MIME type for ``.ai`` files to ``application/pdf``.
(Contributed by Stan Ulbrych in :gh:`141239`.)
mmap
----
* :class:`mmap.mmap` now has a *trackfd* parameter on Windows;
if it is ``False``, the file handle corresponding to *fileno* will
not be duplicated.
(Contributed by Serhiy Storchaka in :gh:`78502`.)
* Added the :meth:`mmap.mmap.set_name` method
to annotate an anonymous memory mapping
if Linux kernel supports :manpage:`PR_SET_VMA_ANON_NAME <PR_SET_VMA(2const)>` (Linux 5.17 or newer).
(Contributed by Donghee Na in :gh:`142419`.)
os
--
* Add :func:`os.statx` on Linux kernel versions 4.11 and later with
glibc versions 2.28 and later.
(Contributed by Jeffrey Bosboom and Victor Stinner in :gh:`83714`.)
os.path
-------
* Add support of the all-but-last mode in :func:`~os.path.realpath`.
(Contributed by Serhiy Storchaka in :gh:`71189`.)
* The *strict* parameter to :func:`os.path.realpath` accepts a new value,
:data:`os.path.ALLOW_MISSING`.
If used, errors other than :exc:`FileNotFoundError` will be re-raised;
the resulting path can be missing but it will be free of symlinks.
(Contributed by Petr Viktorin for :cve:`2025-4517`.)
pickle
------
* Add support for pickling private methods and nested classes.
(Contributed by Zackery Spytz and Serhiy Storchaka in :gh:`77188`.)
pprint
------
* Add an *expand* keyword argument for :func:`pprint.pprint`,
:func:`pprint.pformat`, :func:`pprint.pp`. If true, the output will be
formatted similar to pretty-printed :func:`json.dumps` when
*indent* is supplied.
(Contributed by Stefan Todoran, Semyon Moroz and Hugo van Kemenade in
:gh:`112632`.)
* Add t-string support to :mod:`pprint`.
(Contributed by Loïc Simon and Hugo van Kemenade in :gh:`134551`.)
re
--
* :func:`re.prefixmatch` and a corresponding :meth:`re.Pattern.prefixmatch`
have been added as alternate, more explicit names for the existing
and now :term:`soft deprecated`