44from concurrent .futures import ThreadPoolExecutor
55from pathlib import Path
66from threading import RLock
7- from typing import TYPE_CHECKING , Optional
8-
7+ from typing import TYPE_CHECKING , Any
98
109from appdaemon .admin_loop import AdminLoop
1110from appdaemon .app_management import AppManagement
3029
3130
3231class AppDaemon (metaclass = Singleton ):
33- """Top-level container for the subsystem objects. This gets passed to the subsystem objects and stored in them as the ``self.AD`` attribute.
32+ """Top-level container for the subsystem objects. This gets passed to the subsystem objects and stored in them as
33+ the ``self.AD`` attribute.
3434
3535 Asyncio:
3636
@@ -81,36 +81,22 @@ class AppDaemon(metaclass=Singleton):
8181 """
8282
8383 # subsystems
84- app_management : AppManagement
85- callbacks : Callbacks = None
86- events : Events = None
87- futures : Futures
84+ app_management : " AppManagement"
85+ callbacks : " Callbacks"
86+ events : " Events"
87+ futures : " Futures"
8888 logging : "Logging"
89- plugins : PluginManagement
90- scheduler : Scheduler
91- services : Services
92- sequences : Sequences
93- state : State
94- threading : Threading
95- thread_async : ThreadAsync = None
96- utility : Utility
97-
98- # settings
99- app_dir : Path
100- """Defined in the main YAML config under ``appdaemon.app_dir``. Defaults to ``./apps``
101- """
102- config_dir : Path
103- """Path to the AppDaemon configuration files. Defaults to the first folder that has ``./apps``
104-
105- - ``~/.homeassistant``
106- - ``/etc/appdaemon``
107- """
108- apps : bool
109- """Flag for whether ``disable_apps`` was set in the AppDaemon config
110- """
111-
112- admin_loop : AdminLoop | None = None
113- http : Optional ["HTTP" ] = None
89+ plugins : "PluginManagement"
90+ scheduler : "Scheduler"
91+ services : "Services"
92+ sequences : "Sequences"
93+ state : "State"
94+ threading : "Threading"
95+ thread_async : "ThreadAsync | None" = None
96+ utility : "Utility"
97+
98+ admin_loop : "AdminLoop | None" = None
99+ http : "HTTP | None" = None
114100 global_lock : RLock = RLock ()
115101
116102 # shut down flag
@@ -122,13 +108,13 @@ def __init__(self, logging: "Logging", loop: BaseEventLoop, ad_config_model: App
122108 self .config = ad_config_model
123109 self .booted = "booting"
124110 self .logger = logging .get_logger ()
125- self .logging .register_ad (self ) # needs to go last to reference the config object
111+ self .logging .register_ad (self ) # needs to go last to reference the config object
126112
127- self .global_vars = {}
113+ self .global_vars : Any = {}
128114 self .main_thread_id = threading .current_thread ().ident
129115
130116 if not self .apps :
131- self .logging . log ( "INFO" , "Apps are disabled" )
117+ self .logger . info ( "Apps are disabled" )
132118
133119 # Initialize subsystems
134120 self .callbacks = Callbacks (self )
@@ -143,7 +129,8 @@ def __init__(self, logging: "Logging", loop: BaseEventLoop, ad_config_model: App
143129 assert self .config_dir is not None , "Config_dir not set. This is a development problem"
144130 assert self .config_dir .exists (), f"{ self .config_dir } does not exist"
145131 assert os .access (
146- self .config_dir , os .R_OK | os .X_OK
132+ self .config_dir ,
133+ os .R_OK | os .X_OK ,
147134 ), f"{ self .config_dir } does not have the right permissions"
148135
149136 # this will always be None because it never gets set in ad_kwargs in __main__.py
@@ -152,7 +139,8 @@ def __init__(self, logging: "Logging", loop: BaseEventLoop, ad_config_model: App
152139 if not self .app_dir .exists ():
153140 self .app_dir .mkdir ()
154141 assert os .access (
155- self .app_dir , os .R_OK | os .W_OK | os .X_OK
142+ self .app_dir ,
143+ os .R_OK | os .W_OK | os .X_OK ,
156144 ), f"{ self .app_dir } does not have the right permissions"
157145
158146 self .logger .info (f"Using { self .app_dir } as app_dir" )
@@ -179,19 +167,25 @@ def __init__(self, logging: "Logging", loop: BaseEventLoop, ad_config_model: App
179167 # Property definitions
180168 #
181169 @property
182- def admin_delay (self ):
170+ def admin_delay (self ) -> int :
183171 return self .config .admin_delay
184172
185173 @property
186- def api_port (self ):
174+ def api_port (self ) -> int | None :
187175 return self .config .api_port
188176
189177 @property
190- def app_dir (self ):
178+ def app_dir (self ) -> Path :
179+ """Defined in the main YAML config under ``appdaemon.app_dir``. Defaults to ``./apps``"""
191180 return self .config .app_dir
192181
182+ @app_dir .setter
183+ def app_dir (self , path : os .PathLike ) -> None :
184+ self .config .app_dir = Path (path )
185+
193186 @property
194187 def apps (self ):
188+ """Flag for whether ``disable_apps`` was set in the AppDaemon config"""
195189 return not self .config .disable_apps
196190
197191 @property
@@ -204,8 +198,17 @@ def check_app_updates_profile(self):
204198
205199 @property
206200 def config_dir (self ):
201+ """Path to the AppDaemon configuration files. Defaults to the first folder that has ``./apps``
202+
203+ - ``~/.homeassistant``
204+ - ``/etc/appdaemon``
205+ """
207206 return self .config .config_dir
208207
208+ @config_dir .setter
209+ def config_dir (self , path : os .PathLike ) -> None :
210+ self .config .config_dir = Path (path )
211+
209212 @property
210213 def config_file (self ):
211214 return self .config .config_file
@@ -366,7 +369,7 @@ def terminate(self):
366369 def register_http (self , http : "HTTP" ):
367370 """Sets the ``self.http`` attribute with a :class:`~.http.HTTP` object and starts the admin loop."""
368371
369- self .http : "HTTP" = http
372+ self .http = http
370373 # Create admin loop
371374
372375 if http .old_admin is not None or http .admin is not None :
0 commit comments