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