Fix assets blueprint path management - #547

Merged
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths
Jan 23, 2019
Merged

Fix assets blueprint path management#547
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths

Conversation

@T4rk1n

@T4rk1nT4rk1n commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Fixed

  • Asset blueprint takes routes prefix into it's static path.
  • Asset url path no longer strip routes from requests.

Changed

  • assets_folder argument now default to 'assets'
  • The assets folder is now always relative to the given root path of name argument, the default of __main__ will get the cwd.
  • No longer coerce the name argument from the server if the server argument is provided.

Fixes#529

@T4rk1n
T4rk1n requested a review from ned2January 20, 2019 01:04
Comment threaddash/dash.py Outdated
Comment threaddash/dash.py Outdated
assets_folder='assets',
assets_url_path='/assets',
assets_ignore='',
assets_blueprint_name='assets',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How important is this to be a user-configurable param? If we made the initial value dash-assets (which would still be prefixed by custom route values -- which was a good move btw) then it seems unlikely that a user would need to modify this.

Just thinking about slowing the rate of kwarg growth for the constructor where possible, as it will get a but unwieldy at some point.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good point let's remove that, there's already much clutter in the kwargs. 👌

@ned2ned2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cool, the fix to adding the routes prefix to the assets URL setting and getting looks good!

With the fixes to add better support for multi-route blueprints, I'm wondering if we could improve this some more.

One scenario that I could readily see happening when trying to support multiple Dash apps alongside each other using the same Flask server:

server.py
app1/app1.py
app2/assets/app1.css
app2/app2.py
app2/assets/app2.css

Where server.py defines a Flask instance and app1.py and app2.py both define Dash instances that pass in the Flask instance from the directory above.

app1's Dash instance might look like this:

app=dash.Dash(
server=server,
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

The assets for this app won't actually work however, as the default value of assets_folder is derived from the cwd of the Flask instance. So it will automatically be set to assets (ie at the same level as server.py. So instead the user will have to do:

app=dash.Dash(
server=server,
assets_folder="app1/assets",
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

There would be much less cognitive friction if the correct value of the assets path could be inferred as being relative to the Dash instance rather than the Flask instance. I guess this situation could be more generally described as when a Dash instance isn't found within the path that server.name resolves to. Which, now that I think about it, might actually be a lot harder to make happen, so maybe this is a discussion for another time...

@ned2

ned2 commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Here's the example app I was using to check this was working and find that issue with the static_folder value of the Blueplrint: https://github.com/ned2/dash-embed-recipes/tree/master/flask_multi

It's has the same layout as in the example I mentioned above.

Co-Authored-By: T4rk1n <t4rk@outlook.com>
@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

name=nameifserverisNoneelseserver.name

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

dash/dash/dash.py

Line 105 in e72f483

name = name if server is None else server.name

Yeah, I didn't include the name argument precisely because I knew that it would be changed to be the value of server.name.

yep, so a potential change could be to remove that line overriding name, then flask.helpers.get_root_path(name) would resolve to the path the file with the Dash instance is found in, but server.name would still be whatever the original Flask instance was set to.

Are there any other places that would be affected by decoupling the Dash name param from the Flask name param? I can't see any scanning through dash.py

(also, if we did this, should it be in a separate PR?)

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

I just tested the effect of removing that line that overwrites the name variable with server.name on my example when both Dash instances are updated to pass the name parameter. Looks like it's all working exactly as it should now!

If you think this won't have any other unwanted repercussions, then I'm happy to make that change. I'm also happy with how everything else is looking.

💃

@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

Thanks @ned2, let's remove the line, I don't think it's useful.

@T4rk1n
T4rk1n merged commit 534d285 into masterJan 23, 2019
@T4rk1n
T4rk1n deleted the fix-asset-paths branch January 23, 2019 16:38
alexcjohnson added a commit to plotly/dash-core-components that referenced this pull request Jan 24, 2019
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Don't strip asset paths

2 participants

@T4rk1n@ned2
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Fix assets blueprint path management - #547

Merged
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths
Jan 23, 2019
Merged

Fix assets blueprint path management#547
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths

Conversation

@T4rk1n

@T4rk1nT4rk1n commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Fixed

  • Asset blueprint takes routes prefix into it's static path.
  • Asset url path no longer strip routes from requests.

Changed

  • assets_folder argument now default to 'assets'
  • The assets folder is now always relative to the given root path of name argument, the default of __main__ will get the cwd.
  • No longer coerce the name argument from the server if the server argument is provided.

Fixes#529

@T4rk1n
T4rk1n requested a review from ned2January 20, 2019 01:04
Comment threaddash/dash.py Outdated
Comment threaddash/dash.py Outdated
assets_folder='assets',
assets_url_path='/assets',
assets_ignore='',
assets_blueprint_name='assets',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How important is this to be a user-configurable param? If we made the initial value dash-assets (which would still be prefixed by custom route values -- which was a good move btw) then it seems unlikely that a user would need to modify this.

Just thinking about slowing the rate of kwarg growth for the constructor where possible, as it will get a but unwieldy at some point.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good point let's remove that, there's already much clutter in the kwargs. 👌

@ned2ned2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cool, the fix to adding the routes prefix to the assets URL setting and getting looks good!

With the fixes to add better support for multi-route blueprints, I'm wondering if we could improve this some more.

One scenario that I could readily see happening when trying to support multiple Dash apps alongside each other using the same Flask server:

server.py
app1/app1.py
app2/assets/app1.css
app2/app2.py
app2/assets/app2.css

Where server.py defines a Flask instance and app1.py and app2.py both define Dash instances that pass in the Flask instance from the directory above.

app1's Dash instance might look like this:

app=dash.Dash(
server=server,
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

The assets for this app won't actually work however, as the default value of assets_folder is derived from the cwd of the Flask instance. So it will automatically be set to assets (ie at the same level as server.py. So instead the user will have to do:

app=dash.Dash(
server=server,
assets_folder="app1/assets",
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

There would be much less cognitive friction if the correct value of the assets path could be inferred as being relative to the Dash instance rather than the Flask instance. I guess this situation could be more generally described as when a Dash instance isn't found within the path that server.name resolves to. Which, now that I think about it, might actually be a lot harder to make happen, so maybe this is a discussion for another time...

@ned2

ned2 commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Here's the example app I was using to check this was working and find that issue with the static_folder value of the Blueplrint: https://github.com/ned2/dash-embed-recipes/tree/master/flask_multi

It's has the same layout as in the example I mentioned above.

Co-Authored-By: T4rk1n <t4rk@outlook.com>
@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

name=nameifserverisNoneelseserver.name

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

dash/dash/dash.py

Line 105 in e72f483

name = name if server is None else server.name

Yeah, I didn't include the name argument precisely because I knew that it would be changed to be the value of server.name.

yep, so a potential change could be to remove that line overriding name, then flask.helpers.get_root_path(name) would resolve to the path the file with the Dash instance is found in, but server.name would still be whatever the original Flask instance was set to.

Are there any other places that would be affected by decoupling the Dash name param from the Flask name param? I can't see any scanning through dash.py

(also, if we did this, should it be in a separate PR?)

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

I just tested the effect of removing that line that overwrites the name variable with server.name on my example when both Dash instances are updated to pass the name parameter. Looks like it's all working exactly as it should now!

If you think this won't have any other unwanted repercussions, then I'm happy to make that change. I'm also happy with how everything else is looking.

💃

@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

Thanks @ned2, let's remove the line, I don't think it's useful.

@T4rk1n
T4rk1n merged commit 534d285 into masterJan 23, 2019
@T4rk1n
T4rk1n deleted the fix-asset-paths branch January 23, 2019 16:38
alexcjohnson added a commit to plotly/dash-core-components that referenced this pull request Jan 24, 2019
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Don't strip asset paths

2 participants

@T4rk1n@ned2
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix assets blueprint path management - #547

Merged
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths
Jan 23, 2019
Merged

Fix assets blueprint path management#547
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths

Conversation

@T4rk1n

@T4rk1nT4rk1n commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Fixed

  • Asset blueprint takes routes prefix into it's static path.
  • Asset url path no longer strip routes from requests.

Changed

  • assets_folder argument now default to 'assets'
  • The assets folder is now always relative to the given root path of name argument, the default of __main__ will get the cwd.
  • No longer coerce the name argument from the server if the server argument is provided.

Fixes#529

@T4rk1n
T4rk1n requested a review from ned2January 20, 2019 01:04
Comment threaddash/dash.py Outdated
Comment threaddash/dash.py Outdated
assets_folder='assets',
assets_url_path='/assets',
assets_ignore='',
assets_blueprint_name='assets',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How important is this to be a user-configurable param? If we made the initial value dash-assets (which would still be prefixed by custom route values -- which was a good move btw) then it seems unlikely that a user would need to modify this.

Just thinking about slowing the rate of kwarg growth for the constructor where possible, as it will get a but unwieldy at some point.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good point let's remove that, there's already much clutter in the kwargs. 👌

@ned2ned2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cool, the fix to adding the routes prefix to the assets URL setting and getting looks good!

With the fixes to add better support for multi-route blueprints, I'm wondering if we could improve this some more.

One scenario that I could readily see happening when trying to support multiple Dash apps alongside each other using the same Flask server:

server.py
app1/app1.py
app2/assets/app1.css
app2/app2.py
app2/assets/app2.css

Where server.py defines a Flask instance and app1.py and app2.py both define Dash instances that pass in the Flask instance from the directory above.

app1's Dash instance might look like this:

app=dash.Dash(
server=server,
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

The assets for this app won't actually work however, as the default value of assets_folder is derived from the cwd of the Flask instance. So it will automatically be set to assets (ie at the same level as server.py. So instead the user will have to do:

app=dash.Dash(
server=server,
assets_folder="app1/assets",
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

There would be much less cognitive friction if the correct value of the assets path could be inferred as being relative to the Dash instance rather than the Flask instance. I guess this situation could be more generally described as when a Dash instance isn't found within the path that server.name resolves to. Which, now that I think about it, might actually be a lot harder to make happen, so maybe this is a discussion for another time...

@ned2

ned2 commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Here's the example app I was using to check this was working and find that issue with the static_folder value of the Blueplrint: https://github.com/ned2/dash-embed-recipes/tree/master/flask_multi

It's has the same layout as in the example I mentioned above.

Co-Authored-By: T4rk1n <t4rk@outlook.com>
@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

name=nameifserverisNoneelseserver.name

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

dash/dash/dash.py

Line 105 in e72f483

name = name if server is None else server.name

Yeah, I didn't include the name argument precisely because I knew that it would be changed to be the value of server.name.

yep, so a potential change could be to remove that line overriding name, then flask.helpers.get_root_path(name) would resolve to the path the file with the Dash instance is found in, but server.name would still be whatever the original Flask instance was set to.

Are there any other places that would be affected by decoupling the Dash name param from the Flask name param? I can't see any scanning through dash.py

(also, if we did this, should it be in a separate PR?)

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

I just tested the effect of removing that line that overwrites the name variable with server.name on my example when both Dash instances are updated to pass the name parameter. Looks like it's all working exactly as it should now!

If you think this won't have any other unwanted repercussions, then I'm happy to make that change. I'm also happy with how everything else is looking.

💃

@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

Thanks @ned2, let's remove the line, I don't think it's useful.

@T4rk1n
T4rk1n merged commit 534d285 into masterJan 23, 2019
@T4rk1n
T4rk1n deleted the fix-asset-paths branch January 23, 2019 16:38
alexcjohnson added a commit to plotly/dash-core-components that referenced this pull request Jan 24, 2019
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Don't strip asset paths

2 participants

@T4rk1n@ned2
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix assets blueprint path management - #547

Merged
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths
Jan 23, 2019
Merged

Fix assets blueprint path management#547
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths

Conversation

@T4rk1n

@T4rk1nT4rk1n commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Fixed

  • Asset blueprint takes routes prefix into it's static path.
  • Asset url path no longer strip routes from requests.

Changed

  • assets_folder argument now default to 'assets'
  • The assets folder is now always relative to the given root path of name argument, the default of __main__ will get the cwd.
  • No longer coerce the name argument from the server if the server argument is provided.

Fixes#529

@T4rk1n
T4rk1n requested a review from ned2January 20, 2019 01:04
Comment threaddash/dash.py Outdated
Comment threaddash/dash.py Outdated
assets_folder='assets',
assets_url_path='/assets',
assets_ignore='',
assets_blueprint_name='assets',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How important is this to be a user-configurable param? If we made the initial value dash-assets (which would still be prefixed by custom route values -- which was a good move btw) then it seems unlikely that a user would need to modify this.

Just thinking about slowing the rate of kwarg growth for the constructor where possible, as it will get a but unwieldy at some point.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good point let's remove that, there's already much clutter in the kwargs. 👌

@ned2ned2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cool, the fix to adding the routes prefix to the assets URL setting and getting looks good!

With the fixes to add better support for multi-route blueprints, I'm wondering if we could improve this some more.

One scenario that I could readily see happening when trying to support multiple Dash apps alongside each other using the same Flask server:

server.py
app1/app1.py
app2/assets/app1.css
app2/app2.py
app2/assets/app2.css

Where server.py defines a Flask instance and app1.py and app2.py both define Dash instances that pass in the Flask instance from the directory above.

app1's Dash instance might look like this:

app=dash.Dash(
server=server,
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

The assets for this app won't actually work however, as the default value of assets_folder is derived from the cwd of the Flask instance. So it will automatically be set to assets (ie at the same level as server.py. So instead the user will have to do:

app=dash.Dash(
server=server,
assets_folder="app1/assets",
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

There would be much less cognitive friction if the correct value of the assets path could be inferred as being relative to the Dash instance rather than the Flask instance. I guess this situation could be more generally described as when a Dash instance isn't found within the path that server.name resolves to. Which, now that I think about it, might actually be a lot harder to make happen, so maybe this is a discussion for another time...

@ned2

ned2 commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Here's the example app I was using to check this was working and find that issue with the static_folder value of the Blueplrint: https://github.com/ned2/dash-embed-recipes/tree/master/flask_multi

It's has the same layout as in the example I mentioned above.

Co-Authored-By: T4rk1n <t4rk@outlook.com>
@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

name=nameifserverisNoneelseserver.name

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

dash/dash/dash.py

Line 105 in e72f483

name = name if server is None else server.name

Yeah, I didn't include the name argument precisely because I knew that it would be changed to be the value of server.name.

yep, so a potential change could be to remove that line overriding name, then flask.helpers.get_root_path(name) would resolve to the path the file with the Dash instance is found in, but server.name would still be whatever the original Flask instance was set to.

Are there any other places that would be affected by decoupling the Dash name param from the Flask name param? I can't see any scanning through dash.py

(also, if we did this, should it be in a separate PR?)

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

I just tested the effect of removing that line that overwrites the name variable with server.name on my example when both Dash instances are updated to pass the name parameter. Looks like it's all working exactly as it should now!

If you think this won't have any other unwanted repercussions, then I'm happy to make that change. I'm also happy with how everything else is looking.

💃

@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

Thanks @ned2, let's remove the line, I don't think it's useful.

@T4rk1n
T4rk1n merged commit 534d285 into masterJan 23, 2019
@T4rk1n
T4rk1n deleted the fix-asset-paths branch January 23, 2019 16:38
alexcjohnson added a commit to plotly/dash-core-components that referenced this pull request Jan 24, 2019
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Don't strip asset paths

2 participants

@T4rk1n@ned2
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Fix assets blueprint path management - #547

Merged
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths
Jan 23, 2019
Merged

Fix assets blueprint path management#547
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths

Conversation

@T4rk1n

@T4rk1nT4rk1n commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Fixed

  • Asset blueprint takes routes prefix into it's static path.
  • Asset url path no longer strip routes from requests.

Changed

  • assets_folder argument now default to 'assets'
  • The assets folder is now always relative to the given root path of name argument, the default of __main__ will get the cwd.
  • No longer coerce the name argument from the server if the server argument is provided.

Fixes#529

@T4rk1n
T4rk1n requested a review from ned2January 20, 2019 01:04
Comment threaddash/dash.py Outdated
Comment threaddash/dash.py Outdated
assets_folder='assets',
assets_url_path='/assets',
assets_ignore='',
assets_blueprint_name='assets',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How important is this to be a user-configurable param? If we made the initial value dash-assets (which would still be prefixed by custom route values -- which was a good move btw) then it seems unlikely that a user would need to modify this.

Just thinking about slowing the rate of kwarg growth for the constructor where possible, as it will get a but unwieldy at some point.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good point let's remove that, there's already much clutter in the kwargs. 👌

@ned2ned2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cool, the fix to adding the routes prefix to the assets URL setting and getting looks good!

With the fixes to add better support for multi-route blueprints, I'm wondering if we could improve this some more.

One scenario that I could readily see happening when trying to support multiple Dash apps alongside each other using the same Flask server:

server.py
app1/app1.py
app2/assets/app1.css
app2/app2.py
app2/assets/app2.css

Where server.py defines a Flask instance and app1.py and app2.py both define Dash instances that pass in the Flask instance from the directory above.

app1's Dash instance might look like this:

app=dash.Dash(
server=server,
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

The assets for this app won't actually work however, as the default value of assets_folder is derived from the cwd of the Flask instance. So it will automatically be set to assets (ie at the same level as server.py. So instead the user will have to do:

app=dash.Dash(
server=server,
assets_folder="app1/assets",
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

There would be much less cognitive friction if the correct value of the assets path could be inferred as being relative to the Dash instance rather than the Flask instance. I guess this situation could be more generally described as when a Dash instance isn't found within the path that server.name resolves to. Which, now that I think about it, might actually be a lot harder to make happen, so maybe this is a discussion for another time...

@ned2

ned2 commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Here's the example app I was using to check this was working and find that issue with the static_folder value of the Blueplrint: https://github.com/ned2/dash-embed-recipes/tree/master/flask_multi

It's has the same layout as in the example I mentioned above.

Co-Authored-By: T4rk1n <t4rk@outlook.com>
@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

name=nameifserverisNoneelseserver.name

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

dash/dash/dash.py

Line 105 in e72f483

name = name if server is None else server.name

Yeah, I didn't include the name argument precisely because I knew that it would be changed to be the value of server.name.

yep, so a potential change could be to remove that line overriding name, then flask.helpers.get_root_path(name) would resolve to the path the file with the Dash instance is found in, but server.name would still be whatever the original Flask instance was set to.

Are there any other places that would be affected by decoupling the Dash name param from the Flask name param? I can't see any scanning through dash.py

(also, if we did this, should it be in a separate PR?)

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

I just tested the effect of removing that line that overwrites the name variable with server.name on my example when both Dash instances are updated to pass the name parameter. Looks like it's all working exactly as it should now!

If you think this won't have any other unwanted repercussions, then I'm happy to make that change. I'm also happy with how everything else is looking.

💃

@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

Thanks @ned2, let's remove the line, I don't think it's useful.

@T4rk1n
T4rk1n merged commit 534d285 into masterJan 23, 2019
@T4rk1n
T4rk1n deleted the fix-asset-paths branch January 23, 2019 16:38
alexcjohnson added a commit to plotly/dash-core-components that referenced this pull request Jan 24, 2019
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Don't strip asset paths

2 participants

@T4rk1n@ned2
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix assets blueprint path management - #547

Merged
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths
Jan 23, 2019
Merged

Fix assets blueprint path management#547
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths

Conversation

@T4rk1n

@T4rk1nT4rk1n commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Fixed

  • Asset blueprint takes routes prefix into it's static path.
  • Asset url path no longer strip routes from requests.

Changed

  • assets_folder argument now default to 'assets'
  • The assets folder is now always relative to the given root path of name argument, the default of __main__ will get the cwd.
  • No longer coerce the name argument from the server if the server argument is provided.

Fixes#529

@T4rk1n
T4rk1n requested a review from ned2January 20, 2019 01:04
Comment threaddash/dash.py Outdated
Comment threaddash/dash.py Outdated
assets_folder='assets',
assets_url_path='/assets',
assets_ignore='',
assets_blueprint_name='assets',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How important is this to be a user-configurable param? If we made the initial value dash-assets (which would still be prefixed by custom route values -- which was a good move btw) then it seems unlikely that a user would need to modify this.

Just thinking about slowing the rate of kwarg growth for the constructor where possible, as it will get a but unwieldy at some point.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good point let's remove that, there's already much clutter in the kwargs. 👌

@ned2ned2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cool, the fix to adding the routes prefix to the assets URL setting and getting looks good!

With the fixes to add better support for multi-route blueprints, I'm wondering if we could improve this some more.

One scenario that I could readily see happening when trying to support multiple Dash apps alongside each other using the same Flask server:

server.py
app1/app1.py
app2/assets/app1.css
app2/app2.py
app2/assets/app2.css

Where server.py defines a Flask instance and app1.py and app2.py both define Dash instances that pass in the Flask instance from the directory above.

app1's Dash instance might look like this:

app=dash.Dash(
server=server,
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

The assets for this app won't actually work however, as the default value of assets_folder is derived from the cwd of the Flask instance. So it will automatically be set to assets (ie at the same level as server.py. So instead the user will have to do:

app=dash.Dash(
server=server,
assets_folder="app1/assets",
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

There would be much less cognitive friction if the correct value of the assets path could be inferred as being relative to the Dash instance rather than the Flask instance. I guess this situation could be more generally described as when a Dash instance isn't found within the path that server.name resolves to. Which, now that I think about it, might actually be a lot harder to make happen, so maybe this is a discussion for another time...

@ned2

ned2 commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Here's the example app I was using to check this was working and find that issue with the static_folder value of the Blueplrint: https://github.com/ned2/dash-embed-recipes/tree/master/flask_multi

It's has the same layout as in the example I mentioned above.

Co-Authored-By: T4rk1n <t4rk@outlook.com>
@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

name=nameifserverisNoneelseserver.name

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

dash/dash/dash.py

Line 105 in e72f483

name = name if server is None else server.name

Yeah, I didn't include the name argument precisely because I knew that it would be changed to be the value of server.name.

yep, so a potential change could be to remove that line overriding name, then flask.helpers.get_root_path(name) would resolve to the path the file with the Dash instance is found in, but server.name would still be whatever the original Flask instance was set to.

Are there any other places that would be affected by decoupling the Dash name param from the Flask name param? I can't see any scanning through dash.py

(also, if we did this, should it be in a separate PR?)

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

I just tested the effect of removing that line that overwrites the name variable with server.name on my example when both Dash instances are updated to pass the name parameter. Looks like it's all working exactly as it should now!

If you think this won't have any other unwanted repercussions, then I'm happy to make that change. I'm also happy with how everything else is looking.

💃

@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

Thanks @ned2, let's remove the line, I don't think it's useful.

@T4rk1n
T4rk1n merged commit 534d285 into masterJan 23, 2019
@T4rk1n
T4rk1n deleted the fix-asset-paths branch January 23, 2019 16:38
alexcjohnson added a commit to plotly/dash-core-components that referenced this pull request Jan 24, 2019
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Don't strip asset paths

2 participants

@T4rk1n@ned2
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix assets blueprint path management - #547

Merged
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths
Jan 23, 2019
Merged

Fix assets blueprint path management#547
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths

Conversation

@T4rk1n

@T4rk1nT4rk1n commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Fixed

  • Asset blueprint takes routes prefix into it's static path.
  • Asset url path no longer strip routes from requests.

Changed

  • assets_folder argument now default to 'assets'
  • The assets folder is now always relative to the given root path of name argument, the default of __main__ will get the cwd.
  • No longer coerce the name argument from the server if the server argument is provided.

Fixes#529

@T4rk1n
T4rk1n requested a review from ned2January 20, 2019 01:04
Comment threaddash/dash.py Outdated
Comment threaddash/dash.py Outdated
assets_folder='assets',
assets_url_path='/assets',
assets_ignore='',
assets_blueprint_name='assets',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How important is this to be a user-configurable param? If we made the initial value dash-assets (which would still be prefixed by custom route values -- which was a good move btw) then it seems unlikely that a user would need to modify this.

Just thinking about slowing the rate of kwarg growth for the constructor where possible, as it will get a but unwieldy at some point.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good point let's remove that, there's already much clutter in the kwargs. 👌

@ned2ned2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cool, the fix to adding the routes prefix to the assets URL setting and getting looks good!

With the fixes to add better support for multi-route blueprints, I'm wondering if we could improve this some more.

One scenario that I could readily see happening when trying to support multiple Dash apps alongside each other using the same Flask server:

server.py
app1/app1.py
app2/assets/app1.css
app2/app2.py
app2/assets/app2.css

Where server.py defines a Flask instance and app1.py and app2.py both define Dash instances that pass in the Flask instance from the directory above.

app1's Dash instance might look like this:

app=dash.Dash(
server=server,
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

The assets for this app won't actually work however, as the default value of assets_folder is derived from the cwd of the Flask instance. So it will automatically be set to assets (ie at the same level as server.py. So instead the user will have to do:

app=dash.Dash(
server=server,
assets_folder="app1/assets",
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

There would be much less cognitive friction if the correct value of the assets path could be inferred as being relative to the Dash instance rather than the Flask instance. I guess this situation could be more generally described as when a Dash instance isn't found within the path that server.name resolves to. Which, now that I think about it, might actually be a lot harder to make happen, so maybe this is a discussion for another time...

@ned2

ned2 commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Here's the example app I was using to check this was working and find that issue with the static_folder value of the Blueplrint: https://github.com/ned2/dash-embed-recipes/tree/master/flask_multi

It's has the same layout as in the example I mentioned above.

Co-Authored-By: T4rk1n <t4rk@outlook.com>
@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

name=nameifserverisNoneelseserver.name

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

dash/dash/dash.py

Line 105 in e72f483

name = name if server is None else server.name

Yeah, I didn't include the name argument precisely because I knew that it would be changed to be the value of server.name.

yep, so a potential change could be to remove that line overriding name, then flask.helpers.get_root_path(name) would resolve to the path the file with the Dash instance is found in, but server.name would still be whatever the original Flask instance was set to.

Are there any other places that would be affected by decoupling the Dash name param from the Flask name param? I can't see any scanning through dash.py

(also, if we did this, should it be in a separate PR?)

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

I just tested the effect of removing that line that overwrites the name variable with server.name on my example when both Dash instances are updated to pass the name parameter. Looks like it's all working exactly as it should now!

If you think this won't have any other unwanted repercussions, then I'm happy to make that change. I'm also happy with how everything else is looking.

💃

@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

Thanks @ned2, let's remove the line, I don't think it's useful.

@T4rk1n
T4rk1n merged commit 534d285 into masterJan 23, 2019
@T4rk1n
T4rk1n deleted the fix-asset-paths branch January 23, 2019 16:38
alexcjohnson added a commit to plotly/dash-core-components that referenced this pull request Jan 24, 2019
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Don't strip asset paths

2 participants

@T4rk1n@ned2
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Fix assets blueprint path management - #547

Merged
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths
Jan 23, 2019
Merged

Fix assets blueprint path management#547
T4rk1n merged 7 commits into
masterfrom
fix-asset-paths

Conversation

@T4rk1n

@T4rk1nT4rk1n commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Fixed

  • Asset blueprint takes routes prefix into it's static path.
  • Asset url path no longer strip routes from requests.

Changed

  • assets_folder argument now default to 'assets'
  • The assets folder is now always relative to the given root path of name argument, the default of __main__ will get the cwd.
  • No longer coerce the name argument from the server if the server argument is provided.

Fixes#529

@T4rk1n
T4rk1n requested a review from ned2January 20, 2019 01:04
Comment threaddash/dash.py Outdated
Comment threaddash/dash.py Outdated
assets_folder='assets',
assets_url_path='/assets',
assets_ignore='',
assets_blueprint_name='assets',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How important is this to be a user-configurable param? If we made the initial value dash-assets (which would still be prefixed by custom route values -- which was a good move btw) then it seems unlikely that a user would need to modify this.

Just thinking about slowing the rate of kwarg growth for the constructor where possible, as it will get a but unwieldy at some point.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good point let's remove that, there's already much clutter in the kwargs. 👌

@ned2ned2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cool, the fix to adding the routes prefix to the assets URL setting and getting looks good!

With the fixes to add better support for multi-route blueprints, I'm wondering if we could improve this some more.

One scenario that I could readily see happening when trying to support multiple Dash apps alongside each other using the same Flask server:

server.py
app1/app1.py
app2/assets/app1.css
app2/app2.py
app2/assets/app2.css

Where server.py defines a Flask instance and app1.py and app2.py both define Dash instances that pass in the Flask instance from the directory above.

app1's Dash instance might look like this:

app=dash.Dash(
server=server,
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

The assets for this app won't actually work however, as the default value of assets_folder is derived from the cwd of the Flask instance. So it will automatically be set to assets (ie at the same level as server.py. So instead the user will have to do:

app=dash.Dash(
server=server,
assets_folder="app1/assets",
requests_pathname_prefix='/my-app1/',
routes_pathname_prefix='/my-app1/',
)

There would be much less cognitive friction if the correct value of the assets path could be inferred as being relative to the Dash instance rather than the Flask instance. I guess this situation could be more generally described as when a Dash instance isn't found within the path that server.name resolves to. Which, now that I think about it, might actually be a lot harder to make happen, so maybe this is a discussion for another time...

@ned2

ned2 commented Jan 20, 2019

Copy link
Copy Markdown
Contributor

Here's the example app I was using to check this was working and find that issue with the static_folder value of the Blueplrint: https://github.com/ned2/dash-embed-recipes/tree/master/flask_multi

It's has the same layout as in the example I mentioned above.

Co-Authored-By: T4rk1n <t4rk@outlook.com>
@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

name=nameifserverisNoneelseserver.name

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

@ned2 Your examples are missing the __name__ , but still it won't work because when we provide the server, the name is taken from the server instead so it won't be relative to the app but instead will be relative to where the server was instantiated.

Should we remove that or improve the logic here ?

dash/dash/dash.py

Line 105 in e72f483

name = name if server is None else server.name

Yeah, I didn't include the name argument precisely because I knew that it would be changed to be the value of server.name.

yep, so a potential change could be to remove that line overriding name, then flask.helpers.get_root_path(name) would resolve to the path the file with the Dash instance is found in, but server.name would still be whatever the original Flask instance was set to.

Are there any other places that would be affected by decoupling the Dash name param from the Flask name param? I can't see any scanning through dash.py

(also, if we did this, should it be in a separate PR?)

@ned2

ned2 commented Jan 22, 2019

Copy link
Copy Markdown
Contributor

I just tested the effect of removing that line that overwrites the name variable with server.name on my example when both Dash instances are updated to pass the name parameter. Looks like it's all working exactly as it should now!

If you think this won't have any other unwanted repercussions, then I'm happy to make that change. I'm also happy with how everything else is looking.

💃

@T4rk1n

Copy link
Copy Markdown
ContributorAuthor

Thanks @ned2, let's remove the line, I don't think it's useful.

@T4rk1n
T4rk1n merged commit 534d285 into masterJan 23, 2019
@T4rk1n
T4rk1n deleted the fix-asset-paths branch January 23, 2019 16:38
alexcjohnson added a commit to plotly/dash-core-components that referenced this pull request Jan 24, 2019
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Don't strip asset paths

2 participants

@T4rk1n@ned2