Home Assistant Unofficial Reference 2024.12.1
merge.py
Go to the documentation of this file.
1 """Merging of policies."""
2 
3 from __future__ import annotations
4 
5 from typing import cast
6 
7 from .types import CategoryType, PolicyType
8 
9 
10 def merge_policies(policies: list[PolicyType]) -> PolicyType:
11  """Merge policies."""
12  new_policy: dict[str, CategoryType] = {}
13  seen: set[str] = set()
14  for policy in policies:
15  for category in policy:
16  if category in seen:
17  continue
18  seen.add(category)
19  new_policy[category] = _merge_policies(
20  [policy.get(category) for policy in policies]
21  )
22  cast(PolicyType, new_policy)
23  return new_policy
24 
25 
26 def _merge_policies(sources: list[CategoryType]) -> CategoryType:
27  """Merge a policy."""
28  # When merging policies, the most permissive wins.
29  # This means we order it like this:
30  # True > Dict > None
31  #
32  # True: allow everything
33  # Dict: specify more granular permissions
34  # None: no opinion
35  #
36  # If there are multiple sources with a dict as policy, we recursively
37  # merge each key in the source.
38 
39  policy: CategoryType = None
40  seen: set[str] = set()
41  for source in sources:
42  if source is None:
43  continue
44 
45  # A source that's True will always win. Shortcut return.
46  if source is True:
47  return True
48 
49  assert isinstance(source, dict)
50 
51  if policy is None:
52  policy = cast(CategoryType, {})
53 
54  assert isinstance(policy, dict)
55 
56  for key in source:
57  if key in seen:
58  continue
59  seen.add(key)
60 
61  key_sources = [src.get(key) for src in sources if isinstance(src, dict)]
62 
63  policy[key] = _merge_policies(key_sources)
64 
65  return policy
PolicyType merge_policies(list[PolicyType] policies)
Definition: merge.py:10
CategoryType _merge_policies(list[CategoryType] sources)
Definition: merge.py:26