Skip to content

Commit 2e99ed8

Browse files
committed
Add assets filewatcher to reload on assets changes.
1 parent 7595ed9 commit 2e99ed8

File tree

4 files changed

+61
-7
lines changed

4 files changed

+61
-7
lines changed

dash/_utils.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import uuid
2+
3+
14
def interpolate_str(template, **data):
25
s = template
36
for k, v in data.items():
@@ -20,6 +23,10 @@ def format_tag(tag_name, attributes, inner='', closed=False, opened=False):
2023
'{}="{}"'.format(k, v) for k, v in attributes.items()]))
2124

2225

26+
def generate_hash():
27+
return str(uuid.uuid4().hex).strip('-')
28+
29+
2330
def get_asset_path(requests_pathname, routes_pathname, asset_path):
2431
i = requests_pathname.rfind(routes_pathname)
2532
req = requests_pathname[:i]

dash/_watch.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import collections
2+
import os
3+
import re
4+
import time
5+
6+
7+
def watch(folders, on_change, pattern=None, sleep_time=0.1):
8+
pattern = re.compile(pattern) if pattern else None
9+
watched = collections.defaultdict(lambda: -1)
10+
11+
def walk():
12+
for folder in folders:
13+
for current, _, files, in os.walk(folder):
14+
for f in files:
15+
if pattern and not pattern.search(f):
16+
continue
17+
path = os.path.join(current, f)
18+
info = os.stat(path)
19+
new_time = info.st_mtime
20+
if new_time > watched[path] > 0:
21+
on_change(path)
22+
watched[path] = new_time
23+
24+
while True:
25+
walk()
26+
time.sleep(sleep_time)

dash/dash.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import importlib
77
import json
88
import pkgutil
9-
import uuid
9+
import threading
1010
import warnings
1111
import re
1212

@@ -25,6 +25,8 @@
2525
from ._utils import AttributeDict as _AttributeDict
2626
from ._utils import interpolate_str as _interpolate
2727
from ._utils import format_tag as _format_tag
28+
from ._utils import generate_hash as _generate_hash
29+
from . import _watch
2830
from ._utils import get_asset_path as _get_asset_path
2931
from . import _configs
3032

@@ -105,10 +107,6 @@ def __init__(
105107
flask.helpers.get_root_path(name), 'assets'
106108
)
107109

108-
self._reload_hash = str(uuid.uuid4().hex).strip('-')\
109-
if hot_reload else ''
110-
self._reload_interval = hot_reload_interval
111-
112110
# allow users to supply their own flask server
113111
self.server = server or Flask(name, static_folder=static_folder)
114112

@@ -227,6 +225,20 @@ def add_url(name, view_func, methods=('GET',)):
227225
self._cached_layout = None
228226
self.routes = []
229227

228+
# hot reload
229+
self._reload_hash = _generate_hash() \
230+
if hot_reload else ''
231+
self._reload_interval = hot_reload_interval
232+
self._hard_reload = False
233+
self._lock = threading.RLock()
234+
self._watch_thread = None
235+
if hot_reload:
236+
self._watch_thread = threading.Thread(
237+
target=lambda: _watch.watch([self._assets_folder],
238+
self._on_assets_change,
239+
sleep_time=0.5))
240+
self._watch_thread.start()
241+
230242
@property
231243
def layout(self):
232244
return self._layout
@@ -298,7 +310,10 @@ def _config(self):
298310
return config
299311

300312
def serve_reload_hash(self):
301-
return flask.jsonify({'reloadHash': self._reload_hash})
313+
return flask.jsonify({
314+
'reloadHash': self._reload_hash,
315+
'hard': self._hard_reload
316+
})
302317

303318
def serve_routes(self):
304319
return flask.Response(
@@ -968,6 +983,12 @@ def get_asset_url(self, path):
968983
self.config.routes_pathname_prefix,
969984
path)
970985

986+
def _on_assets_change(self, _):
987+
self._lock.acquire()
988+
self._hard_reload = True
989+
self._reload_hash = _generate_hash()
990+
self._lock.release()
991+
971992
def run_server(self,
972993
port=8050,
973994
debug=False,

dev-requirements-py37.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
dash_core_components>=0.27.2
2-
dash_html_components>=0.12.0rc3
2+
dash_html_components>=0.13.0rc2
33
dash-flow-example==0.0.3
44
dash-dangerously-set-inner-html
55
dash_renderer

0 commit comments

Comments
 (0)