Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hot reload #362

Merged
merged 29 commits into from Nov 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
335e038
Add reload route and renderer config.
T4rk1n Aug 9, 2018
5723533
Add reload interval config.
T4rk1n Aug 9, 2018
5b10597
Add assets filewatcher to reload on assets changes.
T4rk1n Aug 15, 2018
cc6c21c
Always set debug to true when hot_reload=True.
T4rk1n Aug 31, 2018
493f99d
Add comment on the filename in _on_assets_change.
T4rk1n Sep 12, 2018
23882f5
Reset hard reload to false when serving the hash.
T4rk1n Sep 12, 2018
ab53330
Fix activate debug when hot_reload is true.
T4rk1n Sep 13, 2018
13202e5
Disable pylint37 too-many-statements.
T4rk1n Sep 13, 2018
94bf7c0
Hot-reload on adding/removing assets files.
T4rk1n Sep 14, 2018
7c77bc8
Add package list to the reload response.
T4rk1n Sep 14, 2018
8c993fa
Support reloading css only.
T4rk1n Sep 17, 2018
631da7b
Add configurable watch_interval.
T4rk1n Sep 18, 2018
08bbdc1
Integrate hot reload with enable_dev_tools.
T4rk1n Sep 21, 2018
410865e
Line length fix & add more info to the dev tools docstring.
T4rk1n Sep 21, 2018
46383d1
Add hot reload dev tools arguments to run_server.
T4rk1n Sep 21, 2018
1e4eae6
Set to serve locally when dev tools are activated.
T4rk1n Sep 21, 2018
e714af3
Add silence routes logging to dev tools.
T4rk1n Sep 21, 2018
d74498f
Fix logging formatting.
T4rk1n Sep 21, 2018
494243e
Cast registered_paths keys to list, py3 compat.
T4rk1n Oct 3, 2018
1ae7dca
Add hot_reload_max_retry.
T4rk1n Oct 5, 2018
f22ea7d
Generate a debugger PIN and print it when logs are silenced.
T4rk1n Oct 9, 2018
353d79c
Fix rebase.
T4rk1n Oct 18, 2018
4654e5f
Add missing dev_tools docstring.
T4rk1n Oct 18, 2018
beadd63
Fix :bug: with assets watch deletion.
T4rk1n Nov 14, 2018
407e24c
Proper path manipulation on assets change.
T4rk1n Nov 14, 2018
63033ef
:goat: environ -> environment.
T4rk1n Nov 14, 2018
fb26306
Add DASH_HOT_RELOAD_MAX_RETRY environment variable.
T4rk1n Nov 14, 2018
927d69b
:hocho: remove resources cache.
T4rk1n Nov 14, 2018
d410c9c
Update version and changelog.
T4rk1n Nov 14, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion .pylintrc37
Expand Up @@ -146,7 +146,8 @@ disable=invalid-name,
no-else-return,
useless-object-inheritance,
possibly-unused-variable,
too-many-lines
too-many-lines,
too-many-statements

# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,8 @@
## 0.30.0 - 2018-11-14
## Added
- Hot reload from the browser [#362](https://github.com/plotly/dash/pull/362)
- Silence routes logging with `dev_tools_silence_routes_logging`.

## 0.29.0 - 2018-11-06
## Added
- Added component namespaces registry, collect the resources needed by component library when they are imported instead of crawling the layout. [#444](https://github.com/plotly/dash/pull/444)
Expand Down
7 changes: 6 additions & 1 deletion dash/_configs.py
Expand Up @@ -22,7 +22,12 @@ def env_configs():
'DASH_COMPONENTS_CACHE_MAX_AGE',
'DASH_INCLUDE_ASSETS_FILES',
'DASH_SERVE_DEV_BUNDLES',
'DASH_DEBUG'
'DASH_DEBUG',
'DASH_HOT_RELOAD',
'DASH_HOT_RELOAD_INTERVAL',
'DASH_HOT_RELOAD_WATCH_INTERVAL',
'DASH_HOT_RELOAD_MAX_RETRY',
'DASH_SILENCE_ROUTES_LOGGING'
)})


Expand Down
8 changes: 7 additions & 1 deletion dash/_utils.py
@@ -1,3 +1,6 @@
import uuid


def interpolate_str(template, **data):
s = template
for k, v in data.items():
Expand All @@ -20,12 +23,15 @@ def format_tag(tag_name, attributes, inner='', closed=False, opened=False):
'{}="{}"'.format(k, v) for k, v in attributes.items()]))


def generate_hash():
return str(uuid.uuid4().hex).strip('-')


def get_asset_path(
requests_pathname,
routes_pathname,
asset_path,
asset_url_path):

i = requests_pathname.rfind(routes_pathname)
req = requests_pathname[:i]

Expand Down
36 changes: 36 additions & 0 deletions dash/_watch.py
@@ -0,0 +1,36 @@
import collections
import os
import re
import time


def watch(folders, on_change, pattern=None, sleep_time=0.1):
pattern = re.compile(pattern) if pattern else None
watched = collections.defaultdict(lambda: -1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat, didn't know you could do this.


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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os.path.getmtime might be cleaner here. I thought there was platform dependence issue at first (since otherwise why would they even implement os.path.getmtime if you can just os.stat(path).st_mtime, but it turns out thats exactly what os.path.getmtime does.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, some methods in that module seems to be wrapper around os.stat. I'm used to os.stat so I just do that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍, either way is good, just seemed a bit strange, seems to break "There should be one-- and preferably only one --obvious way to do it".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the os module predates the PEP's.

new_time = info.st_mtime

if new_time > watched[path] > 0:
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()
time.sleep(sleep_time)