forked from home-assistant/core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmodel.py
148 lines (116 loc) · 4.22 KB
/
model.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
"""Models for manifest validator."""
from __future__ import annotations
import importlib
import json
import pathlib
from typing import Any
import attr
@attr.s
class Error:
"""Error validating an integration."""
plugin: str = attr.ib()
error: str = attr.ib()
fixable: bool = attr.ib(default=False)
def __str__(self) -> str:
"""Represent error as string."""
return f"[{self.plugin.upper()}] {self.error}"
@attr.s
class Config:
"""Config for the run."""
specific_integrations: pathlib.Path | None = attr.ib()
root: pathlib.Path = attr.ib()
action: str = attr.ib()
requirements: bool = attr.ib()
errors: list[Error] = attr.ib(factory=list)
cache: dict[str, Any] = attr.ib(factory=dict)
plugins: set[str] = attr.ib(factory=set)
def add_error(self, *args: Any, **kwargs: Any) -> None:
"""Add an error."""
self.errors.append(Error(*args, **kwargs))
@attr.s
class Integration:
"""Represent an integration in our validator."""
@classmethod
def load_dir(cls, path: pathlib.Path):
"""Load all integrations in a directory."""
assert path.is_dir()
integrations = {}
for fil in path.iterdir():
if fil.is_file() or fil.name == "__pycache__":
continue
init = fil / "__init__.py"
if not init.exists():
print(
f"Warning: {init} missing, skipping directory. "
"If this is your development environment, "
"you can safely delete this folder."
)
continue
integration = cls(fil)
integration.load_manifest()
integrations[integration.domain] = integration
return integrations
path: pathlib.Path = attr.ib()
manifest: dict[str, Any] | None = attr.ib(default=None)
errors: list[Error] = attr.ib(factory=list)
warnings: list[Error] = attr.ib(factory=list)
@property
def domain(self) -> str:
"""Integration domain."""
return self.path.name
@property
def core(self) -> bool:
"""Core integration."""
return self.path.as_posix().startswith("homeassistant/components")
@property
def disabled(self) -> str | None:
"""Return if integration is disabled."""
return self.manifest.get("disabled")
@property
def name(self) -> str:
"""Return name of the integration."""
return self.manifest["name"]
@property
def quality_scale(self) -> str:
"""Return quality scale of the integration."""
return self.manifest.get("quality_scale")
@property
def config_flow(self) -> str:
"""Return if the integration has a config flow."""
return self.manifest.get("config_flow")
@property
def requirements(self) -> list[str]:
"""List of requirements."""
return self.manifest.get("requirements", [])
@property
def dependencies(self) -> list[str]:
"""List of dependencies."""
return self.manifest.get("dependencies", [])
@property
def integration_type(self) -> str:
"""Get integration_type."""
return self.manifest.get("integration_type", "integration")
def add_error(self, *args: Any, **kwargs: Any) -> None:
"""Add an error."""
self.errors.append(Error(*args, **kwargs))
def add_warning(self, *args: Any, **kwargs: Any) -> None:
"""Add an warning."""
self.warnings.append(Error(*args, **kwargs))
def load_manifest(self) -> None:
"""Load manifest."""
manifest_path = self.path / "manifest.json"
if not manifest_path.is_file():
self.add_error("model", f"Manifest file {manifest_path} not found")
return
try:
manifest = json.loads(manifest_path.read_text())
except ValueError as err:
self.add_error("model", f"Manifest contains invalid JSON: {err}")
return
self.manifest = manifest
def import_pkg(self, platform=None):
"""Import the Python file."""
pkg = f"homeassistant.components.{self.domain}"
if platform is not None:
pkg += f".{platform}"
return importlib.import_module(pkg)