@@ -104,9 +104,11 @@ def _uploaded_dir(self) -> Path:
104104 """Return real path to "/local/uploaded" directory."""
105105 return self ._local_dir / "uploaded"
106106
107- @cached_property
108107 def _local_files (self ) -> list [str ]:
109- """Return a list of files in "/local" and subdirectories."""
108+ """Return a list of files in "/local" and subdirectories.
109+
110+ Must be called in an executor since it does file I/O.
111+ """
110112 if not (local_dir := self ._local_dir ).is_dir ():
111113 _LOGGER .debug ("/local directory (%s) does not exist" , local_dir )
112114 return []
@@ -172,7 +174,7 @@ def _set_entity_picture(
172174 def _save_uploaded_file (self , uploaded_file_id : str ) -> str :
173175 """Save uploaded file.
174176
175- Must be called in an executor.
177+ Must be called in an executor since it does file I/O .
176178
177179 Returns name of file relative to "/local".
178180 """
@@ -284,7 +286,7 @@ async def async_step_ep_menu(
284286 cur_source = entity_id
285287
286288 menu_options = ["all_states" , "ep_upload_file" , "ep_input_entity" ]
287- if self ._local_files :
289+ if await self .hass . async_add_executor_job ( self . _local_files ) :
288290 menu_options .insert (1 , "ep_local_file" )
289291 if cur_source :
290292 menu_options .append ("ep_none" )
@@ -332,7 +334,7 @@ async def async_step_ep_local_file(
332334 self ._set_entity_picture (local_file = user_input .get (CONF_ENTITY_PICTURE ))
333335 return await self .async_step_all_states ()
334336
335- local_files = self ._local_files
337+ local_files = await self .hass . async_add_executor_job ( self . _local_files )
336338 _ , local_file = self ._cur_entity_picture
337339 if local_file and local_file not in local_files :
338340 local_files .append (local_file )
@@ -363,14 +365,24 @@ async def async_step_ep_upload_file(
363365 self ._set_entity_picture ()
364366 return await self .async_step_all_states ()
365367
366- local_dir_exists = self ._local_dir .is_dir ()
367- local_file = await self .hass .async_add_executor_job (
368- self ._save_uploaded_file , uploaded_file_id
368+ def save_uploaded_file () -> tuple [bool , str ]:
369+ """Save uploaded file.
370+
371+ Must be called in an executor since it does file I/O.
372+
373+ Returns if local directory existed beforehand and name of uploaded file.
374+ """
375+ local_dir_exists = self ._local_dir .is_dir ()
376+ local_file = self ._save_uploaded_file (uploaded_file_id )
377+ return local_dir_exists , local_file
378+
379+ local_dir_exists , local_file = await self .hass .async_add_executor_job (
380+ save_uploaded_file
369381 )
370382 self ._set_entity_picture (local_file = local_file )
371- if local_dir_exists :
372- return await self .async_step_all_states ()
373- return await self .async_step_ep_warn ()
383+ if not local_dir_exists :
384+ return await self .async_step_ep_warn ()
385+ return await self .async_step_all_states ()
374386
375387 accept = ", " .join (f".{ ext } " for ext in PICTURE_SUFFIXES )
376388 data_schema = vol .Schema (
@@ -464,9 +476,7 @@ def async_get_options_flow(config_entry: ConfigEntry) -> CompositeOptionsFlow:
464476 @callback
465477 def async_supports_options_flow (cls , config_entry : ConfigEntry ) -> bool :
466478 """Return options flow support for this handler."""
467- if config_entry .source == SOURCE_IMPORT :
468- return False
469- return True
479+ return config_entry .source != SOURCE_IMPORT
470480
471481 @property
472482 def options (self ) -> dict [str , Any ]:
0 commit comments