home-assistant/parse-requirements: write missing deps to component-packages.nix

This commit is contained in:
Jörg Thalheim 2020-02-26 15:22:48 +00:00
parent 0cf1e8ee05
commit de1119f5fb
No known key found for this signature in database
GPG Key ID: 003F2096411B5F92

View File

@ -24,6 +24,7 @@ import sys
import tarfile import tarfile
import tempfile import tempfile
from io import BytesIO from io import BytesIO
from typing import Dict, Optional
from urllib.request import urlopen from urllib.request import urlopen
COMPONENT_PREFIX = "homeassistant.components" COMPONENT_PREFIX = "homeassistant.components"
@ -78,22 +79,23 @@ def get_reqs(components, component):
return requirements return requirements
# Store a JSON dump of Nixpkgs' python3Packages def dump_packages() -> Dict[str, Dict[str, str]]:
output = subprocess.check_output( # Store a JSON dump of Nixpkgs' python3Packages
[ output = subprocess.check_output(
"nix-env", [
"-f", "nix-env",
os.path.dirname(sys.argv[0]) + "/../../..", "-f",
"-qa", os.path.dirname(sys.argv[0]) + "/../../..",
"-A", "-qa",
PKG_SET, "-A",
"--json", PKG_SET,
] "--json",
) ]
packages = json.loads(output) )
return json.loads(output)
def name_to_attr_path(req): def name_to_attr_path(req: str, packages: Dict[str, Dict[str, str]]) -> Optional[str]:
attr_paths = set() attr_paths = set()
names = [req] names = [req]
# E.g. python-mpd2 is actually called python3.6-mpd2 # E.g. python-mpd2 is actually called python3.6-mpd2
@ -124,41 +126,50 @@ def name_to_attr_path(req):
return None return None
version = get_version() def main() -> None:
print("Generating component-packages.nix for version {}".format(version)) packages = dump_packages()
components = parse_components(version=version) version = get_version()
build_inputs = {} print("Generating component-packages.nix for version {}".format(version))
for component in sorted(components.keys()): components = parse_components(version=version)
attr_paths = [] build_inputs = {}
missing_reqs = [] for component in sorted(components.keys()):
reqs = sorted(get_reqs(components, component)) attr_paths = []
for req in reqs: missing_reqs = []
# Some requirements are specified by url, e.g. https://example.org/foobar#xyz==1.0.0 reqs = sorted(get_reqs(components, component))
# Therefore, if there's a "#" in the line, only take the part after it for req in reqs:
req = req[req.find("#") + 1 :] # Some requirements are specified by url, e.g. https://example.org/foobar#xyz==1.0.0
name = req.split("==")[0] # Therefore, if there's a "#" in the line, only take the part after it
attr_path = name_to_attr_path(name) req = req[req.find("#") + 1 :]
if attr_path is not None: name = req.split("==")[0]
# Add attribute path without "python3Packages." prefix attr_path = name_to_attr_path(name, packages)
attr_paths.append(attr_path[len(PKG_SET + ".") :]) if attr_path is not None:
# Add attribute path without "python3Packages." prefix
attr_paths.append(attr_path[len(PKG_SET + ".") :])
else:
missing_reqs.append(name)
else: else:
missing_reqs.append(name) build_inputs[component] = (attr_paths, missing_reqs)
else: n_diff = len(reqs) > len(build_inputs[component])
build_inputs[component] = attr_paths if n_diff > 0:
n_diff = len(reqs) > len(build_inputs[component]) print("Component {} is missing {} dependencies".format(component, n_diff))
if n_diff > 0: print("missing requirements: {}".format(missing_reqs))
print("Component {} is missing {} dependencies".format(component, n_diff))
print("missing requirements: {}".format(missing_reqs))
with open(os.path.dirname(sys.argv[0]) + "/component-packages.nix", "w") as f: with open(os.path.dirname(sys.argv[0]) + "/component-packages.nix", "w") as f:
f.write("# Generated by parse-requirements.py\n") f.write("# Generated by parse-requirements.py\n")
f.write("# Do not edit!\n\n") f.write("# Do not edit!\n\n")
f.write("{\n") f.write("{\n")
f.write(f' version = "{version}";\n') f.write(f' version = "{version}";\n')
f.write(" components = {\n") f.write(" components = {\n")
for component, attr_paths in build_inputs.items(): for component, deps in build_inputs.items():
f.write(' "{component}" = ps: with ps; [ ') available, missing = deps
f.write(" ".join(attr_paths)) f.write(f" \"{component}\" = ps: with ps; [ ")
f.write(" ];\n") f.write(" ".join(available))
f.write(" };\n") f.write("];")
f.write("}\n") if len(missing) > 0:
f.write(f" # missing inputs: {' '.join(missing)}")
f.write("\n")
f.write(" };\n")
f.write("}\n")
if __name__ == '__main__':
main()