The deprecated functionality will be removed from the typing module in the first Python version released 5 years after the release of Python 3.9.0.
where “deprecated functionality” refers to typing.List, typing.Dict, etc.
Removal will break pretty much all typed code and all typing documentation / resources written to support Python 3.8 and earlier. I’m not sure the one year between 3.8 going EOL and the removal date mentioned in PEP 585 is enough to expect all libraries with type hints to update.
I propose we remove the phrasing of a definite timeline from PEP 585. The objects themselves remain deprecated and we’ll work to minimise their use. If there is concern about kicking the can down the road forever, here are some concrete actions we can take in that space to ensure an eventual path to removal:
Evangelising use of tools that can automatically switch to use of builtins, like pyupgrade
Minimising reference to deprecated objects in documentation
I’m not aware of type checkers that have PEP 585’s proposed warning for usage of deprecated typing objects enabled by default. We can help ensure this happens, but likely only feasible following 3.8’s EOL.
I’ll also make note of an alternative history that could have existed at the time of PEP 585’s writing. There is a world in which type hints are only used by static type checkers and from __future__ import annotations is extremely widely used, and the default in Python 3.10. In this alternate history, once Python 3.6 went EOL, most code starts using builtin generics in annotations. Unfortunately, this doesn’t appear to be the history our universe has chosen.
I’m in favour of delaying the removal of these objects from typing; I agree that they’re very widely used at the moment, and that the current timescale probably isn’t long enough for libraries to update their code.
I would like for us to have a plan, though, instead of just saying “the removal date is undecided”. The maintenance cost of these objects is very low, but I’d really like the typing module to have a smaller API — I think the cognitive load for newcomers to Python’s typing system is too big at the moment.
I propose, instead, that we introduce DeprecationWarnings for these objects in 3.14, with a view to removing these objects in 3.16.
I don’t really want to ever remove the deprecated aliases, because doing so will break compatibility for a lot of code written for older Python versions.
To reduce the cognitive load in the docs, we can relegate the aliases to a very concise section that goes “List – deprecated alias for :class:list; Generator – deprecated alias for :class:collections.abc.Generator”. Similarly, at runtime we can simply define List = list in typing.py.
I suppose it will break some code that introspects annotations (and hasn’t been updated to deal with types.GenericAlias). But I’m more willing to break that category of code than to break everyone who writes x: List[int].
A somewhat comparable removal is asyncio.coroutine, since it affects all users of async Python analogously to how this affects all users of typed Python. async def syntax was added in 3.5, in 2015. asyncio.coroutine was removed in 3.11, in 2022. So that would suggest no sooner than 3.16 (2027).
Note, however that:
asyncio.coroutine was provisional in all Python versions that didn’t support async def, so there was less of a stability promise
PEP 3156 to async def was three years, PEP 484 to list[int] was six years.
typing is much more widely used than asyncio
A much more compelling datapoint to me is moving collections ABCs to collections.abc. That deprecation period was 9 years, which would suggest 3.18 (2029), with warnings starting in 3.15 (2026).
And of course, if you think that a better analogy is turning print to a function, that looks more on the lines of keeping things around forever.
My personal opinions:
Like Jelle, I think we can get the costs low enough that an indefinite deprecation would be fine.
If we want removal, I think collections.abc is reasonable prior art. In particular, that timeline would leave a nice window of 2024 to 2026, where people can slowly upgrade to versions of type checkers that statically warn about this, without incurring runtime warnings (which were annoying for a while with collections.abc).
We do not need to decide upon a fixed date today. The date in the PEP is the minimum, we won’t do it sooner than that.
When it comes time to both (a) prominently surface warnings (not intended in the PEP 585 case) and (b) do removals based on an earlier scheduled assumption declared by a PEP we should always take the state of the global Python ecosystem at the time into account. We’ve delayed deprecation removals in the past due to disruption.
In the PEP 585 situation it appears to be merely adopting a conditional import to code still needing to support a very old Python version. Probably not too onerous. But we can wait until after 3.13 is released to start doing research on typed codebases to find out.
I like Serhiy’s steps. I also want to add that I do lookout for feature parity between List and list and often consider different behavior (other than the relaxation of type checks) a bug. So hopefully if we alias List to list in the future, the runtime checkers shouldn’t break. (I bet years from now I’ll look back and realise I’m making a fool of myself here by saying this )
Given a) I don’t think anyone wants to pursue the removal on the original timeline, b) there doesn’t seem much appetite for coming up with a concrete removal timeline, we could alter the PEP 585 wording to say:
The deprecated functionality will eventually be removed from the typing module. Removal will occur no sooner than the first Python version released 5 years after the release of Python 3.9.0.
Realistically, I don’t think there’s any way we remove these in Python 3.14 — this would be unprecedentedly fast — so I’d like to propose the following change:
The deprecated functionality will eventually be removed from the typing module. Removal will occur no sooner than the first Python version released 7 years after the release of Python 3.9.0.
An extra two years is significantly better in that it means most people will stop worrying about whether or not they have to write “bridging code” for Python 3.9, like in today’s case:
It’s a little unclear to me what the process here is. To try and close the loop, if this post gets likes from core devs and no explicit opposition, I’ll open a PR to the PEPs repo, but please let me know if that’s overstepping
In general, PEPs are no longer substantially modified after they have reached the Accepted, Final, Rejected or Superseded state. Once resolution is reached, a PEP is considered a historical document rather than a living specification. Formal documentation of the expected behavior should be maintained elsewhere, such as the Language Reference for core features, the Library Reference for standard library modules or the PyPA Specifications for packaging.
However, here we don’t explicitly address PEP language that talks about planned future events that may change. This particular case is a close parallel to python/peps#2096 in that respect, which also sought to update a specified criterion for a future removal. In that case, we went ahead and merged it, and I believe the same reasoning would apply here, given the cases are nearly identical and the main justification in both was reducing repeated user (and potentially implementer) confusion, which there was clear evidence for.
The main prerequisite is ensuring there is consensus among the PEP author ( @ambv ) and the typing community that the change is both worthwhile and does not compromise the intent of the approved PEP. I suggest making a Typing-SIG thread and if there’s general consensus there and here, and folks like @ambv and @Jelle are on it, then I’d see no objections to merging it following appropriate review (at least speaking for myself here, not the other PEP editors).
When PEP 585 was being written, I was asked to explicitly state when deprecated names would get removed. Regular deprecations are removed two releases after they get deprecated per PEP 387. I felt like the regular deprecation schedule for this would be too aggressive so I opted to extend this period to five years after 3.9.0, which essentially means “after Python 3.9 goes entirely EOL”. That’s October 2025. @srittau is suggesting tying it to “one year after 3.8 EOL” which is also October 2025.
It’s not clear to me how changing the wording from 5 years to 7 improves the situation. I’m pretty sure we’ll get more people to complain when that deadline is reached. Why not 6? Why not 8?
Maybe the only change we require is changing the wording from “will be removed” to “will not be removed before”, i.e. change the requirement to remove the items to a promise that the items won’t be removed for a certain time. Then we can analyze usage and/or introduce more or less aggressive warnings after that date, but are not “forced” to remove the items if usage is still too high.