Skip to content

Commit e8e0ebd

Browse files
authored
Merge pull request #2246 from AppDaemon/typing
Docstrings and Typing
2 parents 9ddcaff + 107bae6 commit e8e0ebd

21 files changed

+2278
-1744
lines changed

appdaemon/adapi.py

Lines changed: 1122 additions & 863 deletions
Large diffs are not rendered by default.

appdaemon/app_management.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
import sys
1111
import traceback
1212
from collections import OrderedDict
13-
from collections.abc import Iterable
13+
from collections.abc import AsyncGenerator, Iterable
1414
from copy import copy
1515
from functools import partial, reduce, wraps
1616
from logging import Logger
1717
from pathlib import Path
18-
from typing import TYPE_CHECKING, Literal
18+
from typing import TYPE_CHECKING, Literal, TypeVar
1919

2020
from pydantic import ValidationError
2121

@@ -33,6 +33,8 @@
3333
from .appdaemon import AppDaemon
3434
from .plugin_management import PluginBase
3535

36+
T = TypeVar("T")
37+
3638

3739
class AppManagement:
3840
"""Subsystem container for managing app lifecycles"""
@@ -44,6 +46,7 @@ class AppManagement:
4446
logger: Logger
4547
"""Standard python logger named ``AppDaemon._app_management``
4648
"""
49+
name: str = "_app_management"
4750
error: Logger
4851
"""Standard python logger named ``Error``
4952
"""
@@ -80,7 +83,7 @@ class AppManagement:
8083
def __init__(self, ad: "AppDaemon"):
8184
self.AD = ad
8285
self.ext = self.AD.config.ext
83-
self.logger = ad.logging.get_child("_app_management")
86+
self.logger = ad.logging.get_child(self.name)
8487
self.error = ad.logging.get_error()
8588
self.diag = ad.logging.get_diag()
8689
self.filter_files = {}
@@ -468,7 +471,7 @@ async def create_app_object(self, app_name: str) -> None:
468471
)
469472

470473
if (pin := cfg.pin_thread) and pin >= self.AD.threading.total_threads:
471-
raise ade.PinOutofRange()
474+
raise ade.PinOutofRange(pin_thread=pin, total_threads=self.AD.threading.total_threads)
472475
elif (obj := self.objects.get(app_name)) and obj.pin_thread is not None:
473476
pin = obj.pin_thread
474477
else:
@@ -538,7 +541,7 @@ async def terminate_sequence(self, name: str) -> bool:
538541
async def read_all(self, config_files: Iterable[Path] = None) -> AllAppConfig:
539542
config_files = config_files or self.dependency_manager.config_files
540543

541-
async def config_model_factory():
544+
async def config_model_factory() -> AsyncGenerator[AllAppConfig, None, None]:
542545
"""Creates a generator that sets the config_path of app configs"""
543546
for path in config_files:
544547
@ade.wrap_async(self.error, self.AD.app_dir, "Reading user apps")
@@ -862,7 +865,9 @@ def _process_import_paths(self):
862865
self.add_to_import_path(path)
863866
case 'legacy':
864867
for root, subdirs, files in os.walk(self.AD.app_dir):
865-
if utils.is_valid_root_path(root) and root not in sys.path:
868+
base = os.path.basename(root)
869+
valid_root = base != "__pycache__" and not base.startswith(".")
870+
if valid_root and root not in sys.path:
866871
self.add_to_import_path(root)
867872

868873
async def _init_dep_manager(self):

appdaemon/dependency.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import ast
22
import logging
3+
from collections.abc import Generator
34
from pathlib import Path
45
from typing import Iterable
56

@@ -46,6 +47,7 @@ def resolve_relative_import(node: ast.ImportFrom, path: Path):
4647
for _ in range(levels_to_remove):
4748
parts.pop(-1)
4849
else:
50+
assert isinstance(node.module, str)
4951
parts = node.module.split(".")
5052

5153
if node.module:
@@ -64,7 +66,7 @@ def __init__(self, base_exception: Exception, *args: object) -> None:
6466
self.base_exception = base_exception
6567

6668

67-
def get_imports(parsed_module: ast.Module):
69+
def get_imports(parsed_module: ast.Module) -> Generator[ast.Import | ast.ImportFrom, None, None]:
6870
yield from (
6971
n for n in parsed_module.body
7072
if isinstance(n, (ast.Import, ast.ImportFrom))
@@ -85,7 +87,7 @@ def get_file_deps(file_path: str | Path) -> set[str]:
8587
with file_path.open("r") as file:
8688
file_content = file.read()
8789

88-
def gen_modules():
90+
def gen_modules() -> Generator[str, None, None]:
8991
try:
9092
mod: ast.Module = ast.parse(file_content, filename=file_path)
9193
except Exception as e:
@@ -99,7 +101,7 @@ def gen_modules():
99101
if node.level:
100102
abs_module = resolve_relative_import(node, file_path)
101103
yield abs_module
102-
else:
104+
elif isinstance(node.module, str):
103105
yield node.module
104106

105107
return set(gen_modules())
@@ -148,7 +150,7 @@ def reverse_graph(graph: dict[str, set[str]]) -> dict[str, set[str]]:
148150
Returns:
149151
Graph: A new graph with the direction of all edges reversed.
150152
"""
151-
reversed_graph = {n: set() for n in get_all_nodes(graph)}
153+
reversed_graph: dict[str, set[str]] = {n: set() for n in get_all_nodes(graph)}
152154

153155
for module, dependencies in graph.items():
154156
if dependencies:
@@ -159,13 +161,16 @@ def reverse_graph(graph: dict[str, set[str]]) -> dict[str, set[str]]:
159161

160162

161163
def find_all_dependents(
162-
base_nodes: Iterable[str], reversed_deps: dict[str, set[str]], visited: set[str] = None
163-
) -> set[str]:
164+
base_nodes: Iterable[str],
165+
reversed_deps: dict[str, set[str]],
166+
visited: set[str] | None = None
167+
) -> set[str]: # fmt: skip
164168
"""Recursively find all nodes that depend on the specified base nodes.
165169
166170
Args:
167171
base_nodes (Iterable[str]): A list or set of base node names to start the search from.
168-
reversed_deps (Graph): A dictionary representing the reversed graph where keys are node names and values are sets of nodes that depend on the key node.
172+
reversed_deps (Graph): A dictionary representing the reversed graph where keys are node names and values are
173+
sets of nodes that depend on the key node.
169174
visited (set[str], optional): A set of nodes that have already been visited. Defaults to None.
170175
171176
Returns:

0 commit comments

Comments
 (0)