@@ -217,24 +217,33 @@ def __init__(
217217 )
218218
219219 def __del__ (self ) -> None :
220+ deps = self ._registered_dependencies .values ()
221+ self ._cleanup_temp_source_dirs (list (deps ))
222+
223+ @staticmethod
224+ def _cleanup_temp_source_dirs (deps : list [HTMLDependency ]) -> None :
225+ # include_css()/include_js() create temporary directories to hold files that
226+ # persist across user sessions, but also need to be cleaned up at some point,
227+ # and Python (unlike R) does not cleanup tempdirs on process exit. So, our next
228+ # best option is to clean them up when the App object is deleted. It's not
229+ # perfect (the App object might be deleted while the process is still running,
230+ # and there might be multiple App objects using the same UI). However, it still
231+ # seems worth doing since that is such a hypothetical edge case. More generally,
232+ # if _any_ HTMLDependency with a source directory that is a _subdirectory_ of
233+ # the (system-wide) temp directory, we should remove it.
220234 current_temp_dir = os .path .realpath (tempfile .gettempdir ())
221-
222- # Ignoring a type hint on source["subdir"] because all of our user-created dependencies
223- # must have a "subdir" source, but the HTMLDependency type allows for other variations.
224- user_dependencies : list [str ] = [
225- v .source ["subdir" ] # type: ignore
226- for k , v in self ._registered_dependencies .items ()
227- if k .startswith ("include-" )
228- ]
229-
230- for item in user_dependencies :
231- # Only remove the item if it exists and it is in the current temp directory
232- if (
233- os .path .exists (item )
234- and os .path .commonprefix ([os .path .realpath (item ), current_temp_dir ])
235- == current_temp_dir
236- ):
237- shutil .rmtree (item )
235+ for dep in deps :
236+ src = dep .source_path_map ()["source" ]
237+ if not src :
238+ continue
239+ src = os .path .realpath (src )
240+ if not os .path .exists (src ):
241+ continue
242+ if src == current_temp_dir :
243+ continue
244+ common = os .path .commonprefix ([src , current_temp_dir ])
245+ if common == current_temp_dir :
246+ shutil .rmtree (src )
238247
239248 def init_starlette_app (self ) -> starlette .applications .Starlette :
240249 routes : list [starlette .routing .BaseRoute ] = [
0 commit comments