"""Validate manifests.""" import pathlib import sys from time import monotonic from . import ( codeowners, config_flow, coverage, dependencies, json, manifest, services, ssdp, zeroconf, ) from .model import Config, Integration PLUGINS = [ json, codeowners, config_flow, coverage, dependencies, manifest, services, ssdp, zeroconf, ] def get_config() -> Config: """Return config.""" if not pathlib.Path("requirements_all.txt").is_file(): raise RuntimeError("Run from project root") return Config( root=pathlib.Path(".").absolute(), action="validate" if sys.argv[-1] == "validate" else "generate", ) def main(): """Validate manifests.""" try: config = get_config() except RuntimeError as err: print(err) return 1 integrations = Integration.load_dir(pathlib.Path("homeassistant/components")) for plugin in PLUGINS: try: start = monotonic() print(f"Validating {plugin.__name__.split('.')[-1]}...", end="", flush=True) plugin.validate(integrations, config) print(" done in {:.2f}s".format(monotonic() - start)) except RuntimeError as err: print() print() print("Error!") print(err) return 1 # When we generate, all errors that are fixable will be ignored, # as generating them will be fixed. if config.action == "generate": general_errors = [err for err in config.errors if not err.fixable] invalid_itg = [ itg for itg in integrations.values() if any(not error.fixable for error in itg.errors) ] else: # action == validate general_errors = config.errors invalid_itg = [itg for itg in integrations.values() if itg.errors] print("Integrations:", len(integrations)) print("Invalid integrations:", len(invalid_itg)) if not invalid_itg and not general_errors: for plugin in PLUGINS: if hasattr(plugin, "generate"): plugin.generate(integrations, config) return 0 print() if config.action == "generate": print("Found errors. Generating files canceled.") print() if general_errors: print("General errors:") for error in general_errors: print("*", error) print() for integration in sorted(invalid_itg, key=lambda itg: itg.domain): print(f"Integration {integration.domain}:") for error in integration.errors: print("*", error) print() return 1 if __name__ == "__main__": sys.exit(main())