Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion appdaemon/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,6 @@ def __init__(self, args: argparse.Namespace) -> None:
self.dep_manager = DependencyManager.from_app_directory(
self.model.appdaemon.app_dir,
exclude=self.model.appdaemon.exclude_dirs,
config_suffix=self.model.appdaemon.ext,
)

except Exception as e:
Expand Down
12 changes: 5 additions & 7 deletions appdaemon/app_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

from pydantic import ValidationError


from appdaemon.dependency import DependencyResolutionFail, find_all_dependents, get_full_module_name
from appdaemon.dependency_manager import DependencyManager
from appdaemon.models.config import AllAppConfig, AppConfig, GlobalModule
Expand All @@ -33,9 +32,9 @@
from .models.internal.app_management import LoadingActions, ManagedObject, UpdateActions, UpdateMode

if TYPE_CHECKING:
from .appdaemon import AppDaemon
from .adbase import ADBase
from .adapi import ADAPI
from .adbase import ADBase
from .appdaemon import AppDaemon
from .plugin_management import PluginBase

T = TypeVar("T")
Expand Down Expand Up @@ -87,7 +86,6 @@ class AppManagement:

def __init__(self, ad: "AppDaemon"):
self.AD = ad
self.ext = self.AD.config.ext
self.logger = ad.logging.get_child(self.name)
self.error = ad.logging.get_error()
self.diag = ad.logging.get_diag()
Expand Down Expand Up @@ -1047,8 +1045,8 @@ def get_app_config_files(self) -> set[Path]:
return set(
utils.recursive_get_files(
base=self.AD.app_dir.resolve(),
suffix=self.ext,
exclude=set(self.AD.exclude_dirs),
suffix={".yaml", ".toml"},
exclude=set(self.AD.exclude_dirs) | {"ruff.toml", "pyproject.toml", "secrets.yaml"},
)
)

Expand Down Expand Up @@ -1323,7 +1321,7 @@ def create_app(self, app: str = None, **kwargs):
return False

app_directory: Path = self.AD.app_dir / kwargs.pop("app_dir", "ad_apps")
app_file: Path = app_directory / kwargs.pop("app_file", f"{app}{self.ext}")
app_file: Path = app_directory / kwargs.pop("app_file", f"{app}{self.AD.config.ext}")
app_directory = app_file.parent # in case the given app_file is multi level

try:
Expand Down
23 changes: 14 additions & 9 deletions appdaemon/dependency_manager.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from abc import ABC
from copy import deepcopy
from dataclasses import InitVar, dataclass, field
from functools import partial
from pathlib import Path
from typing import Iterable

Expand All @@ -16,7 +15,7 @@ class Dependencies(ABC):
"""Wraps an instance of ``FileCheck`` with a corresponding set of dependency graphs."""

files: FileCheck = field(repr=False)
ext: str = field(init=False) # this has to be defined by the children classes
ext: str | set[str] = field(init=False) # this has to be defined by the children classes
dep_graph: dict[str, set[str]] = field(init=False)
rev_graph: dict[str, set[str]] = field(init=False)
bad_files: set[tuple[Path, float]] = field(default_factory=set, init=False)
Expand All @@ -39,7 +38,13 @@ def refresh_dep_graph(self):

@classmethod
def from_path(cls, path: Path):
return cls.from_paths(path.rglob(f"*{cls.ext}"))
return cls.from_paths(
utils.recursive_get_files(
base=path,
suffix={".yaml", ".toml"},
exclude={"ruff.toml", "pyproject.toml", "secrets.yaml"},
)
)

@classmethod
def from_paths(cls, paths: Iterable[Path]):
Expand Down Expand Up @@ -90,7 +95,6 @@ def modules_to_delete(self) -> list[str]:
@dataclass
class AppDeps(Dependencies):
app_config: AllAppConfig = field(init=False, repr=False)
ext: str = ".yaml"

def __post_init__(self):
self.app_config = AllAppConfig.from_config_files(self.files)
Expand Down Expand Up @@ -157,7 +161,6 @@ def from_app_directory(
cls,
app_dir: Path,
exclude: str | Iterable[str] | None = None,
config_suffix: str = ".yaml",
) -> "DependencyManager":
"""Creates a new instance of the dependency manager from the given app directory"""
match exclude:
Expand All @@ -168,12 +171,14 @@ def from_app_directory(
case _:
exclude_set = set(exclude)

get_files = partial(utils.recursive_get_files, base=app_dir, exclude=exclude_set)
return cls(
# python_files=get_files(suffix=".py"),
python_files=list(),
config_files=get_files(suffix=config_suffix)
) # fmt: skip
config_files=utils.recursive_get_files(
base=app_dir,
suffix={".yaml", ".toml"},
exclude=exclude_set,
)
)

@property
def app_config_files(self) -> set[Path]:
Expand Down
5 changes: 3 additions & 2 deletions appdaemon/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1217,7 +1217,7 @@ def deprecation_warnings(model: BaseModel, logger: Logger):
deprecation_warnings(attr, logger)


def recursive_get_files(base: Path, suffix: str, exclude: set[str] | None = None) -> Generator[Path, None, None]:
def recursive_get_files(base: Path, suffix: str | set[str], exclude: set[str] | None = None) -> Generator[Path, None, None]:
"""Recursively generate file paths.

Args:
Expand All @@ -1228,11 +1228,12 @@ def recursive_get_files(base: Path, suffix: str, exclude: set[str] | None = None
Yields:
Path objects to files that have the matching extension and are readable.
"""
suffix = {suffix} if isinstance(suffix, str) else suffix
exclude = set() if exclude is None else exclude
for item in base.iterdir():
if item.name.startswith(".") or (exclude is None or item.name in exclude):
continue
elif item.is_file() and item.suffix == suffix and os.access(item, os.R_OK):
elif item.is_file() and item.suffix in suffix and os.access(item, os.R_OK):
yield item
elif item.is_dir() and os.access(item, os.R_OK):
yield from recursive_get_files(item, suffix, exclude)
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ async def ad(ad_obj: AppDaemon, running_loop: asyncio.BaseEventLoop) -> AsyncGen
# logger.info(f"Passed loop: {hex(id(running_loop))}")
assert running_loop == asyncio.get_running_loop(), "The running loop should match the one passed in"
ad = ad_obj
config_files = list(recursive_get_files(base=ad.app_dir, suffix=ad.config.ext))
config_files = list(recursive_get_files(base=ad.app_dir, suffix={'.yaml', '.toml'}))
ad.app_management.dependency_manager = DependencyManager(python_files=list(), config_files=config_files)

for cfg in ad.app_management.app_config.root.values():
Expand Down
Loading