If IPython is merely installed, don't assume that it's actually used - #5222

Closed
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions
Closed

If IPython is merely installed, don't assume that it's actually used#5222
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions

Conversation

@pfalcon

Copy link
Copy Markdown

In my virtual environment, there happens to be installed IPython package. It wasn't installed by myself, it's merely a transitive dependency of some another package. It's neither intended to be used, nor is actually used by my project. However, mere presense of the IPython package, due to the over-simplistic decision code in this module (io._renderers) leads to drastic behavior change in Plotly.py: calling Figure.repr_html() causes lots of JS garbage to be printed on terminal (by common sense, this should be a side-effects free function, only returning a value). On a higher level, this breaks natural Plotly.py integration in frameworks like Shiny.py (because again, instead of HTML representation being returned for a framework to process, parts of that representation are dumped on terminal).

The real underlying issue is that Plotly.py should not force-import any "optional" packages behind users' back. However, this is a deeper issue requiring consideration and will be reported separately. This patch is a quick solution for the problem describe above.

From interactive session:

>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'

Code PR

  • I have read through the contributing notes and understand the structure of the package. In particular, if my PR modifies code of plotly.graph_objects, my modifications concern the codegen files and not generated files.
  • I have added tests (if submitting a new feature or correcting a bug) or
    modified existing tests.
  • For a new feature, I have added documentation examples in an existing or
    new tutorial notebook (please see the doc checklist as well).
  • I have added a CHANGELOG entry if fixing/changing/adding anything substantial.
  • For a new feature or a change in behaviour, I have updated the relevant docstrings in the code to describe the feature or behaviour (please see the doc checklist as well).

In my virtual environment, there happens to be installed IPython package.
It wasn't installed by myself, it's merely a transitive dependency of
some another package. It's neither intended to be used, nor is actually
used by my project. However, mere presense of the IPython package, due
to the over-simplistic decision code in this module (io._renderers)
leads to drastic behavior change in Plotly.py: calling
Figure._repr_html_() causes lots of JS garbage to be printed on terminal
(by common sense, this should be a side-effects free function, only
returning a value). On a higher level, this breaks natural Plotly.py
integration in frameworks like Shiny.py (because again, instead of
HTML representation being returned for a framework to process, parts
of that representation are dumped on terminal).
The real underlying issue is that Plotly.py should not force-import
any "optional" packages behind users' back. However, this is a deeper
issue requiring consideration and will be reported separately. This
patch is a quick solution for the problem describe above.
From interactive session:
>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'
Signed-off-by: Paul Sokolovsky <pfalcon@users.sourceforge.net>
@pfalcon

Copy link
Copy Markdown
Author

Example of how this affects downstream projects: posit-dev/py-shinywidgets#201 . I'm an experienced Python user, and it took me half a day to debug this issue. I imagine how frustrating it may be for novice users who just wanted to try one of those well-popularized modern Python data visualization packages.

@gvwilson
gvwilson requested a review from emilyklJune 13, 2025 14:12
@gvwilsongvwilson added feature something new P1 needed for current cycle community community contribution labels Jun 13, 2025
@emilykl

Copy link
Copy Markdown
Contributor

Hi @pfalcon , I've just merged a fix in #5258 which takes a slightly different approach to this same issue. Thank you for the contribution and please let me know if that fix addresses the issue on your end!

@emilyklemilykl closed this Oct 1, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

communitycommunity contributionfeaturesomething newP1needed for current cycle

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pfalcon@emilykl@gvwilson
, '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

If IPython is merely installed, don't assume that it's actually used - #5222

Closed
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions
Closed

If IPython is merely installed, don't assume that it's actually used#5222
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions

Conversation

@pfalcon

Copy link
Copy Markdown

In my virtual environment, there happens to be installed IPython package. It wasn't installed by myself, it's merely a transitive dependency of some another package. It's neither intended to be used, nor is actually used by my project. However, mere presense of the IPython package, due to the over-simplistic decision code in this module (io._renderers) leads to drastic behavior change in Plotly.py: calling Figure.repr_html() causes lots of JS garbage to be printed on terminal (by common sense, this should be a side-effects free function, only returning a value). On a higher level, this breaks natural Plotly.py integration in frameworks like Shiny.py (because again, instead of HTML representation being returned for a framework to process, parts of that representation are dumped on terminal).

The real underlying issue is that Plotly.py should not force-import any "optional" packages behind users' back. However, this is a deeper issue requiring consideration and will be reported separately. This patch is a quick solution for the problem describe above.

From interactive session:

>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'

Code PR

  • I have read through the contributing notes and understand the structure of the package. In particular, if my PR modifies code of plotly.graph_objects, my modifications concern the codegen files and not generated files.
  • I have added tests (if submitting a new feature or correcting a bug) or
    modified existing tests.
  • For a new feature, I have added documentation examples in an existing or
    new tutorial notebook (please see the doc checklist as well).
  • I have added a CHANGELOG entry if fixing/changing/adding anything substantial.
  • For a new feature or a change in behaviour, I have updated the relevant docstrings in the code to describe the feature or behaviour (please see the doc checklist as well).

In my virtual environment, there happens to be installed IPython package.
It wasn't installed by myself, it's merely a transitive dependency of
some another package. It's neither intended to be used, nor is actually
used by my project. However, mere presense of the IPython package, due
to the over-simplistic decision code in this module (io._renderers)
leads to drastic behavior change in Plotly.py: calling
Figure._repr_html_() causes lots of JS garbage to be printed on terminal
(by common sense, this should be a side-effects free function, only
returning a value). On a higher level, this breaks natural Plotly.py
integration in frameworks like Shiny.py (because again, instead of
HTML representation being returned for a framework to process, parts
of that representation are dumped on terminal).
The real underlying issue is that Plotly.py should not force-import
any "optional" packages behind users' back. However, this is a deeper
issue requiring consideration and will be reported separately. This
patch is a quick solution for the problem describe above.
From interactive session:
>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'
Signed-off-by: Paul Sokolovsky <pfalcon@users.sourceforge.net>
@pfalcon

Copy link
Copy Markdown
Author

Example of how this affects downstream projects: posit-dev/py-shinywidgets#201 . I'm an experienced Python user, and it took me half a day to debug this issue. I imagine how frustrating it may be for novice users who just wanted to try one of those well-popularized modern Python data visualization packages.

@gvwilson
gvwilson requested a review from emilyklJune 13, 2025 14:12
@gvwilsongvwilson added feature something new P1 needed for current cycle community community contribution labels Jun 13, 2025
@emilykl

Copy link
Copy Markdown
Contributor

Hi @pfalcon , I've just merged a fix in #5258 which takes a slightly different approach to this same issue. Thank you for the contribution and please let me know if that fix addresses the issue on your end!

@emilyklemilykl closed this Oct 1, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

communitycommunity contributionfeaturesomething newP1needed for current cycle

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pfalcon@emilykl@gvwilson
, '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

If IPython is merely installed, don't assume that it's actually used - #5222

Closed
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions
Closed

If IPython is merely installed, don't assume that it's actually used#5222
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions

Conversation

@pfalcon

Copy link
Copy Markdown

In my virtual environment, there happens to be installed IPython package. It wasn't installed by myself, it's merely a transitive dependency of some another package. It's neither intended to be used, nor is actually used by my project. However, mere presense of the IPython package, due to the over-simplistic decision code in this module (io._renderers) leads to drastic behavior change in Plotly.py: calling Figure.repr_html() causes lots of JS garbage to be printed on terminal (by common sense, this should be a side-effects free function, only returning a value). On a higher level, this breaks natural Plotly.py integration in frameworks like Shiny.py (because again, instead of HTML representation being returned for a framework to process, parts of that representation are dumped on terminal).

The real underlying issue is that Plotly.py should not force-import any "optional" packages behind users' back. However, this is a deeper issue requiring consideration and will be reported separately. This patch is a quick solution for the problem describe above.

From interactive session:

>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'

Code PR

  • I have read through the contributing notes and understand the structure of the package. In particular, if my PR modifies code of plotly.graph_objects, my modifications concern the codegen files and not generated files.
  • I have added tests (if submitting a new feature or correcting a bug) or
    modified existing tests.
  • For a new feature, I have added documentation examples in an existing or
    new tutorial notebook (please see the doc checklist as well).
  • I have added a CHANGELOG entry if fixing/changing/adding anything substantial.
  • For a new feature or a change in behaviour, I have updated the relevant docstrings in the code to describe the feature or behaviour (please see the doc checklist as well).

In my virtual environment, there happens to be installed IPython package.
It wasn't installed by myself, it's merely a transitive dependency of
some another package. It's neither intended to be used, nor is actually
used by my project. However, mere presense of the IPython package, due
to the over-simplistic decision code in this module (io._renderers)
leads to drastic behavior change in Plotly.py: calling
Figure._repr_html_() causes lots of JS garbage to be printed on terminal
(by common sense, this should be a side-effects free function, only
returning a value). On a higher level, this breaks natural Plotly.py
integration in frameworks like Shiny.py (because again, instead of
HTML representation being returned for a framework to process, parts
of that representation are dumped on terminal).
The real underlying issue is that Plotly.py should not force-import
any "optional" packages behind users' back. However, this is a deeper
issue requiring consideration and will be reported separately. This
patch is a quick solution for the problem describe above.
From interactive session:
>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'
Signed-off-by: Paul Sokolovsky <pfalcon@users.sourceforge.net>
@pfalcon

Copy link
Copy Markdown
Author

Example of how this affects downstream projects: posit-dev/py-shinywidgets#201 . I'm an experienced Python user, and it took me half a day to debug this issue. I imagine how frustrating it may be for novice users who just wanted to try one of those well-popularized modern Python data visualization packages.

@gvwilson
gvwilson requested a review from emilyklJune 13, 2025 14:12
@gvwilsongvwilson added feature something new P1 needed for current cycle community community contribution labels Jun 13, 2025
@emilykl

Copy link
Copy Markdown
Contributor

Hi @pfalcon , I've just merged a fix in #5258 which takes a slightly different approach to this same issue. Thank you for the contribution and please let me know if that fix addresses the issue on your end!

@emilyklemilykl closed this Oct 1, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

communitycommunity contributionfeaturesomething newP1needed for current cycle

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pfalcon@emilykl@gvwilson
, '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

If IPython is merely installed, don't assume that it's actually used - #5222

Closed
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions
Closed

If IPython is merely installed, don't assume that it's actually used#5222
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions

Conversation

@pfalcon

Copy link
Copy Markdown

In my virtual environment, there happens to be installed IPython package. It wasn't installed by myself, it's merely a transitive dependency of some another package. It's neither intended to be used, nor is actually used by my project. However, mere presense of the IPython package, due to the over-simplistic decision code in this module (io._renderers) leads to drastic behavior change in Plotly.py: calling Figure.repr_html() causes lots of JS garbage to be printed on terminal (by common sense, this should be a side-effects free function, only returning a value). On a higher level, this breaks natural Plotly.py integration in frameworks like Shiny.py (because again, instead of HTML representation being returned for a framework to process, parts of that representation are dumped on terminal).

The real underlying issue is that Plotly.py should not force-import any "optional" packages behind users' back. However, this is a deeper issue requiring consideration and will be reported separately. This patch is a quick solution for the problem describe above.

From interactive session:

>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'

Code PR

  • I have read through the contributing notes and understand the structure of the package. In particular, if my PR modifies code of plotly.graph_objects, my modifications concern the codegen files and not generated files.
  • I have added tests (if submitting a new feature or correcting a bug) or
    modified existing tests.
  • For a new feature, I have added documentation examples in an existing or
    new tutorial notebook (please see the doc checklist as well).
  • I have added a CHANGELOG entry if fixing/changing/adding anything substantial.
  • For a new feature or a change in behaviour, I have updated the relevant docstrings in the code to describe the feature or behaviour (please see the doc checklist as well).

In my virtual environment, there happens to be installed IPython package.
It wasn't installed by myself, it's merely a transitive dependency of
some another package. It's neither intended to be used, nor is actually
used by my project. However, mere presense of the IPython package, due
to the over-simplistic decision code in this module (io._renderers)
leads to drastic behavior change in Plotly.py: calling
Figure._repr_html_() causes lots of JS garbage to be printed on terminal
(by common sense, this should be a side-effects free function, only
returning a value). On a higher level, this breaks natural Plotly.py
integration in frameworks like Shiny.py (because again, instead of
HTML representation being returned for a framework to process, parts
of that representation are dumped on terminal).
The real underlying issue is that Plotly.py should not force-import
any "optional" packages behind users' back. However, this is a deeper
issue requiring consideration and will be reported separately. This
patch is a quick solution for the problem describe above.
From interactive session:
>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'
Signed-off-by: Paul Sokolovsky <pfalcon@users.sourceforge.net>
@pfalcon

Copy link
Copy Markdown
Author

Example of how this affects downstream projects: posit-dev/py-shinywidgets#201 . I'm an experienced Python user, and it took me half a day to debug this issue. I imagine how frustrating it may be for novice users who just wanted to try one of those well-popularized modern Python data visualization packages.

@gvwilson
gvwilson requested a review from emilyklJune 13, 2025 14:12
@gvwilsongvwilson added feature something new P1 needed for current cycle community community contribution labels Jun 13, 2025
@emilykl

Copy link
Copy Markdown
Contributor

Hi @pfalcon , I've just merged a fix in #5258 which takes a slightly different approach to this same issue. Thank you for the contribution and please let me know if that fix addresses the issue on your end!

@emilyklemilykl closed this Oct 1, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

communitycommunity contributionfeaturesomething newP1needed for current cycle

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pfalcon@emilykl@gvwilson
, '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

If IPython is merely installed, don't assume that it's actually used - #5222

Closed
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions
Closed

If IPython is merely installed, don't assume that it's actually used#5222
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions

Conversation

@pfalcon

Copy link
Copy Markdown

In my virtual environment, there happens to be installed IPython package. It wasn't installed by myself, it's merely a transitive dependency of some another package. It's neither intended to be used, nor is actually used by my project. However, mere presense of the IPython package, due to the over-simplistic decision code in this module (io._renderers) leads to drastic behavior change in Plotly.py: calling Figure.repr_html() causes lots of JS garbage to be printed on terminal (by common sense, this should be a side-effects free function, only returning a value). On a higher level, this breaks natural Plotly.py integration in frameworks like Shiny.py (because again, instead of HTML representation being returned for a framework to process, parts of that representation are dumped on terminal).

The real underlying issue is that Plotly.py should not force-import any "optional" packages behind users' back. However, this is a deeper issue requiring consideration and will be reported separately. This patch is a quick solution for the problem describe above.

From interactive session:

>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'

Code PR

  • I have read through the contributing notes and understand the structure of the package. In particular, if my PR modifies code of plotly.graph_objects, my modifications concern the codegen files and not generated files.
  • I have added tests (if submitting a new feature or correcting a bug) or
    modified existing tests.
  • For a new feature, I have added documentation examples in an existing or
    new tutorial notebook (please see the doc checklist as well).
  • I have added a CHANGELOG entry if fixing/changing/adding anything substantial.
  • For a new feature or a change in behaviour, I have updated the relevant docstrings in the code to describe the feature or behaviour (please see the doc checklist as well).

In my virtual environment, there happens to be installed IPython package.
It wasn't installed by myself, it's merely a transitive dependency of
some another package. It's neither intended to be used, nor is actually
used by my project. However, mere presense of the IPython package, due
to the over-simplistic decision code in this module (io._renderers)
leads to drastic behavior change in Plotly.py: calling
Figure._repr_html_() causes lots of JS garbage to be printed on terminal
(by common sense, this should be a side-effects free function, only
returning a value). On a higher level, this breaks natural Plotly.py
integration in frameworks like Shiny.py (because again, instead of
HTML representation being returned for a framework to process, parts
of that representation are dumped on terminal).
The real underlying issue is that Plotly.py should not force-import
any "optional" packages behind users' back. However, this is a deeper
issue requiring consideration and will be reported separately. This
patch is a quick solution for the problem describe above.
From interactive session:
>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'
Signed-off-by: Paul Sokolovsky <pfalcon@users.sourceforge.net>
@pfalcon

Copy link
Copy Markdown
Author

Example of how this affects downstream projects: posit-dev/py-shinywidgets#201 . I'm an experienced Python user, and it took me half a day to debug this issue. I imagine how frustrating it may be for novice users who just wanted to try one of those well-popularized modern Python data visualization packages.

@gvwilson
gvwilson requested a review from emilyklJune 13, 2025 14:12
@gvwilsongvwilson added feature something new P1 needed for current cycle community community contribution labels Jun 13, 2025
@emilykl

Copy link
Copy Markdown
Contributor

Hi @pfalcon , I've just merged a fix in #5258 which takes a slightly different approach to this same issue. Thank you for the contribution and please let me know if that fix addresses the issue on your end!

@emilyklemilykl closed this Oct 1, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

communitycommunity contributionfeaturesomething newP1needed for current cycle

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pfalcon@emilykl@gvwilson
, '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

If IPython is merely installed, don't assume that it's actually used - #5222

Closed
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions
Closed

If IPython is merely installed, don't assume that it's actually used#5222
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions

Conversation

@pfalcon

Copy link
Copy Markdown

In my virtual environment, there happens to be installed IPython package. It wasn't installed by myself, it's merely a transitive dependency of some another package. It's neither intended to be used, nor is actually used by my project. However, mere presense of the IPython package, due to the over-simplistic decision code in this module (io._renderers) leads to drastic behavior change in Plotly.py: calling Figure.repr_html() causes lots of JS garbage to be printed on terminal (by common sense, this should be a side-effects free function, only returning a value). On a higher level, this breaks natural Plotly.py integration in frameworks like Shiny.py (because again, instead of HTML representation being returned for a framework to process, parts of that representation are dumped on terminal).

The real underlying issue is that Plotly.py should not force-import any "optional" packages behind users' back. However, this is a deeper issue requiring consideration and will be reported separately. This patch is a quick solution for the problem describe above.

From interactive session:

>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'

Code PR

  • I have read through the contributing notes and understand the structure of the package. In particular, if my PR modifies code of plotly.graph_objects, my modifications concern the codegen files and not generated files.
  • I have added tests (if submitting a new feature or correcting a bug) or
    modified existing tests.
  • For a new feature, I have added documentation examples in an existing or
    new tutorial notebook (please see the doc checklist as well).
  • I have added a CHANGELOG entry if fixing/changing/adding anything substantial.
  • For a new feature or a change in behaviour, I have updated the relevant docstrings in the code to describe the feature or behaviour (please see the doc checklist as well).

In my virtual environment, there happens to be installed IPython package.
It wasn't installed by myself, it's merely a transitive dependency of
some another package. It's neither intended to be used, nor is actually
used by my project. However, mere presense of the IPython package, due
to the over-simplistic decision code in this module (io._renderers)
leads to drastic behavior change in Plotly.py: calling
Figure._repr_html_() causes lots of JS garbage to be printed on terminal
(by common sense, this should be a side-effects free function, only
returning a value). On a higher level, this breaks natural Plotly.py
integration in frameworks like Shiny.py (because again, instead of
HTML representation being returned for a framework to process, parts
of that representation are dumped on terminal).
The real underlying issue is that Plotly.py should not force-import
any "optional" packages behind users' back. However, this is a deeper
issue requiring consideration and will be reported separately. This
patch is a quick solution for the problem describe above.
From interactive session:
>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'
Signed-off-by: Paul Sokolovsky <pfalcon@users.sourceforge.net>
@pfalcon

Copy link
Copy Markdown
Author

Example of how this affects downstream projects: posit-dev/py-shinywidgets#201 . I'm an experienced Python user, and it took me half a day to debug this issue. I imagine how frustrating it may be for novice users who just wanted to try one of those well-popularized modern Python data visualization packages.

@gvwilson
gvwilson requested a review from emilyklJune 13, 2025 14:12
@gvwilsongvwilson added feature something new P1 needed for current cycle community community contribution labels Jun 13, 2025
@emilykl

Copy link
Copy Markdown
Contributor

Hi @pfalcon , I've just merged a fix in #5258 which takes a slightly different approach to this same issue. Thank you for the contribution and please let me know if that fix addresses the issue on your end!

@emilyklemilykl closed this Oct 1, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

communitycommunity contributionfeaturesomething newP1needed for current cycle

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pfalcon@emilykl@gvwilson
, '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

If IPython is merely installed, don't assume that it's actually used - #5222

Closed
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions
Closed

If IPython is merely installed, don't assume that it's actually used#5222
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions

Conversation

@pfalcon

Copy link
Copy Markdown

In my virtual environment, there happens to be installed IPython package. It wasn't installed by myself, it's merely a transitive dependency of some another package. It's neither intended to be used, nor is actually used by my project. However, mere presense of the IPython package, due to the over-simplistic decision code in this module (io._renderers) leads to drastic behavior change in Plotly.py: calling Figure.repr_html() causes lots of JS garbage to be printed on terminal (by common sense, this should be a side-effects free function, only returning a value). On a higher level, this breaks natural Plotly.py integration in frameworks like Shiny.py (because again, instead of HTML representation being returned for a framework to process, parts of that representation are dumped on terminal).

The real underlying issue is that Plotly.py should not force-import any "optional" packages behind users' back. However, this is a deeper issue requiring consideration and will be reported separately. This patch is a quick solution for the problem describe above.

From interactive session:

>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'

Code PR

  • I have read through the contributing notes and understand the structure of the package. In particular, if my PR modifies code of plotly.graph_objects, my modifications concern the codegen files and not generated files.
  • I have added tests (if submitting a new feature or correcting a bug) or
    modified existing tests.
  • For a new feature, I have added documentation examples in an existing or
    new tutorial notebook (please see the doc checklist as well).
  • I have added a CHANGELOG entry if fixing/changing/adding anything substantial.
  • For a new feature or a change in behaviour, I have updated the relevant docstrings in the code to describe the feature or behaviour (please see the doc checklist as well).

In my virtual environment, there happens to be installed IPython package.
It wasn't installed by myself, it's merely a transitive dependency of
some another package. It's neither intended to be used, nor is actually
used by my project. However, mere presense of the IPython package, due
to the over-simplistic decision code in this module (io._renderers)
leads to drastic behavior change in Plotly.py: calling
Figure._repr_html_() causes lots of JS garbage to be printed on terminal
(by common sense, this should be a side-effects free function, only
returning a value). On a higher level, this breaks natural Plotly.py
integration in frameworks like Shiny.py (because again, instead of
HTML representation being returned for a framework to process, parts
of that representation are dumped on terminal).
The real underlying issue is that Plotly.py should not force-import
any "optional" packages behind users' back. However, this is a deeper
issue requiring consideration and will be reported separately. This
patch is a quick solution for the problem describe above.
From interactive session:
>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'
Signed-off-by: Paul Sokolovsky <pfalcon@users.sourceforge.net>
@pfalcon

Copy link
Copy Markdown
Author

Example of how this affects downstream projects: posit-dev/py-shinywidgets#201 . I'm an experienced Python user, and it took me half a day to debug this issue. I imagine how frustrating it may be for novice users who just wanted to try one of those well-popularized modern Python data visualization packages.

@gvwilson
gvwilson requested a review from emilyklJune 13, 2025 14:12
@gvwilsongvwilson added feature something new P1 needed for current cycle community community contribution labels Jun 13, 2025
@emilykl

Copy link
Copy Markdown
Contributor

Hi @pfalcon , I've just merged a fix in #5258 which takes a slightly different approach to this same issue. Thank you for the contribution and please let me know if that fix addresses the issue on your end!

@emilyklemilykl closed this Oct 1, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

communitycommunity contributionfeaturesomething newP1needed for current cycle

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pfalcon@emilykl@gvwilson
, '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

If IPython is merely installed, don't assume that it's actually used - #5222

Closed
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions
Closed

If IPython is merely installed, don't assume that it's actually used#5222
pfalcon wants to merge 1 commit into
plotly:mainfrom
pfalcon:no-ipython-overdecisions

Conversation

@pfalcon

Copy link
Copy Markdown

In my virtual environment, there happens to be installed IPython package. It wasn't installed by myself, it's merely a transitive dependency of some another package. It's neither intended to be used, nor is actually used by my project. However, mere presense of the IPython package, due to the over-simplistic decision code in this module (io._renderers) leads to drastic behavior change in Plotly.py: calling Figure.repr_html() causes lots of JS garbage to be printed on terminal (by common sense, this should be a side-effects free function, only returning a value). On a higher level, this breaks natural Plotly.py integration in frameworks like Shiny.py (because again, instead of HTML representation being returned for a framework to process, parts of that representation are dumped on terminal).

The real underlying issue is that Plotly.py should not force-import any "optional" packages behind users' back. However, this is a deeper issue requiring consideration and will be reported separately. This patch is a quick solution for the problem describe above.

From interactive session:

>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'

Code PR

  • I have read through the contributing notes and understand the structure of the package. In particular, if my PR modifies code of plotly.graph_objects, my modifications concern the codegen files and not generated files.
  • I have added tests (if submitting a new feature or correcting a bug) or
    modified existing tests.
  • For a new feature, I have added documentation examples in an existing or
    new tutorial notebook (please see the doc checklist as well).
  • I have added a CHANGELOG entry if fixing/changing/adding anything substantial.
  • For a new feature or a change in behaviour, I have updated the relevant docstrings in the code to describe the feature or behaviour (please see the doc checklist as well).

In my virtual environment, there happens to be installed IPython package.
It wasn't installed by myself, it's merely a transitive dependency of
some another package. It's neither intended to be used, nor is actually
used by my project. However, mere presense of the IPython package, due
to the over-simplistic decision code in this module (io._renderers)
leads to drastic behavior change in Plotly.py: calling
Figure._repr_html_() causes lots of JS garbage to be printed on terminal
(by common sense, this should be a side-effects free function, only
returning a value). On a higher level, this breaks natural Plotly.py
integration in frameworks like Shiny.py (because again, instead of
HTML representation being returned for a framework to process, parts
of that representation are dumped on terminal).
The real underlying issue is that Plotly.py should not force-import
any "optional" packages behind users' back. However, this is a deeper
issue requiring consideration and will be reported separately. This
patch is a quick solution for the problem describe above.
From interactive session:
>>> import IPython
>>> IPython.get_ipython().__class__.__name__
'NoneType'
Signed-off-by: Paul Sokolovsky <pfalcon@users.sourceforge.net>
@pfalcon

Copy link
Copy Markdown
Author

Example of how this affects downstream projects: posit-dev/py-shinywidgets#201 . I'm an experienced Python user, and it took me half a day to debug this issue. I imagine how frustrating it may be for novice users who just wanted to try one of those well-popularized modern Python data visualization packages.

@gvwilson
gvwilson requested a review from emilyklJune 13, 2025 14:12
@gvwilsongvwilson added feature something new P1 needed for current cycle community community contribution labels Jun 13, 2025
@emilykl

Copy link
Copy Markdown
Contributor

Hi @pfalcon , I've just merged a fix in #5258 which takes a slightly different approach to this same issue. Thank you for the contribution and please let me know if that fix addresses the issue on your end!

@emilyklemilykl closed this Oct 1, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

communitycommunity contributionfeaturesomething newP1needed for current cycle

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pfalcon@emilykl@gvwilson