Skip to content

Commit 432dd39

Browse files
authored
Merge branch 'main' into gh-161441-tk-tests
2 parents 07fd383 + d746542 commit 432dd39

14 files changed

Lines changed: 115 additions & 28 deletions

‎Doc/deprecations/pending-removal-in-3.21.rst‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,11 @@ Pending removal in Python 3.21
3737

3838
* ``tempfile._TemporaryFileWrapper`` will be removed in Python 3.21. Use the
3939
public :class:`tempfile.TemporaryFileWrapper` instead.
40+
41+
* :mod:`typing`:
42+
43+
* :data:`typing.AnyStr` has been discouraged
44+
and deprecated since Python 3.13
45+
and is scheduled to be removed in Python 3.21.
46+
Use :pep:`695` syntax instead.
47+
(Contributed by Nikita Sobolev in :gh:`150190`.)

‎Doc/library/profiling.sampling.rst‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ code changes or restarts. Because sampling occurs externally to the target
2929
process, overhead is virtually zero, making Tachyon suitable for both
3030
development and production environments.
3131

32+
Tachyon follows earlier work on external sampling profilers such as
33+
`Austin <https://github.com/P403n1x87/austin>`__,
34+
`py-spy <https://github.com/benfred/py-spy>`__,
35+
`Pyflame <https://github.com/uber-archive/pyflame>`__, and
36+
`rbspy <https://github.com/rbspy/rbspy>`__. We thank their authors and the wider
37+
profiling community for their work and ideas.
38+
3239

3340
What is statistical profiling?
3441
==============================

‎Doc/library/typing.rst‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -894,15 +894,15 @@ using ``[]``.
894894
def greet_proper(cond: bool) -> str | bytes:
895895
return "hi there!" if cond else b"greetings!"
896896

897-
.. deprecated-removed:: 3.13 3.18
897+
.. deprecated-removed:: 3.13 3.21
898898
Deprecated in favor of the new :ref:`type parameter syntax <type-params>`.
899899
Use ``class A[T: (str, bytes)]: ...`` instead of importing ``AnyStr``. See
900900
:pep:`695` for more details.
901901

902-
In Python 3.16, ``AnyStr`` will be removed from ``typing.__all__``, and
903-
deprecation warnings will be emitted at runtime when it is accessed or
902+
Since Python 3.16, ``AnyStr`` is removed from ``typing.__all__``, and
903+
deprecation warnings are emitted at runtime when it is accessed or
904904
imported from ``typing``. ``AnyStr`` will be removed from ``typing``
905-
in Python 3.18.
905+
in Python 3.21.
906906

907907
.. data:: LiteralString
908908

‎Doc/whatsnew/3.15.rst‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,13 @@ A new statistical sampling profiler (Tachyon) has been added as
356356
:mod:`profiling.sampling`. This profiler enables low-overhead performance analysis of
357357
running Python processes without requiring code modification or process restart.
358358

359+
Tachyon follows earlier work on external sampling profilers such as
360+
`Austin <https://github.com/P403n1x87/austin>`__,
361+
`py-spy <https://github.com/benfred/py-spy>`__,
362+
`Pyflame <https://github.com/uber-archive/pyflame>`__, and
363+
`rbspy <https://github.com/rbspy/rbspy>`__. We thank their authors and the wider
364+
profiling community for their work and ideas.
365+
359366
Unlike deterministic profilers (such as :mod:`profiling.tracing`) that instrument
360367
every function call, the sampling profiler periodically captures stack traces from
361368
running processes. This approach provides virtually zero overhead while achieving

‎Doc/whatsnew/3.16.rst‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,13 @@ New deprecations
12511251
open them one by one instead.
12521252
(Contributed by Serhiy Storchaka in :gh:`152638`.)
12531253

1254+
* :mod:`typing`:
1255+
1256+
* :data:`typing.AnyStr` now raises :exc:`DeprecationWarning`
1257+
when used and is scheduled to be removed in Python 3.21.
1258+
Use :pep:`695` syntax instead.
1259+
(Contributed by Nikita Sobolev in :gh:`150190`.)
1260+
12541261
.. Add deprecations above alphabetically, not here at the end.
12551262
12561263
.. include:: ../deprecations/pending-removal-in-3.17.rst

‎Lib/test/test_bytes.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2098,6 +2098,22 @@ def g():
20982098
alloc = b.__alloc__()
20992099
self.assertGreater(alloc, len(b))
21002100

2101+
def test_init_from_iterator_with_offset(self):
2102+
# gh-158928: Inserting from an iterator in __init__ needs to take into
2103+
# account if there is a start offset.
2104+
b = bytearray()
2105+
def iterator_which_resets():
2106+
# __init__ reset ob_start. Make it an offset inside by allocating
2107+
# then doing fast prefix delete.
2108+
nonlocal b
2109+
b.resize(200)
2110+
del b[:100]
2111+
# Fill remaining already allocated space
2112+
yield from b'A' * 100
2113+
# Fill to end. Used to land out of bounds and crash.
2114+
b.__init__(iterator_which_resets())
2115+
self.assertEqual(b, bytes(100) + b'A' * 100)
2116+
21012117
def test_extend(self):
21022118
orig = b'hello'
21032119
a = bytearray(orig)

‎Lib/test/test_io/test_textio.py‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ def test_detach(self):
244244
r = self.BytesIO()
245245
b = self.BufferedWriter(r)
246246
t = self.TextIOWrapper(b, encoding="ascii")
247+
self.assertIs(t.buffer, b)
247248
self.assertIs(t.detach(), b)
248249

249250
t = self.TextIOWrapper(b, encoding="ascii")
@@ -259,6 +260,7 @@ def test_detach(self):
259260
self.assertEqual(t.errors, "strict")
260261
self.assertFalse(t.line_buffering)
261262
self.assertFalse(t.write_through)
263+
self.assertIsNone(t.buffer)
262264

263265
def test_repr(self):
264266
raw = self.BytesIO("hello".encode("utf-8"))
@@ -1721,9 +1723,7 @@ def readinto(self, b):
17211723
self.BufferedReader(raw), encoding="utf-8")
17221724
method = getattr(wrapper, method_name)
17231725
self.assertEqual(method(), "ab\n")
1724-
with self.assertRaisesRegex(ValueError,
1725-
"underlying buffer has been detached"):
1726-
getattr(wrapper, 'buffer')
1726+
self.assertIsNone(wrapper.buffer)
17271727

17281728
def test_reentrant_seek_during_tell(self):
17291729
# gh-153539: reading short of _CHUNK_SIZE leaves residual bytes in the

‎Lib/test/test_typing.py‎

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
from typing import Any, NoReturn, Never, assert_never
2323
from typing import overload, get_overloads, clear_overloads
24-
from typing import TypeVar, TypeVarTuple, Unpack, AnyStr
24+
from typing import TypeVar, TypeVarTuple, Unpack
2525
from typing import T, KT, VT # Not in __all__.
2626
from typing import Union, Optional, Literal
2727
from typing import Tuple, List, Dict, MutableMapping
@@ -489,7 +489,6 @@ def test_repr(self):
489489
self.assertEqual(repr(T), '~T')
490490
self.assertEqual(repr(KT), '~KT')
491491
self.assertEqual(repr(VT), '~VT')
492-
self.assertEqual(repr(AnyStr), '~AnyStr')
493492
T_co = TypeVar('T_co', covariant=True)
494493
self.assertEqual(repr(T_co), '+T_co')
495494
T_contra = TypeVar('T_contra', contravariant=True)
@@ -6388,13 +6387,15 @@ def on_bottom(self, a: int) -> int:
63886387
class CastTests(BaseTestCase):
63896388

63906389
def test_basics(self):
6390+
T = TypeVar("T")
6391+
63916392
self.assertEqual(cast(int, 42), 42)
63926393
self.assertEqual(cast(float, 42), 42)
63936394
self.assertIs(type(cast(float, 42)), int)
63946395
self.assertEqual(cast(Any, 42), 42)
63956396
self.assertEqual(cast(list, 42), 42)
63966397
self.assertEqual(cast(Union[str, float], 42), 42)
6397-
self.assertEqual(cast(AnyStr, 42), 42)
6398+
self.assertEqual(cast(T, 42), 42)
63986399
self.assertEqual(cast(None, 42), 42)
63996400

64006401
def test_errors(self):
@@ -6407,9 +6408,10 @@ class AssertTypeTests(BaseTestCase):
64076408

64086409
def test_basics(self):
64096410
arg = 42
6411+
T = TypeVar("T")
64106412
self.assertIs(assert_type(arg, int), arg)
64116413
self.assertIs(assert_type(arg, str | float), arg)
6412-
self.assertIs(assert_type(arg, AnyStr), arg)
6414+
self.assertIs(assert_type(arg, T), arg)
64136415
self.assertIs(assert_type(arg, None), arg)
64146416

64156417
def test_errors(self):
@@ -9637,12 +9639,15 @@ def test_no_isinstance(self):
96379639
class IOTests(BaseTestCase):
96389640

96399641
def test_io(self):
9640-
9641-
def stuff(a: IO) -> AnyStr:
9642+
def stuff(a: IO):
96429643
return a.readline()
96439644

96449645
a = stuff.__annotations__['a']
9645-
self.assertEqual(a.__parameters__, (AnyStr,))
9646+
self.assertEqual(len(a.__parameters__), 1)
9647+
any_str = a.__parameters__[0]
9648+
self.assertEqual(repr(any_str), 'AnyStr')
9649+
self.assertEqual(any_str.__bound__, None)
9650+
self.assertEqual(any_str.__constraints__, (bytes, str))
96469651

96479652
def test_textio(self):
96489653

@@ -11285,13 +11290,22 @@ def test_all_exported_names(self):
1128511290
# there's a few types and metaclasses that aren't exported
1128611291
not k.endswith(('Meta', '_contra', '_co')) and
1128711292
not k.upper() == k and
11288-
k not in {"ByteString"} and
11293+
k not in {"ByteString", "AnyStr"} and
1128911294
# but export all other things that have __module__ == 'typing'
1129011295
getattr(v, '__module__', None) == typing.__name__
1129111296
)
1129211297
}
1129311298
self.assertSetEqual(computed_all, actual_all)
1129411299

11300+
def test_any_str_deprecated(self):
11301+
# gh-105578
11302+
fresh = import_helper.import_fresh_module('typing')
11303+
11304+
with self.assertWarnsRegex(DeprecationWarning, r'typing\.AnyStr'):
11305+
fresh.AnyStr
11306+
11307+
self.assertEqual(repr(fresh.AnyStr), '~AnyStr')
11308+
1129511309

1129611310
class TypeIterationTests(BaseTestCase):
1129711311
_UNITERABLE_TYPES = (

‎Lib/typing.py‎

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,6 @@
123123
'TextIO',
124124

125125
# One-off things.
126-
'AnyStr',
127126
'assert_type',
128127
'assert_never',
129128
'cast',
@@ -2840,11 +2839,6 @@ class Disjoint3(Disjoint1, Disjoint2): pass # Type checker error
28402839
CT_co = TypeVar('CT_co', covariant=True, bound=type)
28412840

28422841

2843-
# A useful type variable with constraints. This represents string types.
2844-
# (This one *is* for export!)
2845-
AnyStr = TypeVar('AnyStr', bytes, str)
2846-
2847-
28482842
# Various ABCs mimicking those in collections.abc.
28492843
_alias = _SpecialGenericAlias
28502844

@@ -3548,8 +3542,9 @@ def __ror__(self, other):
35483542
# Constant that's True when type checking, but False here.
35493543
TYPE_CHECKING = False
35503544

3551-
3552-
class IO(Generic[AnyStr]):
3545+
# Since `AnyStr` public API is deprecated since 3.16 and will be removed
3546+
# in 3.21, we need to keep `IO` protocol the same as it used to be:
3547+
class IO[AnyStr: (bytes, str)]:
35533548
"""Generic base class for TextIO and BinaryIO.
35543549
35553550
This is an abstract, generic version of the return of open().
@@ -3949,6 +3944,20 @@ def __subclasscheck__(self, cls):
39493944
)
39503945

39513946
return ByteString
3947+
elif attr == "AnyStr":
3948+
import warnings
3949+
3950+
warnings._deprecated(
3951+
"typing.AnyStr",
3952+
message=(
3953+
"{name!r} is deprecated and slated for removal "
3954+
"in Python {remove}. Use PEP 695 type parameters "
3955+
"with constraints instead"
3956+
),
3957+
remove=(3, 21),
3958+
)
3959+
AnyStr = globals()["AnyStr"] = TypeVar('AnyStr', bytes, str)
3960+
return AnyStr
39523961
else:
39533962
raise AttributeError(f"module {__name__!r} has no attribute {attr!r}")
39543963
globals()[attr] = obj
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Deprecate :data:`typing.AnyStr` type variable and raise a warning when it
2+
is imported.

0 commit comments

Comments
 (0)