Merge pull request #269940 from mweinelt/home-assistant-errata

Home Assistant Custom Component Errata
This commit is contained in:
Martin Weinelt 2023-12-06 04:11:36 +01:00 committed by GitHub
commit 17c08296e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 24 deletions

View file

@ -43,7 +43,7 @@ in {
# test loading custom components
customComponents = with pkgs.home-assistant-custom-components; [
prometheus-sensor
prometheus_sensor
];
# test loading lovelace modules

View file

@ -1,28 +1,31 @@
#!/usr/bin/env python3
import json
import importlib_metadata
import os
import sys
import importlib_metadata
from packaging.requirements import Requirement
def error(msg: str) -> None:
print(f" - {msg}", file=sys.stderr)
return False
def check_requirement(req: str):
# https://packaging.pypa.io/en/stable/requirements.html
requirement = Requirement(req)
try:
version = importlib_metadata.distribution(requirement.name).version
except importlib_metadata.PackageNotFoundError:
print(f" - Dependency {requirement.name} is missing", file=sys.stderr)
return False
return error(f"{requirement.name}{requirement.specifier} not present")
# https://packaging.pypa.io/en/stable/specifiers.html
if not version in requirement.specifier:
print(
f" - {requirement.name}{requirement.specifier} expected, but got {version}",
file=sys.stderr,
if version not in requirement.specifier:
return error(
f"{requirement.name}{requirement.specifier} expected, but got {version}"
)
return False
return True
@ -30,13 +33,24 @@ def check_requirement(req: str):
def check_manifest(manifest_file: str):
with open(manifest_file) as fd:
manifest = json.load(fd)
ok = True
derivation_domain = os.environ.get("domain")
manifest_domain = manifest["domain"]
if derivation_domain != manifest_domain:
ok = False
error(
f"Derivation attribute domain ({derivation_domain}) must match manifest domain ({manifest_domain})"
)
if "requirements" in manifest:
ok = True
for requirement in manifest["requirements"]:
ok &= check_requirement(requirement)
if not ok:
print("Manifest requirements are not met", file=sys.stderr)
sys.exit(1)
if not ok:
error("Manifest check failed.")
sys.exit(1)
if __name__ == "__main__":

View file

@ -3,7 +3,8 @@
, makeSetupHook
}:
{ pname
{ owner
, domain
, version
, format ? "other"
, ...
@ -17,13 +18,14 @@ let
in
home-assistant.python.pkgs.buildPythonPackage (
{
pname = "${owner}/${domain}";
inherit format;
installPhase = ''
runHook preInstall
mkdir $out
cp -r $src/custom_components/ $out/
cp -r ./custom_components/ $out/
runHook postInstall
'';

View file

@ -25,7 +25,7 @@ versions into the Python environment.
}:
buildHomeAssistantComponent {
# pname, version
# owner, domain, version
src = fetchFromGithub {
# owner, repo, rev, hash
@ -40,18 +40,34 @@ buildHomeAssistantComponent {
}
}
## Package name normalization
## Package attribute
Apply the same normalization rules as defined for python packages in
[PEP503](https://peps.python.org/pep-0503/#normalized-names).
The name should be lowercased and dots, underlines or multiple
dashes should all be replaced by a single dash.
The attribute name must reflect the domain as seen in the
`manifest.json`, which in turn will match the python module name below
in the `custom_components/` directory.
**Example:**
The project [mweinelt/ha-prometheus-sensor](https://github.com/mweinelt/ha-prometheus-sensor/blob/1.0.0/custom_components/prometheus_sensor/manifest.json#L2)
would receive the attribute name `"prometheus_sensor"`, because both
domain in the `manifest.json` as well as the module name are
`prometheus_sensor`.
## Package name
The `pname` attribute is a composition of both `owner` and `domain`.
Don't set `pname`, set `owner and `domain` instead.
Exposing the `domain` attribute separately allows checking for
conflicting components at eval time.
## Manifest check
The `buildHomeAssistantComponent` builder uses a hook to check whether
the dependencies specified in the `manifest.json` are present and
inside the specified version range.
inside the specified version range. It also makes sure derivation
and manifest agree about the domain name.
There shouldn't be a need to disable this hook, but you can set
`dontCheckManifest` to `true` in the derivation to achieve that.

View file

@ -2,5 +2,5 @@
}:
{
prometheus-sensor = callPackage ./prometheus-sensor {};
prometheus_sensor = callPackage ./prometheus_sensor {};
}

View file

@ -4,7 +4,8 @@
}:
buildHomeAssistantComponent rec {
pname = "prometheus-sensor";
owner = "mweinelt";
domain = "prometheus_sensor";
version = "1.0.0";
src = fetchFromGitHub {