Skip to content

Commit e2b5f60

Browse files
authored
Merge pull request #14086 from tacaswell/cpython_support_nep
ENH: Propose standard policy for dropping support of old Python versions
2 parents a6729a0 + 90bd953 commit e2b5f60

File tree

1 file changed

+314
-0
lines changed

1 file changed

+314
-0
lines changed
Lines changed: 314 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
1+
==================================================================================
2+
NEP 29 — Recommend Python and Numpy version support as a community policy standard
3+
==================================================================================
4+
5+
6+
:Author: Thomas A Caswell <tcaswell@gmail.com>, Andreas Mueller, Brian Granger, Madicken Munk, Ralf Gommers, Matt Haberland <mhaberla@calpoly.edu>, Matthias Bussonnier <bussonniermatthias@gmail.com>, Stefan van der Walt
7+
:Status: Draft
8+
:Type: Informational Track
9+
:Created: 2019-07-13
10+
11+
12+
Abstract
13+
--------
14+
15+
This NEP recommends and encourages all projects across the Scientific
16+
Python ecosystem to adopt a common "time window-based" policy for
17+
support of Python and NumPy versions. Standardizing a recommendation
18+
for project support of minimum Python and NumPy versions will improve
19+
downstream project planning.
20+
21+
This is an unusual NEP in that it offers recommendations for
22+
community-wide policy and not for changes to NumPy itself. Since a
23+
common place for SPEEPs (Scientific Python Ecosystem Enhancement
24+
Proposals) does not exist and given NumPy's central role in the
25+
ecosystem, a NEP provides a visible place to document the proposed
26+
policy.
27+
28+
This NEP is being put forward by maintainers of Matplotlib, scikit-learn,
29+
IPython, Jupyter, yt, SciPy, NumPy, and scikit-image.
30+
31+
32+
33+
Detailed description
34+
--------------------
35+
36+
For the purposes of this NEP we assume semantic versioning and define:
37+
38+
*major version*
39+
A release that change the first number (e.g. X.0.0)
40+
41+
*minor version*
42+
A release that changes the second number (e.g x.Y.0)
43+
44+
*patch version*
45+
A release that changes the third number (e.g. x.y.Z)
46+
47+
48+
When a project creates a new major or minor version, we recommend that
49+
the project should support at least all minor versions of Python
50+
introduced and released in the prior 42 months ~~from their
51+
anticipated release date~~ with a minimum of 2 minor versions of
52+
Python, and all minor versions of NumPy released in the prior 24
53+
months ~~from their anticipated release date~~ with a minimum of 3
54+
minor versions of NumPy.
55+
56+
57+
The diagram::
58+
59+
Jan 16 Jan 17 Jan 18 Jan 19 Jan 20
60+
| | | | |
61+
+++++|+++++++++++|+++++++++++|+++++++++++|+++++++++++|++++++++++++
62+
| | | |
63+
py 3.5.0 py 3.6.0 py 3.7.0 py 3.8.0
64+
|-----------------------------------------> Feb19
65+
|-----------------------------------------> Dec19
66+
|-----------------------------------------> Nov20
67+
68+
shows the 42 month support windows for Python. A project with a
69+
major or minor version release in Feb19 should support py35 and newer,
70+
a project with a major or minor version release in Dec19 should
71+
support py36 and newer, and a project with a major or minor version
72+
release in Nov20 should support py37 and newer.
73+
74+
The current Python release cadence is 18 months so a 42 month window
75+
ensures that there will always be at least two minor versions of Python
76+
in the window. By padding the window by 6 months from the anticipated
77+
Python cadence we avoid the edge cases where a project releases
78+
the month after Python and would effectively only support one
79+
minor version of Python that has an installed base.
80+
This six month buffer provides resilience to minor fluctuations /
81+
delays in the Python release schedule.
82+
83+
Because Python minor version support is based on historical release
84+
dates, a 36 month time window, and a project's plans, a project can
85+
decide to drop a given minor version of Python very early in the release
86+
process.
87+
88+
While there will be some unavoidable mismatch in supported versions of
89+
Python between projects if releases occurs immediately after a
90+
minor version of Python ages out. This should not last longer than one
91+
release cycle of each of the projects, and when a given project does a
92+
minor or major release, it is guaranteed that there will be a stable
93+
release of all other projects that support the set of Python the
94+
new release will support.
95+
96+
If there is a Python 4 or a NumPy 2 this policy will have to be
97+
reviewed in light of the community's and projects' best interests.
98+
99+
100+
Support Table
101+
~~~~~~~~~~~~~
102+
103+
============ ====== =====
104+
Date Python NumPy
105+
------------ ------ -----
106+
Jan 16, 2019 3.5+ 1.13+
107+
Mar 14, 2019 3.6+ 1.13+
108+
Jun 08, 2019 3.6+ 1.14+
109+
Jan 07, 2020 3.6+ 1.15+
110+
Jun 23, 2020 3.7+ 1.15+
111+
Jul 23, 2020 3.7+ 1.16+
112+
Jan 13, 2021 3.7+ 1.17+
113+
Jul 26, 2021 3.7+ 1.18+
114+
Dec 26, 2021 3.8+ 1.18+
115+
============ ====== =====
116+
117+
118+
Drop Schedule
119+
~~~~~~~~~~~~~
120+
121+
::
122+
123+
On Jan 16, 2019 drop support for Numpy 1.12 (initially released on Jan 15, 2017)
124+
On Mar 14, 2019 drop support for Python 3.5 (initially released on Sep 13, 2015)
125+
On Jun 08, 2019 drop support for Numpy 1.13 (initially released on Jun 07, 2017)
126+
On Jan 07, 2020 drop support for Numpy 1.14 (initially released on Jan 06, 2018)
127+
On Jun 23, 2020 drop support for Python 3.6 (initially released on Dec 23, 2016)
128+
On Jul 23, 2020 drop support for Numpy 1.15 (initially released on Jul 23, 2018)
129+
On Jan 13, 2021 drop support for Numpy 1.16 (initially released on Jan 13, 2019)
130+
On Jul 26, 2021 drop support for Numpy 1.17 (initially released on Jul 26, 2019)
131+
On Dec 26, 2021 drop support for Python 3.7 (initially released on Jun 27, 2018)
132+
133+
134+
Implementation
135+
--------------
136+
137+
We suggest that all projects adopt the following language into their
138+
development guidelines:
139+
140+
141+
- This project supports at least the minor versions of Python
142+
initially released 42 months prior to a planned project release
143+
date.
144+
- The project will always support at least the 2 latest minor
145+
versions of Python.
146+
- support minor versions of ``numpy`` initially released in the 24
147+
months prior to a planned project release date or the oldest
148+
version that supports the minimum Python version (whichever is
149+
higher).
150+
- The project will always support at least the 3 latest minor
151+
versions of NumPy.
152+
153+
The minimum supported version of Python will be set to
154+
``python_requires`` in ``setup``. All supported minor versions of
155+
Python will be in the test matrix and have binary artifacts built
156+
for releases.
157+
158+
The project should adjust upward the minimum Python and NumPy
159+
version support on every minor and major release, but never on a
160+
patch release.
161+
162+
163+
Backward compatibility
164+
----------------------
165+
166+
No backward compatibility issues.
167+
168+
Alternatives
169+
------------
170+
171+
Ad-Hoc version support
172+
~~~~~~~~~~~~~~~~~~~~~~
173+
174+
A project could on every release evaluate whether to increase
175+
the minimum version of Python supported.
176+
As a major downside, an ad-hoc approach makes it hard for downstream users to predict what
177+
the future minimum versions will be. As there is no objective threshold
178+
to when the minimum version should be dropped, it is easy for these
179+
version support discussions to devolve into [bike shedding](https://en.wikipedia.org/wiki/Wikipedia:Avoid_Parkinson%27s_bicycle-shed_effect) and acrimony.
180+
181+
182+
All CPython supported versions
183+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
184+
185+
The CPython supported versions of Python are listed in the Python
186+
Developers Guide and the Python PEPs. Supporting these is a very
187+
clear and conservative approach. However, it means that there is 4
188+
year lag between when new language features come into the language and
189+
when the projects are able to use them. Additionally, for projects
190+
that have a significant component of compiled extensions this requires
191+
building many binary artifacts for each release.
192+
193+
For the case of NumPy, many projects carry workarounds to bugs that
194+
are fixed in subsequent versions of NumPy. Being proactive about
195+
increasing the minimum version of NumPy will allow downstream
196+
packages to carry fewer version-specific patches.
197+
198+
199+
200+
Default version on Linux distribution
201+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
202+
203+
The policy could be to support the version of Python that ships by
204+
default in the latest Ubuntu LTS or CentOS/RHEL release. However, we
205+
would still have to standardize across the community which
206+
distribution we are following.
207+
208+
By following the versions supported by major Linux distributions, we
209+
are giving up technical control of our projects to external
210+
organizations that may have different motivations and concerns than we
211+
do.
212+
213+
N minor versions of Python
214+
~~~~~~~~~~~~~~~~~~~~~~~~~~
215+
216+
Given the current release cadence of the Python, the proposed time (42
217+
months) is roughly equivalent to "the last two" Python minor versions.
218+
However, if Python changes their release cadence substantially, any
219+
rule based solely on the number of minor releases may need to be
220+
changed to remain sensible.
221+
222+
A more fundamental problem with a policy based on number of Python
223+
releases is that it is hard to predict when support for a given minor
224+
version of Python will be dropped as that requires correctly
225+
predicting the release schedule of Python for the next 3-4 years. A
226+
time-based rule is only depends on things that have already happened
227+
and the length of the support window.
228+
229+
230+
231+
232+
Time window from the X.Y.1 Python release
233+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
234+
235+
This is equivalent to a few month longer support window from the X.Y.0
236+
release. This is because X.Y.1 bug-fix release is typically a few
237+
months after the X.Y.0 release, thus a N month window from X.Y.1 is
238+
roughly equivalent to a N+3 month from X.Y.0.
239+
240+
The X.Y.0 release is naturally a special release. If we were to
241+
anchor the window on X.Y.1 we would then have the discussion of why
242+
not X.Y.M?
243+
244+
245+
Discussion
246+
----------
247+
248+
249+
References and Footnotes
250+
------------------------
251+
252+
Code to generate support and drop schedule tables ::
253+
254+
from datetime import datetime, timedelta
255+
256+
data = """Jan 15, 2017: Numpy 1.12
257+
Sep 13, 2015: Python 3.5
258+
Jun 27, 2018: Python 3.7
259+
Dec 23, 2016: Python 3.6
260+
Jun 07, 2017: Numpy 1.13
261+
Jan 06, 2018: Numpy 1.14
262+
Jul 23, 2018: Numpy 1.15
263+
Jan 13, 2019: Numpy 1.16
264+
Jul 26, 2019: Numpy 1.17
265+
"""
266+
267+
releases = []
268+
269+
plus42 = timedelta(days=int(365*3.5 + 1))
270+
plus24 = timedelta(days=int(365*2 + 1))
271+
272+
for line in data.splitlines():
273+
date, project_version = line.split(':')
274+
project, version = project_version.strip().split(' ')
275+
release = datetime.strptime(date, '%b %d, %Y')
276+
if project.lower() == 'numpy':
277+
drop = release + plus24
278+
else:
279+
drop = release + plus42
280+
releases.append((drop, project, version, release))
281+
282+
releases = sorted(releases, key=lambda x: x[0])
283+
284+
minpy = '3.8+'
285+
minnum = '1.18+'
286+
287+
toprint_drop_dates = ['']
288+
toprint_support_table = []
289+
for d, p, v, r in releases[::-1]:
290+
df = d.strftime('%b %d, %Y')
291+
toprint_drop_dates.append(
292+
f'On {df} drop support for {p} {v} '
293+
f'(initially released on {r.strftime("%b %d, %Y")})')
294+
toprint_support_table.append(f'{df} {minpy:<6} {minnum:<5}')
295+
if p.lower() == 'numpy':
296+
minnum = v+'+'
297+
else:
298+
minpy = v+'+'
299+
300+
for e in toprint_drop_dates[::-1]:
301+
print(e)
302+
303+
print('============ ====== =====')
304+
print('Date Python NumPy')
305+
print('------------ ------ -----')
306+
for e in toprint_support_table[::-1]:
307+
print(e)
308+
print('============ ====== =====')
309+
310+
311+
Copyright
312+
---------
313+
314+
This document has been placed in the public domain.

0 commit comments

Comments
 (0)