Skip to content

Commit 02f066a

Browse files
Backport PR #42720 on branch 1.3.x (CLN: clean the conda-to-pip script) (#42903)
1 parent 271f0d0 commit 02f066a

File tree

1 file changed

+31
-39
lines changed

1 file changed

+31
-39
lines changed

scripts/generate_pip_deps_from_conda.py

+31-39
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
$ python scripts/generate_pip_deps_from_conda.py --compare
1414
"""
1515
import argparse
16-
import os
16+
import pathlib
1717
import re
1818
import sys
1919

@@ -23,7 +23,7 @@
2323
RENAME = {"pytables": "tables", "pyqt": "pyqt5", "dask-core": "dask"}
2424

2525

26-
def conda_package_to_pip(package):
26+
def conda_package_to_pip(package: str):
2727
"""
2828
Convert a conda package to its pip equivalent.
2929
@@ -36,17 +36,13 @@ def conda_package_to_pip(package):
3636
package = re.sub("(?<=[^<>])=", "==", package).strip()
3737

3838
for compare in ("<=", ">=", "=="):
39-
if compare not in package:
40-
continue
39+
if compare in package:
40+
pkg, version = package.split(compare)
41+
if pkg in EXCLUDE:
42+
return
4143

42-
pkg, version = package.split(compare)
43-
if pkg in EXCLUDE:
44-
return
45-
46-
if pkg in RENAME:
47-
return "".join((RENAME[pkg], compare, version))
48-
49-
break
44+
if pkg in RENAME:
45+
return "".join((RENAME[pkg], compare, version))
5046

5147
if package in EXCLUDE:
5248
return
@@ -57,16 +53,18 @@ def conda_package_to_pip(package):
5753
return package
5854

5955

60-
def main(conda_fname, pip_fname, compare=False):
56+
def generate_pip_from_conda(
57+
conda_path: pathlib.Path, pip_path: pathlib.Path, compare: bool = False
58+
) -> bool:
6159
"""
6260
Generate the pip dependencies file from the conda file, or compare that
6361
they are synchronized (``compare=True``).
6462
6563
Parameters
6664
----------
67-
conda_fname : str
65+
conda_path : pathlib.Path
6866
Path to the conda file with dependencies (e.g. `environment.yml`).
69-
pip_fname : str
67+
pip_path : pathlib.Path
7068
Path to the pip file with dependencies (e.g. `requirements-dev.txt`).
7169
compare : bool, default False
7270
Whether to generate the pip file (``False``) or to compare if the
@@ -78,8 +76,8 @@ def main(conda_fname, pip_fname, compare=False):
7876
bool
7977
True if the comparison fails, False otherwise
8078
"""
81-
with open(conda_fname) as conda_fd:
82-
deps = yaml.safe_load(conda_fd)["dependencies"]
79+
with conda_path.open() as file:
80+
deps = yaml.safe_load(file)["dependencies"]
8381

8482
pip_deps = []
8583
for dep in deps:
@@ -88,24 +86,23 @@ def main(conda_fname, pip_fname, compare=False):
8886
if conda_dep:
8987
pip_deps.append(conda_dep)
9088
elif isinstance(dep, dict) and len(dep) == 1 and "pip" in dep:
91-
pip_deps += dep["pip"]
89+
pip_deps.extend(dep["pip"])
9290
else:
9391
raise ValueError(f"Unexpected dependency {dep}")
9492

95-
fname = os.path.split(conda_fname)[1]
9693
header = (
97-
f"# This file is auto-generated from {fname}, do not modify.\n"
94+
f"# This file is auto-generated from {conda_path.name}, do not modify.\n"
9895
"# See that file for comments about the need/usage of each dependency.\n\n"
9996
)
10097
pip_content = header + "\n".join(pip_deps) + "\n"
10198

10299
if compare:
103-
with open(pip_fname) as pip_fd:
104-
return pip_content != pip_fd.read()
105-
else:
106-
with open(pip_fname, "w") as pip_fd:
107-
pip_fd.write(pip_content)
108-
return False
100+
with pip_path.open() as file:
101+
return pip_content != file.read()
102+
103+
with pip_path.open("w") as file:
104+
file.write(pip_content)
105+
return False
109106

110107

111108
if __name__ == "__main__":
@@ -117,25 +114,20 @@ def main(conda_fname, pip_fname, compare=False):
117114
action="store_true",
118115
help="compare whether the two files are equivalent",
119116
)
120-
argparser.add_argument(
121-
"--azure", action="store_true", help="show the output in azure-pipelines format"
122-
)
123117
args = argparser.parse_args()
124118

125-
repo_path = os.path.dirname(os.path.abspath(os.path.dirname(__file__)))
126-
res = main(
127-
os.path.join(repo_path, "environment.yml"),
128-
os.path.join(repo_path, "requirements-dev.txt"),
119+
conda_fname = "environment.yml"
120+
pip_fname = "requirements-dev.txt"
121+
repo_path = pathlib.Path(__file__).parent.parent.absolute()
122+
res = generate_pip_from_conda(
123+
pathlib.Path(repo_path, conda_fname),
124+
pathlib.Path(repo_path, pip_fname),
129125
compare=args.compare,
130126
)
131127
if res:
132128
msg = (
133-
f"`requirements-dev.txt` has to be generated with `{sys.argv[0]}` after "
134-
"`environment.yml` is modified.\n"
129+
f"`{pip_fname}` has to be generated with `{__file__}` after "
130+
f"`{conda_fname}` is modified.\n"
135131
)
136-
if args.azure:
137-
msg = (
138-
f"##vso[task.logissue type=error;sourcepath=requirements-dev.txt]{msg}"
139-
)
140132
sys.stderr.write(msg)
141133
sys.exit(res)

0 commit comments

Comments
 (0)