core/script/gen_requirements_all.py

603 lines
18 KiB
Python
Raw Normal View History

2015-11-17 08:18:42 +00:00
#!/usr/bin/env python3
"""Generate updated constraint and requirements files."""
from __future__ import annotations
import difflib
2015-11-17 08:18:42 +00:00
import importlib
from operator import itemgetter
from pathlib import Path
2015-11-17 08:18:42 +00:00
import pkgutil
import re
2015-12-18 07:51:34 +00:00
import sys
2023-07-22 22:04:45 +00:00
import tomllib
2023-08-21 17:14:07 +00:00
from typing import Any
2023-07-22 22:04:45 +00:00
from homeassistant.util.yaml.loader import load_yaml
from script.hassfest.model import Config, Integration
# Requirements which can't be installed on all systems because they rely on additional
# system packages. Requirements listed in EXCLUDED_REQUIREMENTS_ALL will be commented-out
# in requirements_all.txt and requirements_test_all.txt.
EXCLUDED_REQUIREMENTS_ALL = {
"atenpdu", # depends on pysnmp which is not maintained at this time
"avea", # depends on bluepy
2019-07-31 19:25:30 +00:00
"avion",
"beacontools",
Fix package names to match pypi index metadata (#93883) * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * uses _ * uses - * fix metadata
2023-06-01 01:12:53 +00:00
"beewi-smartclim", # depends on bluepy
2019-07-31 19:25:30 +00:00
"bluepy",
"decora",
Fix package names to match pypi index metadata (#93883) * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * uses _ * uses - * fix metadata
2023-06-01 01:12:53 +00:00
"decora-wifi",
2019-07-31 19:25:30 +00:00
"evdev",
Fix package names to match pypi index metadata (#93883) * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * Fix package names to match pypi index metadata * uses _ * uses - * fix metadata
2023-06-01 01:12:53 +00:00
"face-recognition",
2019-07-31 19:25:30 +00:00
"pybluez",
"pycocotools",
2019-07-31 19:25:30 +00:00
"pycups",
"python-gammu",
2019-07-31 19:25:30 +00:00
"python-lirc",
"pyuserinput",
"tensorflow",
"tf-models-official",
}
# Requirements excluded by EXCLUDED_REQUIREMENTS_ALL which should be included when
# building integration wheels for all architectures.
INCLUDED_REQUIREMENTS_WHEELS = {
"decora-wifi",
"evdev",
"pycups",
"python-gammu",
"pyuserinput",
}
# Requirements to exclude or include when running github actions.
# Requirements listed in "exclude" will be commented-out in
# requirements_all_{action}.txt
# Requirements listed in "include" must be listed in EXCLUDED_REQUIREMENTS_CI, and
# will be included in requirements_all_{action}.txt
OVERRIDDEN_REQUIREMENTS_ACTIONS = {
"pytest": {"exclude": set(), "include": {"python-gammu"}},
"wheels_aarch64": {"exclude": set(), "include": INCLUDED_REQUIREMENTS_WHEELS},
# Pandas has issues building on armhf, it is expected they
# will drop the platform in the near future (they consider it
# "flimsy" on 386). The following packages depend on pandas,
# so we comment them out.
"wheels_armhf": {
"exclude": {"env-canada", "noaa-coops", "pyezviz", "pykrakenapi"},
"include": INCLUDED_REQUIREMENTS_WHEELS,
},
"wheels_armv7": {"exclude": set(), "include": INCLUDED_REQUIREMENTS_WHEELS},
"wheels_amd64": {"exclude": set(), "include": INCLUDED_REQUIREMENTS_WHEELS},
"wheels_i386": {"exclude": set(), "include": INCLUDED_REQUIREMENTS_WHEELS},
}
IGNORE_PIN = ("colorlog>2.1,<3", "urllib3")
2019-07-31 19:25:30 +00:00
URL_PIN = (
"https://developers.home-assistant.io/docs/"
"creating_platform_code_review.html#1-requirements"
)
2017-01-22 16:34:00 +00:00
2015-11-17 08:18:42 +00:00
CONSTRAINT_PATH = (
Path(__file__).parent.parent / "homeassistant" / "package_constraints.txt"
2019-07-31 19:25:30 +00:00
)
CONSTRAINT_BASE = """
# Constrain pycryptodome to avoid vulnerability
# see https://github.com/home-assistant/core/pull/16238
2018-08-28 10:49:50 +00:00
pycryptodome>=3.6.6
# Constrain httplib2 to protect against GHSA-93xj-8mrv-444m
# https://github.com/advisories/GHSA-93xj-8mrv-444m
httplib2>=0.19.0
2020-06-01 07:44:18 +00:00
# gRPC is an implicit dependency that we want to make explicit so we manage
# upgrades intentionally. It is a large package to build from source and we
# want to ensure we have wheels built.
2023-10-06 08:08:01 +00:00
grpcio==1.59.0
grpcio-status==1.59.0
grpcio-reflection==1.59.0
# This is a old unmaintained library and is replaced with pycryptodome
pycrypto==1000000000.0.0
Add python 3.11 to the CI (#88038) * Remove profiler.memory service guppy3 is not python3.11 compat https://github.com/zhuyifei1999/guppy3/issues/41 This service will return if and when guppy3 becomes python3.11 compat * squash * temp remove * temp dump tests * temp dump tests * drop a few more to get a run * drop a few more to get a run * Account for changed python3.11 enum.IntFlag behavior in zha There may be additional changes needed, but I could only see what needed to be updated based on the tests * merge * restore * restore * legacy value * tweak a bit for the python 3.11 timings * block cchardet * conditional * adjust est * test * not yet * tweak * give a little leeway for timing * Fix otbr tests * Increase database test timeout It looks like we need a little more time to run with the addiitonal tests in #87019 * Increase database test timeout It looks like we need a little more time to run with the addiitonal tests in #87019 * Fix aprs tests with python 3.11 * merge fix * hints * Update homeassistant/package_constraints.txt * Update script/gen_requirements_all.py * Constrain uamqp for Python 3.10 only * Bump vulcan-api to 2.3.0 see https://github.com/kapi2289/vulcan-api/pull/126 see https://github.com/home-assistant/core/pull/88038 see https://github.com/home-assistant/docker/pull/260 * add ban * Bump python-matter-server to 2.1.1 * revert * Update tests/asyncio_legacy.py --------- Co-authored-by: Erik <erik@montnemery.com> Co-authored-by: Franck Nijhof <git@frenck.dev> Co-authored-by: Marcel van der Veldt <m.vanderveldt@outlook.com>
2023-02-16 17:38:32 +00:00
# This is a old unmaintained library and is replaced with faust-cchardet
cchardet==1000000000.0.0
2020-08-26 14:53:22 +00:00
# To remove reliance on typing
btlewrap>=0.0.10
# This overrides a built-in Python package
enum34==1000000000.0.0
typing==1000000000.0.0
uuid==1000000000.0.0
# httpx requires httpcore, and httpcore requires anyio and h11, but the version constraints on
# these requirements are quite loose. As the entire stack has some outstanding issues, and
# even newer versions seem to introduce new issues, it's useful for us to pin all these
# requirements so we can directly link HA versions to these library versions.
2024-06-21 08:31:37 +00:00
anyio==4.4.0
2022-11-26 20:04:22 +00:00
h11==0.14.0
httpcore==1.0.5
2022-02-17 13:58:24 +00:00
# Ensure we have a hyperframe version that works in Python 3.10
# 5.2.0 fixed a collections abc deprecation
hyperframe>=5.2.0
# Ensure we run compatible with musllinux build env
numpy==1.26.0
# Constrain multidict to avoid typing issues
# https://github.com/home-assistant/core/pull/67046
multidict>=6.0.2
# Version 2.0 added typing, prevent accidental fallbacks
backoff>=2.0
2023-09-28 17:06:45 +00:00
# Required to avoid breaking (#101042).
# v2 has breaking changes (#99218).
2024-06-21 08:16:36 +00:00
pydantic==1.10.17
2022-07-13 21:12:53 +00:00
# Required for Python 3.12.4 compatibility (#119223).
mashumaro>=3.13.1
2022-07-13 21:12:53 +00:00
# Breaks asyncio
# https://github.com/pubnub/python/issues/130
pubnub!=6.4.0
# Package's __init__.pyi stub has invalid syntax and breaks mypy
# https://github.com/dahlia/iso4217/issues/16
iso4217!=1.10.20220401
2022-09-01 19:00:50 +00:00
# pyOpenSSL 24.0.0 or later required to avoid import errors when
# cryptography 42.0.0 is installed with botocore
pyOpenSSL>=24.0.0
2023-04-17 08:30:22 +00:00
# protobuf must be in package constraints for the wheel
# builder to build binary wheels
2024-08-12 19:51:45 +00:00
protobuf==4.25.4
2023-04-17 08:30:22 +00:00
# faust-cchardet: Ensure we have a version we can build wheels
# 2.1.18 is the first version that works with our wheel builder
faust-cchardet>=2.1.18
# websockets 11.0 is missing files in the source distribution
# which break wheel builds so we need at least 11.0.1
# https://github.com/aaugustin/websockets/issues/1329
websockets>=11.0.1
# pysnmplib is no longer maintained and does not work with newer
# python
pysnmplib==1000000000.0.0
# The get-mac package has been replaced with getmac. Installing get-mac alongside getmac
# breaks getmac due to them both sharing the same python package name inside 'getmac'.
get-mac==1000000000.0.0
# We want to skip the binary wheels for the 'charset-normalizer' packages.
# They are build with mypyc, but causes issues with our wheel builder.
# In order to do so, we need to constrain the version.
charset-normalizer==3.2.0
2023-12-30 10:29:19 +00:00
# dacite: Ensure we have a version that is able to handle type unions for
# Roborock, NAM, Brother, and GIOS.
dacite>=1.7.0
2024-01-20 17:08:35 +00:00
# Musle wheels for pandas 2.2.0 cannot be build for any architecture.
pandas==2.1.4
# chacha20poly1305-reuseable==0.12.x is incompatible with cryptography==43.0.x
chacha20poly1305-reuseable>=0.13.0
# pycountry<23.12.11 imports setuptools at run time
# https://github.com/pycountry/pycountry/blob/ea69bab36f00df58624a0e490fdad4ccdc14268b/HISTORY.txt#L39
pycountry>=23.12.11
2024-03-26 20:31:52 +00:00
# scapy<2.5.0 will not work with python3.12
scapy>=2.5.0
2024-05-02 14:12:26 +00:00
# tuf isn't updated to deal with breaking changes in securesystemslib==1.0.
# Only tuf>=4 includes a constraint to <1.0.
# https://github.com/theupdateframework/python-tuf/releases/tag/v4.0.0
tuf>=4.0.0
2024-06-17 09:17:35 +00:00
# https://github.com/jd/tenacity/issues/471
2024-06-24 16:52:49 +00:00
tenacity!=8.4.0
"""
GENERATED_MESSAGE = (
f"# Automatically generated by {Path(__file__).name}, do not edit\n\n"
)
IGNORE_PRE_COMMIT_HOOK_ID = (
"check-executables-have-shebangs",
"check-json",
"no-commit-to-branch",
"prettier",
"python-typing-update",
"ruff-format", # it's just ruff
)
PACKAGE_REGEX = re.compile(r"^(?:--.+\s)?([-_\.\w\d]+).*==.+$")
def has_tests(module: str) -> bool:
"""Test if a module has tests.
Module format: homeassistant.components.hue
Test if exists: tests/components/hue/__init__.py
"""
path = (
Path(module.replace(".", "/").replace("homeassistant", "tests")) / "__init__.py"
)
return path.exists()
def explore_module(package: str, explore_children: bool) -> list[str]:
2016-03-09 10:15:04 +00:00
"""Explore the modules."""
2015-11-17 08:18:42 +00:00
module = importlib.import_module(package)
found: list[str] = []
2015-11-17 08:18:42 +00:00
2019-07-31 19:25:30 +00:00
if not hasattr(module, "__path__"):
2015-11-17 08:18:42 +00:00
return found
for _, name, _ in pkgutil.iter_modules(module.__path__, f"{package}."):
2015-11-17 08:18:42 +00:00
found.append(name)
if explore_children:
found.extend(explore_module(name, False))
return found
def core_requirements() -> list[str]:
"""Gather core requirements out of pyproject.toml."""
data = tomllib.loads(Path("pyproject.toml").read_text())
dependencies: list[str] = data["project"]["dependencies"]
return dependencies
2015-11-17 08:18:42 +00:00
def gather_recursive_requirements(
domain: str, seen: set[str] | None = None
) -> set[str]:
"""Recursively gather requirements from a module."""
if seen is None:
seen = set()
seen.add(domain)
integration = Integration(
Path(f"homeassistant/components/{domain}"), _get_hassfest_config()
)
integration.load_manifest()
reqs = {x for x in integration.requirements if x not in CONSTRAINT_BASE}
2020-04-03 19:58:19 +00:00
for dep_domain in integration.dependencies:
reqs.update(gather_recursive_requirements(dep_domain, seen))
return reqs
def _normalize_package_name(package_name: str) -> str:
"""Normalize a package name."""
# pipdeptree needs lowercase and dash instead of underscore or period as separator
return package_name.lower().replace("_", "-").replace(".", "-")
def normalize_package_name(requirement: str) -> str:
"""Return a normalized package name from a requirement string."""
# This function is also used in hassfest.
match = PACKAGE_REGEX.search(requirement)
if not match:
return ""
# pipdeptree needs lowercase and dash instead of underscore or period as separator
return _normalize_package_name(match.group(1))
def comment_requirement(req: str) -> bool:
"""Comment out requirement. Some don't install on all systems."""
return normalize_package_name(req) in EXCLUDED_REQUIREMENTS_ALL
def process_action_requirement(req: str, action: str) -> str:
"""Process requirement for a specific github action."""
normalized_package_name = normalize_package_name(req)
if normalized_package_name in OVERRIDDEN_REQUIREMENTS_ACTIONS[action]["exclude"]:
return f"# {req}"
if normalized_package_name in OVERRIDDEN_REQUIREMENTS_ACTIONS[action]["include"]:
return req
if normalized_package_name in EXCLUDED_REQUIREMENTS_ALL:
return f"# {req}"
return req
def gather_modules() -> dict[str, list[str]] | None:
"""Collect the information."""
reqs: dict[str, list[str]] = {}
2015-11-17 08:18:42 +00:00
errors: list[str] = []
2015-11-25 22:31:04 +00:00
gather_requirements_from_manifests(errors, reqs)
gather_requirements_from_modules(errors, reqs)
for key in reqs:
2019-07-31 19:25:30 +00:00
reqs[key] = sorted(reqs[key], key=lambda name: (len(name.split(".")), name))
if errors:
print("******* ERROR")
2019-07-31 19:25:30 +00:00
print("Errors while importing: ", ", ".join(errors))
return None
return reqs
def gather_requirements_from_manifests(
errors: list[str], reqs: dict[str, list[str]]
) -> None:
"""Gather all of the requirements from manifests."""
config = _get_hassfest_config()
integrations = Integration.load_dir(config.core_integrations_path, config)
for domain in sorted(integrations):
integration = integrations[domain]
if integration.disabled:
continue
process_requirements(
errors, integration.requirements, f"homeassistant.components.{domain}", reqs
)
def gather_requirements_from_modules(
errors: list[str], reqs: dict[str, list[str]]
) -> None:
"""Collect the requirements from the modules directly."""
for package in sorted(
2019-07-31 19:25:30 +00:00
explore_module("homeassistant.scripts", True)
+ explore_module("homeassistant.auth", True)
):
2015-11-17 08:18:42 +00:00
try:
module = importlib.import_module(package)
except ImportError as err:
print(f"{package.replace('.', '/')}.py: {err}")
errors.append(package)
2015-11-17 08:18:42 +00:00
continue
2019-07-31 19:25:30 +00:00
if getattr(module, "REQUIREMENTS", None):
process_requirements(errors, module.REQUIREMENTS, package, reqs)
2016-02-01 07:52:42 +00:00
2015-11-17 08:18:42 +00:00
def process_requirements(
errors: list[str],
module_requirements: list[str],
package: str,
reqs: dict[str, list[str]],
) -> None:
"""Process all of the requirements."""
for req in module_requirements:
2019-07-31 19:25:30 +00:00
if "://" in req:
errors.append(f"{package}[Only pypi dependencies are allowed: {req}]")
2019-07-31 19:25:30 +00:00
if req.partition("==")[1] == "" and req not in IGNORE_PIN:
errors.append(f"{package}[Please pin requirement {req}, see {URL_PIN}]")
reqs.setdefault(req, []).append(package)
def generate_requirements_list(reqs: dict[str, list[str]]) -> str:
"""Generate a pip file based on requirements."""
output = []
for pkg, requirements in sorted(reqs.items(), key=itemgetter(0)):
output.extend(f"\n# {req}" for req in sorted(requirements))
if comment_requirement(pkg):
output.append(f"\n# {pkg}\n")
else:
output.append(f"\n{pkg}\n")
2019-07-31 19:25:30 +00:00
return "".join(output)
def generate_action_requirements_list(reqs: dict[str, list[str]], action: str) -> str:
"""Generate a pip file based on requirements."""
output = []
for pkg, requirements in sorted(reqs.items(), key=itemgetter(0)):
output.extend(f"\n# {req}" for req in sorted(requirements))
processed_pkg = process_action_requirement(pkg, action)
output.append(f"\n{processed_pkg}\n")
return "".join(output)
def requirements_output() -> str:
"""Generate output for requirements."""
output = [
GENERATED_MESSAGE,
"-c homeassistant/package_constraints.txt\n",
"\n",
"# Home Assistant Core\n",
]
2019-07-31 19:25:30 +00:00
output.append("\n".join(core_requirements()))
output.append("\n")
return "".join(output)
def requirements_all_output(reqs: dict[str, list[str]]) -> str:
"""Generate output for requirements_all."""
output = [
2020-08-27 14:56:53 +00:00
"# Home Assistant Core, full dependency set\n",
GENERATED_MESSAGE,
"-r requirements.txt\n",
]
output.append(generate_requirements_list(reqs))
2019-07-31 19:25:30 +00:00
return "".join(output)
def requirements_all_action_output(reqs: dict[str, list[str]], action: str) -> str:
"""Generate output for requirements_all_{action}."""
output = [
f"# Home Assistant Core, full dependency set for {action}\n",
GENERATED_MESSAGE,
"-r requirements.txt\n",
]
output.append(generate_action_requirements_list(reqs, action))
return "".join(output)
def requirements_test_all_output(reqs: dict[str, list[str]]) -> str:
"""Generate output for test_requirements."""
output = [
"# Home Assistant tests, full dependency set\n",
GENERATED_MESSAGE,
2020-08-27 14:56:53 +00:00
"-r requirements_test.txt\n",
]
2019-07-31 19:25:30 +00:00
filtered = {
requirement: modules
for requirement, modules in reqs.items()
2019-07-31 19:25:30 +00:00
if any(
# Always install requirements that are not part of integrations
not mdl.startswith("homeassistant.components.")
or
# Install tests for integrations that have tests
has_tests(mdl)
for mdl in modules
2019-07-31 19:25:30 +00:00
)
}
output.append(generate_requirements_list(filtered))
2015-11-25 22:31:04 +00:00
2019-07-31 19:25:30 +00:00
return "".join(output)
2015-11-25 22:31:04 +00:00
def requirements_pre_commit_output() -> str:
"""Generate output for pre-commit dependencies."""
source = ".pre-commit-config.yaml"
pre_commit_conf: dict[str, list[dict[str, Any]]]
pre_commit_conf = load_yaml(source) # type: ignore[assignment]
reqs: list[str] = []
hook: dict[str, Any]
for repo in (x for x in pre_commit_conf["repos"] if x.get("rev")):
rev: str = repo["rev"]
for hook in repo["hooks"]:
if hook["id"] not in IGNORE_PRE_COMMIT_HOOK_ID:
reqs.append(f"{hook['id']}=={rev.lstrip('v')}")
reqs.extend(x for x in hook.get("additional_dependencies", ()))
output = [
f"# Automatically generated "
f"from {source} by {Path(__file__).name}, do not edit",
"",
]
output.extend(sorted(reqs))
return "\n".join(output) + "\n"
def gather_constraints() -> str:
"""Construct output for constraint file."""
return (
GENERATED_MESSAGE
+ "\n".join(
[
*sorted(
{
*core_requirements(),
*gather_recursive_requirements("default_config"),
*gather_recursive_requirements("mqtt"),
},
key=str.lower,
),
"",
]
2019-07-31 19:25:30 +00:00
)
+ CONSTRAINT_BASE
2019-07-31 19:25:30 +00:00
)
def diff_file(filename: str, content: str) -> list[str]:
"""Diff a file."""
return list(
difflib.context_diff(
[f"{line}\n" for line in Path(filename).read_text().split("\n")],
[f"{line}\n" for line in content.split("\n")],
filename,
"generated",
)
)
def main(validate: bool, ci: bool) -> int:
"""Run the script."""
if not Path("requirements_all.txt").is_file():
2019-07-31 19:25:30 +00:00
print("Run this from HA root dir")
2018-03-09 20:27:39 +00:00
return 1
2015-11-25 22:31:04 +00:00
data = gather_modules()
if data is None:
2018-03-09 20:27:39 +00:00
return 1
2015-12-18 07:51:34 +00:00
reqs_file = requirements_output()
reqs_all_file = requirements_all_output(data)
reqs_all_action_files = {
action: requirements_all_action_output(data, action)
for action in OVERRIDDEN_REQUIREMENTS_ACTIONS
}
2020-08-27 14:56:53 +00:00
reqs_test_all_file = requirements_test_all_output(data)
# Always calling requirements_pre_commit_output is intentional to ensure
# the code is called by the pre-commit hooks.
reqs_pre_commit_file = requirements_pre_commit_output()
constraints = gather_constraints()
files = [
("requirements.txt", reqs_file),
("requirements_all.txt", reqs_all_file),
("requirements_test_pre_commit.txt", reqs_pre_commit_file),
2020-08-27 14:56:53 +00:00
("requirements_test_all.txt", reqs_test_all_file),
("homeassistant/package_constraints.txt", constraints),
]
if ci:
files.extend(
(f"requirements_all_{action}.txt", reqs_all_file)
for action, reqs_all_file in reqs_all_action_files.items()
)
2018-03-09 20:27:39 +00:00
if validate:
errors = []
for filename, content in files:
diff = diff_file(filename, content)
if diff:
errors.append("".join(diff))
if errors:
print("ERROR - FOUND THE FOLLOWING DIFFERENCES")
print()
print()
print("\n\n".join(errors))
print()
print("Please run python3 -m script.gen_requirements_all")
2018-03-09 20:27:39 +00:00
return 1
2018-03-09 20:27:39 +00:00
return 0
for filename, content in files:
Path(filename).write_text(content)
2018-03-09 20:27:39 +00:00
return 0
2015-11-17 08:18:42 +00:00
2016-11-19 05:47:59 +00:00
def _get_hassfest_config() -> Config:
"""Get hassfest config."""
return Config(
root=Path().absolute(),
specific_integrations=None,
action="validate",
requirements=True,
core_integrations_path=Path("homeassistant/components"),
)
2019-07-31 19:25:30 +00:00
if __name__ == "__main__":
_VAL = sys.argv[-1] == "validate"
_CI = sys.argv[-1] == "ci"
sys.exit(main(_VAL, _CI))