Skip to content

Commit

Permalink
Hot-reload on adding/removing assets files.
Browse files Browse the repository at this point in the history
  • Loading branch information
T4rk1n committed Sep 14, 2018
1 parent b97f6c9 commit a1848f4
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 14 deletions.
12 changes: 11 additions & 1 deletion dash/_watch.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,27 @@ def watch(folders, on_change, pattern=None, sleep_time=0.1):
watched = collections.defaultdict(lambda: -1)

def walk():
walked = []
for folder in folders:
for current, _, files, in os.walk(folder):
for f in files:
if pattern and not pattern.search(f):
continue
path = os.path.join(current, f)

info = os.stat(path)
new_time = info.st_mtime

if new_time > watched[path] > 0:
on_change(path)
on_change(path, new_time, False)

watched[path] = new_time
walked.append(path)

# Look for deleted files
for w in (x for x in watched.keys() if x not in walked):
del watched[w]
on_change(w, -1, True)

while True:
walk()
Expand Down
60 changes: 47 additions & 13 deletions dash/dash.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ def add_url(name, view_func, methods=('GET',)):
self._cached_layout = None
self.routes = []

self._assets_files = []

# hot reload
self._reload_hash = _generate_hash() \
if hot_reload else ''
Expand Down Expand Up @@ -942,19 +944,20 @@ def _setup_server(self):
self._generate_scripts_html()
self._generate_css_dist_html()

def _add_assets_resource(self, url_path, file_path):
res = {'asset_path': url_path, 'filepath': file_path}
if self.config.assets_external_path:
res['external_url'] = '{}{}'.format(
self.config.assets_external_path, url_path)
self._assets_files.append(file_path)
return res

def _walk_assets_directory(self):
walk_dir = self._assets_folder
slash_splitter = re.compile(r'[\\/]+')
ignore_filter = re.compile(self.assets_ignore) \
if self.assets_ignore else None

def add_resource(p, filepath):
res = {'asset_path': p, 'filepath': filepath}
if self.config.assets_external_path:
res['external_url'] = '{}{}'.format(
self.config.assets_external_path, path)
return res

for current, _, files in os.walk(walk_dir):
if current == walk_dir:
base = ''
Expand All @@ -979,9 +982,9 @@ def add_resource(p, filepath):

if f.endswith('js'):
self.scripts.append_script(
add_resource(path, full))
self._add_assets_resource(path, full))
elif f.endswith('css'):
self.css.append_css(add_resource(path, full))
self.css.append_css(self._add_assets_resource(path, full))
elif f == 'favicon.ico':
self._favicon = path

Expand All @@ -995,12 +998,43 @@ def get_asset_url(self, path):

return asset

def _on_assets_change(self, _):
# The `_` argument is the name of the file that changed.
# If we ever setup a logging system, we could use the parameter.
# noinspection PyProtectedMember
def _on_assets_change(self, filename, _, deleted):
# The `_` argument is the time modified, to be used later.
self._lock.acquire()
self._hard_reload = True
self._hard_reload = True # filename.endswith('js')
self._reload_hash = _generate_hash()

asset_path = filename.replace(self._assets_folder, '')\
.replace('\\', '/').lstrip('/')

if filename not in self._assets_files and not deleted:
res = self._add_assets_resource(asset_path, filename)
if filename.endswith('js'):
self.scripts.append_script(res)
elif filename.endswith('css'):
self.css.append_css(res)

if deleted:
if filename in self._assets_files:
self._assets_files.remove(filename)

def delete_resource(resources):
to_delete = None
for r in resources:
if r.get('asset_path') == asset_path:
to_delete = r
break
if to_delete:
resources.remove(to_delete)

if filename.endswith('js'):
# pylint: disable=protected-access
delete_resource(self.scripts._resources._resources)
elif filename.endswith('css'):
# pylint: disable=protected-access
delete_resource(self.css._resources._resources)

self._lock.release()

def run_server(self,
Expand Down

0 comments on commit a1848f4

Please sign in to comment.