Skip to content

Commit e31ea13

Browse files
committed
Refactored min.py to be more robust/readable
1 parent d09a1c5 commit e31ea13

File tree

1 file changed

+141
-47
lines changed

1 file changed

+141
-47
lines changed

min.py

Lines changed: 141 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,162 @@
11
#!/usr/bin/env python
22

3+
import argparse
4+
35
import pandas as pd
46
from packaging.specifiers import SpecifierSet
57
from packaging.version import Version
68

79

8-
def check_compatibility(row, min_python, min_numpy):
10+
def get_min_python_version():
11+
"""
12+
Find the minimum version of Python supported (i.e., not end-of-life)
13+
"""
14+
min_python = (
15+
pd.read_html("https://devguide.python.org/versions/")[0].iloc[-1].Branch
16+
)
17+
return min_python
18+
19+
20+
def get_min_numba_numpy_version(min_python):
21+
"""
22+
Find the minimum versions of Numba and NumPy that supports the specified
23+
`min_python` version
24+
"""
25+
df = (
26+
pd.read_html(
27+
"https://numba.readthedocs.io/en/stable/user/installing.html#version-support-information" # noqa
28+
)[0]
29+
.dropna()
30+
.drop(columns=["Numba.1", "llvmlite", "LLVM", "TBB"])
31+
.query('`Python`.str.contains("2.7") == False')
32+
.query('`Numba`.str.contains(".x") == False')
33+
.query('`Numba`.str.contains("{") == False')
34+
.pipe(
35+
lambda df: df.assign(
36+
MIN_PYTHON_SPEC=(
37+
df.Python.str.split().str[1].replace({"<": ">"}, regex=True)
38+
+ df.Python.str.split().str[0].replace({".x": ""}, regex=True)
39+
).apply(SpecifierSet)
40+
)
41+
)
42+
.pipe(
43+
lambda df: df.assign(
44+
MAX_PYTHON_SPEC=(
45+
df.Python.str.split().str[3].replace({">": "<"}, regex=True)
46+
+ df.Python.str.split().str[4].replace({".x": ""}, regex=True)
47+
).apply(SpecifierSet)
48+
)
49+
)
50+
.pipe(
51+
lambda df: df.assign(
52+
MIN_NUMPY=(df.NumPy.str.split().str[0].replace({".x": ""}, regex=True))
53+
)
54+
)
55+
.assign(
56+
COMPATIBLE=lambda row: row.apply(
57+
check_python_compatibility, axis=1, args=(Version(min_python),)
58+
)
59+
)
60+
.query("COMPATIBLE == True")
61+
.pipe(lambda df: df.assign(MINOR=df.Numba.str.split(".").str[1]))
62+
.pipe(lambda df: df.assign(PATCH=df.Numba.str.split(".").str[2]))
63+
.sort_values(["MINOR", "PATCH"], ascending=[False, True])
64+
.iloc[-1]
65+
)
66+
return df.Numba, df.MIN_NUMPY
67+
68+
69+
def check_python_compatibility(row, min_python):
970
"""
10-
Determines the Python and NumPy version compatibility
71+
Determine the Python version compatibility
1172
"""
1273
python_compatible = min_python in (row.MIN_PYTHON_SPEC & row.MAX_PYTHON_SPEC)
13-
numpy_compatible = min_numpy in (row.MIN_NUMPY_SPEC & row.MAX_NUMPY_SPEC)
14-
return python_compatible & numpy_compatible
74+
return python_compatible
1575

1676

17-
MIN_PYTHON = "3.8" # Change this
77+
def check_scipy_compatibility(row, min_python, min_numpy):
78+
"""
79+
Determine the Python and NumPy version compatibility
80+
"""
81+
python_compatible = min_python in (row.MIN_PYTHON_SPEC & row.MAX_PYTHON_SPEC)
82+
numpy_compatible = min_numpy in (row.MIN_NUMPY_SPEC & row.MAX_NUMPY_SPEC)
83+
return python_compatible & numpy_compatible
1884

19-
df = (
20-
pd.read_html(
21-
"https://numba.readthedocs.io/en/stable/user/installing.html#version-support-information" # noqa
22-
)[0]
23-
.dropna()
24-
.query(f'Python.str.startswith("{MIN_PYTHON}")', engine="python")
25-
.pipe(lambda df: df.assign(NumPy=df.NumPy.str.split().str[0]))
26-
.iloc[-1]
27-
)
28-
MIN_NUMBA = df.Numba
29-
MIN_NUMPY = df.NumPy
3085

31-
df = (
32-
pd.read_html("https://docs.scipy.org/doc/scipy/dev/toolchain.html#numpy")[1]
33-
.replace({".x": ""}, regex=True)
34-
.rename(columns=lambda x: x.replace(" ", "_"))
35-
.query('`Python_versions`.str.contains("2.7") == False')
36-
.pipe(
37-
lambda df: df.assign(
38-
MIN_PYTHON_SPEC=df.Python_versions.str.split(",").str[0].apply(SpecifierSet)
86+
def get_min_scipy_version(min_python, min_numpy):
87+
"""
88+
Determine the SciPy version compatibility
89+
"""
90+
df = (
91+
pd.read_html("https://docs.scipy.org/doc/scipy/dev/toolchain.html#numpy")[1]
92+
.rename(columns=lambda x: x.replace(" ", "_"))
93+
.replace({".x": ""}, regex=True)
94+
.pipe(
95+
lambda df: df.assign(
96+
SciPy_version=df.SciPy_version.str.replace(
97+
"\d\/", "", regex=True # noqa
98+
)
99+
)
39100
)
40-
)
41-
.pipe(
42-
lambda df: df.assign(
43-
MAX_PYTHON_SPEC=df.Python_versions.str.split(",").str[1].apply(SpecifierSet)
101+
.query('`Python_versions`.str.contains("2.7") == False')
102+
.pipe(
103+
lambda df: df.assign(
104+
MIN_PYTHON_SPEC=df.Python_versions.str.split(",")
105+
.str[0]
106+
.apply(SpecifierSet)
107+
)
44108
)
45-
)
46-
.pipe(
47-
lambda df: df.assign(
48-
MIN_NUMPY_SPEC=df.NumPy_versions.str.split(",").str[0].apply(SpecifierSet)
109+
.pipe(
110+
lambda df: df.assign(
111+
MAX_PYTHON_SPEC=df.Python_versions.str.split(",")
112+
.str[1]
113+
.apply(SpecifierSet)
114+
)
49115
)
50-
)
51-
.pipe(
52-
lambda df: df.assign(
53-
MAX_NUMPY_SPEC=df.NumPy_versions.str.split(",").str[1].apply(SpecifierSet)
116+
.pipe(
117+
lambda df: df.assign(
118+
MIN_NUMPY_SPEC=df.NumPy_versions.str.split(",")
119+
.str[0]
120+
.apply(SpecifierSet)
121+
)
54122
)
55-
)
56-
.assign(
57-
COMPATIBLE=lambda row: row.apply(
58-
check_compatibility, axis=1, args=(Version(MIN_PYTHON), Version(MIN_NUMPY))
123+
.pipe(
124+
lambda df: df.assign(
125+
MAX_NUMPY_SPEC=df.NumPy_versions.str.split(",")
126+
.str[1]
127+
.apply(SpecifierSet)
128+
)
59129
)
130+
.assign(
131+
COMPATIBLE=lambda row: row.apply(
132+
check_scipy_compatibility,
133+
axis=1,
134+
args=(Version(min_python), Version(min_numpy)),
135+
)
136+
)
137+
.query("COMPATIBLE == True")
138+
.pipe(lambda df: df.assign(MINOR=df.SciPy_version.str.split(".").str[1]))
139+
.pipe(lambda df: df.assign(PATCH=df.SciPy_version.str.split(".").str[2]))
140+
.sort_values(["MINOR", "PATCH"], ascending=[False, True])
141+
.iloc[-1]
60142
)
61-
.query("COMPATIBLE == True")
62-
.iloc[-1]
63-
)
64-
MIN_SCIPY = df.SciPy_version
143+
return df.SciPy_version
144+
65145

66-
print(
67-
f"python: {MIN_PYTHON}\nnumba: {MIN_NUMBA}\nnumpy: {MIN_NUMPY}\nscipy: {MIN_SCIPY}"
68-
)
146+
if __name__ == "__main__":
147+
parser = argparse.ArgumentParser()
148+
parser.add_argument("min_python", nargs="?", default=None)
149+
args = parser.parse_args()
150+
151+
if args.min_python is not None:
152+
MIN_PYTHON = str(args.min_python)
153+
else:
154+
MIN_PYTHON = get_min_python_version()
155+
MIN_NUMBA, MIN_NUMPY = get_min_numba_numpy_version(MIN_PYTHON)
156+
MIN_SCIPY = get_min_scipy_version(MIN_PYTHON, MIN_NUMPY)
157+
print(
158+
f"python: {MIN_PYTHON}\n"
159+
f"numba: {MIN_NUMBA}\n"
160+
f"numpy: {MIN_NUMPY}\n"
161+
f"scipy: {MIN_SCIPY}"
162+
)

0 commit comments

Comments
 (0)